From 0ef94304dc11f7ce64ee378a7e166ee408fccbd3 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Wed, 27 Apr 2016 17:39:17 +0100 Subject: [PATCH 1/4] Added MapAccess. Added serialization of env vars to CommandInvocation. --- .../operations/build/BuildManager_Test.java | 5 +- .../build/BuildTargetsSerializer_Test.java | 67 +++++++++++++-- .../core/operations/build/BuildManager.java | 2 +- .../build/BuildTargetsSerializer.java | 13 +-- .../operations/build/CommandInvocation.java | 41 ++++++++-- .../build/CommandInvocationSerializer.java | 82 +++++++++++++++---- .../operations/build/VariablesResolver.java | 2 +- .../ide/ui/preferences/BuildTargetEditor.java | 11 +-- .../preferences/CommandInvocationEditor.java | 21 ++--- .../fields/FieldCompositeWidget.java | 5 ++ .../lang/utils/DocumentSerializerHelper.java | 43 +++++++++- .../utilbox/collections/HashMap2.java | 5 +- .../utilbox/collections/LinkedHashMap2.java | 9 +- .../utilbox/collections/MapAccess.java | 49 +++++++++++ 14 files changed, 290 insertions(+), 65 deletions(-) create mode 100644 plugin_tooling/src-util/melnorme/utilbox/collections/MapAccess.java diff --git a/plugin_ide.core.tests/src-lang/melnorme/lang/ide/core/operations/build/BuildManager_Test.java b/plugin_ide.core.tests/src-lang/melnorme/lang/ide/core/operations/build/BuildManager_Test.java index 65f5f5d12..6889d69bd 100644 --- a/plugin_ide.core.tests/src-lang/melnorme/lang/ide/core/operations/build/BuildManager_Test.java +++ b/plugin_ide.core.tests/src-lang/melnorme/lang/ide/core/operations/build/BuildManager_Test.java @@ -233,8 +233,7 @@ public void test_compositeBuildTargetSettings() throws Exception { protected CompositeBuildTargetSettings btSettings( String buildTargetName, String buildArguments, String artifactPath) { - CommandInvocation buildCommand = buildArguments == null ? null : new CommandInvocation(buildArguments); - return getBuiltTargetSettingsValidator(project.getName(), buildTargetName, buildCommand, artifactPath); + return getBuiltTargetSettingsValidator(project.getName(), buildTargetName, cmd(buildArguments), artifactPath); } protected CompositeBuildTargetSettings getBuiltTargetSettingsValidator( @@ -352,7 +351,7 @@ protected void testBuildOperation_Vars(ProjectBuildInfo buildInfo, BuildTarget b protected Indexable getBuildOperation(ProjectBuildInfo buildInfo, BuildTarget btB, String buildArguments) throws CommonException { BuildTargetData dataCopy = btB.getDataCopy(); - dataCopy.buildCommand = cmd(buildArguments); + dataCopy.buildCommand = new CommandInvocation(buildArguments); BuildTarget newBuildTarget = buildInfo.buildMgr.createBuildTarget(buildInfo.project, dataCopy); ToolManager toolMgr = buildInfo.buildMgr.getToolManager(); diff --git a/plugin_ide.core.tests/src-lang/melnorme/lang/ide/core/operations/build/BuildTargetsSerializer_Test.java b/plugin_ide.core.tests/src-lang/melnorme/lang/ide/core/operations/build/BuildTargetsSerializer_Test.java index 49649c3cf..4d5ae5a9c 100644 --- a/plugin_ide.core.tests/src-lang/melnorme/lang/ide/core/operations/build/BuildTargetsSerializer_Test.java +++ b/plugin_ide.core.tests/src-lang/melnorme/lang/ide/core/operations/build/BuildTargetsSerializer_Test.java @@ -14,17 +14,73 @@ import org.junit.Test; -import melnorme.lang.ide.core.LangCore; import melnorme.utilbox.collections.ArrayList2; +import melnorme.utilbox.collections.HashMap2; import melnorme.utilbox.core.CommonException; +import melnorme.utilbox.misc.Pair; import melnorme.utilbox.tests.CommonTest; public class BuildTargetsSerializer_Test extends CommonTest { + private static final String STRING_ENCODING__ALL_ASCII = "value:a;b\\\"()dff{}[]"; + public static CommandInvocation cmd(String commandArguments) { - return commandArguments == null ? null :new CommandInvocation(commandArguments); + if(commandArguments == null) { + return null; + } + HashMap2 map = new HashMap2<>(); + map.put("MY_ENV_VAR", STRING_ENCODING__ALL_ASCII); + return new CommandInvocation(commandArguments, map, true); + } + + public static CommandInvocation cmd(String commandArguments, boolean append, Pair[] entries) { + HashMap2 envMap = null; + + if(entries != null) { + envMap = new HashMap2<>(); + for (Pair pair : entries) { + envMap.put(pair.getFirst(), pair.getSecond()); + } + } + return new CommandInvocation(commandArguments, envMap, append); + } + + public static Pair entry(String key, String value) { + return new Pair<>(key, value); } + @Test + public void test_CommandInvocation() throws Exception { test_CommandInvocation$(); } + public void test_CommandInvocation$() throws Exception { + testSerializeCmd(null); + testSerializeCmd(cmd("", true, null)); + testSerializeCmd(cmd("", false, null)); + testSerializeCmd(cmd("asdf", true, array())); + + testSerializeCmd(cmd("asdf", true, array( + entry("one", "1") + ))); + testSerializeCmd(cmd("asdf", true, array( + entry("one", "") + ))); + testSerializeCmd(cmd("asdf", true, array( + entry("one", "1"), + entry("two", ""), + entry(STRING_ENCODING__ALL_ASCII, STRING_ENCODING__ALL_ASCII) + ))); + } + + protected void testSerializeCmd(CommandInvocation command) { + CommandInvocationSerializer serializer = new CommandInvocationSerializer(); + try { + String xml = serializer.writeToString(command); + assertAreEqual(command, serializer.readFromString(xml)); + } catch(CommonException e) { + assertFail(); + } + } + + public static BuildTargetData bt(String targetName, boolean enabled, boolean autoEnabled, String buildArguments, String executablePath) { return btd(targetName, enabled, autoEnabled, cmd(buildArguments), executablePath); @@ -45,19 +101,18 @@ public static BuildTargetData btd(String targetName, boolean enabled, boolean au return bt; } - protected final BuildManager buildMgr = LangCore.getBuildManager(); - protected BuildTargetsSerializer serializer = buildMgr.createSerializer(); + protected BuildTargetsSerializer serializer = new BuildTargetsSerializer(); @Test public void test() throws Exception { test$(); } public void test$() throws Exception { testSerialize(new ArrayList2<>()); - testSerialize(new ArrayList2<>(bt("", false, false, null, null))); + testSerialize(new ArrayList2<>(btd("", false, false, null, null))); testSerialize(new ArrayList2<>(btd("", true, true, cmd("-opt"), "foo.exe"))); testSerialize(new ArrayList2<>( btd("", false, true, cmd(""), ""), btd("blah", true, false, cmd("-opt"), "foo.exe"), - bt("xxx", true, false, null, "foo/bar.ooo") + btd("xxx", true, false, null, "foo/bar.ooo") )); } diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/BuildManager.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/BuildManager.java index 66569d301..e872c42ac 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/BuildManager.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/BuildManager.java @@ -162,7 +162,7 @@ public ProjectBuildInfo getValidBuildInfo(IProject project, boolean requireNonEm new StringPreference("build_targets", "").getProjectPreference(); protected BuildTargetsSerializer createSerializer() { - return new BuildTargetsSerializer(this); + return new BuildTargetsSerializer(); } protected String getBuildTargetsPref(IProject project) { diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/BuildTargetsSerializer.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/BuildTargetsSerializer.java index 24d6a420c..dba47cb0b 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/BuildTargetsSerializer.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/BuildTargetsSerializer.java @@ -37,12 +37,9 @@ public class BuildTargetsSerializer extends DocumentSerializerHelper readFromString(String targetsXml) throws CommonException { + return (ArrayList2) super.readFromString(targetsXml); + } + + @Override + public ArrayList2 doReadFromString(String targetsXml) throws CommonException { Document doc = parseDocumentFromXml(targetsXml); Node buildTargetsElem = doc.getFirstChild(); @@ -93,7 +96,7 @@ protected Element writeBuildTargetElement(Document doc, BuildTargetDataView btd) commandSerializer.writeToParent(targetElem, btd.getBuildCommand()); - setOptionalAttribute(targetElem, PROP_EXE_PATH, btd.getExecutablePath()); + setAttribute(targetElem, PROP_EXE_PATH, btd.getExecutablePath()); return targetElem; } diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/CommandInvocation.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/CommandInvocation.java index 8140e1073..4c255ccc4 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/CommandInvocation.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/CommandInvocation.java @@ -19,20 +19,26 @@ import melnorme.lang.tooling.data.StatusException; import melnorme.lang.tooling.data.validation.ValidatedValueSource; import melnorme.utilbox.collections.ArrayList2; +import melnorme.utilbox.collections.HashMap2; import melnorme.utilbox.collections.Indexable; +import melnorme.utilbox.collections.MapAccess; import melnorme.utilbox.core.CommonException; import melnorme.utilbox.misc.HashcodeUtil; public class CommandInvocation { protected final String commandArguments; + protected final MapAccess environmentVars; // Can be null + protected final boolean appendEnvironment; public CommandInvocation(String commandArguments) { - this.commandArguments = assertNotNull(commandArguments); + this(commandArguments, null, true); } - public String getCommandArguments() { - return commandArguments; + public CommandInvocation(String commandArguments, MapAccess envVars, boolean appendEnv) { + this.commandArguments = assertNotNull(commandArguments); + this.environmentVars = envVars != null ? envVars : new HashMap2<>(); + this.appendEnvironment = appendEnv; } @Override @@ -42,14 +48,31 @@ public boolean equals(Object obj) { CommandInvocation other = (CommandInvocation) obj; - return areEqual(commandArguments, other.commandArguments); + return + areEqual(commandArguments, other.commandArguments) && + areEqual(environmentVars, other.environmentVars) && + areEqual(appendEnvironment, other.appendEnvironment); } @Override public int hashCode() { - return HashcodeUtil.combinedHashCode(commandArguments); + return HashcodeUtil.combinedHashCode(commandArguments, environmentVars); + } + + public String getCommandArguments() { + return commandArguments; } + public MapAccess getEnvironmentVars() { + return environmentVars; + } + + public boolean isAppendEnvironment() { + return appendEnvironment; + } + + /* ----------------- ----------------- */ + public void validate(VariablesResolver variablesResolver) throws StatusException { getValidatedCommandArguments(variablesResolver).validate(); } @@ -80,17 +103,21 @@ public Indexable getValidatedValue() throws StatusException { } public Indexable doGetValidatedValue(VariablesResolver variablesResolver) throws CommonException { + if(commandArguments == null) { + handleNoCommandLine(); + } + String evaluatedCommandLine = variablesResolver.performStringSubstitution(commandArguments); if(evaluatedCommandLine.trim().isEmpty()) { - handleEmptyCommandLine(); + handleNoCommandLine(); } String[] evaluatedArguments = DebugPlugin.parseArguments(evaluatedCommandLine); return new ArrayList2<>(evaluatedArguments); } - protected void handleEmptyCommandLine() throws CommonException { + protected void handleNoCommandLine() throws CommonException { throw new CommonException(MSG_NO_COMMAND_SPECIFIED); } diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/CommandInvocationSerializer.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/CommandInvocationSerializer.java index 315b74a36..384fcfa4a 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/CommandInvocationSerializer.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/CommandInvocationSerializer.java @@ -10,11 +10,17 @@ *******************************************************************************/ package melnorme.lang.ide.core.operations.build; +import static melnorme.utilbox.misc.CollectionUtil.nullToEmpty; + +import java.util.Map.Entry; + import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import melnorme.lang.utils.DocumentSerializerHelper; +import melnorme.utilbox.collections.HashMap2; +import melnorme.utilbox.collections.MapAccess; import melnorme.utilbox.core.CommonException; public class CommandInvocationSerializer extends DocumentSerializerHelper { @@ -22,10 +28,11 @@ public class CommandInvocationSerializer extends DocumentSerializerHelper envVars) { + for (Entry entry : nullToEmpty(envVars)) { + Element entryElement = addChild(envVarsElement, ELEM_ENTRY); + entryElement.setAttribute(PROP_KEY, entry.getKey()); + addTextChild(entryElement, entry.getValue()); } } /* ----------------- read ----------------- */ @Override - public CommandInvocation readFromString(String targetsXml) throws CommonException { - if(targetsXml == null) { - return null; - } + public CommandInvocation doReadFromString(String targetsXml) throws CommonException { Document doc = parseDocumentFromXml(targetsXml); - return readFromNode(doc.createElement(PROP_COMMAND_INVOCATION)); + + for(int ix = 0; ix < doc.getChildNodes().getLength(); ix++) { + Node node = doc.getChildNodes().item(ix); + if(node.getNodeName().equals(CommandInvocationSerializer.PROP_COMMAND_INVOCATION)) { + return readFromNode(node); + } + } + return null; } - public CommandInvocation readFromNode(Node node) { - String commandArguments = getAttribute(node, PROP_ARGUMENTS, null); - if(commandArguments != null) { - return new CommandInvocation(commandArguments); + public CommandInvocation readFromNode(Node cmdElement) { + + String commandArguments = getAttribute(cmdElement, PROP_ARGUMENTS, ""); + boolean appendEnv = getBooleanAttribute(cmdElement, PROP_APPEND_ENV, true); + + HashMap2 envVars = new HashMap2<>(); + + for(int ix = 0; ix < cmdElement.getChildNodes().getLength(); ix++) { + Node node = cmdElement.getChildNodes().item(ix); + if(node.getNodeName().equals(CommandInvocationSerializer.ELEM_ENV_VARS)) { + readEnvVars(envVars, node); + } + } + + return new CommandInvocation(commandArguments, envVars, appendEnv); + } + + public void readEnvVars(HashMap2 envVars, Node envVarsNode) { + for(int ix = 0; ix < envVarsNode.getChildNodes().getLength(); ix++) { + Node child = envVarsNode.getChildNodes().item(ix); + if(child.getNodeType() != Node.ELEMENT_NODE || !child.getNodeName().equals(ELEM_ENTRY)) { + continue; + } + + String key = getAttribute(child, PROP_KEY, null); + if(key == null) { + continue; + } + String entryValue = child.getTextContent(); + envVars.put(key, entryValue); } - return null; } } \ No newline at end of file diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/VariablesResolver.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/VariablesResolver.java index 628e48c4b..72750ba2f 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/VariablesResolver.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/VariablesResolver.java @@ -98,7 +98,7 @@ public IDynamicVariable getDynamicVariable(String name) { @Override public IDynamicVariable[] getDynamicVariables() { - HashMap2 newMap = dynamicVariables.copy(); + HashMap2 newMap = dynamicVariables.copyToHashMap(); IDynamicVariable[] parentVars = super.getDynamicVariables(); for (IDynamicVariable parentVar : parentVars) { diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/BuildTargetEditor.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/BuildTargetEditor.java index ff0746745..45eaad61d 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/BuildTargetEditor.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/BuildTargetEditor.java @@ -117,17 +117,12 @@ public BuildCommandEditor(CommonGetter getDefaultBuildCommand } @Override - protected void handleNoBuildCommandSupplied() throws StatusException { - throw new StatusException("No build command supplied."); - } - - @Override - protected void doValidate(String commandArguments) throws StatusException { + protected void validateArguments() throws StatusException { try { - new CommandInvocation(commandArguments).validate(variablesResolver); + super.validateArguments(); } catch(StatusException se) { if(se.getMessage() == ValidatedCommandArgumentsSource.MSG_NO_COMMAND_SPECIFIED) { - handleNoBuildCommandSupplied(); + throw new StatusException("No build command supplied."); } } } diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/CommandInvocationEditor.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/CommandInvocationEditor.java index 44159858c..eb12839ad 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/CommandInvocationEditor.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/CommandInvocationEditor.java @@ -76,7 +76,12 @@ protected void doUpdateWidgetFromInput() { } protected void updateCommandInvocationField() { - commandInvocation.set(new CommandInvocation(commandArgumentsField.get())); + CommandInvocation current = commandInvocation.get(); + commandInvocation.set(new CommandInvocation( + commandArgumentsField.get(), + current.getEnvironmentVars(), + current.isAppendEnvironment() + )); } @Override @@ -126,19 +131,7 @@ protected void createContents_layout() { /* ----------------- ----------------- */ protected void validateArguments() throws StatusException { - String commandArguments = this.commandArgumentsField.get(); - if(commandArguments == null) { - handleNoBuildCommandSupplied(); - } - doValidate(commandArguments); - } - - protected void handleNoBuildCommandSupplied() throws StatusException { - throw new StatusException("No command supplied."); - } - - protected void doValidate(String commandArguments) throws StatusException { - new CommandInvocation(commandArguments).validate(variablesResolver); + getFieldValue().validate(variablesResolver); } /* ----------------- button handlers ----------------- */ diff --git a/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/FieldCompositeWidget.java b/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/FieldCompositeWidget.java index 5ed259e4b..87be0b982 100644 --- a/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/FieldCompositeWidget.java +++ b/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/FieldCompositeWidget.java @@ -28,8 +28,13 @@ protected Field init_valueField() { return new Field<>(); } + /* FIXME: rename*/ public Field getField() { return valueField; } + public VALUE getFieldValue() { + return valueField.get(); + } + } \ No newline at end of file diff --git a/plugin_tooling/src-lang/melnorme/lang/utils/DocumentSerializerHelper.java b/plugin_tooling/src-lang/melnorme/lang/utils/DocumentSerializerHelper.java index 213691bce..b6a29780a 100644 --- a/plugin_tooling/src-lang/melnorme/lang/utils/DocumentSerializerHelper.java +++ b/plugin_tooling/src-lang/melnorme/lang/utils/DocumentSerializerHelper.java @@ -10,6 +10,8 @@ *******************************************************************************/ package melnorme.lang.utils; +import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; + import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; @@ -29,10 +31,12 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.w3c.dom.Text; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import melnorme.utilbox.core.CommonException; +import melnorme.utilbox.misc.StringUtil; public abstract class DocumentSerializerHelper { @@ -44,7 +48,17 @@ protected DocumentBuilder getDocumentBuilder() throws CommonException { } } + protected Document getDocumentParent(Node parentElement) { + if(parentElement instanceof Document) { + return (Document) parentElement; + } + return parentElement.getOwnerDocument(); + } + public String writeToString(ELEMENT buildTargets) throws CommonException { + if(buildTargets == null) { + return ""; + } Document doc = getDocumentBuilder().newDocument(); writeDocument(doc, buildTargets); return documentToString(doc); @@ -54,7 +68,14 @@ public String writeToString(ELEMENT buildTargets) throws CommonException { /* ----------------- read ----------------- */ - public abstract ELEMENT readFromString(String targetsXml) throws CommonException; + public ELEMENT readFromString(String targetsXml) throws CommonException { + if(StringUtil.emptyAsNull(targetsXml) == null) { + return null; + } + return doReadFromString(targetsXml); + } + + public abstract ELEMENT doReadFromString(String targetsXml) throws CommonException; public String documentToString(Document doc) throws TransformerFactoryConfigurationError, CommonException { Transformer transformer; @@ -73,7 +94,25 @@ public String documentToString(Document doc) throws TransformerFactoryConfigurat return writer.toString(); } - protected static void setOptionalAttribute(Element targetElem, String name, String value) { + /* ----------------- ----------------- */ + + public Element addChild(Element parent, String elementName) { + assertNotNull(elementName); + Element newChild = parent.getOwnerDocument().createElement(elementName); + parent.appendChild(newChild); + return newChild; + } + + public Text addTextChild(Element targetElem, String value) { + if(value == null) { + return null; + } + Text newChild = targetElem.getOwnerDocument().createTextNode(value); + targetElem.appendChild(newChild); + return newChild; + } + + protected static void setAttribute(Element targetElem, String name, String value) { if(value != null) { targetElem.setAttribute(name, value); } diff --git a/plugin_tooling/src-util/melnorme/utilbox/collections/HashMap2.java b/plugin_tooling/src-util/melnorme/utilbox/collections/HashMap2.java index 50242577e..7a9e04011 100644 --- a/plugin_tooling/src-util/melnorme/utilbox/collections/HashMap2.java +++ b/plugin_tooling/src-util/melnorme/utilbox/collections/HashMap2.java @@ -20,7 +20,7 @@ * Extension to {@link java.util.HashMap}, with some helper methods, * and implementing the read-only interface {@link Collection2}. */ -public class HashMap2 extends HashMap implements Collection2> { +public class HashMap2 extends HashMap implements MapAccess { private static final long serialVersionUID = -7612795787860334443L; @@ -32,7 +32,8 @@ public HashMap2(Map map) { super(map); } - public HashMap2 copy() { + @Override + public HashMap2 copyToHashMap() { return new HashMap2(this); } diff --git a/plugin_tooling/src-util/melnorme/utilbox/collections/LinkedHashMap2.java b/plugin_tooling/src-util/melnorme/utilbox/collections/LinkedHashMap2.java index 374b7f7ed..40e81dfb1 100644 --- a/plugin_tooling/src-util/melnorme/utilbox/collections/LinkedHashMap2.java +++ b/plugin_tooling/src-util/melnorme/utilbox/collections/LinkedHashMap2.java @@ -20,7 +20,7 @@ * Extension to {@link java.util.LinkedHashMap}, with some helper methods, * and implementing the read-only interface {@link Collection2}. */ -public class LinkedHashMap2 extends LinkedHashMap implements Collection2> { +public class LinkedHashMap2 extends LinkedHashMap implements MapAccess { private static final long serialVersionUID = -7612795787860334443L; @@ -55,4 +55,11 @@ public Collection2 getValuesView() { return valuesView; } + /* ----------------- ----------------- */ + + @Override + public HashMap2 copyToHashMap() { + return new HashMap2<>(this); + } + } \ No newline at end of file diff --git a/plugin_tooling/src-util/melnorme/utilbox/collections/MapAccess.java b/plugin_tooling/src-util/melnorme/utilbox/collections/MapAccess.java new file mode 100644 index 000000000..b3a8f573c --- /dev/null +++ b/plugin_tooling/src-util/melnorme/utilbox/collections/MapAccess.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2016 Bruno Medeiros and other Contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Bruno Medeiros - initial API and implementation + *******************************************************************************/ +package melnorme.utilbox.collections; + +import java.util.Map; +import java.util.Set; + +/** + * A read-only view of a map, based on {@link Map} + */ +public interface MapAccess extends Collection2> { + + /** See {@link Map#containsKey(Object)} */ + boolean containsKey(Object key); + + /** See {@link Map#containsValue(Object)} */ + boolean containsValue(Object value); + + /** See {@link Map#get(Object)}*/ + V get(Object key); + + /** See {@link Map#getOrDefault(Object, Object)}*/ + default V getOrDefault(Object key, V defaultValue) { + V v; + return (((v = get(key)) != null) || containsKey(key)) + ? v + : defaultValue; + } + + /** See {@link Map#entrySet()}. WARNING: Clients must not modify this set. */ + Set> entrySet(); + + + /* ----------------- ----------------- */ + + /** + * @return a copy of this collection. + */ + public HashMap2 copyToHashMap(); + +} \ No newline at end of file From 1619d41f6bfdf05df375760fd7c51b1727b3ba40 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Wed, 27 Apr 2016 18:44:37 +0100 Subject: [PATCH 2/4] Editor for environment variables of Build Target --- documentation/ChangeLog.md | 1 + .../icons/icons-lang/environment_obj.png | Bin 0 -> 616 bytes plugin_ide.ui/icons/icons-lang/envvar_obj.png | Bin 0 -> 377 bytes .../internal/ui/MultipleInputDialog.java | 435 +++++++++++++ .../eclipse/debug/internal/ui/SWTFactory.java | 590 ++++++++++++++++++ .../melnorme/lang/ide/ui/LangImages.java | 8 +- .../BuildTargetEditor.java | 4 +- .../CommandInvocationEditor.java | 32 +- .../ui/build/EnvironmentSettingsEditor.java | 491 +++++++++++++++ .../ide/ui/build/EnvironmentVariable.java | 70 +++ .../build/LaunchConfigurationsMessages.java | 217 +++++++ .../LaunchConfigurationsMessages.properties | 212 +++++++ .../NativeEnvironmentSelectionDialog.java | 487 +++++++++++++++ .../lang/ide/ui/fields/FieldDialog.java | 51 ++ .../ui/launch/MainLaunchConfigurationTab.java | 4 +- .../ProjectBuildConfigurationComponent.java | 1 + .../util/swt/components/AbstractWidget.java | 4 +- .../util/swt/components/CompositeWidget.java | 2 +- .../fields/EnablementButtonTextField2.java | 2 +- .../fields/EnablementCompositeWidget.java | 12 +- .../fields/FieldCompositeWidget.java | 9 +- .../lang/tooling/ops/EnvironmentSettings.java | 50 ++ .../utilbox/collections/HashMap2.java | 4 + 23 files changed, 2664 insertions(+), 22 deletions(-) create mode 100644 plugin_ide.ui/icons/icons-lang/environment_obj.png create mode 100644 plugin_ide.ui/icons/icons-lang/envvar_obj.png create mode 100644 plugin_ide.ui/src-lang/_org/eclipse/debug/internal/ui/MultipleInputDialog.java create mode 100644 plugin_ide.ui/src-lang/_org/eclipse/debug/internal/ui/SWTFactory.java rename plugin_ide.ui/src-lang/melnorme/lang/ide/ui/{preferences => build}/BuildTargetEditor.java (95%) rename plugin_ide.ui/src-lang/melnorme/lang/ide/ui/{preferences => build}/CommandInvocationEditor.java (84%) create mode 100644 plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/EnvironmentSettingsEditor.java create mode 100644 plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/EnvironmentVariable.java create mode 100644 plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/LaunchConfigurationsMessages.java create mode 100644 plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/LaunchConfigurationsMessages.properties create mode 100644 plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/NativeEnvironmentSelectionDialog.java create mode 100644 plugin_ide.ui/src-lang/melnorme/lang/ide/ui/fields/FieldDialog.java create mode 100644 plugin_tooling/src-lang/melnorme/lang/tooling/ops/EnvironmentSettings.java diff --git a/documentation/ChangeLog.md b/documentation/ChangeLog.md index 3e9bdf0e6..9bcbbaaac 100644 --- a/documentation/ChangeLog.md +++ b/documentation/ChangeLog.md @@ -8,6 +8,7 @@ It's now possible to specify a command other than the default one (the $$SDK too * Added a setting to invoke a special build target when a $IDE editor is saved. * This allows invoking a build command (informally called a "check-build") that only checks for compiler errors, but doesn't not produce binaries. This has the potential to be faster than a full build. * Default is `` for $$IDE + * Added support for modifying the environment variables of a Build Target's build command. * Fixed "IllegalStateException: The service has been unregistered" on Mars.2 when Eclipse is closed. * Added signing to releases. diff --git a/plugin_ide.ui/icons/icons-lang/environment_obj.png b/plugin_ide.ui/icons/icons-lang/environment_obj.png new file mode 100644 index 0000000000000000000000000000000000000000..01ec97291deb80406f683117e8faf22aa200f974 GIT binary patch literal 616 zcmV-u0+;=XP)XqED4dY!pgTPAPGm9#XQjAN6tz4~ z&_rsMwQ|k|8`-91)?)qGT3c>C34C|oFLaWt<%4c}?LK$A_xtX)@3*Sze;n0qk-|}D zv`AF9Z>XuDCOS%LJ8l-$&g+GZ0&fZz<126^-oQ1viq6zq2*b`(<&Gjy(Wpn<_bJxh_9 zWR!wPpAn~QL1@kj$S$s;x%~>A39Usy-GvZLoCI@s5@tRLQ)e6lej6!J(SmC}GtRk2 zz=uRUo_~qcEdvUpGmIu-0^!smVvk-?L&=<6HV%VN+CvM1-4;0cD3)I5(G|D@n|qjQ zks0MT`^T~f$sr<0By!+m3ovkrFSNkVH6tp{B9mJIj; literal 0 HcmV?d00001 diff --git a/plugin_ide.ui/icons/icons-lang/envvar_obj.png b/plugin_ide.ui/icons/icons-lang/envvar_obj.png new file mode 100644 index 0000000000000000000000000000000000000000..b49cfd927908be960221cbbf0db8a67324b3ee14 GIT binary patch literal 377 zcmV-<0fzpGP)4Ibbv!?IAkJEsRnFs$x_3i#2*^9stJs`a6e>f0>I#5&(^K~OiI@LH!fKX$412n43hI|+42Xc0k&1^zG~&I_^+0;{J%OH*2rD{U$=1O zf5)12&u|*x-msy?tbFZ1hnkH*g+N@p34v=i{WmRJ`_HFwV>I5Fu&G#g&9rpwzks$K z|D${N{Eq~NfnV!(pm)~%v#VUYgQ&FNP_?ebxMs)n}*bbr}q!fVKbt X^DEy!LzY3600000NkvXXu0mjfbX~%` literal 0 HcmV?d00001 diff --git a/plugin_ide.ui/src-lang/_org/eclipse/debug/internal/ui/MultipleInputDialog.java b/plugin_ide.ui/src-lang/_org/eclipse/debug/internal/ui/MultipleInputDialog.java new file mode 100644 index 000000000..f80c2be50 --- /dev/null +++ b/plugin_ide.ui/src-lang/_org/eclipse/debug/internal/ui/MultipleInputDialog.java @@ -0,0 +1,435 @@ +/******************************************************************************* + * Copyright (c) 2003, 2013 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Jan Opacki (jan.opacki@gmail.com) bug 307139 + *******************************************************************************/ +package _org.eclipse.debug.internal.ui; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.debug.ui.StringVariableSelectionDialog; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.TraverseEvent; +import org.eclipse.swt.events.TraverseListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.DirectoryDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +interface IInternalDebugCoreConstants { + + /** + * Represents the empty string + */ + public static final String EMPTY_STRING = ""; //$NON-NLS-1$ + +} + +public class MultipleInputDialog extends Dialog { + protected static final String FIELD_NAME = "FIELD_NAME"; //$NON-NLS-1$ + protected static final int TEXT = 100; + protected static final int BROWSE = 101; + protected static final int VARIABLE = 102; + protected static final int MULTILINE_VARIABLE = 103; + + protected Composite panel; + + protected List fieldList = new ArrayList(); + protected List controlList = new ArrayList(); + protected List validators = new ArrayList(); + protected Map valueMap = new HashMap(); + + private String title; + + + + public MultipleInputDialog(Shell shell, String title) { + super(shell); + this.title = title; + setShellStyle(getShellStyle() | SWT.RESIZE); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) + */ + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + if (title != null) { + shell.setText(title); + } + + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createButtonBar(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createButtonBar(Composite parent) { + Control bar = super.createButtonBar(parent); + validateFields(); + return bar; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createDialogArea(Composite parent) { + Composite container = (Composite)super.createDialogArea(parent); + container.setLayout(new GridLayout(2, false)); + container.setLayoutData(new GridData(GridData.FILL_BOTH)); + + panel = new Composite(container, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + panel.setLayout(layout); + panel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + for (FieldSummary field : fieldList) { + switch(field.type) { + case TEXT: + createTextField(field.name, field.initialValue, field.allowsEmpty); + break; + case BROWSE: + createBrowseField(field.name, field.initialValue, field.allowsEmpty); + break; + case VARIABLE: + createVariablesField(field.name, field.initialValue, field.allowsEmpty); + break; + case MULTILINE_VARIABLE: + createMultilineVariablesField(field.name, field.initialValue, field.allowsEmpty); + break; + default: + break; + } + } + + fieldList = null; // allow it to be gc'd + Dialog.applyDialogFont(container); + return container; + } + + public void addBrowseField(String labelText, String initialValue, boolean allowsEmpty) { + fieldList.add(new FieldSummary(BROWSE, labelText, initialValue, allowsEmpty)); + } + public void addTextField(String labelText, String initialValue, boolean allowsEmpty) { + fieldList.add(new FieldSummary(TEXT, labelText, initialValue, allowsEmpty)); + } + public void addVariablesField(String labelText, String initialValue, boolean allowsEmpty) { + fieldList.add(new FieldSummary(VARIABLE, labelText, initialValue, allowsEmpty)); + } + public void addMultilinedVariablesField(String labelText, String initialValue, boolean allowsEmpty) { + fieldList.add(new FieldSummary(MULTILINE_VARIABLE, labelText, initialValue, allowsEmpty)); + } + + protected void createTextField(String labelText, String initialValue, boolean allowEmpty) { + Label label = new Label(panel, SWT.NONE); + label.setText(labelText); + label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + + final Text text = new Text(panel, SWT.SINGLE | SWT.BORDER); + text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + text.setData(FIELD_NAME, labelText); + + // make sure rows are the same height on both panels. + label.setSize(label.getSize().x, text.getSize().y); + + if (initialValue != null) { + text.setText(initialValue); + } + + if (!allowEmpty) { + validators.add(new Validator() { + @Override + public boolean validate() { + return !text.getText().equals(IInternalDebugCoreConstants.EMPTY_STRING); + } + }); + text.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validateFields(); + } + }); + } + + controlList.add(text); + } + + protected void createBrowseField(String labelText, String initialValue, boolean allowEmpty) { + Label label = new Label(panel, SWT.NONE); + label.setText(labelText); + label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + + Composite comp = new Composite(panel, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight=0; + layout.marginWidth=0; + comp.setLayout(layout); + comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + final Text text = new Text(comp, SWT.SINGLE | SWT.BORDER); + GridData data = new GridData(GridData.FILL_HORIZONTAL); + data.widthHint = 200; + text.setLayoutData(data); + text.setData(FIELD_NAME, labelText); + + // make sure rows are the same height on both panels. + label.setSize(label.getSize().x, text.getSize().y); + + if (initialValue != null) { + text.setText(initialValue); + } + + if (!allowEmpty) { + validators.add(new Validator() { + @Override + public boolean validate() { + return !text.getText().equals(IInternalDebugCoreConstants.EMPTY_STRING); + } + }); + + text.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validateFields(); + } + }); + } + + Button button = createButton(comp, IDialogConstants.IGNORE_ID, "&Browse...", false); + button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + DirectoryDialog dialog = new DirectoryDialog(getShell()); + dialog.setMessage("Select a file:"); + String currentWorkingDir = text.getText(); + if (!currentWorkingDir.trim().equals(IInternalDebugCoreConstants.EMPTY_STRING)) { + File path = new File(currentWorkingDir); + if (path.exists()) { + dialog.setFilterPath(currentWorkingDir); + } + } + + String selectedDirectory = dialog.open(); + if (selectedDirectory != null) { + text.setText(selectedDirectory); + } + } + }); + + controlList.add(text); + + } + + + public void createVariablesField(String labelText, String initialValue, boolean allowEmpty) { + Label label = new Label(panel, SWT.NONE); + label.setText(labelText); + label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + + Composite comp = new Composite(panel, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight=0; + layout.marginWidth=0; + comp.setLayout(layout); + comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + final Text text = new Text(comp, SWT.SINGLE | SWT.BORDER); + GridData data = new GridData(GridData.FILL_HORIZONTAL); + data.widthHint = 200; + text.setLayoutData(data); + text.setData(FIELD_NAME, labelText); + + // make sure rows are the same height on both panels. + label.setSize(label.getSize().x, text.getSize().y); + + if (initialValue != null) { + text.setText(initialValue); + } + + if (!allowEmpty) { + validators.add(new Validator() { + @Override + public boolean validate() { + return !text.getText().equals(IInternalDebugCoreConstants.EMPTY_STRING); + } + }); + + text.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validateFields(); + } + }); + } + + Button button = createButton(comp, IDialogConstants.IGNORE_ID, "Varia&bles...", false); + button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + StringVariableSelectionDialog dialog = new StringVariableSelectionDialog(getShell()); + int code = dialog.open(); + if (code == IDialogConstants.OK_ID) { + String variable = dialog.getVariableExpression(); + if (variable != null) { + text.insert(variable); + } + } + } + }); + + controlList.add(text); + + } + + public void createMultilineVariablesField(String labelText, String initialValue, boolean allowEmpty) { + Label label = new Label(panel, SWT.NONE); + label.setText(labelText); + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); + gd.horizontalSpan = 2; + label.setLayoutData(gd); + + final Text text = new Text(panel, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL); + gd = new GridData(GridData.FILL_BOTH); + gd.widthHint = 300; + gd.heightHint = 4 * text.getLineHeight(); + gd.horizontalSpan = 2; + text.setLayoutData(gd); + text.setData(FIELD_NAME, labelText); + + text.addTraverseListener(new TraverseListener () { + @Override + public void keyTraversed(TraverseEvent e) { + if(e.detail == SWT.TRAVERSE_RETURN && e.stateMask == SWT.SHIFT) { + e.doit = true; + } + } + }); + + // make sure rows are the same height on both panels. + label.setSize(label.getSize().x, text.getSize().y); + + if (initialValue != null) { + text.setText(initialValue); + } + + if (!allowEmpty) { + validators.add(new Validator() { + @Override + public boolean validate() { + return !text.getText().equals(IInternalDebugCoreConstants.EMPTY_STRING); + } + }); + + text.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validateFields(); + } + }); + } + Composite comp = SWTFactory.createComposite(panel, panel.getFont(), 1, 2, GridData.HORIZONTAL_ALIGN_END); + GridLayout ld = (GridLayout)comp.getLayout(); + ld.marginHeight = 1; + ld.marginWidth = 0; + ld.horizontalSpacing = 0; + Button button = createButton(comp, IDialogConstants.IGNORE_ID, "Varia&bles...", false); + + button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + StringVariableSelectionDialog dialog = new StringVariableSelectionDialog(getShell()); + int code = dialog.open(); + if (code == IDialogConstants.OK_ID) { + String variable = dialog.getVariableExpression(); + if (variable != null) { + text.insert(variable); + } + } + } + }); + + controlList.add(text); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#okPressed() + */ + @Override + protected void okPressed() { + for (Text control : controlList) { + valueMap.put(control.getData(FIELD_NAME), control.getText()); + } + controlList = null; + super.okPressed(); + } + + + /* (non-Javadoc) + * @see org.eclipse.jface.window.Window#open() + */ + @Override + public int open() { + applyDialogFont(panel); + return super.open(); + } + + public Object getValue(String key) { + return valueMap.get(key); + } + + public String getStringValue(String key) { + return (String) getValue(key); + } + + public void validateFields() { + for (Validator validator : validators) { + if (!validator.validate()) { + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + } + } + getButton(IDialogConstants.OK_ID).setEnabled(true); + } + + protected class FieldSummary { + int type; + String name; + String initialValue; + boolean allowsEmpty; + + public FieldSummary(int type, String name, String initialValue, boolean allowsEmpty) { + this.type = type; + this.name = name; + this.initialValue = initialValue; + this.allowsEmpty = allowsEmpty; + } + } + + protected class Validator { + boolean validate() { + return true; + } + } +} diff --git a/plugin_ide.ui/src-lang/_org/eclipse/debug/internal/ui/SWTFactory.java b/plugin_ide.ui/src-lang/_org/eclipse/debug/internal/ui/SWTFactory.java new file mode 100644 index 000000000..239633d8f --- /dev/null +++ b/plugin_ide.ui/src-lang/_org/eclipse/debug/internal/ui/SWTFactory.java @@ -0,0 +1,590 @@ +/******************************************************************************* + * Copyright (c) 2000, 2012 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package _org.eclipse.debug.internal.ui; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.layout.PixelConverter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.custom.ViewForm; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Layout; +import org.eclipse.swt.widgets.Text; + +public class SWTFactory { + + /** + * Returns a width hint for a button control. + */ + public static int getButtonWidthHint(Button button) { + /*button.setFont(JFaceResources.getDialogFont());*/ + PixelConverter converter= new PixelConverter(button); + int widthHint= converter.convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); + return Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x); + } + + /** + * Sets width and height hint for the button control. + * Note: This is a NOP if the button's layout data is not + * an instance of GridData. + * + * @param the button for which to set the dimension hint + */ + public static void setButtonDimensionHint(Button button) { + Assert.isNotNull(button); + Object gd= button.getLayoutData(); + if (gd instanceof GridData) { + ((GridData)gd).widthHint= getButtonWidthHint(button); + ((GridData)gd).horizontalAlignment = GridData.FILL; + } + } + + /** + * Creates a check box button using the parents' font + * @param parent the parent to add the button to + * @param label the label for the button + * @param image the image for the button + * @param checked the initial checked state of the button + * @param hspan the horizontal span to take up in the parent composite + * @return a new checked button set to the initial checked state + * @since 3.3 + */ + public static Button createCheckButton(Composite parent, String label, Image image, boolean checked, int hspan) { + Button button = new Button(parent, SWT.CHECK); + button.setFont(parent.getFont()); + button.setSelection(checked); + if(image != null) { + button.setImage(image); + } + if(label != null) { + button.setText(label); + } + GridData gd = new GridData(); + gd.horizontalSpan = hspan; + button.setLayoutData(gd); + setButtonDimensionHint(button); + return button; + } + + /** + * Creates and returns a new push button with the given + * label and/or image. + * + * @param parent parent control + * @param label button label or null + * @param image image of null + * + * @return a new push button + */ + public static Button createPushButton(Composite parent, String label, Image image) { + Button button = new Button(parent, SWT.PUSH); + button.setFont(parent.getFont()); + if (image != null) { + button.setImage(image); + } + if (label != null) { + button.setText(label); + } + GridData gd = new GridData(); + button.setLayoutData(gd); + setButtonDimensionHint(button); + return button; + } + + /** + * Creates and returns a new push button with the given + * label and/or image. + * + * @param parent parent control + * @param label button label or null + * @param image image of null + * @param fill the alignment for the new button + * + * @return a new push button + * @since 3.4 + */ + public static Button createPushButton(Composite parent, String label, Image image, int fill) { + Button button = new Button(parent, SWT.PUSH); + button.setFont(parent.getFont()); + if (image != null) { + button.setImage(image); + } + if (label != null) { + button.setText(label); + } + GridData gd = new GridData(fill); + button.setLayoutData(gd); + setButtonDimensionHint(button); + return button; + } + + /** + * Creates and returns a new push button with the given + * label, tooltip and/or image. + * + * @param parent parent control + * @param label button label or null + * @param tooltip the tooltip text for the button or null + * @param image image of null + * + * @return a new push button + * @since 3.6 + */ + public static Button createPushButton(Composite parent, String label, String tooltip, Image image) { + Button button = createPushButton(parent, label, image); + button.setToolTipText(tooltip); + return button; + } + + /** + * Creates and returns a new radio button with the given + * label. + * + * @param parent parent control + * @param label button label or null + * + * @return a new radio button + */ + public static Button createRadioButton(Composite parent, String label) { + Button button = new Button(parent, SWT.RADIO); + button.setFont(parent.getFont()); + if (label != null) { + button.setText(label); + } + GridData gd = new GridData(); + button.setLayoutData(gd); + setButtonDimensionHint(button); + return button; + } + + /** + * Creates and returns a new radio button with the given + * label. + * + * @param parent parent control + * @param label button label or null + * @param hspan the number of columns to span in the parent composite + * + * @return a new radio button + * @since 3.6 + */ + public static Button createRadioButton(Composite parent, String label, int hspan) { + Button button = new Button(parent, SWT.RADIO); + button.setFont(parent.getFont()); + if (label != null) { + button.setText(label); + } + GridData gd = new GridData(GridData.BEGINNING); + gd.horizontalSpan = hspan; + button.setLayoutData(gd); + setButtonDimensionHint(button); + return button; + } + + /** + * Creates a new label widget + * @param parent the parent composite to add this label widget to + * @param text the text for the label + * @param hspan the horizontal span to take up in the parent composite + * @return the new label + * @since 3.2 + * + */ + public static Label createLabel(Composite parent, String text, int hspan) { + Label l = new Label(parent, SWT.NONE); + l.setFont(parent.getFont()); + l.setText(text); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = hspan; + gd.grabExcessHorizontalSpace = false; + l.setLayoutData(gd); + return l; + } + + /** + * Creates a new label widget + * @param parent the parent composite to add this label widget to + * @param text the text for the label + * @param font the font for the label + * @param hspan the horizontal span to take up in the parent composite + * @return the new label + * @since 3.3 + */ + public static Label createLabel(Composite parent, String text, Font font, int hspan) { + Label l = new Label(parent, SWT.NONE); + l.setFont(font); + l.setText(text); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = hspan; + l.setLayoutData(gd); + return l; + } + + /** + * Creates a wrapping label + * @param parent the parent composite to add this label to + * @param text the text to be displayed in the label + * @param hspan the horizontal span that label should take up in the parent composite + * @param wrapwidth the width hint that the label should wrap at + * @return a new label that wraps at a specified width + * @since 3.3 + */ + public static Label createWrapLabel(Composite parent, String text, int hspan, int wrapwidth) { + Label l = new Label(parent, SWT.NONE | SWT.WRAP); + l.setFont(parent.getFont()); + l.setText(text); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = hspan; + gd.widthHint = wrapwidth; + l.setLayoutData(gd); + return l; + } + + /** + * Creates a new CLabel that will wrap at the specified width and has the specified image + * @param parent the parent to add this label to + * @param text the text for the label + * @param image the image for the label + * @param hspan the h span to take up in the parent + * @param wrapwidth the with to wrap at + * @return a new CLabel + * @since 3.3 + */ + public static CLabel createWrapCLabel(Composite parent, String text, Image image, int hspan, int wrapwidth) { + CLabel label = new CLabel(parent, SWT.NONE | SWT.WRAP); + label.setFont(parent.getFont()); + if(text != null) { + label.setText(text); + } + if(image != null) { + label.setImage(image); + } + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = hspan; + gd.widthHint = wrapwidth; + label.setLayoutData(gd); + return label; + } + + /** + * Creates a wrapping label + * @param parent the parent composite to add this label to + * @param text the text to be displayed in the label + * @param hspan the horizontal span that label should take up in the parent composite + * @return a new label that wraps at a specified width + * @since 3.3 + */ + public static Label createWrapLabel(Composite parent, String text, int hspan) { + Label l = new Label(parent, SWT.NONE | SWT.WRAP); + l.setFont(parent.getFont()); + l.setText(text); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = hspan; + l.setLayoutData(gd); + return l; + } + + /** + * Creates a new text widget + * @param parent the parent composite to add this text widget to + * @param hspan the horizontal span to take up on the parent composite + * @return the new text widget + * @since 3.2 + * + */ + public static Text createSingleText(Composite parent, int hspan) { + Text t = new Text(parent, SWT.SINGLE | SWT.BORDER); + t.setFont(parent.getFont()); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = hspan; + t.setLayoutData(gd); + return t; + } + + /** + * Creates a new text widget + * @param parent the parent composite to add this text widget to + * @param style the style bits for the text widget + * @param hspan the horizontal span to take up on the parent composite + * @param fill the fill for the grid layout + * @return the new text widget + * @since 3.3 + */ + public static Text createText(Composite parent, int style, int hspan, int fill) { + Text t = new Text(parent, style); + t.setFont(parent.getFont()); + GridData gd = new GridData(fill); + gd.horizontalSpan = hspan; + t.setLayoutData(gd); + return t; + } + + /** + * Creates a new text widget + * @param parent the parent composite to add this text widget to + * @param style the style bits for the text widget + * @param hspan the horizontal span to take up on the parent composite + * @return the new text widget + * @since 3.3 + */ + public static Text createText(Composite parent, int style, int hspan) { + Text t = new Text(parent, style); + t.setFont(parent.getFont()); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = hspan; + t.setLayoutData(gd); + return t; + } + + /** + * Creates a new text widget + * @param parent the parent composite to add this text widget to + * @param style the style bits for the text widget + * @param hspan the horizontal span to take up on the parent composite + * @param width the desired width of the text widget + * @param height the desired height of the text widget + * @param fill the fill style for the widget + * @return the new text widget + * @since 3.3 + */ + public static Text createText(Composite parent, int style, int hspan, int width, int height, int fill) { + Text t = new Text(parent, style); + t.setFont(parent.getFont()); + GridData gd = new GridData(fill); + gd.horizontalSpan = hspan; + gd.widthHint = width; + gd.heightHint = height; + t.setLayoutData(gd); + return t; + } + + /** + * Creates a new styled text widget + * @param parent the parent composite to add this styled text widget to + * @param style the style bits for the styled text widget + * @param hspan the horizontal span to take up on the parent composite + * @param width the desired width of the styled text widget + * @param height the desired height of the styled text widget + * @param fill the fill style for the widget + * @return the new styled text widget + * @since 3.9 + */ + public static StyledText createStyledText(Composite parent, int style, int hspan, int width, int height, int fill) { + StyledText t = new StyledText(parent, style); + t.setFont(parent.getFont()); + GridData gd = new GridData(fill); + gd.horizontalSpan = hspan; + gd.widthHint = width; + gd.heightHint = height; + t.setLayoutData(gd); + return t; + } + + /** + * Creates a new text widget + * @param parent the parent composite to add this text widget to + * @param style the style bits for the text widget + * @param hspan the horizontal span to take up on the parent composite + * @param text the initial text, not null + * @return the new text widget + * @since 3.6 + */ + public static Text createText(Composite parent, int style, int hspan, String text) { + Text t = new Text(parent, style); + t.setFont(parent.getFont()); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = hspan; + t.setLayoutData(gd); + t.setText(text); + return t; + } + + /** + * Creates a Group widget + * @param parent the parent composite to add this group to + * @param text the text for the heading of the group + * @param columns the number of columns within the group + * @param hspan the horizontal span the group should take up on the parent + * @param fill the style for how this composite should fill into its parent + * @return the new group + * @since 3.2 + * + */ + public static Group createGroup(Composite parent, String text, int columns, int hspan, int fill) { + Group g = new Group(parent, SWT.NONE); + g.setLayout(new GridLayout(columns, false)); + g.setText(text); + g.setFont(parent.getFont()); + GridData gd = new GridData(fill); + gd.horizontalSpan = hspan; + g.setLayoutData(gd); + return g; + } + + /** + * Creates a Composite widget + * @param parent the parent composite to add this composite to + * @param font the font to set on the control + * @param columns the number of columns within the composite + * @param hspan the horizontal span the composite should take up on the parent + * @param fill the style for how this composite should fill into its parent + * @return the new group + * @since 3.3 + */ + public static Composite createComposite(Composite parent, Font font, int columns, int hspan, int fill) { + Composite g = new Composite(parent, SWT.NONE); + g.setLayout(new GridLayout(columns, false)); + g.setFont(font); + GridData gd = new GridData(fill); + gd.horizontalSpan = hspan; + g.setLayoutData(gd); + return g; + } + + /** + * Creates a composite that uses the parent's font and has a grid layout + * @param parent the parent to add the composite to + * @param columns the number of columns the composite should have + * @param hspan the horizontal span the new composite should take up in the parent + * @param fill the fill style of the composite {@link GridData} + * @return a new composite with a grid layout + * + * @since 3.3 + */ + public static Composite createComposite(Composite parent, int columns, int hspan, int fill) { + Composite g = new Composite(parent, SWT.NONE); + g.setLayout(new GridLayout(columns, false)); + g.setFont(parent.getFont()); + GridData gd = new GridData(fill); + gd.horizontalSpan = hspan; + g.setLayoutData(gd); + return g; + } + + /** + * Creates a vertical spacer for separating components. If applied to a + * GridLayout, this method will automatically span all of the columns of the parent + * to make vertical space + * + * @param parent the parent composite to add this spacer to + * @param numlines the number of vertical lines to make as space + * @since 3.3 + */ + public static void createVerticalSpacer(Composite parent, int numlines) { + Label lbl = new Label(parent, SWT.NONE); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + Layout layout = parent.getLayout(); + if(layout instanceof GridLayout) { + gd.horizontalSpan = ((GridLayout)parent.getLayout()).numColumns; + } + gd.heightHint = numlines; + lbl.setLayoutData(gd); + } + + /** + * creates a horizontal spacer for separating components + * @param comp + * @param numlines + * @since 3.3 + */ + public static void createHorizontalSpacer(Composite comp, int numlines) { + Label lbl = new Label(comp, SWT.NONE); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = numlines; + lbl.setLayoutData(gd); + } + + /** + * Creates a Composite widget + * @param parent the parent composite to add this composite to + * @param font the font to set on the control + * @param columns the number of columns within the composite + * @param hspan the horizontal span the composite should take up on the parent + * @param fill the style for how this composite should fill into its parent + * @param marginwidth the width of the margin to place on the sides of the composite (default is 5, specified by GridLayout) + * @param marginheight the height of the margin to place o the top and bottom of the composite + * @return the new composite + * @since 3.3 + */ + public static Composite createComposite(Composite parent, Font font, int columns, int hspan, int fill, int marginwidth, int marginheight) { + Composite g = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(columns, false); + layout.marginWidth = marginwidth; + layout.marginHeight = marginheight; + g.setLayout(layout); + g.setFont(font); + GridData gd = new GridData(fill); + gd.horizontalSpan = hspan; + g.setLayoutData(gd); + return g; + } + + /** + * Creates a {@link ViewForm} + * @param parent + * @param style + * @param cols + * @param span + * @param fill + * @param marginwidth + * @param marginheight + * @return a new {@link ViewForm} + * @since 3.6 + */ + public static ViewForm createViewform(Composite parent, int style, int cols, int span, int fill, int marginwidth, int marginheight) { + ViewForm form = new ViewForm(parent, style); + form.setFont(parent.getFont()); + GridLayout layout = new GridLayout(cols, false); + layout.marginWidth = marginwidth; + layout.marginHeight = marginheight; + form.setLayout(layout); + GridData gd = new GridData(fill); + gd.horizontalSpan = span; + form.setLayoutData(gd); + return form; + } + + /** + * Creates a Composite widget + * @param parent the parent composite to add this composite to + * @param font the font to set on the control + * @param style the style bits for the composite. See {@link Composite} for details on supported style bits + * @param columns the number of columns within the composite + * @param hspan the horizontal span the composite should take up on the parent + * @param fill the style for how this composite should fill into its parent + * @param marginwidth the width of the margin to place on the sides of the composite (default is 5, specified by GridLayout) + * @param marginheight the height of the margin to place o the top and bottom of the composite + * @return the new composite + * @since 3.6 + */ + public static Composite createComposite(Composite parent, Font font, int style, int columns, int hspan, int fill, int marginwidth, int marginheight) { + Composite g = new Composite(parent, style); + GridLayout layout = new GridLayout(columns, false); + layout.marginWidth = marginwidth; + layout.marginHeight = marginheight; + g.setLayout(layout); + g.setFont(font); + GridData gd = new GridData(fill); + gd.horizontalSpan = hspan; + g.setLayoutData(gd); + return g; + } + +} diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/LangImages.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/LangImages.java index 5beeeb374..466dc1573 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/LangImages.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/LangImages.java @@ -54,6 +54,7 @@ protected static ImageDescriptor createUnmanaged(String prefix, String name) { /* ---------------- Common Lang images ---------------- */ + public static final String ICONS = "icons-lang/"; public static final String LANG_ACTIONS = "icons-lang/actions/"; public static final String LANG_OVERLAYS = "icons-lang/overlays/"; public static final String LANG_NAVIGATOR = "icons-lang/navigator/"; @@ -77,6 +78,9 @@ protected static ImageDescriptor createUnmanaged(String prefix, String name) { public static final ImageHandle IMG_CLEAR_CONSOLE = createManaged(LANG_ACTIONS, "clear_co.png"); public static final ImageHandle IMG_PIN_CONSOLE = createManaged(LANG_ACTIONS, "pin.png"); + public static final ImageHandle IMG_ENV_VAR = createManaged(ICONS, "envvar_obj.png"); + public static final ImageHandle IMG_ENVIRONMENT = createManaged(ICONS, "environment_obj.png"); + /* ----------------- overlay decorations ----------------- */ @@ -126,8 +130,8 @@ protected static ImageDescriptor createUnmanaged(String prefix, String name) { /* ----------------- Debug ----------------- */ - public static final ImageDescriptor BREAKPOINT_ENABLED = createUnmanaged("icons-lang", "brkp_obj.png"); - public static final ImageDescriptor BREAKPOINT_DISABLED = createUnmanaged("icons-lang", "brkpd_obj.png"); + public static final ImageDescriptor BREAKPOINT_ENABLED = createUnmanaged(ICONS, "brkp_obj.png"); + public static final ImageDescriptor BREAKPOINT_DISABLED = createUnmanaged(ICONS, "brkpd_obj.png"); /* ----------------- Image cache keyed by ImageDescriptor ----------------- */ diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/BuildTargetEditor.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/BuildTargetEditor.java similarity index 95% rename from plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/BuildTargetEditor.java rename to plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/BuildTargetEditor.java index 45eaad61d..ca88e218c 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/BuildTargetEditor.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/BuildTargetEditor.java @@ -8,7 +8,7 @@ * Contributors: * Bruno Medeiros - initial API and implementation *******************************************************************************/ -package melnorme.lang.ide.ui.preferences; +package melnorme.lang.ide.ui.build; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; @@ -65,7 +65,7 @@ public BuildTargetEditor( } buildCommandField = addChildWidget(init_createArgumentsField()); - buildCommandField.getField().addChangeListener(() -> { + buildCommandField.addEffectiveValueChangeListener(() -> { btData.buildCommand = getEffectiveBuildCommand(); }); diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/CommandInvocationEditor.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/CommandInvocationEditor.java similarity index 84% rename from plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/CommandInvocationEditor.java rename to plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/CommandInvocationEditor.java index eb12839ad..ac76d82a7 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/CommandInvocationEditor.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/CommandInvocationEditor.java @@ -8,10 +8,9 @@ * Contributors: * Bruno Medeiros - initial API and implementation *******************************************************************************/ -package melnorme.lang.ide.ui.preferences; +package melnorme.lang.ide.ui.build; import org.eclipse.debug.ui.StringVariableSelectionDialog; -import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; @@ -19,8 +18,10 @@ import melnorme.lang.ide.core.operations.build.CommandInvocation; import melnorme.lang.ide.core.operations.build.VariablesResolver; +import melnorme.lang.ide.ui.fields.FieldDialog; import melnorme.lang.ide.ui.utils.ControlUtils; import melnorme.lang.tooling.data.StatusException; +import melnorme.lang.tooling.ops.EnvironmentSettings; import melnorme.util.swt.components.ButtonWidget; import melnorme.util.swt.components.CompositeWidget; import melnorme.util.swt.components.fields.EnablementCompositeWidget; @@ -45,7 +46,7 @@ public CommandInvocationEditor(CommonGetter getDefaultCommand super("Command Invocation:", LABEL_UseDefault); this.createInlined = false; - this.commandInvocation = getField(); + this.commandInvocation = field(); this.getDefaultArguments = getDefaultCommandInvocation; this.variablesResolver = variablesResolver; @@ -131,7 +132,12 @@ protected void createContents_layout() { /* ----------------- ----------------- */ protected void validateArguments() throws StatusException { - getFieldValue().validate(variablesResolver); + CommandInvocation fieldValue = getFieldValue(); + if(fieldValue == null) { + return; + } + + fieldValue.validate(variablesResolver); } /* ----------------- button handlers ----------------- */ @@ -148,8 +154,22 @@ protected String newValueFromCommandVariablesDialog() throws OperationCancellati protected void handleEditEnvironmentVars() { Shell shell = getButtonTextField().getFieldControl().getShell(); - /* FIXME: todo EnvironmentVar*/ - MessageDialog.openInformation(shell, "TODO", "NOT Implement"); + + CommandInvocation cmd = getFieldValue(); + EnvironmentSettings envSettings = new EnvironmentSettings( + cmd.getEnvironmentVars().copyToHashMap(), cmd.isAppendEnvironment()); + + try { + envSettings = new FieldDialog<>(shell, new EnvironmentSettingsEditor()).openDialog(envSettings); + } catch(OperationCancellation e) { + return; + } + + setFieldValue(new CommandInvocation( + cmd.getCommandArguments(), + envSettings.envVars.copy(), + envSettings.appendEnv + )); } } \ No newline at end of file diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/EnvironmentSettingsEditor.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/EnvironmentSettingsEditor.java new file mode 100644 index 000000000..65330831b --- /dev/null +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/EnvironmentSettingsEditor.java @@ -0,0 +1,491 @@ +package melnorme.lang.ide.ui.build; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.ScrollBar; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +import _org.eclipse.debug.internal.ui.MultipleInputDialog; +import _org.eclipse.debug.internal.ui.SWTFactory; +import melnorme.lang.ide.ui.LangImages; +import melnorme.lang.tooling.ops.EnvironmentSettings; +import melnorme.util.swt.components.AbstractWidget; +import melnorme.util.swt.components.fields.FieldCompositeWidget; +import melnorme.util.swt.jface.AbstractContentProvider; + +class EnvironmentSettingsEditor_Base extends FieldCompositeWidget { + + protected Composite topControl; + + public EnvironmentSettingsEditor_Base(boolean createInlined) { + super(createInlined); + } + + @Override + protected void createContents(Composite topControl) { + this.topControl = topControl; + super.createContents(topControl); + } + + protected Shell getShell() { + return topControl.getShell(); + } + + @Override + protected void _verifyContract_IDisableableComponent() { +// super._verifyContract_IDisableableComponent(); + } + + protected class EnvironmentVariableContentProvider extends AbstractContentProvider { + @Override + public Object[] getElements(Object inputElement) { + return getFieldValue().envVars.map((entry) -> { + return new EnvironmentVariable(entry.getKey(), entry.getValue()); + }).toArray(); + } + } + +} + + + +/** + * Launch configuration tab for configuring the environment passed + * into Runtime.exec(...) when a config is launched. + *

+ * Clients may call {@link #setHelpContextId(String)} on this tab prior to control + * creation to alter the default context help associated with this tab. + *

+ *

+ * This class may be instantiated. + *

+ * @since 3.0 + * @noextend This class is not intended to be sub-classed by clients. + */ +public class EnvironmentSettingsEditor extends EnvironmentSettingsEditor_Base { + + protected static final String[] envTableColumnHeaders = { + "Variable", + "Value", + }; + private static final String NAME_LABEL= "&Name:"; + private static final String VALUE_LABEL= "&Value:"; + protected static final String P_VARIABLE = "variable"; //$NON-NLS-1$ + protected static final String P_VALUE = "value"; //$NON-NLS-1$ + + protected TableViewer environmentTable; + protected Button envAddButton; + protected Button envEditButton; + protected Button envRemoveButton; + protected Button appendEnvironment; + protected Button replaceEnvironment; + protected Button envSelectButton; + + /** + * Constructs a new tab with default context help. + */ + public EnvironmentSettingsEditor() { + super(false); + } + + { + layoutColumns = 2; + } + + @Override + protected void doSetEnabled(boolean enabled) { + super.doSetEnabled(enabled); + + if(environmentTable == null) { + return; + } + setControlEnabled(environmentTable.getTable(), enabled); + setControlEnabled(envAddButton, enabled); + setControlEnabled(envEditButton, enabled); + setControlEnabled(envRemoveButton, enabled); + setControlEnabled(appendEnvironment, enabled); + setControlEnabled(replaceEnvironment, enabled); + setControlEnabled(envSelectButton, enabled); + } + + @Override + protected void createContents(Composite topControl) { + super.createContents(topControl); + + createEnvironmentTable(topControl); + createTableButtons(topControl); + createAppendReplace(topControl); + + Dialog.applyDialogFont(topControl); + } + + /** + * Creates and configures the widgets which allow the user to + * choose whether the specified environment should be appended + * to the native environment or if it should completely replace it. + * @param parent the composite in which the widgets should be created + */ + protected void createAppendReplace(Composite parent) { + Composite comp = SWTFactory.createComposite(parent, 1, 2, GridData.FILL_HORIZONTAL); + appendEnvironment= SWTFactory.createRadioButton(comp, LaunchConfigurationsMessages.EnvironmentTab_16); + appendEnvironment.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + field().get().appendEnv = appendEnvironment.getSelection(); + notifyFieldChanged(); + } + }); + replaceEnvironment= SWTFactory.createRadioButton(comp, LaunchConfigurationsMessages.EnvironmentTab_17); + + field().addListener(true, (newValue) -> { + appendEnvironment.setSelection(newValue.appendEnv); + replaceEnvironment.setSelection(!newValue.appendEnv); + }); + } + + /** + * Creates and configures the table that displayed the key/value + * pairs that comprise the environment. + * @param parent the composite in which the table should be created + */ + protected void createEnvironmentTable(Composite parent) { + + Font font = parent.getFont(); + // Create label, add it to the parent to align the right side buttons with the top of the table + SWTFactory.createLabel(parent, LaunchConfigurationsMessages.EnvironmentTab_Environment_variables_to_set__3, 2); + // Create table composite + Composite tableComposite = SWTFactory.createComposite(parent, font, 1, 1, GridData.FILL_BOTH, 0, 0); + // Create table + environmentTable = new TableViewer(tableComposite, + SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION); + Table table = environmentTable.getTable(); + table.setLayout(new GridLayout()); + table.setLayoutData(AbstractWidget.gdGrabAll(400, 200)); + table.setHeaderVisible(true); + table.setLinesVisible(true); + table.setFont(font); + environmentTable.setContentProvider(new EnvironmentVariableContentProvider()); + environmentTable.setLabelProvider(new EnvironmentVariableLabelProvider()); + environmentTable.setColumnProperties(new String[] {P_VARIABLE, P_VALUE}); + environmentTable.setComparator(new ViewerComparator() { + @Override + public int compare(Viewer iviewer, Object e1, Object e2) { + if (e1 == null) { + return -1; + } else if (e2 == null) { + return 1; + } else { + return ((EnvironmentVariable)e1).getName().compareToIgnoreCase(((EnvironmentVariable)e2).getName()); + } + } + }); + + environmentTable.addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + handleTableSelectionChanged(event); + } + }); + environmentTable.addDoubleClickListener(new IDoubleClickListener() { + @Override + public void doubleClick(DoubleClickEvent event) { + if (!environmentTable.getSelection().isEmpty()) { + handleEnvEditButtonSelected(); + } + } + }); + // Create columns + final TableColumn tc1 = new TableColumn(table, SWT.NONE, 0); + tc1.setText(envTableColumnHeaders[0]); + final TableColumn tc2 = new TableColumn(table, SWT.NONE, 1); + tc2.setText(envTableColumnHeaders[1]); + final Table tref = table; + final Composite comp = tableComposite; + tableComposite.addControlListener(new ControlAdapter() { + @Override + public void controlResized(ControlEvent e) { + Rectangle area = comp.getClientArea(); + Point size = tref.computeSize(SWT.DEFAULT, SWT.DEFAULT); + ScrollBar vBar = tref.getVerticalBar(); + int width = area.width - tref.computeTrim(0,0,0,0).width - 2; + if (size.y > area.height + tref.getHeaderHeight()) { + Point vBarSize = vBar.getSize(); + width -= vBarSize.x; + } + Point oldSize = tref.getSize(); + if (oldSize.x > area.width) { + tc1.setWidth(width/2-1); + tc2.setWidth(width - tc1.getWidth()); + tref.setSize(area.width, area.height); + } else { + tref.setSize(area.width, area.height); + tc1.setWidth(width/2-1); + tc2.setWidth(width - tc1.getWidth()); + } + } + }); + + field().addListener(true, (newValue) -> { + environmentTable.setInput(field().get()); + environmentTable.refresh(); + }); + } + + /** + * Label provider for the environment table + */ + public class EnvironmentVariableLabelProvider extends LabelProvider implements ITableLabelProvider { + @Override + public String getColumnText(Object element, int columnIndex) { + String result = null; + if (element != null) { + EnvironmentVariable var = (EnvironmentVariable) element; + switch (columnIndex) { + case 0: // variable + result = var.getName(); + break; + case 1: // value + result = var.getValue(); + break; + default: + break; + } + } + return result; + } + @Override + public Image getColumnImage(Object element, int columnIndex) { + if (columnIndex == 0) { + return LangImages.IMG_ENV_VAR.getImage(); + } + return null; + } + } + + /** + * Responds to a selection changed event in the environment table + * @param event the selection change event + */ + protected void handleTableSelectionChanged(SelectionChangedEvent event) { + int size = ((IStructuredSelection)event.getSelection()).size(); + envEditButton.setEnabled(size == 1); + envRemoveButton.setEnabled(size > 0); + } + + /** + * Creates the add/edit/remove buttons for the environment table + * @param parent the composite in which the buttons should be created + */ + protected void createTableButtons(Composite parent) { + // Create button composite + Composite buttonComposite = SWTFactory.createComposite(parent, parent.getFont(), 1, 1, GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_END, 0, 0); + + // Create buttons + envAddButton = SWTFactory.createPushButton(buttonComposite, LaunchConfigurationsMessages.EnvironmentTab_New_4, null); + envAddButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + handleEnvAddButtonSelected(); + } + }); + envSelectButton = SWTFactory.createPushButton(buttonComposite, LaunchConfigurationsMessages.EnvironmentTab_18, null); + envSelectButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + handleEnvSelectButtonSelected(); + } + }); + envEditButton = SWTFactory.createPushButton(buttonComposite, LaunchConfigurationsMessages.EnvironmentTab_Edit_5, null); + envEditButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + handleEnvEditButtonSelected(); + } + }); + envEditButton.setEnabled(false); + envRemoveButton = SWTFactory.createPushButton(buttonComposite, LaunchConfigurationsMessages.EnvironmentTab_Remove_6, null); + envRemoveButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + handleEnvRemoveButtonSelected(); + } + }); + envRemoveButton.setEnabled(false); + } + + /** + * Adds a new environment variable to the table. + */ + protected void handleEnvAddButtonSelected() { + MultipleInputDialog dialog = new MultipleInputDialog(getShell(), LaunchConfigurationsMessages.EnvironmentTab_22); + dialog.addTextField(NAME_LABEL, null, false); + dialog.addVariablesField(VALUE_LABEL, null, true); + + if (dialog.open() != Window.OK) { + return; + } + + String name = dialog.getStringValue(NAME_LABEL); + String value = dialog.getStringValue(VALUE_LABEL); + + if (name != null && value != null && name.length() > 0 && value.length() >0) { + addVariable(new EnvironmentVariable(name.trim(), value.trim())); + } + } + + /** + * Attempts to add the given variable. Returns whether the variable + * was added or not (as when the user answers not to overwrite an + * existing variable). + * @param variable the variable to add + * @return whether the variable was added + */ + protected boolean addVariable(EnvironmentVariable variable) { + String name= variable.getName(); + + if (getFieldValue().envVars.containsKey(name)) { + boolean overWrite = MessageDialog.openQuestion(getShell(), LaunchConfigurationsMessages.EnvironmentTab_12, MessageFormat.format(LaunchConfigurationsMessages.EnvironmentTab_13, new Object[] { name })); // + if (!overWrite) { + return false; + } + getFieldValue().envVars.remove(name); + } + + getFieldValue().envVars.put(name, variable.getValue()); + notifyFieldChanged(); + return true; + } + + /** + * Displays a dialog that allows user to select native environment variables + * to add to the table. + */ + private void handleEnvSelectButtonSelected() { + //get Environment Variables from the OS + Map envVariables = getNativeEnvironment(); + + //get Environment Variables from the table + for (String varName : getFieldValue().envVars.keySet()) { + envVariables.remove(varName); + } + + NativeEnvironmentSelectionDialog dialog = new NativeEnvironmentSelectionDialog(getShell(), envVariables); + dialog.setTitle(LaunchConfigurationsMessages.EnvironmentTab_20); + + int button = dialog.open(); + if (button == Window.OK) { + Object[] selected = dialog.getResult(); + for (int i = 0; i < selected.length; i++) { + EnvironmentVariable envVar = (EnvironmentVariable) selected[i]; + getFieldValue().envVars.put(envVar.getName(), envVar.getValue()); + } + } + + notifyFieldChanged(); + } + + /** + * Gets native environment variable from the LaunchManager. Creates EnvironmentVariable objects. + * @return Map of name - EnvironmentVariable pairs based on native environment. + */ + protected Map getNativeEnvironment() { + Map stringVars = DebugPlugin.getDefault().getLaunchManager().getNativeEnvironmentCasePreserved(); + HashMap vars = new HashMap(); + for (Entry entry : stringVars.entrySet()) { + vars.put(entry.getKey(), new EnvironmentVariable(entry.getKey(), entry.getValue())); + } + return vars; + } + + /** + * Creates an editor for the value of the selected environment variable. + */ + private void handleEnvEditButtonSelected() { + IStructuredSelection sel= (IStructuredSelection) environmentTable.getSelection(); + EnvironmentVariable originalVar= (EnvironmentVariable) sel.getFirstElement(); + if (originalVar == null) { + return; + } + String originalName= originalVar.getName(); + String value= originalVar.getValue(); + MultipleInputDialog dialog= new MultipleInputDialog(getShell(), LaunchConfigurationsMessages.EnvironmentTab_11); + dialog.addTextField(NAME_LABEL, originalName, false); + if(value != null && value.indexOf(System.getProperty("line.separator")) > -1) { //$NON-NLS-1$ + dialog.addMultilinedVariablesField(VALUE_LABEL, value, true); + } + else { + dialog.addVariablesField(VALUE_LABEL, value, true); + } + + if (dialog.open() != Window.OK) { + return; + } + String name= dialog.getStringValue(NAME_LABEL); + value= dialog.getStringValue(VALUE_LABEL); + if (!originalName.equals(name)) { + if (addVariable(new EnvironmentVariable(name, value))) { + getFieldValue().envVars.remove(originalVar.getName()); + notifyFieldChanged(); + } + } else { + getFieldValue().envVars.put(name, value); + notifyFieldChanged(); + } + } + + /** + * Removes the selected environment variable from the table. + */ + private void handleEnvRemoveButtonSelected() { + IStructuredSelection sel = (IStructuredSelection) environmentTable.getSelection(); + try { +// environmentTable.getControl().setRedraw(false); + for (Iterator i = sel.iterator(); i.hasNext();) { + EnvironmentVariable var = (EnvironmentVariable) i.next(); + getFieldValue().envVars.remove(var.getName()); +// environmentTable.remove(var); + } + } finally { +// environmentTable.getControl().setRedraw(true); + } + notifyFieldChanged(); + } + + protected void notifyFieldChanged() { + field().fireFieldValueChanged(); + } + +} diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/EnvironmentVariable.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/EnvironmentVariable.java new file mode 100644 index 000000000..316b22adb --- /dev/null +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/EnvironmentVariable.java @@ -0,0 +1,70 @@ +package melnorme.lang.ide.ui.build; + +/** + * A key/value set whose data is passed into Runtime.exec(...) + */ +public class EnvironmentVariable +{ + // The name of the environment variable + private String name; + + // The value of the environment variable + private String value; + + public EnvironmentVariable(String name, String value) + { + this.name = name; + this.value = value; + } + + /** + * Returns this variable's name, which serves as the key in the key/value + * pair this variable represents + * + * @return this variable's name + */ + public String getName() + { + return name; + } + + /** + * Returns this variables value. + * + * @return this variable's value + */ + public String getValue() + { + return value; + } + +// /** +// * Sets this variable's value +// * @param value +// */ +// public void setValue(String value) +// { +// this.value = value; +// } + + @Override + public String toString() { + return getName(); + } + + + @Override + public boolean equals(Object obj) { + boolean equal = false; + if (obj instanceof EnvironmentVariable) { + EnvironmentVariable var = (EnvironmentVariable)obj; + equal = var.getName().equals(name); + } + return equal; + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/LaunchConfigurationsMessages.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/LaunchConfigurationsMessages.java new file mode 100644 index 000000000..e5741947b --- /dev/null +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/LaunchConfigurationsMessages.java @@ -0,0 +1,217 @@ +package melnorme.lang.ide.ui.build; + +import org.eclipse.osgi.util.NLS; + +public class LaunchConfigurationsMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsMessages";//$NON-NLS-1$ + + public static String CommonTab__Browse_6; + public static String CommonTab__Common_15; + public static String CommonTab_Display_in_favorites_menu__10; + public static String CommonTab_Invalid_shared_configuration_location_14; + public static String CommonTab_Invalid_stdin_file_location_15; + public static String CommonTab_L_ocal_3; + public static String CommonTab_S_hared_4; + public static String CommonTab_Select_a_location_for_the_launch_configuration_13; + public static String CommonTab_Select_a_location_for_the_Input_File_15; + public static String CommonTab_Cannot_save_launch_configuration_in_a_closed_project__1; + public static String CommonTab_10; + public static String CommonTab_11; + public static String CommonTab_12; + public static String CommonTab_13; + public static String CommonTab_14; + public static String CommonTab_0; + public static String CommonTab_1; + + public static String CommonTab_15; + public static String CommonTab_16; + public static String CommonTab_17; + public static String CommonTab_18; + public static String CommonTab_19; + public static String CommonTab_2; + public static String CommonTab_20; + public static String CommonTab_3; + public static String CommonTab_4; + public static String CommonTab_5; + public static String CommonTab_6; + public static String CommonTab_7; + public static String CommonTab_8; + public static String CommonTab_9; + + public static String CompileErrorProjectPromptStatusHandler_0; + public static String CompileErrorProjectPromptStatusHandler_1; + public static String CompileErrorPromptStatusHandler_0; + public static String CompileErrorPromptStatusHandler_1; + public static String CompileErrorPromptStatusHandler_2; + public static String EnvironmentTab_22; + + public static String EnvironmentTab_7; + + public static String LaunchConfigurationDialog__Apply_17; + public static String LaunchConfigurationDialog__Name__16; + public static String LaunchConfigurationDialog_An_exception_occurred_while_retrieving_launch_configurations_20; + public static String LaunchConfigurationEditDialog_0; + public static String LaunchConfigurationEditDialog_1; + public static String LaunchConfigurationFilteredTree_discard_changes; + public static String LaunchConfigurationFilteredTree_save_changes; + + public static String LaunchConfigurationFilteredTree_search_with_changes; + public static String LaunchConfigurationFilteredTree_search_with_errors; + public static String LaunchConfigurationDialog_Create__manage__and_run_launch_configurations_8; + public static String LaunchConfigurationDialog_Discard_changes__38; + public static String LaunchConfigurationDialog_Do_you_wish_to_discard_changes_37; + public static String LaunchConfigurationDialog_Error_19; + public static String LaunchConfigurationDialog_Exception_occurred_creating_launch_configuration_tabs_27; + public static String LaunchConfigurationDialog_Exception_occurred_while_saving_launch_configuration_47; + public static String LaunchConfigurationDialog_Launch_configuration_already_exists_with_this_name_12; + public static String LaunchConfigurationDialog_Launch_Configuration_Error_46; + public static String LaunchConfigurationDialog_Launch_Configurations_18; + public static String LaunchConfigurationDialog_Name_required_for_launch_configuration_11; + public static String LaunchConfigurationDialog_No_33; + public static String LaunchConfigurationDialog_Ready_to_launch_2; + public static String LaunchConfigurationDialog_The_configuration___29; + public static String LaunchConfigurationDialog_The_configuration___35; + public static String LaunchConfigurationDialog_unspecified_28; + public static String LaunchConfigurationDialog_Yes_32; + public static String LaunchConfigurationDialog_Do_you_wish_to_delete_the_selected_launch_configurations__1; + public static String LaunchConfigurationDialog_Do_you_wish_to_delete_the_selected_launch_configuration__2; + public static String LaunchConfigurationDialog_Confirm_Launch_Configuration_Deletion_3; + public static String LaunchConfigurationDialog_Close_1; + public static String LaunchConfigurationDialog_Revert_2; + public static String LaunchConfigurationsDialog_Error_1; + public static String LaunchConfigurationsDialog_Warning_2; + public static String LaunchConfigurationsDialog_Information_3; + public static String LaunchConfigurationSelectionDialog_0; + public static String LaunchConfigurationSelectionDialog_1; + + public static String LaunchConfigurationTabGroupViewer_14; + + public static String LaunchConfigurationTabGroupViewer_15; + + public static String LaunchConfigurationTabGroupViewer_16; + + public static String LaunchConfigurationTabGroupViewer_17; + + public static String LaunchConfigurationTabGroupViewer_18; + public static String LaunchConfigurationTabGroupViewer_13; + public static String LaunchConfigurationView_0; + + public static String LaunchShortcutSelectionDialog_0; + + public static String LaunchShortcutSelectionDialog_1; + + public static String LaunchShortcutSelectionDialog_2; + + public static String LaunchShortcutSelectionDialog_3; + + public static String LaunchShortcutSelectionDialog_4; + + public static String PerspectiveManager_Error_1; + public static String PerspectiveManager_Unable_to_switch_perpsectives_as_specified_by_launch___0__4; + public static String PerspectiveManager_Unable_to_switch_to_perspective___0__2; + + public static String LaunchConfigurationPresentationManager_0; + + public static String LaunchConfigurationPropertiesDialog_Edit_launch_configuration_properties_1; + public static String LaunchConfigurationPropertiesDialog_Properties_for__0__2; + + public static String LaunchConfigurationDialog_Modify_attributes_and_launch__1; + + public static String LaunchConfigurationTabGroupViewer_No_tabs_defined_for_launch_configuration_type__0__1; + + public static String DuplicateLaunchConfigurationAction__Duplicate_1; + + public static String DeleteLaunchConfigurationAction_Dele_te_1; + + public static String CreateLaunchConfigurationAction_Ne_w_1; + public static String CreateLaunchConfigurationAction_New_configuration_2; + + public static String EnvironmentTab_Variable_1; + public static String EnvironmentTab_Value_2; + public static String EnvironmentTab_Environment_variables_to_set__3; + public static String EnvironmentTab_New_4; + public static String EnvironmentTab_Edit_5; + public static String EnvironmentTab_Remove_6; + public static String EnvironmentTab_Environment_7; + public static String EnvironmentTab_8; + public static String EnvironmentTab_9; + public static String EnvironmentTab_11; + public static String EnvironmentTab_12; + public static String EnvironmentTab_13; + public static String EnvironmentTab_16; + public static String EnvironmentTab_17; + public static String EnvironmentTab_18; + public static String EnvironmentTab_19; + public static String EnvironmentTab_20; + + public static String FavoritesDialog_1; + public static String FavoritesDialog_2; + public static String FavoritesDialog_3; + public static String FavoritesDialog_4; + public static String FavoritesDialog_5; + public static String FavoritesDialog_6; + public static String FavoritesDialog_7; + public static String FavoritesDialog_0; + + public static String OrganizeFavoritesAction_0; + public static String PerspectiveManager_12; + public static String PerspectiveManager_13; + public static String PerspectiveManager_15; + public static String PerspectiveManager_suspend_description; + public static String PerspectiveManager_launch_description; + + public static String DebugModePromptStatusHandler_0; + public static String DebugModePromptStatusHandler_1; + + static { + // load message values from bundle file + NLS.initializeMessages(BUNDLE_NAME, LaunchConfigurationsMessages.class); + } + + public static String LaunchConfigurationTabGroupViewer_1; + public static String LaunchConfigurationTabGroupViewer_2; + public static String LaunchConfigurationTabGroupViewer_3; + public static String LaunchConfigurationTabGroupViewer_4; + public static String LaunchConfigurationTabGroupViewer_5; + public static String LaunchConfigurationTabGroupViewer_6; + + public static String SaveScopeResourcesHandler_1; + public static String SaveScopeResourcesHandler_2; + public static String SaveScopeResourcesHandler_3; + + public static String FavoritesDialog_8; + + public static String LaunchConfigurationsDialog_0; + public static String LaunchConfigurationsDialog_1; + public static String LaunchConfigurationsDialog_4; + public static String LaunchConfigurationsDialog_5; + public static String FilterLaunchConfigurationAction_0; + + + public static String LaunchConfigurationTabGroupViewer_8; + + public static String FilterDropDownMenuCreator_0; + public static String FilterDropDownMenuCreator_1; + public static String FilterDropDownMenuCreator_2; + public static String FilterDropDownMenuCreator_3; + public static String FilterDropDownMenuCreator_4; + + public static String LaunchConfigurationsDialog_c_ancel; + + public static String LaunchConfigurationsDialog_configurations; + + public static String CollapseAllLaunchConfigurationAction_0; + public static String CollapseAllLaunchConfigurationAction_1; + public static String CollapseAllLaunchConfigurationAction_2; + + public static String SelectLaunchersDialog_0; + public static String SelectLaunchersDialog_1; + public static String SelectLaunchersDialog_2; + public static String SelectLaunchersDialog_4; + public static String SelectLaunchersDialog_5; + + public static String SelectLaunchersDialog_launchers; + public static String SelectLaunchOptionsDialog_3; + public static String SelectLaunchOptionsDialog_4; + +} diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/LaunchConfigurationsMessages.properties b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/LaunchConfigurationsMessages.properties new file mode 100644 index 000000000..e09810df3 --- /dev/null +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/LaunchConfigurationsMessages.properties @@ -0,0 +1,212 @@ +############################################################################### +# Copyright (c) 2000, 2014 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### + +CommonTab__Browse_6=&Browse... +CommonTab__Common_15=&Common +CommonTab_Display_in_favorites_menu__10=Display in favo&rites menu +CommonTab_Invalid_shared_configuration_location_14=Invalid shared configuration location +CommonTab_Invalid_stdin_file_location_15=No file specified for process input +CommonTab_L_ocal_3=L&ocal file +CommonTab_S_hared_4=S&hared file: +CommonTab_Select_a_location_for_the_launch_configuration_13=Select a location for the launch configuration +CommonTab_Select_a_location_for_the_Input_File_15=Select a location for the standard input file +CommonTab_Cannot_save_launch_configuration_in_a_closed_project__1=Cannot save launch configuration in a closed project. +CommonTab_10=Launch in bac&kground +CommonTab_11=A&ppend +CommonTab_12=&Workspace... +CommonTab_13=Select a Resource: +CommonTab_14=Select a resource to redirect output to: +CommonTab_0=Save as +CommonTab_1=Encoding +CommonTab_15=The selected encoding is not supported. +CommonTab_16=Workspace... +CommonTab_17=Input &File: +CommonTab_18=Select a resource to redirect input from: +CommonTab_19=File System... +CommonTab_2=Defa&ult - inherited ({0}) +CommonTab_20=Variables... +CommonTab_3=Oth&er +CommonTab_4=Standard Input and Output +CommonTab_5=&Allocate console (necessary for input) +CommonTab_6=Output Fi&le: +CommonTab_7=File &System... +CommonTab_8=No file specified for process output +CommonTab_9=Variables... + +CompileErrorPromptStatusHandler_0=Errors in Workspace +CompileErrorPromptStatusHandler_1=Errors exist in a required project. Continue launch? +CompileErrorPromptStatusHandler_2=Errors exist in required project(s):\n\n{0}\n\nProceed with launch? +CompileErrorProjectPromptStatusHandler_1=&Always launch without asking +# {0} is replaced with a comma separated list of project names +CompileErrorProjectPromptStatusHandler_0={0}... + +EnvironmentTab_22=New Environment Variable + +LaunchConfigurationDialog__Apply_17=Appl&y +LaunchConfigurationDialog__Name__16=&Name: +LaunchConfigurationDialog_An_exception_occurred_while_retrieving_launch_configurations_20=An exception occurred while retrieving launch configurations + +LaunchConfigurationTabGroupViewer_1=Configure launch settings from this dialog: +LaunchConfigurationTabGroupViewer_2=- Press the 'New' button to create a configuration of the selected type. +LaunchConfigurationTabGroupViewer_3=- Edit or view an existing configuration by selecting it. +LaunchConfigurationTabGroupViewer_4=- Press the 'Delete' button to remove the selected configuration. +LaunchConfigurationTabGroupViewer_6=- Press the 'Duplicate' button to copy the selected configuration. +LaunchConfigurationTabGroupViewer_5=Configure launch perspective settings from the 'Perspectives' preference page. +LaunchConfigurationTabGroupViewer_8=- Press the 'Filter' button to configure filtering options. +LaunchConfigurationTabGroupViewer_13=Select a supported launch mode. +LaunchConfigurationTabGroupViewer_14=Mixed launch mode not supported: {0} +LaunchConfigurationTabGroupViewer_15=More than one launcher available - Select other... +LaunchConfigurationTabGroupViewer_16=Using {0} - Select other... +LaunchConfigurationTabGroupViewer_17=Multiple launchers available - Select one... +LaunchConfigurationTabGroupViewer_18=Multiple launchers available - select one to continue + +LaunchConfigurationDialog_Create__manage__and_run_launch_configurations_8=Create, manage, and run configurations +LaunchConfigurationDialog_Discard_changes__38=Discard changes? +LaunchConfigurationDialog_Do_you_wish_to_discard_changes_37=\nDo you wish to discard changes?\n +LaunchConfigurationDialog_Error_19=Error +LaunchConfigurationDialog_Exception_occurred_creating_launch_configuration_tabs_27=Exception occurred creating launch configuration tabs +LaunchConfigurationDialog_Exception_occurred_while_saving_launch_configuration_47=Exception occurred while saving launch configuration +LaunchConfigurationDialog_Launch_configuration_already_exists_with_this_name_12=A ''{0}'' configuration with this name already exists +LaunchConfigurationDialog_Launch_Configuration_Error_46=Launch Configuration Error +LaunchConfigurationDialog_Launch_Configurations_18=Launch Configurations +LaunchConfigurationFilteredTree_save_changes=Save Changes +LaunchConfigurationFilteredTree_search_with_changes=You cannot perform a text search when the current configuration has pending changes.\n\nDo you want to save the changes and continue searching? +LaunchConfigurationFilteredTree_search_with_errors=You cannot perform a text search when the current configuration has errors.\n\nDo you want to discard the changes and continue searching? +LaunchConfigurationDialog_Name_required_for_launch_configuration_11=A name is required for the configuration +LaunchConfigurationDialog_No_33=No +LaunchConfigurationEditDialog_0=Modify configuration and continue. +LaunchConfigurationEditDialog_1=Con&tinue +LaunchConfigurationDialog_Ready_to_launch_2=Ready to launch +LaunchConfigurationDialog_The_configuration___29=The configuration "{0}" has unsaved changes. Do you wish to save them? +LaunchConfigurationDialog_The_configuration___35=The configuration "{0}" has unsaved changes that CANNOT be saved because of the following error:\n\n +LaunchConfigurationFilteredTree_discard_changes=Discard Changes +LaunchConfigurationDialog_unspecified_28=unspecified +LaunchConfigurationDialog_Yes_32=Yes +LaunchConfigurationDialog_Do_you_wish_to_delete_the_selected_launch_configurations__1=Do you wish to delete the selected launch configurations? +LaunchConfigurationDialog_Do_you_wish_to_delete_the_selected_launch_configuration__2=Do you wish to delete the selected launch configuration? +LaunchConfigurationDialog_Confirm_Launch_Configuration_Deletion_3=Confirm Launch Configuration Deletion +LaunchConfigurationDialog_Close_1=Close +LaunchConfigurationDialog_Revert_2=Re&vert +LaunchConfigurationsDialog_Error_1=Error +LaunchConfigurationsDialog_Warning_2=Warning +LaunchConfigurationsDialog_Information_3=Information +LaunchConfigurationsDialog_0=New launch configuration +LaunchConfigurationsDialog_1=Delete selected launch configuration(s) +LaunchConfigurationsDialog_4=Filter launch configurations... +LaunchConfigurationsDialog_5=Duplicates the currently selected launch configuration +LaunchConfigurationSelectionDialog_0=Select Configuration +LaunchConfigurationSelectionDialog_1=&Select a configuration to launch: +LaunchConfigurationView_0=Filter matched {0} of {1} items +LaunchConfigurationsDialog_c_ancel=Cancel + +# {0} is substituted with a launch mode - possible values include run, debug, profile, or +# any label of a contributed ILaunchMode. +LaunchConfigurationsDialog_configurations={0} Configurations +PerspectiveManager_Error_1=Error +PerspectiveManager_Unable_to_switch_perpsectives_as_specified_by_launch___0__4=Unable to open perspectives as specified by launch: {0} +PerspectiveManager_Unable_to_switch_to_perspective___0__2=Unable to open perspective: {0} + +# {0} is substituted with a launch mode - possible values include Run, Debug, Profile, +# or any label of a contributed ILaunchMode. +LaunchShortcutSelectionDialog_0={0} As + +# {0} is substituted with a launch mode - possible values include run, debug, profile, or +# any label of a contributed ILaunchMode. +# +# {1} is the name of the resource being launched (run or debugged, etc.). +# Possible values can be the name of any IResource in the current workspace: for example +# if you tried to launch a class named Main in the file Main.java and you were presented +# with the selection dialog, the value of {1} would be Main.java (the name of the IResource) +LaunchShortcutSelectionDialog_1=&Select a way to {0} ''{1}'': +LaunchShortcutSelectionDialog_2=Description +LaunchShortcutSelectionDialog_3=Description not available +# {0} is substituted with a launch mode - possible values include Run, Debug, Profile, +# or any label of a contributed ILaunchMode. +LaunchShortcutSelectionDialog_4=&Select what to {0}: + +LaunchConfigurationPresentationManager_0=Tab group extension: {0} for type {1} for the {2} mode has been replaced by extension: {3} +LaunchConfigurationPropertiesDialog_Edit_launch_configuration_properties_1=Edit launch configuration properties +LaunchConfigurationPropertiesDialog_Properties_for__0__2=Edit Configuration + +LaunchConfigurationDialog_Modify_attributes_and_launch__1=Edit configuration and launch. + +LaunchConfigurationTabGroupViewer_No_tabs_defined_for_launch_configuration_type__0__1=No tabs defined for launch configuration type {0} + +DuplicateLaunchConfigurationAction__Duplicate_1=&Duplicate + +DeleteLaunchConfigurationAction_Dele_te_1=Dele&te + +CreateLaunchConfigurationAction_Ne_w_1=Ne&w +CreateLaunchConfigurationAction_New_configuration_2=New_configuration + +EnvironmentTab_Variable_1=Variable +EnvironmentTab_Value_2=Value +EnvironmentTab_Environment_variables_to_set__3=Environment variables to &set: +EnvironmentTab_New_4=N&ew... +EnvironmentTab_Edit_5=E&dit... +EnvironmentTab_Remove_6=Rem&ove +EnvironmentTab_Environment_7=Environment +EnvironmentTab_8=&Name: +EnvironmentTab_9=&Value: + +# This externalized string is used in the select environment variables dialog's label provider. +# Each item in the dialog is a single environment variable. +# {0} is replaced with the name of the environment variable +# {1} is replaced with the current value of the environment variable +EnvironmentTab_7={0} [ {1} ] +EnvironmentTab_11=Edit Environment Variable +EnvironmentTab_12=Overwrite variable? +EnvironmentTab_13=A variable named {0} already exists. Overwrite? +EnvironmentTab_16=&Append environment to native environment +EnvironmentTab_17=Re&place native environment with specified environment +EnvironmentTab_18=Se&lect... +EnvironmentTab_19=Select &environment variables to add: +EnvironmentTab_20=Select Environment Variables + +FavoritesDialog_1=Organize {0} Favorites +FavoritesDialog_2=Fa&vorites: +FavoritesDialog_3=Ad&d... +FavoritesDialog_4=Re&move +FavoritesDialog_5=U&p +FavoritesDialog_6=Do&wn +FavoritesDialog_7=Select &Launch Configurations: +FavoritesDialog_0=Add {0} Favorites +FavoritesDialog_8=Updating Favorites... + +OrganizeFavoritesAction_0=Organize Fa&vorites... +PerspectiveManager_12=Confirm Perspective Switch +PerspectiveManager_13=This kind of launch is configured to open the {0} perspective when it suspends. Do you want to open this perspective now? +PerspectiveManager_15=This kind of launch is associated with the {0} perspective. Do you want to open this perspective now? +PerspectiveManager_suspend_description=This kind of launch is configured to open the {0} perspective when it suspends.\n\n{1}\n\nDo you want to open this perspective now? +PerspectiveManager_launch_description=This kind of launch is associated with the {0} perspective.\n\n{1}\n\nDo you want to open this perspective now? + +DebugModePromptStatusHandler_0=Breakpoints in Workspace +DebugModePromptStatusHandler_1=There are breakpoints enabled in the workspace. Would you rather launch in debug mode? +SaveScopeResourcesHandler_2=Select resources to save: +SaveScopeResourcesHandler_3=Save and Launch +SaveScopeResourcesHandler_1=Always save &resources before launching +FilterLaunchConfigurationAction_0=Filter +FilterDropDownMenuCreator_0=Filter &Closed Projects +FilterDropDownMenuCreator_1=Filter &Deleted/Unavailable Projects +FilterDropDownMenuCreator_2=Filter Configuration &Types +FilterDropDownMenuCreator_3=Filtering &Preferences... +FilterDropDownMenuCreator_4=Apply Window &Working Set(s) +CollapseAllLaunchConfigurationAction_0=Collapse All +CollapseAllLaunchConfigurationAction_1=Collapses all expanded launch configurations. +CollapseAllLaunchConfigurationAction_2=This action collapses all of the launch configurations currently visible and expanded. +SelectLaunchOptionsDialog_3=Select Launch Mode +SelectLaunchOptionsDialog_4=&Select a supported mode combination: +SelectLaunchersDialog_0=Select Preferred Launcher +SelectLaunchersDialog_1=&Use configuration specific settings +SelectLaunchersDialog_2=This dialog allows you to specify which launcher to use when multiple launchers are available for a configuration and launch mode. +SelectLaunchersDialog_4=Change Workspace Settings... +SelectLaunchersDialog_5=Description +SelectLaunchersDialog_launchers=Launc&hers: diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/NativeEnvironmentSelectionDialog.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/NativeEnvironmentSelectionDialog.java new file mode 100644 index 000000000..858f77e2c --- /dev/null +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/NativeEnvironmentSelectionDialog.java @@ -0,0 +1,487 @@ +/******************************************************************************* + * Copyright (c) 2016 Bruno Medeiros and other Contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Bruno Medeiros - initial API and implementation + *******************************************************************************/ +package melnorme.lang.ide.ui.build; + +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.SelectionDialog; + +import _org.eclipse.debug.internal.ui.SWTFactory; +import melnorme.lang.ide.core.LangCore; +import melnorme.lang.ide.ui.LangImages; +import melnorme.lang.ide.ui.LangUIPlugin; + +/** + * This class provides the framework for a general selection dialog class. + * + * @see AbstractDebugCheckboxSelectionDialog + * + * @since 3.3 + */ +abstract class AbstractDebugSelectionDialog extends SelectionDialog { + + public static String EMPTY_STRING = ""; + + protected StructuredViewer fViewer = null; + + /** + * Constructor + * @param parentShell the parent shell + */ + public AbstractDebugSelectionDialog(Shell parentShell) { + super(parentShell); + setDialogBoundsSettings(getDialogBoundsSettings(), Dialog.DIALOG_PERSISTSIZE); + } + + /** + * returns the dialog settings area id + * @return the id of the dialog settings area + */ + protected abstract String getDialogSettingsId(); + + /** + * Returns the object to use as input for the viewer + * @return the object to use as input for the viewer + */ + protected abstract Object getViewerInput(); + + /** + * Create and return a viewer to use in this dialog. + * + * @param parent the composite the viewer should be created in + * @return the viewer to use in the dialog + */ + protected abstract StructuredViewer createViewer(Composite parent); + + /** + * Returns if the dialog and/or current selection is/are valid. + * This method is polled when selection changes are made to update the enablement + * of the OK button by default + * @return true if the dialog is in a valid state, false otherwise + * + * @since 3.4 + */ + protected abstract boolean isValid(); + + /** + * Returns the content provider for the viewer + * @return the content provider for the viewer + */ + protected IContentProvider getContentProvider() { + //by default return a simple array content provider + return new ArrayContentProvider(); + } + + protected abstract IBaseLabelProvider getLabelProvider(); + + /** + * Returns the help context id for this dialog + * @return the help context id for this dialog + */ + abstract protected String getHelpContextId(); + + /** + * This method allows listeners to be added to the viewer after it + * is created. + */ + /** + * This method allows listeners to be added to the viewer. Called + * after the viewer has been created and its input set. + * + * @param viewer the viewer returned by createViewer() + */ + protected void addViewerListeners(StructuredViewer viewer){ + //do nothing by default + } + + /** + * This method allows custom controls to be added before the viewer + * @param parent the parent composite to add these custom controls to + */ + protected void addCustomHeaderControls(Composite parent) { + //do nothing by default + } + + /** + * This method allows custom controls to be added after the viewer + * @param parent the parent composite to add these controls to + */ + protected void addCustomFooterControls(Composite parent) { + //do nothing by default + } + + /** + * This method allows the newly created controls to be initialized. + * This method is called only once all controls have been created from the + * createContents method. + * + * By default this method initializes the OK button control. + */ + protected void initializeControls() { + getButton(IDialogConstants.OK_ID).setEnabled(isValid()); + } + + /** + * Returns the viewer used to display information in this dialog. + * Can be null if the viewer has not been created. + * @return viewer used in this dialog + */ + protected Viewer getViewer(){ + return fViewer; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createContents(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createContents(Composite parent) { + Composite comp = (Composite) super.createContents(parent); + initializeControls(); + return comp; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createDialogArea(Composite parent) { + initializeDialogUnits(parent); + Composite comp = (Composite) super.createDialogArea(parent); + addCustomHeaderControls(comp); + String label = getMessage(); + if(label != null && !EMPTY_STRING.equals(label)) { + SWTFactory.createWrapLabel(comp, label, 1); + } + label = getViewerLabel(); + if(label != null && !EMPTY_STRING.equals(label)) { + SWTFactory.createLabel(comp, label, 1); + } + fViewer = createViewer(comp); + fViewer.setLabelProvider(getLabelProvider()); + fViewer.setContentProvider(getContentProvider()); + fViewer.setInput(getViewerInput()); + List selectedElements = getInitialElementSelections(); + if (selectedElements != null && !selectedElements.isEmpty()){ + fViewer.setSelection(new StructuredSelection(selectedElements)); + } + addViewerListeners(fViewer); + addCustomFooterControls(comp); + Dialog.applyDialogFont(comp); + String help = getHelpContextId(); + if(help != null) { + PlatformUI.getWorkbench().getHelpSystem().setHelp(comp, help); + } + return comp; + } + + /** + * This method returns the label describing what to do with the viewer. Typically this label + * will include the key accelerator to get to the viewer via the keyboard + * @return the label for the viewer + */ + abstract protected String getViewerLabel(); + + /* (non-Javadoc) + * @see org.eclipse.ui.dialogs.SelectionDialog#getDialogBoundsSettings() + */ + @Override + protected IDialogSettings getDialogBoundsSettings() { + IDialogSettings settings = LangUIPlugin.getDefault().getDialogSettings(); + IDialogSettings section = settings.getSection(getDialogSettingsId()); + if (section == null) { + section = settings.addNewSection(getDialogSettingsId()); + } + return section; + } +} + +/******************************************************************************* + * Copyright (c) 2006, 2013 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + + +/** + * This class provides selection dialog using a check box table viewer. + * + * @since 3.4 + */ +abstract class AbstractDebugCheckboxSelectionDialog extends AbstractDebugSelectionDialog { + + /** + * Whether to add Select All / De-select All buttons to the custom footer controls. + */ + private boolean fShowSelectButtons = false; + + /** + * Constructor + * @param parentShell the parent shell + */ + public AbstractDebugCheckboxSelectionDialog(Shell parentShell) { + super(parentShell); + setShellStyle(getShellStyle() | SWT.RESIZE); + } + + /** + * Returns the viewer cast to the correct instance. Possibly null if + * the viewer has not been created yet. + * @return the viewer cast to CheckboxTableViewer + */ + protected CheckboxTableViewer getCheckBoxTableViewer() { + return (CheckboxTableViewer) fViewer; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#initializeControls() + */ + @Override + protected void initializeControls() { + List selectedElements = getInitialElementSelections(); + if (selectedElements != null && !selectedElements.isEmpty()){ + getCheckBoxTableViewer().setCheckedElements(selectedElements.toArray()); + getCheckBoxTableViewer().setSelection(StructuredSelection.EMPTY); + } + super.initializeControls(); + } + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#createViewer(org.eclipse.swt.widgets.Composite) + */ + @Override + protected StructuredViewer createViewer(Composite parent){ + //by default return a checkbox table viewer + Table table = new Table(parent, SWT.BORDER | SWT.SINGLE | SWT.CHECK); + GridData gd = new GridData(GridData.FILL_BOTH); + gd.heightHint = 150; + gd.widthHint = 250; + table.setLayoutData(gd); + return new CheckboxTableViewer(table); + } + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#addViewerListeners(org.eclipse.jface.viewers.StructuredViewer) + */ + @Override + protected void addViewerListeners(StructuredViewer viewer) { + getCheckBoxTableViewer().addCheckStateListener(new DefaultCheckboxListener()); + } + + /** + * A checkbox state listener that ensures that exactly one element is checked + * and enables the OK button when this is the case. + * + */ + private class DefaultCheckboxListener implements ICheckStateListener{ + @Override + public void checkStateChanged(CheckStateChangedEvent event) { + getButton(IDialogConstants.OK_ID).setEnabled(isValid()); + } + } + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.ui.AbstractDebugSelectionDialog#isValid() + */ + @Override + protected boolean isValid() { + return getCheckBoxTableViewer().getCheckedElements().length > 0; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#okPressed() + */ + @Override + protected void okPressed() { + Object[] elements = getCheckBoxTableViewer().getCheckedElements(); + setResult(Arrays.asList(elements)); + super.okPressed(); + } + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#addCustomFooterControls(org.eclipse.swt.widgets.Composite) + */ + @Override + protected void addCustomFooterControls(Composite parent) { + if (fShowSelectButtons){ + Composite comp = SWTFactory.createComposite(parent, 2, 1, GridData.FILL_HORIZONTAL); + GridData gd = (GridData) comp.getLayoutData(); + gd.horizontalAlignment = SWT.END; + Button button = SWTFactory.createPushButton(comp, "&Select All", null); + button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + getCheckBoxTableViewer().setAllChecked(true); + getButton(IDialogConstants.OK_ID).setEnabled(isValid()); + } + }); + button = SWTFactory.createPushButton(comp, "&Deselect All", null); + button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + getCheckBoxTableViewer().setAllChecked(false); + getButton(IDialogConstants.OK_ID).setEnabled(isValid()); + } + }); + } + } + + /** + * If this setting is set to true before the dialog is opened, a Select All and + * a De-select All button will be added to the custom footer controls. The default + * setting is false. + * + * @param setting whether to show the select all and de-select all buttons + */ + protected void setShowSelectAllButtons(boolean setting){ + fShowSelectButtons = setting; + } + +} + +/** + * This dialog allows users to select one or more known native environment variables from a list. + */ +class NativeEnvironmentSelectionDialog extends AbstractDebugCheckboxSelectionDialog { + + private Object fInput; + + public NativeEnvironmentSelectionDialog(Shell parentShell, Object input) { + super(parentShell); + fInput = input; + setShellStyle(getShellStyle() | SWT.RESIZE); + setShowSelectAllButtons(true); + } + + @Override + protected String getDialogSettingsId() { + return LangCore.PLUGIN_ID + ".ENVIRONMENT_TAB.NATIVE_ENVIROMENT_DIALOG"; //$NON-NLS-1$ + } + + @Override + protected String getHelpContextId() { + return null; + } + + @Override + protected Object getViewerInput() { + return fInput; + } + + @Override + protected String getViewerLabel() { + return LaunchConfigurationsMessages.EnvironmentTab_19; + } + + @Override + protected IBaseLabelProvider getLabelProvider() { + return new ILabelProvider() { + @Override + public Image getImage(Object element) { + return LangImages.IMG_ENVIRONMENT.getImage(); + } + @Override + public String getText(Object element) { + EnvironmentVariable var = (EnvironmentVariable) element; + return MessageFormat.format(LaunchConfigurationsMessages.EnvironmentTab_7, new Object[] { + var.getName(), var.getValue() }); + } + @Override + public void addListener(ILabelProviderListener listener) { + } + @Override + public void dispose() { + } + @Override + public boolean isLabelProperty(Object element, String property) { + return false; + } + @Override + public void removeListener(ILabelProviderListener listener) { + } + }; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractDebugSelectionDialog#getContentProvider() + */ + @Override + protected IContentProvider getContentProvider() { + return new IStructuredContentProvider() { + @Override + public Object[] getElements(Object inputElement) { + EnvironmentVariable[] elements = null; + if (inputElement instanceof HashMap) { + Comparator comparator = new Comparator() { + @Override + public int compare(Object o1, Object o2) { + String s1 = (String) o1; + String s2 = (String) o2; + return s1.compareTo(s2); + } + }; + TreeMap envVars = new TreeMap(comparator); + envVars.putAll((Map) inputElement); + elements = new EnvironmentVariable[envVars.size()]; + int index = 0; + for (Iterator iterator = envVars.keySet().iterator(); iterator.hasNext(); index++) { + Object key = iterator.next(); + elements[index] = (EnvironmentVariable) envVars.get(key); + } + } + return elements; + } + @Override + public void dispose() { + } + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + }; + } +} \ No newline at end of file diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/fields/FieldDialog.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/fields/FieldDialog.java new file mode 100644 index 000000000..fdcfed1ed --- /dev/null +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/fields/FieldDialog.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2016 Bruno Medeiros and other Contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Bruno Medeiros - initial API and implementation + *******************************************************************************/ +package melnorme.lang.ide.ui.fields; + +import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +import melnorme.util.swt.components.AbstractWidget; +import melnorme.util.swt.components.fields.FieldCompositeWidget; +import melnorme.utilbox.concurrency.OperationCancellation; + +public class FieldDialog extends Dialog { + + protected final FieldCompositeWidget fieldEditor; + + public FieldDialog(Shell parentShell, FieldCompositeWidget fieldEditor) { + super(parentShell); + setShellStyle(getShellStyle() | SWT.RESIZE); + this.fieldEditor = assertNotNull(fieldEditor); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite topControl = (Composite) super.createDialogArea(parent); + return fieldEditor.createComponent(topControl, AbstractWidget.gdGrabAll(SWT.DEFAULT, SWT.DEFAULT)); + } + + public VALUE openDialog(VALUE initialValue) throws OperationCancellation { + int result = open(); + + fieldEditor.field().set(initialValue); + if(result == Dialog.OK) { + return fieldEditor.field().get(); + } + throw new OperationCancellation(); + } + +} \ No newline at end of file diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/launch/MainLaunchConfigurationTab.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/launch/MainLaunchConfigurationTab.java index 78a75e656..9e1016605 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/launch/MainLaunchConfigurationTab.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/launch/MainLaunchConfigurationTab.java @@ -29,7 +29,7 @@ import melnorme.lang.ide.core.operations.build.CommandInvocation; import melnorme.lang.ide.core.operations.build.ProjectBuildInfo; import melnorme.lang.ide.ui.LangUIMessages; -import melnorme.lang.ide.ui.preferences.BuildTargetEditor; +import melnorme.lang.ide.ui.build.BuildTargetEditor; import melnorme.lang.tooling.data.StatusException; import melnorme.utilbox.collections.Collection2; import melnorme.utilbox.core.CommonException; @@ -148,7 +148,7 @@ protected void initBindings() { projectField.addChangeListener(this::projectFieldChanged); buildTargetField.addChangeListener(this::buildTargetFieldChanged); - buildTargetEditor.buildCommandField.getField().addChangeListener(this::updateLaunchConfigurationDialog); + buildTargetEditor.buildCommandField.field().addChangeListener(this::updateLaunchConfigurationDialog); buildTargetEditor.programPathField.addChangeListener(this::updateLaunchConfigurationDialog); } diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/ProjectBuildConfigurationComponent.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/ProjectBuildConfigurationComponent.java index cd2c0fe88..57ede326c 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/ProjectBuildConfigurationComponent.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/ProjectBuildConfigurationComponent.java @@ -24,6 +24,7 @@ import melnorme.lang.ide.core.operations.build.CommandInvocation; import melnorme.lang.ide.core.operations.build.ProjectBuildInfo; import melnorme.lang.ide.core.utils.ProjectValidator; +import melnorme.lang.ide.ui.build.BuildTargetEditor; import melnorme.lang.ide.ui.launch.BuildTargetField; import melnorme.lang.ide.ui.preferences.common.IPreferencesEditor; import melnorme.lang.ide.ui.utils.UIOperationsStatusHandler; diff --git a/plugin_ide.ui/src-lang/melnorme/util/swt/components/AbstractWidget.java b/plugin_ide.ui/src-lang/melnorme/util/swt/components/AbstractWidget.java index 7f51e450f..9d36f1a15 100644 --- a/plugin_ide.ui/src-lang/melnorme/util/swt/components/AbstractWidget.java +++ b/plugin_ide.ui/src-lang/melnorme/util/swt/components/AbstractWidget.java @@ -83,11 +83,11 @@ protected void _verifyContract_IDisableableComponent() { /* ----------------- Shortcut utils ----------------- */ - protected static GridDataFactory gdfSwtDefaults() { + public static GridDataFactory gdfSwtDefaults() { return GridDataFactory.swtDefaults(); } - protected static GridDataFactory gdfFillDefaults() { + public static GridDataFactory gdfFillDefaults() { return GridDataFactory.fillDefaults(); } diff --git a/plugin_ide.ui/src-lang/melnorme/util/swt/components/CompositeWidget.java b/plugin_ide.ui/src-lang/melnorme/util/swt/components/CompositeWidget.java index c1ac0bc78..931f2b659 100644 --- a/plugin_ide.ui/src-lang/melnorme/util/swt/components/CompositeWidget.java +++ b/plugin_ide.ui/src-lang/melnorme/util/swt/components/CompositeWidget.java @@ -96,7 +96,7 @@ protected GridData createSubComponentDefaultGridData() { } @Override - protected final void doSetEnabled(boolean enabled) { + protected void doSetEnabled(boolean enabled) { subComponents.forEach(subComponent -> { subComponent.updateControlEnablement2(); }); diff --git a/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/EnablementButtonTextField2.java b/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/EnablementButtonTextField2.java index 52e98b601..d8c66ba7d 100644 --- a/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/EnablementButtonTextField2.java +++ b/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/EnablementButtonTextField2.java @@ -28,7 +28,7 @@ public EnablementButtonTextField2(String label, String useDefaultCheckboxLabel) super(label, useDefaultCheckboxLabel); this.createInlined = false; - this.buttonTextField = init_createButtonTextField(getField()); + this.buttonTextField = init_createButtonTextField(field()); addChildWidget(buttonTextField); } diff --git a/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/EnablementCompositeWidget.java b/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/EnablementCompositeWidget.java index c4cb3b039..cb1384edb 100644 --- a/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/EnablementCompositeWidget.java +++ b/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/EnablementCompositeWidget.java @@ -21,6 +21,7 @@ import melnorme.util.swt.components.IDisableableWidget; import melnorme.utilbox.core.CommonException; import melnorme.utilbox.fields.IProperty; +import melnorme.utilbox.fields.FieldValueListener.FieldChangeListener; public abstract class EnablementCompositeWidget extends FieldCompositeWidget { @@ -66,7 +67,7 @@ protected void handleEnablementChanged() { defaultFieldValue = null; getValidation().setExplicitStatus(e.toStatusException()); } - getField().setFieldValue(defaultFieldValue); + field().setFieldValue(defaultFieldValue); } updateChildrenEnablement(); } @@ -85,14 +86,14 @@ protected void updateChildrenEnablement() { /* ----------------- effective value ----------------- */ public VALUE getEffectiveFieldValue() { - return isUseDefault() ? null : getField().getFieldValue(); + return isUseDefault() ? null : field().getFieldValue(); } public void setEffectiveFieldValue(VALUE effectiveFieldValue) { getEnablementField().setFieldValue(effectiveFieldValue == null); if(effectiveFieldValue != null) { - getField().setFieldValue(effectiveFieldValue); + field().setFieldValue(effectiveFieldValue); } } @@ -112,6 +113,11 @@ public IProperty asEffectiveValueProperty() { return effectiveValueProperty; } + public void addEffectiveValueChangeListener(FieldChangeListener listener) { + getEnablementField().addChangeListener(listener); + field().addChangeListener(listener); + } + /* ----------------- ----------------- */ @Override diff --git a/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/FieldCompositeWidget.java b/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/FieldCompositeWidget.java index 87be0b982..1f2d2cc07 100644 --- a/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/FieldCompositeWidget.java +++ b/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/FieldCompositeWidget.java @@ -28,13 +28,16 @@ protected Field init_valueField() { return new Field<>(); } - /* FIXME: rename*/ - public Field getField() { + public Field field() { return valueField; } public VALUE getFieldValue() { - return valueField.get(); + return field().get(); + } + + public void setFieldValue(VALUE newValue) { + field().set(newValue); } } \ No newline at end of file diff --git a/plugin_tooling/src-lang/melnorme/lang/tooling/ops/EnvironmentSettings.java b/plugin_tooling/src-lang/melnorme/lang/tooling/ops/EnvironmentSettings.java new file mode 100644 index 000000000..529de2d67 --- /dev/null +++ b/plugin_tooling/src-lang/melnorme/lang/tooling/ops/EnvironmentSettings.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2016 Bruno Medeiros and other Contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Bruno Medeiros - initial API and implementation + *******************************************************************************/ +package melnorme.lang.tooling.ops; + +import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; +import static melnorme.utilbox.core.CoreUtil.areEqual; + +import melnorme.utilbox.collections.HashMap2; +import melnorme.utilbox.misc.HashcodeUtil; + +public class EnvironmentSettings { + + public final HashMap2 envVars; + public boolean appendEnv; + + public EnvironmentSettings() { + this(new HashMap2<>(), true); + } + + public EnvironmentSettings(HashMap2 envVars, boolean appendEnv) { + this.envVars = assertNotNull(envVars); + this.appendEnv = appendEnv; + } + + @Override + public boolean equals(Object obj) { + if(this == obj) return true; + if(!(obj instanceof EnvironmentSettings)) return false; + + EnvironmentSettings other = (EnvironmentSettings) obj; + + return + areEqual(envVars, other.envVars) && + areEqual(appendEnv, other.appendEnv); + } + + @Override + public int hashCode() { + return HashcodeUtil.combinedHashCode(envVars, appendEnv); + } + +} \ No newline at end of file diff --git a/plugin_tooling/src-util/melnorme/utilbox/collections/HashMap2.java b/plugin_tooling/src-util/melnorme/utilbox/collections/HashMap2.java index 7a9e04011..8f47eb10f 100644 --- a/plugin_tooling/src-util/melnorme/utilbox/collections/HashMap2.java +++ b/plugin_tooling/src-util/melnorme/utilbox/collections/HashMap2.java @@ -34,6 +34,10 @@ public HashMap2(Map map) { @Override public HashMap2 copyToHashMap() { + return copy(); + } + + public HashMap2 copy() { return new HashMap2(this); } From 042a1ca957ef3f3bfb49300e1daad2abb220a05c Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Fri, 29 Apr 2016 12:41:18 +0100 Subject: [PATCH 3/4] Fixed some layout issues. --- .../ide/ui/build/CommandInvocationEditor.java | 13 +++-- .../ProjectBuildConfigurationComponent.java | 2 +- .../pages/DownloadToolTextField.java | 4 +- .../melnorme/util/swt/SWTFactory.java | 26 +++++++--- .../melnorme/util/swt/SWTFactoryUtil.java | 51 ------------------- .../util/swt/components/AbstractWidget.java | 2 +- .../util/swt/components/ButtonWidget.java | 11 ++-- .../util/swt/components/CompositeWidget.java | 2 +- .../components/fields/ButtonTextField.java | 4 +- 9 files changed, 39 insertions(+), 76 deletions(-) diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/CommandInvocationEditor.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/CommandInvocationEditor.java index ac76d82a7..52149bcc5 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/CommandInvocationEditor.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/build/CommandInvocationEditor.java @@ -11,7 +11,6 @@ package melnorme.lang.ide.ui.build; import org.eclipse.debug.ui.StringVariableSelectionDialog; -import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; @@ -78,6 +77,9 @@ protected void doUpdateWidgetFromInput() { protected void updateCommandInvocationField() { CommandInvocation current = commandInvocation.get(); + if(current == null) { + return; + } commandInvocation.set(new CommandInvocation( commandArgumentsField.get(), current.getEnvironmentVars(), @@ -98,7 +100,6 @@ protected void createButtonArea() { ButtonWidget variablesDialogButton = new ButtonWidget("Insert/Edit Substitution Variables...", new SetFieldValueOperation(commandArgumentsField, this::newValueFromCommandVariablesDialog)); - /* FIXME: buttons layout issue */ CompositeWidget buttonArea = addChildWidget(new CompositeWidget(false) { { layoutColumns = 2; } @@ -107,11 +108,9 @@ protected void createButtonArea() { protected void createContents(Composite topControl) { super.createContents(topControl); - environmentVarButton.getButton().setLayoutData( - GridDataFactory.fillDefaults().create()); - - variablesDialogButton.getButton().setLayoutData( - gdfGrabHorizontal().align(GridData.END, GridData.CENTER).create()); + GridData layoutData = (GridData) variablesDialogButton.getButton().getLayoutData(); + layoutData.grabExcessHorizontalSpace = true; + layoutData.horizontalAlignment = GridData.END; } }); buttonArea.addChildWidget(environmentVarButton); diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/ProjectBuildConfigurationComponent.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/ProjectBuildConfigurationComponent.java index 57ede326c..58ae7a512 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/ProjectBuildConfigurationComponent.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/ProjectBuildConfigurationComponent.java @@ -174,7 +174,7 @@ protected void handleStatusException(CommonException ce) { protected void createContents(Composite topControl) { super.createContents(topControl); - SWTFactoryUtil.createPushButton2(topControl, + SWTFactoryUtil.createPushButton(topControl, "Restore all targets to defaults", null, new GridData(GridData.HORIZONTAL_ALIGN_END), (e) -> loadDefaults() diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/pages/DownloadToolTextField.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/pages/DownloadToolTextField.java index 57280ae7f..e7182a546 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/pages/DownloadToolTextField.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/preferences/pages/DownloadToolTextField.java @@ -17,7 +17,7 @@ import melnorme.lang.ide.ui.utils.ControlUtils; import melnorme.lang.ide.ui.utils.operations.BasicUIOperation; -import melnorme.util.swt.SWTFactoryUtil; +import melnorme.util.swt.SWTFactory; import melnorme.util.swt.SWTLayoutUtil; import melnorme.util.swt.SWTUtil; import melnorme.util.swt.WidgetSelectedRunner; @@ -82,7 +82,7 @@ protected String getNewValueFromButtonSelection() throws OperationCancellation { /* ----------------- Download Button ----------------- */ protected void createContents_DownloadButton(Composite topControl) { - downloadButton = SWTFactoryUtil.createPushButton(topControl, downloadButtonLabel, null); + downloadButton = SWTFactory.createPushButton(topControl, downloadButtonLabel, null); downloadButton.addSelectionListener(new WidgetSelectedRunner(getDownloadButtonHandler())); } diff --git a/plugin_ide.ui/src-lang/melnorme/util/swt/SWTFactory.java b/plugin_ide.ui/src-lang/melnorme/util/swt/SWTFactory.java index d093046dd..6eb094d9b 100644 --- a/plugin_ide.ui/src-lang/melnorme/util/swt/SWTFactory.java +++ b/plugin_ide.ui/src-lang/melnorme/util/swt/SWTFactory.java @@ -12,7 +12,9 @@ import static melnorme.util.swt.SWTLayoutUtil.setLayoutData; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.layout.PixelConverter; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; @@ -127,18 +129,28 @@ public static Button createButton(Composite parent, int style, String label, Ima return button; } - public static Button createPushButton2(Composite parent, String label, Image image) { - return createButton(parent, SWT.PUSH, label, image, new GridData()); + public static Button createPushButton(Composite parent, String label, Image image) { + return createPushButton(parent, label, image, new GridData()); } - public static Button createPushButton2(Composite parent, String label, Image image, GridData gridData) { - Button button = createPushButton2(parent, label, image); - return setLayoutData(button, gridData); + public static Button createPushButton(Composite parent, String label, Image image, GridData gridData) { + Button button = createButton(parent, SWT.PUSH, label, image, gridData); + if(gridData != null) { + gridData.minimumWidth = getButtonWidthHint(button); + setLayoutData(button, gridData); + } + return button; + } + + public static int getButtonWidthHint(Button button) { + PixelConverter converter = new PixelConverter(button); + int widthHint = converter.convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); + return Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x); } - public static Button createPushButton2(Composite parent, String label, Image image, GridData gridData, + public static Button createPushButton(Composite parent, String label, Image image, GridData gridData, WidgetSelectedListener listener) { - Button button = createPushButton2(parent, label, image); + Button button = createPushButton(parent, label, image); button.addSelectionListener(listener); return setLayoutData(button, gridData); } diff --git a/plugin_ide.ui/src-lang/melnorme/util/swt/SWTFactoryUtil.java b/plugin_ide.ui/src-lang/melnorme/util/swt/SWTFactoryUtil.java index 655ffff3a..09f4f890c 100644 --- a/plugin_ide.ui/src-lang/melnorme/util/swt/SWTFactoryUtil.java +++ b/plugin_ide.ui/src-lang/melnorme/util/swt/SWTFactoryUtil.java @@ -10,57 +10,6 @@ *******************************************************************************/ package melnorme.util.swt; -import org.eclipse.core.runtime.Assert; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.layout.PixelConverter; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; - public class SWTFactoryUtil extends SWTFactory { - /** - * Creates and returns a new push button with the given - * label and/or image. - * - * @param parent parent control - * @param label button label or null - * @param image image of null - * - * @return a new push button - */ - public static Button createPushButton(Composite parent, String label, Image image) { - Button button = createButton(parent, SWT.PUSH, label, image, new GridData()); - setButtonDimensionHint(button); - return button; - } - - /** - * Sets width and height hint for the button control. - * Note: This is a NOP if the button's layout data is not - * an instance of GridData. - * - * @param the button for which to set the dimension hint - */ - public static void setButtonDimensionHint(Button button) { - Assert.isNotNull(button); - Object gd= button.getLayoutData(); - if (gd instanceof GridData) { - ((GridData)gd).widthHint= getButtonWidthHint(button); - ((GridData)gd).horizontalAlignment = GridData.FILL; - } - } - - /** - * Returns a width hint for a button control. - */ - public static int getButtonWidthHint(Button button) { - /*button.setFont(JFaceResources.getDialogFont());*/ - PixelConverter converter= new PixelConverter(button); - int widthHint= converter.convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); - return Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x); - } - } \ No newline at end of file diff --git a/plugin_ide.ui/src-lang/melnorme/util/swt/components/AbstractWidget.java b/plugin_ide.ui/src-lang/melnorme/util/swt/components/AbstractWidget.java index 9d36f1a15..b34985811 100644 --- a/plugin_ide.ui/src-lang/melnorme/util/swt/components/AbstractWidget.java +++ b/plugin_ide.ui/src-lang/melnorme/util/swt/components/AbstractWidget.java @@ -46,7 +46,7 @@ public void createComponentInlined(Composite parent) { updateWidgetFromInput(); } - protected final Composite createTopLevelControl(Composite parent) { + protected Composite createTopLevelControl(Composite parent) { Composite topControl = doCreateTopLevelControl(parent); topControl.setLayout(createTopLevelLayout().create()); return topControl; diff --git a/plugin_ide.ui/src-lang/melnorme/util/swt/components/ButtonWidget.java b/plugin_ide.ui/src-lang/melnorme/util/swt/components/ButtonWidget.java index 5f3f7fc42..60cdbc528 100644 --- a/plugin_ide.ui/src-lang/melnorme/util/swt/components/ButtonWidget.java +++ b/plugin_ide.ui/src-lang/melnorme/util/swt/components/ButtonWidget.java @@ -12,7 +12,6 @@ import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; -import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; @@ -47,11 +46,15 @@ public int getPreferredLayoutColumns() { return 1; } + @Override + protected Composite createTopLevelControl(Composite parent) { + // Don't create parent composite + return parent; + } + @Override protected void createContents(Composite topControl) { - button = SWTFactory.createButton(topControl, SWT.PUSH, buttonLabel); - /* FIXME: button width */ -// button = SWTFactoryUtil.createPushButton(topControl, buttonLabel, null); + button = SWTFactory.createPushButton(topControl, buttonLabel, null); button.addSelectionListener(new WidgetSelectedRunner(buttonHandler)); } diff --git a/plugin_ide.ui/src-lang/melnorme/util/swt/components/CompositeWidget.java b/plugin_ide.ui/src-lang/melnorme/util/swt/components/CompositeWidget.java index 931f2b659..9c80842bc 100644 --- a/plugin_ide.ui/src-lang/melnorme/util/swt/components/CompositeWidget.java +++ b/plugin_ide.ui/src-lang/melnorme/util/swt/components/CompositeWidget.java @@ -30,7 +30,7 @@ public class CompositeWidget extends AbstractDisableableWidget { public CompositeWidget(boolean createInlined) { this.createInlined = createInlined; - this.defaultRowLayout = gdfFillDefaults().grab(true, false).hint(200, SWT.DEFAULT); + this.defaultRowLayout = gdfFillDefaults().grab(true, false).hint(SWT.DEFAULT, SWT.DEFAULT); } public void addChildWidget(AbstractDisableableWidget... subComponents) { diff --git a/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/ButtonTextField.java b/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/ButtonTextField.java index ab342d749..dc37c218c 100644 --- a/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/ButtonTextField.java +++ b/plugin_ide.ui/src-lang/melnorme/util/swt/components/fields/ButtonTextField.java @@ -17,7 +17,7 @@ import org.eclipse.swt.widgets.Composite; import melnorme.lang.ide.ui.utils.operations.BasicUIOperation; -import melnorme.util.swt.SWTFactoryUtil; +import melnorme.util.swt.SWTFactory; import melnorme.util.swt.SWTLayoutUtil; import melnorme.util.swt.SWTUtil; import melnorme.util.swt.WidgetSelectedRunner; @@ -66,7 +66,7 @@ protected void createContents_layout() { /* ----------------- Button ----------------- */ protected void createContents_Button(Composite topControl) { - button = SWTFactoryUtil.createPushButton(topControl, getButtonLabel(), null); + button = SWTFactory.createPushButton(topControl, getButtonLabel(), null); button.addSelectionListener(new WidgetSelectedRunner(getButtonHandler())); } From e561eb3df43a7ec17100545a1496740736342869 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Fri, 29 Apr 2016 13:22:31 +0100 Subject: [PATCH 4/4] Command Invocation: actually modify environment --- .../operations/build/BuildManager_Test.java | 4 +-- .../lang/ide/core/operations/ToolManager.java | 6 +++- .../build/BuildTargetOperation.java | 13 +++++---- .../operations/build/CommandInvocation.java | 29 ++++++++++++++++++- .../melnorme/lang/utils/ProcessUtils.java | 8 +---- 5 files changed, 43 insertions(+), 17 deletions(-) diff --git a/plugin_ide.core.tests/src-lang/melnorme/lang/ide/core/operations/build/BuildManager_Test.java b/plugin_ide.core.tests/src-lang/melnorme/lang/ide/core/operations/build/BuildManager_Test.java index 6889d69bd..cade707b8 100644 --- a/plugin_ide.core.tests/src-lang/melnorme/lang/ide/core/operations/build/BuildManager_Test.java +++ b/plugin_ide.core.tests/src-lang/melnorme/lang/ide/core/operations/build/BuildManager_Test.java @@ -348,7 +348,7 @@ protected void testBuildOperation_Vars(ProjectBuildInfo buildInfo, BuildTarget b } - protected Indexable getBuildOperation(ProjectBuildInfo buildInfo, BuildTarget btB, String buildArguments) + protected Iterable getBuildOperation(ProjectBuildInfo buildInfo, BuildTarget btB, String buildArguments) throws CommonException { BuildTargetData dataCopy = btB.getDataCopy(); dataCopy.buildCommand = new CommandInvocation(buildArguments); @@ -356,7 +356,7 @@ protected Indexable getBuildOperation(ProjectBuildInfo buildInfo, BuildT ToolManager toolMgr = buildInfo.buildMgr.getToolManager(); BuildTargetOperation buildOperation = newBuildTarget.getBuildOperation(toolMgr, opMonitor); - return buildOperation.getEffectiveProccessCommandLine(); + return buildOperation.getConfiguredProcessBuilder().command(); } /* ----------------- ----------------- */ diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/ToolManager.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/ToolManager.java index ca7716d5d..1e483b92d 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/ToolManager.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/ToolManager.java @@ -114,7 +114,11 @@ public final ProcessBuilder createToolProcessBuilder(IProject project, Path tool } public ProcessBuilder createToolProcessBuilder(Indexable commandLine, Location workingDir) { - return ProcessUtils.createProcessBuilder(commandLine, workingDir); + return modifyToolProcessBuilder(ProcessUtils.createProcessBuilder(commandLine, workingDir)); + } + + public ProcessBuilder modifyToolProcessBuilder(ProcessBuilder pb) { + return pb; } public ProcessBuilder createSimpleProcessBuilder(IProject project, String... commands) diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/BuildTargetOperation.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/BuildTargetOperation.java index b5a859379..68160f13a 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/BuildTargetOperation.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/BuildTargetOperation.java @@ -20,6 +20,7 @@ import melnorme.lang.ide.core.operations.ILangOperationsListener_Default.IOperationMonitor; import melnorme.lang.ide.core.operations.ToolManager; import melnorme.lang.ide.core.utils.ProgressSubTaskHelper; +import melnorme.lang.tooling.data.StatusException; import melnorme.utilbox.collections.Indexable; import melnorme.utilbox.concurrency.OperationCancellation; import melnorme.utilbox.core.CommonException; @@ -75,16 +76,16 @@ protected String getBuildOperationName() { public Indexable getEffectiveProccessCommandLine() throws CommonException { VariablesResolver variablesManager = toolManager.getVariablesManager(option(getProject())); - return buildCommand.getValidatedCommandArguments(variablesManager).getValidatedValue(); + return buildCommand.validateCommandArguments(variablesManager); } - public ProcessBuilder getToolProcessBuilder() throws CommonException, OperationCancellation { - return getProcessBuilder3(getEffectiveProccessCommandLine()); + public ProcessBuilder getConfiguredProcessBuilder() throws StatusException { + VariablesResolver variablesManager = toolManager.getVariablesManager(option(getProject())); + return buildCommand.getProcessBuilder(variablesManager); } - protected ProcessBuilder getProcessBuilder3(Indexable commandLine) - throws CommonException, OperationCancellation { - return getToolManager().createToolProcessBuilder(commandLine, getProjectLocation()); + public ProcessBuilder getToolProcessBuilder() throws CommonException, OperationCancellation { + return getToolManager().modifyToolProcessBuilder(getConfiguredProcessBuilder()); } public void runBuildToolAndProcessOutput(ProcessBuilder pb, IProgressMonitor pm) diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/CommandInvocation.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/CommandInvocation.java index 4c255ccc4..a398dc3c7 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/CommandInvocation.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/build/CommandInvocation.java @@ -13,11 +13,15 @@ import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import static melnorme.utilbox.core.CoreUtil.areEqual; +import java.util.Map; +import java.util.Map.Entry; + import org.eclipse.debug.core.DebugPlugin; import melnorme.lang.tooling.data.Severity; import melnorme.lang.tooling.data.StatusException; import melnorme.lang.tooling.data.validation.ValidatedValueSource; +import melnorme.lang.utils.ProcessUtils; import melnorme.utilbox.collections.ArrayList2; import melnorme.utilbox.collections.HashMap2; import melnorme.utilbox.collections.Indexable; @@ -73,8 +77,31 @@ public boolean isAppendEnvironment() { /* ----------------- ----------------- */ + public ProcessBuilder getProcessBuilder(VariablesResolver variablesResolver) throws StatusException { + Indexable CommandLine = validateCommandArguments(variablesResolver); + + ProcessBuilder pb = ProcessUtils.createProcessBuilder(CommandLine, null); + + setupEnvironment(pb.environment()); + + return pb; + } + + public void setupEnvironment(Map environment) { + if(!isAppendEnvironment()) { + environment.clear(); + } + for (Entry envVar : getEnvironmentVars()) { + environment.put(envVar.getKey(), envVar.getValue()); + } + } + public void validate(VariablesResolver variablesResolver) throws StatusException { - getValidatedCommandArguments(variablesResolver).validate(); + validateCommandArguments(variablesResolver); + } + + public Indexable validateCommandArguments(VariablesResolver variablesResolver) throws StatusException { + return getValidatedCommandArguments(variablesResolver).getValidatedValue(); } public ValidatedCommandArgumentsSource getValidatedCommandArguments(VariablesResolver variablesResolver) { diff --git a/plugin_tooling/src-lang/melnorme/lang/utils/ProcessUtils.java b/plugin_tooling/src-lang/melnorme/lang/utils/ProcessUtils.java index 83e5a6f20..e05134ff9 100644 --- a/plugin_tooling/src-lang/melnorme/lang/utils/ProcessUtils.java +++ b/plugin_tooling/src-lang/melnorme/lang/utils/ProcessUtils.java @@ -12,7 +12,6 @@ import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue; -import java.io.File; import java.nio.file.Path; import melnorme.lang.tooling.ToolingMessages; @@ -24,16 +23,11 @@ public class ProcessUtils { public static ProcessBuilder createProcessBuilder(Indexable commandLine, Location workingDir) { - File file = workingDir == null ? null : workingDir.toFile(); - return createProcessBuilder(commandLine, file); - } - - public static ProcessBuilder createProcessBuilder(Indexable commandLine, File workingDir) { assertTrue(commandLine.size() > 0); ProcessBuilder pb = new ProcessBuilder(commandLine.toArrayList()); if(workingDir != null) { - pb.directory(workingDir); + pb.directory(workingDir.toFile()); } return pb; }