summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormhussein2012-05-03 11:12:57 (EDT)
committer Doug Schaefer2012-05-04 09:55:26 (EDT)
commita2cfb6e5cd7eacc5415d74e5ccf29f36fc6c7037 (patch)
treec690288b323f12c6c5197abf771c3b4b9e794d33
parent621ee0fe2260723d9a134e0938ac748ce6528ec9 (diff)
downloadorg.eclipse.cdt-a2cfb6e5cd7eacc5415d74e5ccf29f36fc6c7037.zip
org.eclipse.cdt-a2cfb6e5cd7eacc5415d74e5ccf29f36fc6c7037.tar.gz
org.eclipse.cdt-a2cfb6e5cd7eacc5415d74e5ccf29f36fc6c7037.tar.bz2
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>
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml62
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildCoreTests.java64
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd115
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IOption.java173
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedOptionValueHandler.java1
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildStep.java2
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ConfigurationV2.java1
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Option.java426
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionReference.java59
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Tool.java7
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ToolReference.java9
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/enablement/CheckOptionExpression.java2
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/enablement/OptionEnablementExpression.java1
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/macros/MbsMacroSupplier.java4
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java2
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/ManagedBuildGnuToolInfo.java2
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/projectconverter/UpdateManagedProject12.java13
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/projectconverter/UpdateManagedProject20.java1
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/templateengine/processes/SetMBSStringOptionValue.java4
-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
23 files changed, 1230 insertions, 60 deletions
diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml b/build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml
index 67494d8..dfaafb8 100644
--- a/build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml
+++ b/build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml
@@ -9311,4 +9311,66 @@
name="Test Plugin GCC BOP Patterns Highlighter">
</errorparser>
</extension>
+ <!-- Tree Option -->
+ <extension
+ id="cdt.managed.build.test.tree.option"
+ name="Test Managed Build TreeOption"
+ point="org.eclipse.cdt.managedbuilder.core.buildDefinitions">
+ <managedBuildRevision fileVersion="4.0.0"/>
+ <tool
+ natureFilter="cnature"
+ name="Test Tool"
+ outputFlag="-o"
+ command="gcc"
+ id="cdt.managedbuild.tool.gnu.c.linker.test.tree.tool"
+ errorParsers="org.eclipse.cdt.core.GLDErrorParser">
+
+ <option
+ defaultValue="grandChild_1_1_1"
+ name="Dummy Tree Option"
+ command="-dummy"
+ id="cdt.managedbuild.tool.gnu.c.linker.test.tree.option"
+ valueType="tree">
+ <treeOptionRoot name="root" id="option.tree.root">
+ <treeOption name="Parent 1" id="parent_1">
+ <treeOption name="Child 1 1" id="child_1_1">
+ <treeOption name="Grand Child 1 1 1" id="grandChild_1_1_1" />
+ <treeOption name="Grand Child 1 1 2" id="grandChild_1_1_2" />
+ <treeOption name="Grand Child 1 1 3" id="grandChild_1_1_3" />
+ </treeOption>
+ <treeOption name="Child 1 2" id="child_1_2">
+ <treeOption name="Grand Child 1 2 1" id="grandChild_1_2_1" />
+ <treeOption name="Grand Child 1 2 2" id="grandChild_1_2_2" command="-dummy122" />
+ <treeOption name="Grand Child 1 2 3" id="grandChild_1_2_3" />
+ </treeOption>
+ </treeOption>
+ <treeOption name="Parent 2" id="parent_2">
+ <treeOption name="Child 2 1" id="child_2_1">
+ <treeOption name="Grand Child 2 1 1" id="grandChild_2_1_1" />
+ <treeOption name="Grand Child 2 1 2" id="grandChild_2_1_2" />
+ <treeOption name="Grand Child 2 1 3" id="grandChild_2_1_3" />
+ </treeOption>
+ <treeOption name="Child 2 2" id="child_2_2">
+ <treeOption name="Grand Child 2 2 1" id="grandChild_2_2_1" />
+ <treeOption name="Grand Child 2 2 2" id="grandChild_2_2_2" />
+ <treeOption name="Grand Child 2 2 3" id="grandChild_2_2_3" />
+ </treeOption>
+ </treeOption>
+ <treeOption name="Parent 3" id="parent_3" order="0">
+ <treeOption name="Child 3 1" id="child_3_1">
+ <treeOption name="Grand Child 3 1 1" id="grandChild_3_1_1" />
+ <treeOption name="Grand Child 3 1 2" id="grandChild_3_1_2" />
+ <treeOption name="Grand Child 3 1 3" id="grandChild_3_1_3" />
+ </treeOption>
+ <treeOption name="Child 3 2" id="child_3_2">
+ <treeOption name="Grand Child 3 2 1" id="grandChild_3_2_1" />
+ <treeOption name="Grand Child 3 2 2" id="grandChild_3_2_2" />
+ <treeOption name="Grand Child 3 2 3" id="grandChild_3_2_3" />
+ </treeOption>
+ </treeOption>
+ </treeOptionRoot>
+ </option>
+ </tool>
+ </extension>
+
</plugin>
diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildCoreTests.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildCoreTests.java
index 68e2a10..e1bf503 100644
--- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildCoreTests.java
+++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildCoreTests.java
@@ -22,6 +22,9 @@ import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IBuilder;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
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.IProjectType;
import org.eclipse.cdt.managedbuilder.core.ITargetPlatform;
@@ -30,6 +33,7 @@ import org.eclipse.cdt.managedbuilder.core.IToolChain;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.internal.core.Builder;
import org.eclipse.core.runtime.IConfigurationElement;
+import org.junit.Assert;
public class ManagedBuildCoreTests extends TestCase {
@@ -44,6 +48,7 @@ public class ManagedBuildCoreTests extends TestCase {
public static Test suite() {
TestSuite suite = new TestSuite(ManagedBuildCoreTests.class.getName());
suite.addTest(new ManagedBuildCoreTests("testLoadManifest"));
+ suite.addTest(new ManagedBuildCoreTests("testTreeOptions"));
return suite;
}
@@ -598,5 +603,64 @@ public class ManagedBuildCoreTests extends TestCase {
} // end for
} // end routine
+
+ /**
+ * Tests Options of type tree as implemented in bug 365718
+ * @throws Exception
+ */
+ public void testTreeOptions() throws Exception {
+ IOption treeOption = ManagedBuildManager.getExtensionOption("cdt.managedbuild.tool.gnu.c.linker.test.tree.option");
+ assertNotNull(treeOption);
+
+ // standard options
+ assertEquals(IOption.TREE, treeOption.getValueType());
+ assertEquals("grandChild_1_1_1", treeOption.getValue());
+ assertEquals("grandChild_1_1_1", treeOption.getDefaultValue());
+ assertEquals("cdt.managedbuild.tool.gnu.c.linker.test.tree.option", treeOption.getId());
+ assertEquals("-dummy", treeOption.getCommand());
+ assertEquals("-dummy122", treeOption.getCommand("grandChild_1_2_2"));
+
+ String[] applicableValues = treeOption.getApplicableValues();
+ String[] expected = new String[18];
+ int index = 0;
+ for (int i = 1; i < 4; i++) {
+ for (int j = 1; j < 3; j++) {
+ for (int k = 1; k < 4; k++) {
+ expected[index++] = "Grand Child " + i + ' ' + j + ' ' + k;
+ }
+ }
+ }
+ Assert.assertArrayEquals(expected, applicableValues);
+
+ ITreeRoot treeRoot = treeOption.getTreeRoot();
+ assertNotNull(treeRoot);
+
+ // test some tree option attributes
+ ITreeOption[] children = treeRoot.getChildren();
+ assertNotNull(children);
+ assertEquals(0, children[2].getOrder());
+ assertEquals("Parent 2", children[1].getName());
+ assertTrue(children[0].isContainer());
+
+ ITreeOption findNode = treeRoot.findNode("grandChild_2_1_3");
+ assertNotNull(findNode);
+
+ int size = children.length;
+ treeRoot.addChild("newID", "New Name");
+ assertEquals(size+1, treeRoot.getChildren().length);
+ assertEquals("newID", treeRoot.getChild("New Name").getID());
+
+ // check tree only methods
+ IOption nonTreeOption = ManagedBuildManager.getExtensionOption("testgnu.c.compiler.exe.debug.option.debugging.level");
+ assertFalse(IOption.TREE == nonTreeOption.getValueType());
+ boolean exception = false;
+ try {
+ nonTreeOption.getTreeRoot();
+ } catch (Exception e) {
+ exception = true;
+ }
+ assertTrue(exception);
+
+ }
} // end class
diff --git a/build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd b/build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd
index e8a5678..6e8e0e3 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd
+++ b/build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd
@@ -1178,6 +1178,7 @@ Options can also be associated with a toolchain. However in such a case the opti
<choice>
<element ref="listOptionValue" minOccurs="0" maxOccurs="unbounded"/>
<element ref="enumeratedOptionValue" minOccurs="0" maxOccurs="unbounded"/>
+ <element ref="treeOptionRoot" minOccurs="0" maxOccurs="1"/>
</choice>
<element ref="enablement" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
@@ -1289,6 +1290,8 @@ Additional special types exist to flag options of special relevance to the build
</enumeration>
<enumeration value="undefSymbolFiles">
</enumeration>
+ <enumeration value="tree">
+ </enumeration>
</restriction>
</simpleType>
</attribute>
@@ -1512,6 +1515,118 @@ A custom field-editor needs to be registered, under the same ID, through the &lt
</complexType>
</element>
+ <element name="treeOption">
+ <complexType>
+ <sequence minOccurs="0" maxOccurs="unbounded">
+ <element ref="treeOption"/>
+ </sequence>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+ The id should be the value used for determining which treeOption is selected, it has to be unique within the tree.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string" use="required">
+ <annotation>
+ <documentation>
+ Display name for the option
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="description" type="string">
+ <annotation>
+ <documentation>
+ Description of the option to be presented to the user
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="command" type="string">
+ <annotation>
+ <documentation>
+ The command that the tree value translates to on the command line.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="isDefault" type="boolean">
+ <annotation>
+ <documentation>
+ Flags this tree value as the default to apply to the option if the user has not changed the setting.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="icon" type="string">
+ <annotation>
+ <documentation>
+ An icon to be used for this node in the tree representation. Should use full path for the icon: e.g., platform:/plugin/org.eclipse.cdt/icons/wizard.png
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="resource"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="order" type="string">
+ <annotation>
+ <documentation>
+ An integer representing the order of this option within its peers in the tree. The order is a relative number, were smaller numbers appear on top of larger numbers.
+If no order is defined a default order is assumed, see &quot;org.eclipse.cdt.managedbuilder.core.IOption.ITreeOption.DEFAULT_ORDER&quot; for more details.
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="treeOptionRoot">
+ <annotation>
+ <documentation>
+ Represents the root of a tree of options. Note that the root is never shown to the user and can&apos;t be selected. It is a place holder for settings affecting the options tree behavior
+ </documentation>
+ </annotation>
+ <complexType>
+ <sequence minOccurs="1" maxOccurs="unbounded">
+ <element ref="treeOption"/>
+ </sequence>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="icon" type="string">
+ <annotation>
+ <documentation>
+ The tree root icon can be used in branding the UI representation of the tree. Should use full path for the icon: e.g., platform:/plugin/org.eclipse.cdt/icons/wizard.png
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="resource"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="selectLeafOnly" type="boolean">
+ <annotation>
+ <documentation>
+ Determines whether this tree allows selecting categories as well as leaf nodes, or leaf nodes only.
+Default is true (leaf nodes only).
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
<element name="builder">
<annotation>
<documentation>
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IOption.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IOption.java
index 2196fd1..85ac319 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IOption.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IOption.java
@@ -55,6 +55,12 @@ public interface IOption extends IBuildObject {
public static final int LIBRARY_FILES = 10;
public static final int MACRO_FILES = 11;
+ /**
+ * Tree of items to select one from.
+ * @since 8.1
+ */
+ public static final int TREE = 12;
+
public static final int UNDEF_INCLUDE_PATH = -INCLUDE_PATH;
public static final int UNDEF_PREPROCESSOR_SYMBOLS = -PREPROCESSOR_SYMBOLS;
public static final int UNDEF_INCLUDE_FILES = -INCLUDE_FILES;
@@ -84,6 +90,14 @@ public interface IOption extends IBuildObject {
/** @since 7.0 */
public static final String BROWSE_FILTER_EXTENSIONS = "browseFilterExtensions"; //$NON-NLS-1$
public static final String CATEGORY = "category"; //$NON-NLS-1$
+ /**
+ * @since 8.1
+ */
+ public static final String ICON = "icon"; //$NON-NLS-1$
+ /**
+ * @since 8.1
+ */
+ public static final String ORDER = "order"; //$NON-NLS-1$
public static final String COMMAND = "command"; //$NON-NLS-1$
public static final String COMMAND_FALSE = "commandFalse"; //$NON-NLS-1$
/** @since 8.0 */
@@ -92,6 +106,22 @@ public interface IOption extends IBuildObject {
public static final String CONTEXT_ID = "contextId"; //$NON-NLS-1$
public static final String DEFAULT_VALUE = "defaultValue"; //$NON-NLS-1$
public static final String ENUM_VALUE = "enumeratedOptionValue"; //$NON-NLS-1$
+ /**
+ * @since 8.1
+ */
+ public static final String TREE_ROOT = "treeOptionRoot"; //$NON-NLS-1$
+ /**
+ * @since 8.1
+ */
+ public static final String SELECT_LEAF_ONLY = "selectLeafOnly"; //$NON-NLS-1$
+ /**
+ * @since 8.1
+ */
+ public static final String TREE_VALUE = "treeOption"; //$NON-NLS-1$
+ /**
+ * @since 8.1
+ */
+ public static final String DESCRIPTION = "description"; //$NON-NLS-1$
public static final String IS_DEFAULT = "isDefault"; //$NON-NLS-1$
public static final String LIST_VALUE = "listOptionValue"; //$NON-NLS-1$
public static final String RESOURCE_FILTER = "resourceFilter"; //$NON-NLS-1$
@@ -114,6 +144,10 @@ public interface IOption extends IBuildObject {
public static final String TYPE_UNDEF_LIB_FILES = "undefLibFiles"; //$NON-NLS-1$
public static final String TYPE_UNDEF_INC_FILES = "undefIncludeFiles"; //$NON-NLS-1$
public static final String TYPE_UNDEF_SYMBOL_FILES = "undefSymbolFiles"; //$NON-NLS-1$
+ /**
+ * @since 8.1
+ */
+ public static final String TYPE_TREE = "tree"; //$NON-NLS-1$
public static final String VALUE = "value"; //$NON-NLS-1$
public static final String VALUE_TYPE = "valueType"; //$NON-NLS-1$
@@ -326,18 +360,59 @@ public interface IOption extends IBuildObject {
public String getEnumCommand (String id) throws BuildException;
/**
+ * Returns the command associated with the child of this option
+ * with the given id. Applies to options of types that has children
+ * for example {@link #TREE} or {@link #ENUMERATED}
+ *
+ * @param id - child id
+ * @return the command associated with the child id. For
+ * example, if the child id was <code>gnu.debug.level.default</code>
+ * for the debug level option of the Gnu compiler, and the plugin
+ * manifest defined that as -g, then the return value would be the
+ * String "-g"
+ *
+ * @throws BuildException
+ * @since 8.1
+ */
+ public String getCommand (String id) throws BuildException;
+
+ /**
* @param id - enumeration id
* @return the "name" associated with the enumeration id.
*/
public String getEnumName (String id) throws BuildException;
/**
+ * Returns the name associated with the child of this option
+ * with the given id. Applies to options of types that has children
+ * for example {@link #TREE} or {@link #ENUMERATED}
+ *
+ * @param id The id to look for
+ * @return Name of the child with the passed id or <code>null</code> if not found.
+ * @throws BuildException if any issue happened while searching.
+ * @since 8.1
+ */
+ public abstract String getName(String id) throws BuildException;
+
+ /**
* @param name - a "name" associated with enumeration id
* @return enumeration id
*/
public String getEnumeratedId(String name) throws BuildException;
/**
+ * Returns the id associated with the child of this option
+ * with the given name. Applies to options of types that has children
+ * for example {@link #TREE} or {@link #ENUMERATED}
+ *
+ * @param name the name of the child to look for.
+ * @return The id of the found child or <code>null</code> if not found.
+ * @throws BuildException if any error happened while searching
+ * @since 8.1
+ */
+ public abstract String getId(String name) throws BuildException;
+
+ /**
* @return an array of <code>String</code> containing the includes paths
* defined in the build model.
*/
@@ -514,6 +589,7 @@ public interface IOption extends IBuildObject {
* <li/>{@link IOption#BOOLEAN}
* <li/>{@link IOption#STRING}
* <li/>{@link IOption#ENUMERATED}
+ * <li/>{@link IOption#TREE}
* <li/>{@link IOption#STRING_LIST} - corresponds to
* {@link IOption#INCLUDE_PATH}, {@link IOption#PREPROCESSOR_SYMBOLS}, {@link IOption#LIBRARIES},
* {@link IOption#OBJECTS}, {@link IOption#INCLUDE_FILES}, {@link IOption#LIBRARY_PATHS},
@@ -528,4 +604,101 @@ public interface IOption extends IBuildObject {
String[] getBasicStringListValue() throws BuildException;
public OptionStringValue[] getBasicStringListValueElements() throws BuildException;
+
+ /**
+ * Returns the tree root of this option if it is of type {@link #TREE}
+ * @return tree root of this option or <code>null</code> if not found.
+ * @throws BuildException if this option is not of type {@link #TREE}
+ * @since 8.1
+ */
+ public ITreeRoot getTreeRoot() throws BuildException;
+
+ /**
+ * Represents the root of the tree of values in options of
+ * type {@link IOption#TREE}
+ * @author mhussein
+ * @since 8.1
+ *
+ */
+ public interface ITreeRoot extends ITreeOption {
+ /**
+ * Determines whether this tree allows selecting leaf nodes
+ * only or any nodes.
+ * @return <code>true</code> if only leaf nodes are allowed.
+ * <code>false</code> if all child nodes could be selected.
+ * @see ITreeOption#isContainer()
+ */
+ boolean isSelectLeafsOnly();
+
+ /**
+ * Locates the node with the given id anywhere in the tree.
+ * @param id the id to search for
+ * @return the found child or <code>null</code> if not found.
+ */
+ ITreeOption findNode(String id);
+
+ /**
+ * Adds a new node to the tree.
+ * @param id The id of the new child.
+ * @param name The name of the new child.
+ * @param category The category of the new child.category is a '.'
+ * separated string representing hierarchical path
+ * of the child from the root of the tree.
+ * can cause other nodes to be created to construct the
+ * full path to the new child.
+ * @param order The order of the newly created node among its peers.
+ * see {@link ITreeOption#getOrder()} for more information.
+ * Note: this order will apply to any parents auto-created
+ * according to the passed category.
+ * if <code>null</code> the {@link ITreeOption#DEFAULT_ORDER}
+ * will be used.
+ * @return the newly added node.
+ */
+ ITreeOption addNode(String id, String name, String category, Integer order);
+ }
+
+ /**
+ * Represents a one of the possible values for options of type
+ * {@link IOption#TREE}
+ * @author mhussein
+ * @since 8.1
+ *
+ */
+ public interface ITreeOption {
+ /**
+ * The default order for tree nodes without order specified.
+ * Tree options with Orders smaller than this should appear above
+ * tree options with no order specified and vice versa.
+ */
+ public static final int DEFAULT_ORDER = 1000;
+
+ String getName();
+ String getID();
+ String getDescription();
+ /**
+ * The order that determines UI appearance of the tree node,
+ * not necessarily its position in {@link #getChildren()}
+ * @return The order of this tree option relative to its peers.
+ * Smaller number means it should appear above peers.
+ * @see #DEFAULT_ORDER
+ */
+ int getOrder();
+ void setOrder(int order);
+
+ ITreeOption[] getChildren();
+ ITreeOption getParent();
+ boolean isContainer();
+ String getCommand();
+ ITreeOption getChild(String name);
+
+ /**
+ * Adds a new child directly under this node.
+ * @param id
+ * @param name
+ * @return
+ */
+ ITreeOption addChild(String id, String name);
+ void remove();
+ String getIcon();
+ }
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedOptionValueHandler.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedOptionValueHandler.java
index cf081b2..0304e01 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedOptionValueHandler.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedOptionValueHandler.java
@@ -120,6 +120,7 @@ public class ManagedOptionValueHandler implements
}
break;
case IOption.ENUMERATED:
+ case IOption.TREE:
if (option.getValue().toString().equals(defaultValue.toString())) {
return true;
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildStep.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildStep.java
index 0142f70..62b8143 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildStep.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildStep.java
@@ -657,7 +657,7 @@ public class BuildStep implements IBuildStep {
} else {
ManagedBuildManager.setOption(cfg, fTool, assignToOption, false);
}
- } else if (optType == IOption.ENUMERATED) {
+ } else if (optType == IOption.ENUMERATED || optType == IOption.TREE) {
if (bRcs.length > 0) {
ManagedBuildManager.setOption(cfg, fTool, assignToOption, BuildDescriptionManager.getRelPath(cwd, bRcs[0].getLocation()).toOSString());
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ConfigurationV2.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ConfigurationV2.java
index f65adbc..f3d8fb9 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ConfigurationV2.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ConfigurationV2.java
@@ -132,6 +132,7 @@ public class ConfigurationV2 extends BuildObject implements IConfigurationV2 {
new OptionReference(newRef, opt).setValue(optRef.getBooleanValue());
break;
case IOption.STRING:
+ case IOption.TREE:
new OptionReference(newRef, opt).setValue(optRef.getStringValue());
break;
case IOption.ENUMERATED:
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Option.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Option.java
index 711e3c6..07d69fe 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Option.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Option.java
@@ -39,6 +39,7 @@ import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.cdt.managedbuilder.core.ManagedOptionValueHandler;
import org.eclipse.cdt.managedbuilder.core.OptionStringValue;
+import org.eclipse.cdt.managedbuilder.core.IOption.ITreeOption;
import org.eclipse.cdt.managedbuilder.internal.enablement.OptionEnablementExpression;
import org.eclipse.cdt.managedbuilder.internal.macros.OptionContextData;
import org.eclipse.cdt.managedbuilder.macros.IOptionContextData;
@@ -71,9 +72,9 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
private String commandFalse;
private String tip;
private String contextId;
- private List<String> enumList;
- private Map<String, String> enumCommands;
- private Map<String, String> enumNames;
+ private List<String> applicableValuesList;
+ private Map<String, String> commandsMap;
+ private Map<String, String> namesMap;
private Object value;
private Object defaultValue;
private Integer valueType;
@@ -87,6 +88,7 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
private IConfigurationElement applicabilityCalculatorElement = null;
private IOptionApplicability applicabilityCalculator = null;
private BooleanExpressionApplicabilityCalculator booleanExpressionCalculator = null;
+ private ITreeRoot treeRoot;
// Miscellaneous
private boolean isExtensionOption = false;
private boolean isDirty = false;
@@ -222,10 +224,13 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
if (option.resourceFilter != null) {
resourceFilter = new Integer(option.resourceFilter.intValue());
}
- if (option.enumList != null) {
- enumList = new ArrayList<String>(option.enumList);
- enumCommands = new HashMap<String, String>(option.enumCommands);
- enumNames = new HashMap<String, String>(option.enumNames);
+ if (option.applicableValuesList != null) {
+ applicableValuesList = new ArrayList<String>(option.applicableValuesList);
+ commandsMap = new HashMap<String, String>(option.commandsMap);
+ namesMap = new HashMap<String, String>(option.namesMap);
+ }
+ if (option.treeRoot != null) {
+ treeRoot = new TreeRoot((TreeRoot) option.treeRoot);
}
if (option.valueType != null) {
@@ -245,6 +250,7 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
break;
case STRING:
case ENUMERATED:
+ case TREE:
if (option.value != null) {
value = new String((String)option.value);
}
@@ -549,18 +555,18 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
ICStorageElement configElement = configNode;
String optId = SafeStringInterner.safeIntern(configElement.getAttribute(ID));
if (i == 0) {
- enumList = new ArrayList<String>();
+ applicableValuesList = new ArrayList<String>();
if (defaultValue == null) {
defaultValue = optId; // Default value to be overridden is default is specified
}
}
- enumList.add(optId);
+ applicableValuesList.add(optId);
if (configElement.getAttribute(COMMAND) != null) {
- getEnumCommandMap().put(optId, SafeStringInterner.safeIntern(configElement.getAttribute(COMMAND)));
+ getCommandMap().put(optId, SafeStringInterner.safeIntern(configElement.getAttribute(COMMAND)));
} else {
- getEnumCommandMap().put(optId, EMPTY_STRING);
+ getCommandMap().put(optId, EMPTY_STRING);
}
- getEnumNameMap().put(optId, SafeStringInterner.safeIntern(configElement.getAttribute(NAME)));
+ getNameMap().put(optId, SafeStringInterner.safeIntern(configElement.getAttribute(NAME)));
if (configElement.getAttribute(IS_DEFAULT) != null) {
Boolean isDefault = new Boolean(configElement.getAttribute(IS_DEFAULT));
if (isDefault.booleanValue()) {
@@ -570,6 +576,14 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
}
}
break;
+ case TREE:
+ if (element.getAttribute(VALUE) != null) {
+ value = element.getAttribute(VALUE);
+ }
+ if (element.getAttribute(DEFAULT_VALUE) != null) {
+ defaultValue = element.getAttribute(DEFAULT_VALUE);
+ }
+ break;
case STRING_LIST:
case INCLUDE_PATH:
case PREPROCESSOR_SYMBOLS:
@@ -727,6 +741,8 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
return UNDEF_INCLUDE_FILES;
else if (valueTypeStr.equals(TYPE_UNDEF_SYMBOL_FILES))
return UNDEF_MACRO_FILES;
+ else if (valueTypeStr.equals(TYPE_TREE))
+ return TREE;
else {
// TODO: This was the CDT 2.0 default - should we keep it?
return PREPROCESSOR_SYMBOLS;
@@ -789,6 +805,7 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
break;
case STRING:
case ENUMERATED:
+ case TREE:
element.setAttribute(VALUE, (String)value);
break;
case STRING_LIST:
@@ -834,6 +851,7 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
break;
case STRING:
case ENUMERATED:
+ case TREE:
element.setAttribute(DEFAULT_VALUE, (String)defaultValue);
break;
default:
@@ -898,6 +916,9 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
case UNDEF_MACRO_FILES:
str = TYPE_UNDEF_SYMBOL_FILES;
break;
+ case TREE:
+ str = TYPE_TREE;
+ break;
default:
// TODO; is this a problem...
str = EMPTY_STRING;
@@ -1039,7 +1060,7 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
@Override
public String[] getApplicableValues() {
// Does this option instance have the list of values?
- if (enumList == null) {
+ if (applicableValuesList == null) {
if (superClass != null) {
return superClass.getApplicableValues();
} else {
@@ -1047,13 +1068,13 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
}
}
// Get all of the enumerated names from the option
- if (enumList.size() == 0) {
+ if (applicableValuesList.size() == 0) {
return EMPTY_STRING_ARRAY;
} else {
// Return the elements in the order they are specified in the manifest
- String[] enumNames = new String[enumList.size()];
- for (int index = 0; index < enumList.size(); ++ index) {
- enumNames[index] = getEnumNameMap().get(enumList.get(index));
+ String[] enumNames = new String[applicableValuesList.size()];
+ for (int index = 0; index < applicableValuesList.size(); ++ index) {
+ enumNames[index] = getNameMap().get(applicableValuesList.get(index));
}
return enumNames;
}
@@ -1311,35 +1332,35 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
}
/* (non-Javadoc)
- * @see org.eclipse.cdt.managedbuilder.core.IOption#getEnumCommand(java.lang.String)
+ * @see org.eclipse.cdt.managedbuilder.core.IOption#getCommand(java.lang.String)
*/
@Override
- public String getEnumCommand(String id) throws BuildException {
+ public String getCommand(String id) throws BuildException {
// Sanity
if (id == null) return EMPTY_STRING;
// Does this option instance have the list of values?
- if (enumList == null) {
+ if (applicableValuesList == null) {
if (superClass != null) {
- return superClass.getEnumCommand(id);
+ return superClass.getCommand(id);
} else {
return EMPTY_STRING;
}
}
- if (getValueType() != ENUMERATED) {
+ if (getValueType() != ENUMERATED && getValueType() != TREE) {
throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$
}
// First check for the command in ID->command map
- String cmd = getEnumCommandMap().get(id);
+ String cmd = getCommandMap().get(id);
if (cmd == null) {
// This may be a 1.2 project or plugin manifest. If so, the argument is the human readable
// name of the enumeration. Search for the ID that maps to the name and use that to find the
// command.
- for (String realID : enumList) {
- String name = getEnumNameMap().get(realID);
+ for (String realID : applicableValuesList) {
+ String name = getNameMap().get(realID);
if (id.equals(name)) {
- cmd = getEnumCommandMap().get(realID);
+ cmd = getCommandMap().get(realID);
break;
}
}
@@ -1348,17 +1369,30 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
}
/* (non-Javadoc)
+ * @see org.eclipse.cdt.managedbuilder.core.IOption#getEnumCommand(java.lang.String)
+ */
+ @Override
+ public String getEnumCommand(String id) throws BuildException {
+ return getCommand(id);
+ }
+
+ /* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.core.IOption#getEnumName(java.lang.String)
*/
@Override
public String getEnumName(String id) throws BuildException {
+ return getName(id);
+ }
+
+ @Override
+ public String getName(String id) throws BuildException {
// Sanity
if (id == null) return EMPTY_STRING;
// Does this option instance have the list of values?
- if (enumList == null) {
+ if (applicableValuesList == null) {
if (superClass != null) {
- return superClass.getEnumName(id);
+ return superClass.getName(id);
} else {
return EMPTY_STRING;
}
@@ -1368,7 +1402,7 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
}
// First check for the command in ID->name map
- String name = getEnumNameMap().get(id);
+ String name = getNameMap().get(id);
if (name == null) {
// This may be a 1.2 project or plugin manifest. If so, the argument is the human readable
// name of the enumeration.
@@ -1384,11 +1418,11 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
* @return a Map of enumerated option value IDs to actual commands that are passed
* to a tool on the command line.
*/
- private Map<String, String> getEnumCommandMap() {
- if (enumCommands == null) {
- enumCommands = new HashMap<String, String>();
+ private Map<String, String> getCommandMap() {
+ if (commandsMap == null) {
+ commandsMap = new HashMap<String, String>();
}
- return enumCommands;
+ return commandsMap;
}
/* (non-Javadoc)
@@ -1396,23 +1430,28 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
*/
@Override
public String getEnumeratedId(String name) throws BuildException {
+ return getId(name);
+ }
+
+ @Override
+ public String getId(String name) throws BuildException {
if (name == null) return null;
// Does this option instance have the list of values?
- if (enumList == null) {
+ if (applicableValuesList == null) {
if (superClass != null) {
- return superClass.getEnumeratedId(name);
+ return superClass.getId(name);
} else {
return EMPTY_STRING;
}
}
- if (getValueType() != ENUMERATED) {
+ if (getValueType() != ENUMERATED && getValueType() != TREE) {
throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$
}
- Set<String> idSet = getEnumNameMap().keySet();
+ Set<String> idSet = getNameMap().keySet();
for (String id : idSet) {
- String enumName = getEnumNameMap().get(id);
+ String enumName = getNameMap().get(id);
if (name.equals(enumName)) {
return id;
}
@@ -1424,11 +1463,11 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
*
* @return a Map of enumerated option value IDs to the selection displayed to the user.
*/
- private Map<String, String> getEnumNameMap() {
- if (enumNames == null) {
- enumNames = new HashMap<String, String>();
+ private Map<String, String> getNameMap() {
+ if (namesMap == null) {
+ namesMap = new HashMap<String, String>();
}
- return enumNames;
+ return namesMap;
}
/* (non-Javadoc)
@@ -1537,7 +1576,7 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
*/
@Override
public String getStringValue() throws BuildException {
- if (getValueType() != STRING && getValueType() != ENUMERATED) {
+ if (getValueType() != STRING && getValueType() != ENUMERATED && getValueType() != TREE) {
throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$
}
return getValue() == null ? EMPTY_STRING : (String)getValue();
@@ -1609,6 +1648,7 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
val = new Boolean(false);
break;
case STRING:
+ case TREE:
val = EMPTY_STRING;
break;
case ENUMERATED:
@@ -1669,6 +1709,7 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
val = new Boolean(false);
break;
case STRING:
+ case TREE:
val = EMPTY_STRING;
break;
case ENUMERATED:
@@ -1949,7 +1990,7 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
@Override
public void setValue(String value) throws BuildException {
// Note that we can still set the human-readable value here
- if (/*!isExtensionElement() && */(getValueType() == STRING || getValueType() == ENUMERATED)) {
+ if (/*!isExtensionElement() && */(getValueType() == STRING || getValueType() == ENUMERATED || getValueType() == TREE)) {
this.value = value;
} else {
throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$
@@ -2281,20 +2322,44 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
for (int i = 0; i < enumElements.length; ++i) {
String optId = SafeStringInterner.safeIntern(enumElements[i].getAttribute(ID));
if (i == 0) {
- enumList = new ArrayList<String>();
+ applicableValuesList = new ArrayList<String>();
if (defaultValue == null) {
defaultValue = optId; // Default value to be overridden if default is specified
}
}
- enumList.add(optId);
- getEnumCommandMap().put(optId, SafeStringInterner.safeIntern(enumElements[i].getAttribute(COMMAND)));
- getEnumNameMap().put(optId, SafeStringInterner.safeIntern(enumElements[i].getAttribute(NAME)));
+ applicableValuesList.add(optId);
+ getCommandMap().put(optId, SafeStringInterner.safeIntern(enumElements[i].getAttribute(COMMAND)));
+ getNameMap().put(optId, SafeStringInterner.safeIntern(enumElements[i].getAttribute(NAME)));
Boolean isDefault = new Boolean(enumElements[i].getAttribute(IS_DEFAULT));
if (isDefault.booleanValue()) {
defaultValue = optId;
}
}
break;
+ case TREE:
+ value = element.getAttribute(VALUE);
+ defaultValue = element.getAttribute(DEFAULT_VALUE);
+
+ IManagedConfigElement[] treeRootConfigs = element.getChildren(TREE_ROOT);
+ if (treeRootConfigs != null && treeRootConfigs.length == 1) {
+ IManagedConfigElement treeRootConfig = treeRootConfigs[0];
+ treeRoot = new TreeRoot(treeRootConfig, element, getParent() instanceof IToolChain);
+ applicableValuesList = new ArrayList<String>();
+ iterateOnTree(treeRoot, new ITreeNodeIterator() {
+
+ @Override
+ public void iterateOnNode(ITreeOption node) {}
+
+ @Override
+ public void iterateOnLeaf(ITreeOption leafNode) {
+ applicableValuesList.add(leafNode.getID());
+ getCommandMap().put(leafNode.getID(), leafNode.getCommand());
+ getNameMap().put(leafNode.getID(), leafNode.getName());
+ }
+ });
+ }
+
+ break;
case STRING_LIST:
case INCLUDE_PATH:
case PREPROCESSOR_SYMBOLS:
@@ -2613,6 +2678,8 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
return IOption.STRING;
case IOption.ENUMERATED:
return IOption.ENUMERATED;
+ case IOption.TREE:
+ return IOption.TREE;
default:
return IOption.STRING_LIST;
}
@@ -2658,4 +2725,267 @@ public class Option extends BuildObject implements IOption, IBuildPropertiesRest
}
return 0;
}
+
+ public static class TreeRoot extends TreeOption implements ITreeRoot {
+ private boolean selectLeafOnly = true;
+ TreeRoot(IManagedConfigElement element, IManagedConfigElement buildOption, boolean readTool) {
+ super(element, null, readTool);
+ String leaf = element.getAttribute(SELECT_LEAF_ONLY);
+ if (leaf != null) {
+ selectLeafOnly = Boolean.valueOf(leaf);
+ }
+ String toolTip = buildOption.getAttribute(TOOL_TIP);
+ if (description == null && toolTip != null) {
+ description = toolTip;
+ }
+ }
+
+ public TreeRoot() {
+ super("", "", null); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public TreeRoot(TreeRoot clone) {
+ super(clone, null);
+ selectLeafOnly = clone.selectLeafOnly;
+ }
+
+ @Override
+ public boolean isSelectLeafsOnly() {
+ return selectLeafOnly;
+ }
+
+ @Override
+ public ITreeOption findNode(String id) {
+ if(id == null) return null;
+ return find(id, children);
+ }
+
+ private ITreeOption find(String id, List<ITreeOption> children) {
+ ITreeOption found = null;
+ if (children != null) {
+ for (ITreeOption child : children) {
+ if (id.equals(child.getID())) {
+ found = child;
+ break;
+ }
+ found = find(id, ((TreeOption)child).children);
+ if (found != null) break;
+ }
+ }
+ return found;
+ }
+
+ @Override
+ public ITreeOption addNode(String id, String name, String category, Integer order) {
+ ITreeOption parent = this;
+ if (category != null && category.length() > 0) {
+ ITreeOption tempParent;
+ String tempCategory = "";
+ String[] categories = category.split("\\."); //$NON-NLS-1$
+ for (String cat : categories) {
+ tempCategory += cat;
+ tempParent = parent.getChild(cat);
+ if (tempParent == null) {
+ tempParent = parent.addChild(cat, cat);
+ if (order != null) {
+ tempParent.setOrder(order);
+ }
+ }
+ parent = tempParent;
+ tempCategory += '.';
+ }
+ }
+
+ ITreeOption child = parent.addChild(id, name);
+ if (order != null) {
+ child.setOrder(order);
+ }
+ return child;
+ }
+
+ }
+
+ private static class TreeOption implements ITreeOption {
+ private String treeNodeId;
+ private String treeNodeName;
+ protected String description;
+ protected String icon;
+ protected String command;
+ protected List<ITreeOption> children = null;
+ private int order = DEFAULT_ORDER;
+ private ITreeOption parent;
+
+ TreeOption(IManagedConfigElement element, ITreeOption parent, boolean readTool) {
+ treeNodeId = element.getAttribute(ID);
+ treeNodeName = element.getAttribute(NAME);
+ description = element.getAttribute(DESCRIPTION);
+ command = element.getAttribute(COMMAND);
+ icon = element.getAttribute(ICON);
+
+ String orderStr = element.getAttribute(ORDER);
+ if (orderStr != null && orderStr.trim().length() > 0) {
+ try {
+ order = Integer.parseInt(orderStr);
+ } catch (NumberFormatException e) {
+ // Do nothing, default value is used.
+ }
+ }
+ this.parent = parent;
+
+ IManagedConfigElement[] treeChildren = element.getChildren(TREE_VALUE);
+ if (treeChildren != null && treeChildren.length > 0) {
+ children = new ArrayList<IOption.ITreeOption>();
+ for (IManagedConfigElement configElement : treeChildren) {
+ children.add(new TreeOption(configElement, this, readTool));
+ }
+ }
+ }
+
+ TreeOption(TreeOption clone, ITreeOption parent) {
+ treeNodeId = clone.treeNodeId;
+ treeNodeName = clone.treeNodeName;
+ description = clone.description;
+ command = clone.command;
+ icon = clone.icon;
+ order = clone.order;
+ this.parent = parent;
+
+ if (clone.children != null) {
+ children = new ArrayList<IOption.ITreeOption>();
+ for (ITreeOption cloneChild : clone.children) {
+ children.add(new TreeOption((TreeOption) cloneChild, this));
+ }
+ }
+ }
+
+ private TreeOption(String id, String name, ITreeOption parent) {
+ this.treeNodeId = id;
+ this.treeNodeName = name;
+ this.parent = parent;
+ }
+
+ @Override
+ public ITreeOption addChild(String id, String name) {
+ ITreeOption option = new TreeOption(id, name, this);
+ if (children == null) {
+ children = new ArrayList<IOption.ITreeOption>();
+ }
+ children.add(0, option);
+ return option;
+ }
+
+ @Override
+ public boolean isContainer() {
+ return children != null && !children.isEmpty(); // TODO do we need explicit marking as container for empty ones
+ }
+
+ @Override
+ public String getName() {
+ return treeNodeName;
+ }
+
+ @Override
+ public String getID() {
+ return treeNodeId;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getCommand() {
+ return command;
+ }
+
+ @Override
+ public String getIcon() {
+ return icon;
+ }
+
+ @Override
+ public ITreeOption[] getChildren() {
+ if (children == null) return null;
+ return children.toArray(new ITreeOption[children.size()]);
+ }
+
+ @Override
+ public ITreeOption getChild(String name) {
+ if (children == null || name == null) return null;
+ for (ITreeOption child : children) {
+ if (name.equals(child.getName())) {
+ return child;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public ITreeOption getParent() {
+ return parent;
+ }
+
+ @Override
+ public int getOrder() {
+ return order;
+ }
+
+ @Override
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ @Override
+ public void remove() {
+ ((TreeOption)parent).children.remove(this);
+
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+ }
+
+ /**
+ * Calls the iterator (visitor) on the passed parent as well as all nodes in its subtree.
+ * @param it
+ * @param parent
+ */
+ public static void iterateOnTree(ITreeOption parent, ITreeNodeIterator it) {
+
+ it.iterateOnNode(parent);
+ if (!parent.isContainer()) {
+ it.iterateOnLeaf(parent);
+ }
+
+ ITreeOption[] children = parent.getChildren();
+ if (children != null) {
+ for (ITreeOption option : children) {
+ iterateOnTree(option, it);
+ }
+ }
+ }
+
+ public interface ITreeNodeIterator {
+ void iterateOnNode(ITreeOption node);
+ void iterateOnLeaf(ITreeOption leafNode);
+ }
+
+ @Override
+ public ITreeRoot getTreeRoot() throws BuildException {
+ if (treeRoot == null) {
+ if (superClass != null) {
+ return superClass.getTreeRoot();
+ } else {
+ return null;
+ }
+ }
+ if (getValueType() != TREE) {
+ throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$
+ }
+
+ return treeRoot;
+ }
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionReference.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionReference.java
index e26d2cf..f6d544f 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionReference.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionReference.java
@@ -117,6 +117,7 @@ public class OptionReference implements IOption {
value = new Boolean(element.getAttribute(DEFAULT_VALUE));
break;
case STRING:
+ case TREE:
case ENUMERATED:
// Pre-2.0 the value was the string for the UI
// Post-2.0 it is the ID of the enumerated option
@@ -189,6 +190,7 @@ public class OptionReference implements IOption {
case STRING:
value = element.getAttribute(DEFAULT_VALUE);
break;
+ case TREE:
case ENUMERATED:
String temp = element.getAttribute(DEFAULT_VALUE);
if (temp != null) {
@@ -248,6 +250,7 @@ public class OptionReference implements IOption {
element.setAttribute(DEFAULT_VALUE, ((Boolean)value).toString());
break;
case STRING:
+ case TREE:
case ENUMERATED:
element.setAttribute(DEFAULT_VALUE, (String)value);
break;
@@ -384,6 +387,19 @@ public class OptionReference implements IOption {
return new String();
}
+ public String getCommand(String id) throws BuildException {
+ if (!resolved) {
+ resolveReferences();
+ }
+ if (option != null) {
+ try {
+ String command = option.getCommand(id);
+ return command;
+ } catch (BuildException e) {}
+ }
+ return new String();
+ }
+
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IOption#getEnumName(java.lang.String)
*/
@@ -401,6 +417,19 @@ public class OptionReference implements IOption {
return new String();
}
+ public String getName(String id) throws BuildException {
+ if (!resolved) {
+ resolveReferences();
+ }
+ if (option != null) {
+ try {
+ String name = option.getName(id);
+ return name;
+ } catch (BuildException e) {}
+ }
+ return new String();
+ }
+
/* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.core.IOption#getEnumeratedId(java.lang.String)
*/
@@ -418,6 +447,19 @@ public class OptionReference implements IOption {
return new String();
}
+ public String getId(String name) throws BuildException {
+ if (!resolved) {
+ resolveReferences();
+ }
+ if (option != null) {
+ try {
+ String id = option.getId(name);
+ return id;
+ } catch (BuildException e) {}
+ }
+ return new String();
+ }
+
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IBuildObject#getId()
*/
@@ -730,7 +772,7 @@ public class OptionReference implements IOption {
@Override
public void setValue(String value) throws BuildException {
// Note that we can still set the human-readable value here
- if (getValueType() == STRING || getValueType() == ENUMERATED) {
+ if (getValueType() == STRING || getValueType() == ENUMERATED || getValueType() == TREE) {
this.value = value;
} else {
throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$
@@ -1024,6 +1066,8 @@ public class OptionReference implements IOption {
return IOption.STRING;
case IOption.ENUMERATED:
return IOption.ENUMERATED;
+ case IOption.TREE:
+ return IOption.TREE;
default:
return IOption.STRING_LIST;
}
@@ -1039,4 +1083,17 @@ public class OptionReference implements IOption {
}
return ve;
}
+ public ITreeRoot getTreeRoot() {
+ if (!resolved) {
+ resolveReferences();
+ }
+ if (option != null) {
+ try {
+ return option.getTreeRoot();
+ } catch (BuildException e) {
+ }
+ }
+ return null;
+ }
+
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Tool.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Tool.java
index d1f67bc..d1189ad 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Tool.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Tool.java
@@ -2625,6 +2625,13 @@ public class Tool extends HoldsOptions implements ITool, IOptionCategory, IMatch
}
break;
+ case IOption.TREE :
+ String treeVal = option.getCommand(option.getStringValue());
+ if (treeVal.length() > 0) {
+ sb.append(treeVal);
+ }
+ break;
+
case IOption.STRING :{
String strCmd = option.getCommand();
String val = option.getStringValue();
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ToolReference.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ToolReference.java
index a983b1c..701d6ca 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ToolReference.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ToolReference.java
@@ -201,7 +201,9 @@ public class ToolReference implements IToolReference {
clone.setValue(parent.getBooleanValue());
break;
case IOption.STRING:
+ case IOption.TREE:
clone.setValue(parent.getStringValue());
+ break;
case IOption.ENUMERATED:
clone.setValue(parent.getSelectedEnum());
break;
@@ -518,6 +520,13 @@ public class ToolReference implements IToolReference {
}
break;
+ case IOption.TREE :
+ String treeVal = option.getCommand(option.getStringValue());
+ if (treeVal.length() > 0) {
+ buf.append(treeVal + WHITE_SPACE);
+ }
+ break;
+
case IOption.STRING :
String strCmd = option.getCommand();
String val = option.getStringValue();
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/enablement/CheckOptionExpression.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/enablement/CheckOptionExpression.java
index 9a4a12c..5ebcf95 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/enablement/CheckOptionExpression.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/enablement/CheckOptionExpression.java
@@ -112,6 +112,7 @@ public class CheckOptionExpression implements IBooleanExpression {
switch(option.getValueType()){
case IOption.STRING:
+ case IOption.TREE:
case IOption.ENUMERATED:{
String stringValue = option.getStringValue();
stringValue = provider.resolveValue(stringValue, inexVal, delimiter,
@@ -177,6 +178,7 @@ public class CheckOptionExpression implements IBooleanExpression {
switch(option.getValueType()){
case IOption.STRING:
+ case IOption.TREE:
case IOption.ENUMERATED:{
String stringValue = option.getStringValue();
stringValue = provider.resolveValue(stringValue, inexVal, delimiter,
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/enablement/OptionEnablementExpression.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/enablement/OptionEnablementExpression.java
index 1974450..57bb78e 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/enablement/OptionEnablementExpression.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/enablement/OptionEnablementExpression.java
@@ -298,6 +298,7 @@ public class OptionEnablementExpression extends AndExpression{
}
break;
case IOption.ENUMERATED:
+ case IOption.TREE:
case IOption.STRING:
if(extensionAdjustment)
setOption.setValue(value);
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/macros/MbsMacroSupplier.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/macros/MbsMacroSupplier.java
index 6336160..f61fb6e 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/macros/MbsMacroSupplier.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/macros/MbsMacroSupplier.java
@@ -913,6 +913,8 @@ public class MbsMacroSupplier extends BuildCdtVariablesSupplierBase {
break;
case IOption.ENUMERATED:
break;
+ case IOption.TREE:
+ break;
case IOption.STRING_LIST:
fType = IBuildMacro.VALUE_TEXT_LIST;
fStringListValue = option.getStringListValue();
@@ -1138,6 +1140,8 @@ public class MbsMacroSupplier extends BuildCdtVariablesSupplierBase {
break;
case IOption.ENUMERATED:
break;
+ case IOption.TREE:
+ break;
case IOption.STRING_LIST:
can = true;
break;
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java
index e23dbd5..22aa3e8 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java
@@ -3044,7 +3044,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 {
boolean b = false;
if (allRes.size() > 0) b = true;
ManagedBuildManager.setOption(rcInfo, tool, assignToOption, b);
- } else if (optType == IOption.ENUMERATED) {
+ } else if (optType == IOption.ENUMERATED || optType == IOption.TREE) {
if (allRes.size() > 0) {
String s = allRes.get(0).toString();
ManagedBuildManager.setOption(rcInfo, tool, assignToOption, s);
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/ManagedBuildGnuToolInfo.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/ManagedBuildGnuToolInfo.java
index 3ede508..d96ce0b 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/ManagedBuildGnuToolInfo.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/ManagedBuildGnuToolInfo.java
@@ -422,7 +422,7 @@ public class ManagedBuildGnuToolInfo implements IManagedBuildGnuToolInfo {
} else {
ManagedBuildManager.setOption(config, tool, assignToOption, false);
}
- } else if (optType == IOption.ENUMERATED) {
+ } else if (optType == IOption.ENUMERATED || optType == IOption.TREE) {
if (itCommandInputs.size() > 0) {
ManagedBuildManager.setOption(config, tool, assignToOption, itCommandInputs.firstElement());
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/projectconverter/UpdateManagedProject12.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/projectconverter/UpdateManagedProject12.java
index de7cefb..79c113f 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/projectconverter/UpdateManagedProject12.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/projectconverter/UpdateManagedProject12.java
@@ -397,6 +397,19 @@ class UpdateManagedProject12 {
}
configuration.setOption(tool, newOpt, idValue != null ? idValue : name);
break;
+ case IOption.TREE:
+ // This is going to be the human readable form of the tree value
+ name = optRef.getAttribute(IOption.DEFAULT_VALUE);
+ // Convert it to the ID
+ idValue = newOpt.getId(name);
+ if (idValue == null) {
+ // If the name does not match one of the enumerations values, probably because
+ // the list of enumerands has changed, set the name to be the name used for the
+ // enumeration's default value
+ name = (String)newOpt.getDefaultValue();
+ }
+ configuration.setOption(tool, newOpt, idValue != null ? idValue : name);
+ break;
case IOption.STRING_LIST:
case IOption.INCLUDE_PATH:
case IOption.PREPROCESSOR_SYMBOLS:
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/projectconverter/UpdateManagedProject20.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/projectconverter/UpdateManagedProject20.java
index 69360b4..0b0448d 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/projectconverter/UpdateManagedProject20.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/projectconverter/UpdateManagedProject20.java
@@ -427,6 +427,7 @@ class UpdateManagedProject20 {
break;
}
case IOption.ENUMERATED:
+ case IOption.TREE:
case IOption.STRING:{
if(optRef.hasAttribute(IOption.DEFAULT_VALUE))
configuration.setOption(tool,option,optRef.getAttribute(IOption.DEFAULT_VALUE));
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/templateengine/processes/SetMBSStringOptionValue.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/templateengine/processes/SetMBSStringOptionValue.java
index fbb5c76..754f492 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/templateengine/processes/SetMBSStringOptionValue.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/templateengine/processes/SetMBSStringOptionValue.java
@@ -118,7 +118,7 @@ public class SetMBSStringOptionValue extends ProcessRunner {
for (IOption option : options) {
if (option.getBaseId().toLowerCase().matches(lowerId)) {
int optionType = option.getValueType();
- if ((optionType == IOption.STRING) || (optionType == IOption.ENUMERATED)) {
+ if ((optionType == IOption.STRING) || (optionType == IOption.ENUMERATED) || (optionType == IOption.TREE)) {
ManagedBuildManager.setOption(resourceConfig, optionHolder, option, value);
modified = true;
}
@@ -133,7 +133,7 @@ public class SetMBSStringOptionValue extends ProcessRunner {
for (IOption option : options) {
if (option.getBaseId().toLowerCase().matches(lowerId)) {
int optionType = option.getValueType();
- if ((optionType == IOption.STRING) || (optionType == IOption.ENUMERATED)) {
+ if ((optionType == IOption.STRING) || (optionType == IOption.ENUMERATED) || (optionType == IOption.TREE)) {
ManagedBuildManager.setOption(config, optionHolder, option, value);
modified = true;
}
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 b940a74..d082e0c 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 685cf46..547d4d6 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 f1f0ec3..dd5c356 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 db50560..a6e7dab 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;