Bug 530425 - [foramtter][preferences] Add "Expand All" context menu in section headers
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/FilteredPreferenceTree.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/FilteredPreferenceTree.java
index 68c265e..ae1a5a0 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/FilteredPreferenceTree.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/FilteredPreferenceTree.java
@@ -537,7 +537,7 @@
 		item.addSelectionListener(new SelectionAdapter() {
 			@Override
 			public void widgetSelected(SelectionEvent e) {
-				setAllExpanded(expand);
+				setAllExpanded(null, expand);
 			}
 		});
 		item.addDisposeListener(new DisposeListener() {
@@ -683,12 +683,16 @@
 		return node;
 	}
 
-	protected void setAllExpanded(boolean expanded) {
+	protected void setAllExpanded(PreferenceTreeNode<?> start, boolean expanded) {
 		fScrolledPageContent.setRedraw(false);
 		fScrolledPageContent.setReflow(false);
 
 		ArrayList<PreferenceTreeNode<?>> bfsNodes= new ArrayList<>();
-		bfsNodes.addAll(fRoot.getChildren());
+		if (start != null) {
+			bfsNodes.add(start);
+		} else {
+			bfsNodes.addAll(fRoot.getChildren());
+		}
 		for (int i= 0; i < bfsNodes.size(); i++) {
 			PreferenceTreeNode<?> node= bfsNodes.get(i);
 			bfsNodes.addAll(bfsNodes.get(i).getChildren());
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/formatter/ModifyDialog.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/formatter/ModifyDialog.java
index 36ae24d..a46b90e 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/formatter/ModifyDialog.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/formatter/ModifyDialog.java
@@ -54,6 +54,8 @@
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.FileDialog;
 import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.Spinner;
 import org.eclipse.swt.widgets.Text;
@@ -93,6 +95,7 @@
 import org.eclipse.jdt.internal.ui.preferences.FilteredPreferenceTree;
 import org.eclipse.jdt.internal.ui.preferences.FilteredPreferenceTree.HighlightHelper;
 import org.eclipse.jdt.internal.ui.preferences.FilteredPreferenceTree.PreferenceTreeNode;
+import org.eclipse.jdt.internal.ui.preferences.PreferencesMessages;
 import org.eclipse.jdt.internal.ui.preferences.formatter.IModifyDialogTabPage.IModificationListener;
 import org.eclipse.jdt.internal.ui.preferences.formatter.ProfileManager.CustomProfile;
 import org.eclipse.jdt.internal.ui.preferences.formatter.ProfileManager.Profile;
@@ -119,7 +122,7 @@
 				boolean fExpandLock= false;
 				{
 					textLabel.addListener(SWT.MouseEnter, e -> fHasFocusBeforeClick= toggle.isFocusControl());
-					textLabel.addListener(SWT.MouseDown, e -> fExpandLock= !fHasFocusBeforeClick);
+					textLabel.addListener(SWT.MouseDown, e -> fExpandLock= !fHasFocusBeforeClick || e.button != 1);
 				}
 
 				@Override
@@ -132,6 +135,12 @@
 						super.internalSetExpanded(expanded);
 					}
 				}
+
+				@Override
+				public void setMenu(Menu menu) {
+					// add only to header, not the rest of the composite
+					textLabel.setMenu(menu);
+				}
 			};
 			excomposite.clientVerticalSpacing= 0;
 			excomposite.setText(label);
@@ -884,6 +893,17 @@
 			ExpandableComposite excomposite= section.getControl();
 			getScrolledPageContent().adaptChild(excomposite);
 
+			Menu expandAllMenu= new Menu(excomposite);
+			MenuItem expandAllItem= new MenuItem(expandAllMenu, SWT.NONE);
+			expandAllItem.setText(PreferencesMessages.FilteredPreferencesTree_expandAll_tooltip);
+			expandAllItem.addSelectionListener(new SelectionAdapter() {
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					setAllExpanded(section, true);
+				}
+			});
+			excomposite.setMenu(expandAllMenu);
+
 			return addChild(parent, section);
 		}
 
@@ -1039,7 +1059,7 @@
 
 		public void unifySectionTitlesHeights(Section section) {
 			List<PreferenceTreeNode<?>> children= section == null ? fRoot.getChildren() : section.getChildren();
-			int maxHeightDiff= 5;
+			int maxHeightDiff= 0;
 			for (PreferenceTreeNode<?> child : children) {
 				if (child instanceof Section)
 					maxHeightDiff= Math.max(maxHeightDiff, ((Section) child).getControl().getTextClientHeightDifference());