Bug 569300: Allow custom build option editors to save the value

Added a new interface with a method that is called when the value is to
be saved into a resource configuration.
If the function returns false, then the default implementation of
handling property changes will kick in. If the function returns true,
then it's assumed that the value has been handled.

Change-Id: I0523d15ba0a3ec9dbc24c3e4afc070b071d8fb7e
Signed-off-by: Torbjörn Svensson <azoff@svenskalinuxforeningen.se>
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF b/build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF
index a854688..df49c1b 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF
+++ b/build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.cdt.managedbuilder.ui; singleton:=true
-Bundle-Version: 9.2.100.qualifier
+Bundle-Version: 9.3.0.qualifier
 Bundle-Activator: org.eclipse.cdt.managedbuilder.ui.properties.ManagedBuilderUIPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/schema/buildDefinitionsUI.exsd b/build/org.eclipse.cdt.managedbuilder.ui/schema/buildDefinitionsUI.exsd
index d0515d1..e7a6e99 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/schema/buildDefinitionsUI.exsd
+++ b/build/org.eclipse.cdt.managedbuilder.ui/schema/buildDefinitionsUI.exsd
@@ -64,7 +64,7 @@
          <attribute name="class" type="string" use="required">
             <annotation>
                <documentation>
-                  Specifies the Java class which implements the custom field-editor.  This class must extend JFace&apos;s &lt;code&gt;FieldEditor&lt;/code&gt; abstract class, and implement the &lt;code&gt;ICustomBuildOptionEditor&lt;/code&gt; interface.
+                  Specifies the Java class which implements the custom field-editor.  This class must extend JFace&apos;s &lt;code&gt;FieldEditor&lt;/code&gt; abstract class, and implement the &lt;code&gt;ICustomBuildOptionEditor2&lt;/code&gt; interface.
                </documentation>
                <appInfo>
                   <meta.attribute kind="java" basedOn="org.eclipse.jface.preference.FieldEditor:org.eclipse.cdt.managedbuilder.ui.properties.ICustomBuildOptionEditor"/>
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 d20ac18..991aa0d 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
@@ -808,59 +808,66 @@
 				changedOption = (IOption) option[1];
 				changedHolder = (IHoldsOptions) option[0];
 				try {
-					switch (changedOption.getValueType()) {
-					case IOption.STRING:
-						if (fe instanceof StringFieldEditor) {
-							String val = ((StringFieldEditor) fe).getStringValue();
-							ManagedBuildManager.setOption(fInfo, changedHolder, changedOption, val);
-						}
-						break;
-					case IOption.BOOLEAN:
-						if (fe instanceof BooleanFieldEditor) {
-							boolean val = ((BooleanFieldEditor) fe).getBooleanValue();
-							ManagedBuildManager.setOption(fInfo, changedHolder, changedOption, val);
-						}
-						break;
-					case IOption.ENUMERATED:
-						if (fe instanceof BuildOptionComboFieldEditor) {
-							String name = ((BuildOptionComboFieldEditor) fe).getSelection();
-							String enumId = changedOption.getEnumeratedId(name);
-							ManagedBuildManager.setOption(fInfo, changedHolder, changedOption,
-									(enumId != null && enumId.length() > 0) ? enumId : name);
+					boolean saved = false;
+					if (fe instanceof ICustomBuildOptionEditor2) {
+						saved = ((ICustomBuildOptionEditor2) fe).save(fInfo, changedHolder, changedOption);
+					}
 
-						}
-						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);
+					if (!saved) {
+						switch (changedOption.getValueType()) {
+						case IOption.STRING:
+							if (fe instanceof StringFieldEditor) {
+								String val = ((StringFieldEditor) fe).getStringValue();
+								ManagedBuildManager.setOption(fInfo, changedHolder, changedOption, val);
+							}
+							break;
+						case IOption.BOOLEAN:
+							if (fe instanceof BooleanFieldEditor) {
+								boolean val = ((BooleanFieldEditor) fe).getBooleanValue();
+								ManagedBuildManager.setOption(fInfo, changedHolder, changedOption, val);
+							}
+							break;
+						case IOption.ENUMERATED:
+							if (fe instanceof BuildOptionComboFieldEditor) {
+								String name = ((BuildOptionComboFieldEditor) fe).getSelection();
+								String enumId = changedOption.getEnumeratedId(name);
+								ManagedBuildManager.setOption(fInfo, changedHolder, changedOption,
+										(enumId != null && enumId.length() > 0) ? enumId : name);
 
+							}
+							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:
+						case IOption.LIBRARIES:
+						case IOption.OBJECTS:
+						case IOption.INCLUDE_FILES:
+						case IOption.LIBRARY_PATHS:
+						case IOption.LIBRARY_FILES:
+						case IOption.MACRO_FILES:
+						case IOption.UNDEF_INCLUDE_PATH:
+						case IOption.UNDEF_PREPROCESSOR_SYMBOLS:
+						case IOption.UNDEF_INCLUDE_FILES:
+						case IOption.UNDEF_LIBRARY_PATHS:
+						case IOption.UNDEF_LIBRARY_FILES:
+						case IOption.UNDEF_MACRO_FILES:
+							if (fe instanceof FileListControlFieldEditor) {
+								String val[] = ((FileListControlFieldEditor) fe).getStringListValue();
+								ManagedBuildManager.setOption(fInfo, changedHolder, changedOption, val);
+							}
+							break;
+						default:
+							break;
 						}
-						break;
-					case IOption.INCLUDE_PATH:
-					case IOption.STRING_LIST:
-					case IOption.PREPROCESSOR_SYMBOLS:
-					case IOption.LIBRARIES:
-					case IOption.OBJECTS:
-					case IOption.INCLUDE_FILES:
-					case IOption.LIBRARY_PATHS:
-					case IOption.LIBRARY_FILES:
-					case IOption.MACRO_FILES:
-					case IOption.UNDEF_INCLUDE_PATH:
-					case IOption.UNDEF_PREPROCESSOR_SYMBOLS:
-					case IOption.UNDEF_INCLUDE_FILES:
-					case IOption.UNDEF_LIBRARY_PATHS:
-					case IOption.UNDEF_LIBRARY_FILES:
-					case IOption.UNDEF_MACRO_FILES:
-						if (fe instanceof FileListControlFieldEditor) {
-							String val[] = ((FileListControlFieldEditor) fe).getStringListValue();
-							ManagedBuildManager.setOption(fInfo, changedHolder, changedOption, val);
-						}
-						break;
-					default:
-						break;
 					}
 				} catch (BuildException e) {
 				}
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ICustomBuildOptionEditor.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ICustomBuildOptionEditor.java
index ee7d49f..0a4d7f9 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ICustomBuildOptionEditor.java
+++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ICustomBuildOptionEditor.java
@@ -29,6 +29,7 @@
  * org.eclipse.cdt.managedbuilder.core.buildDefinitions extension-point.
  *
  * @since 8.0
+ * @see {@link ICustomBuildOptionEditor2}
  */
 public interface ICustomBuildOptionEditor {
 	/**
@@ -39,7 +40,7 @@
 	 * 			for the field-editor. May be {@code null}.
 	 * @param preferenceName the name of the preference this field editor binds to.
 	 * @param parent the parent of the field editor's control.
-	 * @return {@code true} iff the custom field-editor can be successfully displayed. Returning {@code false}
+	 * @return {@code true} if the custom field-editor can be successfully displayed. Returning {@code false}
 	 * 			would cause the built-in field-editor to be displayed based on the option's {@link IOption#getValueType() valueType}.
 	 */
 	boolean init(IOption option, String extraArgument, String preferenceName, Composite parent);
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ICustomBuildOptionEditor2.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ICustomBuildOptionEditor2.java
new file mode 100644
index 0000000..1232f34
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/ICustomBuildOptionEditor2.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Torbjörn Svensson, and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Torbjörn Svensson - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.managedbuilder.ui.properties;
+
+import org.eclipse.cdt.managedbuilder.core.IHoldsOptions;
+import org.eclipse.cdt.managedbuilder.core.IOption;
+import org.eclipse.cdt.managedbuilder.core.IResourceInfo;
+
+/**
+ * This interface can be implemented by clients to contribute custom build-option
+ * editors to the CDT Build Settings page in the project Properties dialog.
+ *
+ * In addition to implementing this interface, the custom build-option editor class
+ * must also extend the {@link org.eclipse.jface.preference.FieldEditor} class. The
+ * custom build-option editor class should be contributed through the <fieldEditor>
+ * element of the org.eclipse.cdt.managedbuilder.ui.buildDefinitionsUI extension-point,
+ * and then referenced, by its ID, from the <option>/fieldEditorId attribute of the
+ * org.eclipse.cdt.managedbuilder.core.buildDefinitions extension-point.
+ *
+ * @since 9.3
+ */
+public interface ICustomBuildOptionEditor2 extends ICustomBuildOptionEditor {
+	/**
+	 * Save the option value to the resource info
+	 * Typical usage is:
+	 * <code>ManagedBuildManager.setOption(resConfig, holder, option, theValue);</code>
+	 *
+	 * @param resConfig The resource configuration the option belongs to.
+	 * @param holder The holder/parent of the option.
+	 * @param option The option to set the value for.
+	 * @return {@code true} if the save was successful. Returning {@code false}
+	 * 			to fall back to generic save implementation.
+	 */
+	boolean save(IResourceInfo resConfig, IHoldsOptions holder, IOption option);
+}