Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormhussein2012-05-03 11:12:57 -0400
committerDoug Schaefer2012-05-04 09:55:26 -0400
commita2cfb6e5cd7eacc5415d74e5ccf29f36fc6c7037 (patch)
treec690288b323f12c6c5197abf771c3b4b9e794d33 /build/org.eclipse.cdt.managedbuilder.ui
parent621ee0fe2260723d9a134e0938ac748ce6528ec9 (diff)
downloadorg.eclipse.cdt-a2cfb6e5cd7eacc5415d74e5ccf29f36fc6c7037.tar.gz
org.eclipse.cdt-a2cfb6e5cd7eacc5415d74e5ccf29f36fc6c7037.tar.xz
org.eclipse.cdt-a2cfb6e5cd7eacc5415d74e5ccf29f36fc6c7037.zip
Bug 365718: Support tree option style in managed build options
Managed build options in tools provide several styles for option type, for example: string, boolean, libPaths, enumerated, ... The enumerated type allows the user to select from a pre-defined list of values. A usability problem might happen if the list of possible values is Huge, in this case the simple drop-box wouldn't be sufficient for the user to properly and easily select the needed option. In most of those cases the huge list of options can be organized in some hierarchy that allows the user to easily pick the needed option. The attached patch attempts to support this by doing the following: 1- Adding support of a new option valueType "tree" - Adding schema for treeOption - Adding support for tree type similar to enumerated option type 2- Provide UI to easily select items from this tree - Provide a field editor with a text box and browse button - Provide popup tree picker with filtered search - Each item in the tree can optionally provide an icon, and specify its relative order among its peers. Updates: - Expose TreeSelectionDialog and TreeRoot to allow usage in other contexts - Remove extra whitespaces. - Support Double-click to select - Added unit test Change-Id: I3e7e8c6e3e9878f7c6dadeb149326b375cd3631d Reviewed-on: https://git.eclipse.org/r/5558 Reviewed-by: Doug Schaefer <dschaefer@qnx.com> IP-Clean: Doug Schaefer <dschaefer@qnx.com> Tested-by: Doug Schaefer <dschaefer@qnx.com>
Diffstat (limited to 'build/org.eclipse.cdt.managedbuilder.ui')
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuildOptionSettingsUI.java317
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuildToolSettingUI.java15
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ToolSettingsPrefStore.java7
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ToolSettingsTab.java3
4 files changed, 336 insertions, 6 deletions
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuildOptionSettingsUI.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuildOptionSettingsUI.java
index b940a747ef..d082e0c696 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuildOptionSettingsUI.java
+++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuildOptionSettingsUI.java
@@ -14,8 +14,12 @@
package org.eclipse.cdt.managedbuilder.ui.properties;
import java.io.File;
+import java.net.URL;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -28,6 +32,8 @@ import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IHoldsOptions;
import org.eclipse.cdt.managedbuilder.core.IManagedOptionValueHandler;
import org.eclipse.cdt.managedbuilder.core.IOption;
+import org.eclipse.cdt.managedbuilder.core.IOption.ITreeOption;
+import org.eclipse.cdt.managedbuilder.core.IOption.ITreeRoot;
import org.eclipse.cdt.managedbuilder.core.IOptionApplicability;
import org.eclipse.cdt.managedbuilder.core.IOptionCategory;
import org.eclipse.cdt.managedbuilder.core.IResourceInfo;
@@ -42,18 +48,37 @@ import org.eclipse.cdt.ui.newui.AbstractPage;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.DirectoryFieldEditor;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.FileFieldEditor;
+import org.eclipse.jface.preference.StringButtonFieldEditor;
import org.eclipse.jface.preference.StringFieldEditor;
+import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.TextProcessor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
@@ -61,10 +86,13 @@ import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.osgi.framework.Bundle;
+import org.eclipse.ui.dialogs.FilteredTree;
+import org.eclipse.ui.dialogs.PatternFilter;
/**
* Option settings page in project properties Build Settings under Tool Settings tab.
@@ -87,6 +115,35 @@ public class BuildOptionSettingsUI extends AbstractToolSettingUI {
** currently set to Enter rather than Hover since the former seems more responsive **/
private final static int selectAction = SWT.MouseEnter;
+ private final class TreeBrowseFieldEditor extends StringButtonFieldEditor {
+ private final String nameStr;
+ private final IOption option;
+ private String contextId;
+
+ private TreeBrowseFieldEditor(String name, String labelText, Composite parent, String nameStr,
+ IOption option, String contextId) {
+ super(name, labelText, parent);
+ this.nameStr = nameStr;
+ this.option = option;
+ this.contextId = contextId;
+ }
+
+ @Override
+ protected String changePressed() {
+ ITreeRoot treeRoot;
+ try {
+ treeRoot = option.getTreeRoot();
+ TreeSelectionDialog dlg = new TreeSelectionDialog(getShell(), treeRoot, nameStr, contextId);
+ if (dlg.open() == Window.OK) {
+ ITreeOption selected = dlg.getSelection();
+ return selected.getName();
+ }
+ } catch (BuildException e) {
+ }
+ return null;
+ }
+ }
+
private class TipInfo {
private String name;
private String tip;
@@ -212,7 +269,7 @@ public class BuildOptionSettingsUI extends AbstractToolSettingUI {
if (applicabilityCalculator == null || applicabilityCalculator.isOptionVisible(config, holder, opt)) {
String optId = getToolSettingsPrefStore().getOptionId(opt);
- String nameStr = TextProcessor.process(opt.getName());
+ final String nameStr = TextProcessor.process(opt.getName());
String tipStr = TextProcessor.process(opt.getToolTip());
String contextId = opt.getContextId();
@@ -374,6 +431,20 @@ public class BuildOptionSettingsUI extends AbstractToolSettingUI {
}
} break;
+ case IOption.TREE:
+ fieldEditor = new TreeBrowseFieldEditor(optId, nameStr, fieldEditorParent, nameStr, opt, contextId);
+ ((StringButtonFieldEditor)fieldEditor).setChangeButtonText("..."); //$NON-NLS-1$
+
+ if (pageHasToolTipBox) {
+ Text text = ((StringButtonFieldEditor)fieldEditor).getTextControl(fieldEditorParent);
+ Label label = fieldEditor.getLabelControl(fieldEditorParent);
+ text.setData(new TipInfo(nameStr,tipStr));
+ text.addListener(selectAction, tipSetListener);
+ label.setData(new TipInfo(nameStr,tipStr));
+ label.addListener(selectAction, tipSetListener);
+ }
+ break;
+
case IOption.INCLUDE_PATH:
case IOption.STRING_LIST:
case IOption.PREPROCESSOR_SYMBOLS:
@@ -563,8 +634,9 @@ public class BuildOptionSettingsUI extends AbstractToolSettingUI {
// }
break;
case IOption.ENUMERATED :
+ case IOption.TREE :
String enumVal = clonedOption.getStringValue();
- String enumId = clonedOption.getEnumeratedId(enumVal);
+ String enumId = clonedOption.getId(enumVal);
setOption = ManagedBuildManager.setOption(realCfg, realHolder, realOption,
(enumId != null && enumId.length() > 0) ? enumId : enumVal);
// Reset the preference store since the Id may have changed
@@ -757,6 +829,15 @@ public class BuildOptionSettingsUI extends AbstractToolSettingUI {
}
break;
+ case IOption.TREE:
+ if(fe instanceof TreeBrowseFieldEditor){
+ String name = ((TreeBrowseFieldEditor)fe).getStringValue();
+ String treeId = changedOption.getId(name);
+ ManagedBuildManager.setOption(fInfo,changedHolder,changedOption,
+ (treeId != null && treeId.length() > 0) ? treeId : name);
+
+ }
+ break;
case IOption.INCLUDE_PATH:
case IOption.STRING_LIST:
case IOption.PREPROCESSOR_SYMBOLS:
@@ -1004,5 +1085,237 @@ public class BuildOptionSettingsUI extends AbstractToolSettingUI {
}
}
+ /**
+ * @since 8.1
+ */
+ public static class TreeSelectionDialog extends TitleAreaDialog {
+ private final ITreeRoot treeRoot;
+ private ITreeOption selected;
+ private final String name;
+ private String contextId;
+ private String baseMessage = ""; //$NON-NLS-1$
+
+ public TreeSelectionDialog(Shell parentShell, ITreeRoot root, String name, String contextId) {
+ super(parentShell);
+ treeRoot = root;
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ if (root.getIcon() != null) {
+ Image img = createImage(root.getIcon());
+ if (img != null) {
+ setTitleImage(img);
+ }
+ }
+ this.name = name;
+ this.contextId = contextId;
+ if (contextId != null && contextId.length() > 0) {
+ setHelpAvailable(true);
+ }
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ if (contextId != null && contextId.length() > 0) {
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, contextId);
+ }
+
+ Composite control = new Composite(parent, SWT.NULL);
+ GridData gd= new GridData(GridData.FILL_BOTH);
+ GridLayout topLayout = new GridLayout();
+ topLayout.numColumns = 1;
+ control.setLayout(topLayout);
+ control.setLayoutData(gd);
+
+ PatternFilter filter = new PatternFilter();
+ filter.setIncludeLeadingWildcard(true);
+ FilteredTree tree = new FilteredTree(control,
+ SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER,
+ filter, true);
+ final TreeViewer viewer = tree.getViewer();
+ viewer.setContentProvider(new ITreeContentProvider() {
+
+ @Override
+ public void dispose() {
+ }
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ return getChildren(inputElement);
+ }
+
+ @Override
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof ITreeOption) {
+ ITreeOption[] children = ((ITreeOption)parentElement).getChildren();
+
+ // Not entirely sure whether this method is allowed to return null,
+ // but let's play safe.
+ if (children == null)
+ return null;
+
+ List<ITreeOption> childrenList = new ArrayList<ITreeOption>(Arrays.asList(children));
+
+ // Check if any of the children has empty name
+ List<ITreeOption> toRemove = null;
+ for (ITreeOption child : children) {
+ if (child.getName() == null || child.getName().trim().length() == 0) {
+ if (toRemove == null) {
+ toRemove = new ArrayList<ITreeOption>();
+ }
+ toRemove.add(child);
+ }
+ }
+ if (toRemove != null) {
+ childrenList.removeAll(toRemove);
+ }
+
+ // Sort the children.
+ Collections.sort(childrenList, new Comparator<ITreeOption>() {
+ @Override
+ public int compare(ITreeOption arg0, ITreeOption arg1) {
+ if (arg0.getOrder() == arg1.getOrder()) {
+ return arg0.getName().compareToIgnoreCase(arg1.getName());
+ } else {
+ return arg0.getOrder() - arg1.getOrder();
+ }
+ }
+ });
+
+ return childrenList.toArray(new ITreeOption[0]);
+ }
+ return null;
+ }
+
+ @Override
+ public Object getParent(Object element) {
+ if (element instanceof ITreeOption) {
+ return ((ITreeOption)element).getParent();
+ }
+ return null;
+ }
+
+ @Override
+ public boolean hasChildren(Object element) {
+ Object[] children = getChildren(element);
+ return children != null && children.length > 0;
+ }
+
+ });
+
+ viewer.setLabelProvider(new LabelProvider() {
+
+ @Override
+ public String getText(Object element) {
+ if (element instanceof ITreeOption) {
+ return ((ITreeOption)element).getName();
+ }
+ return super.getText(element);
+ }
+
+ @Override
+ public Image getImage(Object element) {
+ if (element instanceof ITreeOption) {
+ String icon = ((ITreeOption)element).getIcon();
+ return createImage(icon);
+ }
+ return super.getImage(element);
+ }
+ });
+
+ viewer.addSelectionChangedListener(new ISelectionChangedListener() {
+
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ ISelection selection = event.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ Object selectedObj = ((IStructuredSelection)selection).getFirstElement();
+ if (selectedObj instanceof ITreeOption) {
+ selected = (ITreeOption) selectedObj;
+
+ updateOKButton(selected);
+
+ // Adjust Message
+ String description = selected.getDescription();
+ if (description == null) {
+ ITreeOption node = selected;
+ description = ""; //$NON-NLS-1$
+ String sep = ": "; //$NON-NLS-1$
+ while (node != null && node.getParent() != null) { // ignore root
+ description = sep + node.getName() + description;
+ node = node.getParent();
+ }
+ description = description.substring(sep.length()); // remove the first separator.
+ }
+ setMessage(baseMessage + description);
+ }
+ }
+ }
+ });
+
+ viewer.addDoubleClickListener(new IDoubleClickListener() {
+
+ @Override
+ public void doubleClick(DoubleClickEvent event) {
+ ISelection selection = event.getSelection();
+ if (!selection.isEmpty() && selection instanceof IStructuredSelection && ((IStructuredSelection)selection).size() == 1) {
+ Object selectedNode = ((IStructuredSelection)selection).getFirstElement();
+ if (selectedNode instanceof ITreeOption) {
+ if (updateOKButton((ITreeOption)selectedNode)) {
+ TreeSelectionDialog.this.okPressed();
+ } else { // if doubleclick is not on selectable item, expand/collapse
+ viewer.setExpandedState(selectedNode,!viewer.getExpandedState(selectedNode));
+ }
+ }
+ }
+ }
+ });
+
+ viewer.setInput(treeRoot);
+
+ String msg = "Select " + name; //$NON-NLS-1$
+ getShell().setText(msg);
+ setTitle(msg);
+ if (treeRoot.getDescription() != null) {
+ baseMessage = treeRoot.getDescription();
+ setMessage(baseMessage);
+ baseMessage += "\nCurrent Selection: "; //$NON-NLS-1$
+ } else {
+ setMessage(msg);
+ }
+
+ return control;
+ }
+
+ public ITreeOption getSelection() {
+ return selected;
+ }
+
+ private Image createImage(String icon) {
+ if (icon != null) {
+ URL url = null;
+ try {
+ url = FileLocator.find(new URL(icon));
+ } catch (Exception e) {
+ }
+ if (url != null) {
+ ImageDescriptor desc = ImageDescriptor.createFromURL(url);
+ return desc.createImage();
+ }
+ }
+ return null;
+ }
+ private boolean updateOKButton(ITreeOption selection) {
+ // Check if Valid selection (only allow selecting leaf nodes)
+ if (treeRoot.isSelectLeafsOnly()) {
+ boolean enableOK = !selection.isContainer();
+ getButton(IDialogConstants.OK_ID).setEnabled(enableOK);
+ return enableOK;
+ }
+ return false;
+ }
+ }
}
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuildToolSettingUI.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuildToolSettingUI.java
index 685cf46fee..547d4d61f8 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuildToolSettingUI.java
+++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuildToolSettingUI.java
@@ -20,6 +20,7 @@ import java.util.Vector;
import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IOption;
+import org.eclipse.cdt.managedbuilder.core.IOption.ITreeRoot;
import org.eclipse.cdt.managedbuilder.core.IResourceInfo;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.internal.core.MultiResourceInfo;
@@ -316,6 +317,20 @@ public class BuildToolSettingUI extends AbstractToolSettingUI {
if (!enumeration.equals("")) //$NON-NLS-1$
setOption(opt, enumeration);
break;
+ case IOption.TREE :
+ String selectedID = ""; //$NON-NLS-1$
+ ITreeRoot treeRoot = opt.getTreeRoot();
+ String[] treeValues = opt.getApplicableValues();
+ for (int i = 0; i < treeValues.length; i++) {
+ if (opt.getCommand(treeValues[i]).equals(
+ optionValue)) {
+ selectedID = treeValues[i];
+ optionValueExist = true;
+ }
+ }
+ if (!selectedID.equals("")) //$NON-NLS-1$
+ setOption(opt, selectedID);
+ break;
case IOption.STRING_LIST :
case IOption.INCLUDE_PATH :
case IOption.PREPROCESSOR_SYMBOLS :
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ToolSettingsPrefStore.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ToolSettingsPrefStore.java
index f1f0ec3eae..dd5c356a01 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ToolSettingsPrefStore.java
+++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ToolSettingsPrefStore.java
@@ -205,8 +205,8 @@ public class ToolSettingsPrefStore implements IPreferenceStore {
try {
IOption opt = (IOption)option[1];
Object val = opt.getValue();
- if(opt.getValueType() == IOption.ENUMERATED && val instanceof String)
- val = opt.getEnumName((String)val);
+ if((opt.getValueType() == IOption.ENUMERATED || opt.getValueType() == IOption.TREE) && val instanceof String)
+ val = opt.getName((String)val);
return val;
} catch (BuildException e) {
}
@@ -313,9 +313,10 @@ public class ToolSettingsPrefStore implements IPreferenceStore {
}
break;
case IOption.ENUMERATED:
+ case IOption.TREE:
if(value instanceof String){
String val = (String)value;
- String enumId = option.getEnumeratedId(val);
+ String enumId = option.getId(val);
newOption = rcInfo.setOption(holder, option,
(enumId != null && enumId.length() > 0) ? enumId : val);
}
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ToolSettingsTab.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ToolSettingsTab.java
index db5056087e..a6e7dabb92 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ToolSettingsTab.java
+++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ToolSettingsTab.java
@@ -568,8 +568,9 @@ public class ToolSettingsTab extends AbstractCBuildPropertyTab implements IPrefe
ManagedBuildManager.setOption(res, dst, op2, boolVal);
break;
case IOption.ENUMERATED :
+ case IOption.TREE :
String enumVal = op1.getStringValue();
- String enumId = op1.getEnumeratedId(enumVal);
+ String enumId = op1.getId(enumVal);
String out = (enumId != null && enumId.length() > 0) ? enumId : enumVal;
ManagedBuildManager.setOption(res, dst, op2, out);
break;

Back to the top