Sync git svn branch with SVN repository r33269.
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 30 Sep 2016 07:59:43 +0000 (10:59 +0300)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 30 Sep 2016 07:59:43 +0000 (10:59 +0300)
refs #6724
refs #6723
refs #6704
refs #6495

29 files changed:
bundles/org.simantics.charts/src/org/simantics/charts/Charts.java
bundles/org.simantics.charts/src/org/simantics/charts/ITrendSupport.java
bundles/org.simantics.diagram/src/org/simantics/diagram/elements/TextNode.java
bundles/org.simantics.diagram/src/org/simantics/diagram/ui/WorkbenchSelectionProvider.java
bundles/org.simantics.document.server.io/src/org/simantics/document/server/io/IAbstractRequestInterface.java
bundles/org.simantics.document.server.io/src/org/simantics/document/server/io/JSONObjectUtils.java
bundles/org.simantics.document.server/scl/Document/All.scl
bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLHandlerValueRequest.java
bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementJSON.java [new file with mode: 0644]
bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java
bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementTransferableProvider.java [new file with mode: 0644]
bundles/org.simantics.modeling/src/org/simantics/modeling/scl/SCLNodeManager.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/NodeEventHandler.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/adapter/AWTMouseEventAdapter.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionNode.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SingleElementNode.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TransferableProvider.java [new file with mode: 0644]
bundles/org.simantics.ui/src/org/simantics/ui/dnd/MultiTransferable.java
bundles/org.simantics.ui/src/org/simantics/ui/dnd/PlaintextTransfer.java
bundles/org.simantics.utils.ui.workbench/src/org/simantics/utils/ui/workbench/dialogs/ColorDialog.java [new file with mode: 0644]
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/Color.java
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorComposite.java
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorDialog.java [new file with mode: 0644]
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorGradient.java
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorGradientAdjustingCanvas.java [new file with mode: 0644]
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorGradientCanvas.java
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorGradientComposite.java
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorGradientComposite2.java [new file with mode: 0644]
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorValue.java

index dd7ae02a08bf809c4b5aaa607a7681e89af5520b..1e503159e0cb8af4585ce6a17882dbd0440cb0c1 100644 (file)
@@ -3,7 +3,6 @@ package org.simantics.charts;
 import java.util.Collections;\r
 import java.util.List;\r
 \r
-import org.simantics.Simantics;\r
 import org.simantics.charts.editor.ChartData;\r
 import org.simantics.charts.editor.ChartKeys;\r
 import org.simantics.databoard.binding.error.BindingException;\r
@@ -12,6 +11,7 @@ import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;\r
 import org.simantics.db.common.request.PossibleIndexRoot;\r
 import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.variable.Variable;\r
 import org.simantics.history.HistoryException;\r
 import org.simantics.history.HistorySamplerItem;\r
 import org.simantics.history.ItemManager;\r
@@ -19,7 +19,7 @@ import org.simantics.history.util.subscription.SamplingFormat;
 import org.simantics.modeling.subscription.SubscriptionItem;\r
 import org.simantics.modeling.subscription.SubscriptionItemQuery;\r
 import org.simantics.project.IProject;\r
-import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+import org.simantics.simulation.experiment.IExperiment;\r
 \r
 /**\r
  * Main facade for externally dealing with the trending system.\r
@@ -38,40 +38,38 @@ public final class Charts {
         }\r
     }\r
 \r
-       public static HistorySamplerItem createHistorySamplerItem(ReadGraph graph, Resource subscriptionItem) throws DatabaseException {\r
-               \r
-               try {\r
-\r
-                       Resource model = graph.syncRequest(new PossibleIndexRoot(subscriptionItem));\r
-                       if ( model == null ) {\r
-                               throw new DatabaseException("There is no model for " + subscriptionItem);\r
-                       }\r
-\r
-                       Key chartDataKey = ChartKeys.chartSourceKey(model);\r
+       public static HistorySamplerItem createHistorySamplerItem(ReadGraph graph, Variable run, Resource subscriptionItem) throws DatabaseException {\r
+                       IExperiment exp = (IExperiment) run.getPropertyValue(graph, "iExperiment");\r
+                       ITrendSupport support = exp.getService(ITrendSupport.class);\r
+                       ChartData data = support.getChartData();\r
+                       return createHistorySamplerItem(graph, subscriptionItem, data);\r
+       }\r
 \r
-                       final ChartData data = Simantics.getProject().getHint(chartDataKey);\r
-                       if ( data == null ) {\r
-                               throw new DatabaseException("There is no chart data for " + model);\r
-                       }\r
+    public static HistorySamplerItem createHistorySamplerItem(ReadGraph graph, Resource subscriptionItem, ChartData data) throws DatabaseException {\r
 \r
-                       ItemManager im = new ItemManager( data.history.getItems() );\r
+        try {\r
+            Resource model = graph.syncRequest(new PossibleIndexRoot(subscriptionItem));\r
+            if (model == null) {\r
+                throw new DatabaseException("There is no model for " + subscriptionItem);\r
+            }\r
 \r
-                       SubscriptionItem i = graph.syncRequest(new SubscriptionItemQuery(subscriptionItem));\r
+            ItemManager im = new ItemManager(data.history.getItems());\r
 \r
-                       List<Bean> items = im.search("variableId", i.variableId);\r
-                       Collections.sort(items, SamplingFormat.INTERVAL_COMPARATOR);\r
-                       if (items.isEmpty()) new DatabaseException("There is history item for " + i.variableId);\r
-                       Bean config = items.get(0);\r
-                       String historyId = (String) config.getFieldUnchecked("id");\r
+            SubscriptionItem i = graph.syncRequest(new SubscriptionItemQuery(subscriptionItem));\r
 \r
-                       return new HistorySamplerItem(data.collector, data.history, historyId, System.identityHashCode(data));\r
+            List<Bean> items = im.search("variableId", i.variableId);\r
+            Collections.sort(items, SamplingFormat.INTERVAL_COMPARATOR);\r
+            if (items.isEmpty())\r
+                new DatabaseException("There is history item for " + i.variableId);\r
+            Bean config = items.get(0);\r
+            String historyId = (String) config.getFieldUnchecked("id");\r
 \r
-               } catch (HistoryException e) {\r
-                       throw new DatabaseException(e);\r
-               } catch (BindingException e) {\r
-                       throw new DatabaseException(e);\r
-               }\r
-       \r
-       }\r
+            return new HistorySamplerItem(data.collector, data.history, historyId, System.identityHashCode(data));\r
+        } catch (HistoryException e) {\r
+            throw new DatabaseException(e);\r
+        } catch (BindingException e) {\r
+            throw new DatabaseException(e);\r
+        }\r
+    }\r
 \r
 }\r
index c7a1f84a286c64ff3ff428240cd686ee629d2673..d1c374e60b94c41ae650060863a426ceb906ffe2 100644 (file)
@@ -1,5 +1,6 @@
 package org.simantics.charts;\r
 \r
+import org.simantics.charts.editor.ChartData;\r
 import org.simantics.db.ReadGraph;\r
 import org.simantics.db.exception.DatabaseException;\r
 \r
@@ -7,4 +8,6 @@ public interface ITrendSupport {
 \r
        void setChartData(ReadGraph graph) throws DatabaseException;\r
        \r
+       ChartData getChartData();\r
+       \r
 }\r
index ed8df095a72b587f297002fcc3ecca9d80852e04..96cd573cc626860a43d51775d7cb20106ca98a3b 100644 (file)
@@ -11,8 +11,6 @@
  *******************************************************************************/\r
 package org.simantics.diagram.elements;\r
 \r
-import gnu.trove.list.array.TIntArrayList;\r
-\r
 import java.awt.AlphaComposite;\r
 import java.awt.BasicStroke;\r
 import java.awt.Color;\r
@@ -42,6 +40,7 @@ import java.text.AttributedString;
 import java.util.ArrayList;\r
 import java.util.Arrays;\r
 import java.util.Hashtable;\r
+import java.util.List;\r
 \r
 import org.simantics.datatypes.literal.RGB;\r
 import org.simantics.db.layer0.variable.RVI;\r
@@ -62,15 +61,17 @@ import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent;
 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDoubleClickedEvent;\r
 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin;\r
 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;\r
+import org.simantics.scenegraph.g2d.events.NodeEventHandler;\r
 import org.simantics.scenegraph.g2d.events.command.CommandEvent;\r
 import org.simantics.scenegraph.g2d.events.command.Commands;\r
-import org.simantics.scenegraph.g2d.events.NodeEventHandler;\r
 import org.simantics.scenegraph.utils.GeometryUtils;\r
 import org.simantics.scenegraph.utils.NodeUtil;\r
 import org.simantics.scl.runtime.function.Function1;\r
 import org.simantics.scl.runtime.function.Function2;\r
 import org.simantics.ui.colors.Colors;\r
 import org.simantics.ui.dnd.LocalObjectTransferable;\r
+import org.simantics.ui.dnd.MultiTransferable;\r
+import org.simantics.ui.dnd.PlaintextTransfer;\r
 import org.simantics.ui.fonts.Fonts;\r
 import org.simantics.utils.threads.AWTThread;\r
 \r
@@ -82,6 +83,8 @@ import com.lowagie.text.pdf.PdfFormField;
 import com.lowagie.text.pdf.PdfWriter;\r
 import com.lowagie.text.pdf.TextField;\r
 \r
+import gnu.trove.list.array.TIntArrayList;\r
+\r
 \r
 /**\r
  * TextNode which supports in-line editing.\r
@@ -1858,9 +1861,19 @@ public class TextNode extends G2DNode implements IDynamicSelectionPainterNode, L
         if (isHovering()\r
                 && (isControlDown(e) || isShiftDown(e))\r
                 && e.context instanceof NodeEventHandler\r
-                && dataRVI != null)\r
+                && (dataRVI != null || text != null))\r
         {\r
-            e.transferable = new LocalObjectTransferable(dataRVI);\r
+            List<Transferable> trs = new ArrayList<>(2);\r
+            if (dataRVI != null) {\r
+                trs.add(new LocalObjectTransferable(dataRVI));\r
+                trs.add(new PlaintextTransfer(dataRVI.toString()));\r
+            } else if (text != null && !text.isEmpty()) {\r
+                trs.add(new PlaintextTransfer(text));\r
+            }\r
+            if (!trs.isEmpty()) {\r
+                e.transferable = new MultiTransferable(trs);\r
+                return true;\r
+            }\r
         }\r
         return false;\r
     }\r
@@ -1930,7 +1943,7 @@ public class TextNode extends G2DNode implements IDynamicSelectionPainterNode, L
     @Override\r
     public int getEventMask() {\r
         return EventTypes.KeyPressedMask | EventTypes.MouseMovedMask | EventTypes.MouseButtonPressedMask\r
-                | EventTypes.MouseClickMask | EventTypes.CommandMask;\r
+                | EventTypes.MouseClickMask | EventTypes.MouseDragBeginMask | EventTypes.CommandMask;\r
     }\r
 \r
     private MouseEvent lastMouseEvent = null;\r
index 096fd7aae54fc21adf301415d37728a7a3031a24..aa50762782398a452ff6cb8116e61592d62d9d53 100644 (file)
@@ -13,6 +13,7 @@ package org.simantics.diagram.ui;
 \r
 import java.util.ArrayList;\r
 import java.util.Collections;\r
+import java.util.Optional;\r
 import java.util.concurrent.CopyOnWriteArrayList;\r
 import java.util.concurrent.TimeUnit;\r
 \r
@@ -22,14 +23,18 @@ import org.eclipse.jface.viewers.ISelectionChangedListener;
 import org.eclipse.jface.viewers.SelectionChangedEvent;\r
 import org.eclipse.jface.viewers.StructuredSelection;\r
 import org.eclipse.ui.IWorkbenchPartSite;\r
+import org.simantics.Logger;\r
+import org.simantics.db.exception.DatabaseException;\r
 import org.simantics.diagram.elements.AdaptableImmutableProxyElement;\r
 import org.simantics.g2d.canvas.ICanvasContext;\r
 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;\r
 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;\r
 import org.simantics.g2d.canvas.impl.HintReflection.HintListener;\r
+import org.simantics.g2d.diagram.participant.ElementJSON;\r
 import org.simantics.g2d.diagram.participant.Selection;\r
 import org.simantics.g2d.element.ElementHints;\r
 import org.simantics.g2d.element.IElement;\r
+import org.simantics.ui.selection.WorkbenchSelectionUtils;\r
 import org.simantics.utils.datastructures.hints.IHintObservable;\r
 import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
 import org.simantics.utils.threads.IThreadWorkQueue;\r
@@ -41,7 +46,7 @@ import org.simantics.utils.threads.ThreadUtils;
  * \r
  * @author Tuukka Lehtonen\r
  */\r
-public class WorkbenchSelectionProvider extends AbstractCanvasParticipant implements IPostSelectionProvider {\r
+public class WorkbenchSelectionProvider extends AbstractCanvasParticipant implements IPostSelectionProvider, ElementJSON {\r
 \r
     private static final long                                 POST_SELECTION_DELAY = 300;\r
 \r
@@ -205,4 +210,15 @@ public class WorkbenchSelectionProvider extends AbstractCanvasParticipant implem
         System.out.println("WorkbenchSelectionProvider: TODO: set selection: " + selection);\r
     }\r
 \r
+    @Override\r
+    public Optional<String> getJSON(IElement element) {\r
+        ISelection sel = constructAdaptableSelection(Collections.singleton(element));\r
+        try {\r
+            return Optional.ofNullable( WorkbenchSelectionUtils.getPossibleJSON(sel) );\r
+        } catch (DatabaseException e) {\r
+            Logger.defaultLogError(e);\r
+            return Optional.empty();\r
+        }\r
+    }\r
+\r
 }\r
index 0419534909e6bdc73df3c28efc63c854f0616b0d..c7bd2939271d5c48f6f69da87238e0120976bc9d 100644 (file)
@@ -6,6 +6,7 @@ public interface IAbstractRequestInterface {
        void createSession(String sessionGUID, IConsole console);\r
        void deleteSession(String sessionGUID);\r
        void setInputURI(String sessionGUID, String inputURI);\r
+       void setSessionParameter(String sessionGUID, String parameterName, Object value);\r
        public IJSONResult requestDocument(String document, int sequenceNumber, int pollingHint, String sessionGUID);\r
        public String requestDocumentURI(String alias);\r
        String requestCSS(String documentURI);\r
index 794b9e55b364a524c9e5a8fe583e153c10d8d429..c9e438af647aa258311422262443918949980607 100644 (file)
@@ -62,7 +62,11 @@ public class JSONObjectUtils {
     public static boolean selected(IJSONObject object) {\r
         return getValueOrDefault(object, "selected", false);\r
     }\r
-    \r
+\r
+    public static boolean followEditMode(IJSONObject object) {\r
+        return getValueOrDefault(object, "followEditMode", true);\r
+    }\r
+\r
     public static String getType(IJSONObject object) {\r
        String result = (String)object.getValue("type");\r
        if(result == null) throw new IllegalStateException("No type for object " + object);\r
index 3d63eaf6a9463ade923a41b168ac0ba78a4d9fd5..1f567a6fce500ce549597c6cf4d5b7913bc05a52 100644 (file)
@@ -1,9 +1,11 @@
 import "Simantics/DB"\r
 import "Simantics/Variables"\r
+import "JavaBuiltin" as Java\r
 \r
 importJava "org.simantics.document.server.io.IConsole" where\r
     data IConsole\r
     addMessage :: IConsole -> String -> <Proc> ()\r
+    sendEvent :: IConsole -> String -> String -> Vector Dynamic -> <Proc> ()\r
 \r
 importJava "org.simantics.document.server.io.IDocument" where\r
     data IDocument\r
@@ -63,11 +65,19 @@ importJava "org.simantics.document.server.io.CommandContextMutable" where
     \r
     putValue :: CommandContextMutable -> String -> a -> <Proc> CommandContextMutable\r
 \r
+    merge :: CommandContextMutable -> CommandContext -> <Proc> CommandContextMutable    \r
+\r
 importJava "org.simantics.document.server.io.CommandContextImpl" where\r
 \r
     @JavaName create\r
     commandContext :: () -> CommandContextMutable\r
 \r
+instance Coercible CommandContextMutable CommandContext where\r
+    coerce = Java.unsafeCoerce\r
+\r
+cloneCommandContext :: CommandContext -> <Proc> CommandContextMutable\r
+cloneCommandContext context = merge (commandContext ()) context\r
+\r
 importJava "org.simantics.document.server.io.CommandResult" where\r
     data CommandResult\r
 \r
index ab72524b3f6260b75686d3538a8bafc1b2dab491..ca82be6c94ee53d624fdcb539573186602cb962e 100644 (file)
@@ -1,5 +1,6 @@
 package org.simantics.document.server.request;\r
 \r
+import java.util.HashMap;\r
 import java.util.List;\r
 import java.util.Map;\r
 \r
@@ -8,16 +9,21 @@ import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;\r
 import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
 import org.simantics.db.common.request.IndexRoot;\r
-import org.simantics.db.common.request.UnaryRead;\r
 import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.request.VariableRead;\r
 import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext;\r
 import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest;\r
 import org.simantics.db.layer0.util.RuntimeEnvironmentRequest;\r
 import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.document.server.Functions;\r
+import org.simantics.document.server.bean.DataDefinition;\r
 import org.simantics.document.server.request.ServerSCLHandlerValueRequest.CompilationContext;\r
 import org.simantics.layer0.Layer0;\r
+import org.simantics.scl.compiler.constants.StringConstant;\r
 import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
 import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVar;\r
 import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
 import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
@@ -37,6 +43,7 @@ import org.simantics.utils.datastructures.Pair;
 \r
 public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationRequest<CompilationContext, Variable> {\r
 \r
+       private final Variable context;\r
        private final Pair<Resource,Resource> componentTypeAndRoot;\r
        private final Resource literal;\r
 \r
@@ -50,14 +57,15 @@ public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationR
                }\r
        }\r
 \r
-       private ServerSCLHandlerValueRequest(Pair<Resource,Resource> componentTypeAndRoot, Resource literal) {\r
+       private ServerSCLHandlerValueRequest(Variable context, Pair<Resource,Resource> componentTypeAndRoot, Resource literal) {\r
                assert(literal != null);\r
+               this.context = context;\r
                this.literal = literal;\r
                this.componentTypeAndRoot = componentTypeAndRoot;\r
        }\r
 \r
        public ServerSCLHandlerValueRequest(ReadGraph graph, Variable context) throws DatabaseException {\r
-               this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph));\r
+               this(context, getComponentTypeAndRoot(graph, context), context.getRepresents(graph));\r
        }\r
 \r
        private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Variable property)  throws DatabaseException {\r
@@ -122,19 +130,31 @@ public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationR
        }\r
 \r
        @Override\r
-       protected CompilationContext getCompilationContext(ReadGraph graph)\r
-                       throws DatabaseException {\r
-               return graph.syncRequest(new UnaryRead<Pair<Resource,Resource>,CompilationContext>(componentTypeAndRoot) {\r
+       protected CompilationContext getCompilationContext(ReadGraph graph) throws DatabaseException {\r
+               \r
+               return graph.syncRequest(new VariableRead<CompilationContext>(context) {\r
+                       \r
                        @Override\r
-                       public CompilationContext perform(ReadGraph graph)\r
-                                       throws DatabaseException {\r
+                       public CompilationContext perform(ReadGraph graph) throws DatabaseException {\r
+                               \r
+                               Pair<Resource,Resource> parameter = getComponentTypeAndRoot(graph, variable);\r
                                RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.second));\r
+                               \r
                                Map<String, ComponentTypeProperty> propertyMap =\r
                                                graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),\r
                                                                TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());\r
+\r
+//                             Map<String, ComponentTypeProperty> result = new HashMap<String,ComponentTypeProperty>(propertyMap); \r
+//                             for(DataDefinition dd : Functions.dataDefinitions(graph, variable)) {\r
+//                                     result.put(dd.target, null);\r
+//                             }\r
+                               \r
                                return new CompilationContext(runtimeEnvironment, propertyMap);\r
+                               \r
                        }\r
+                       \r
                });\r
+               \r
        }\r
 \r
        @Override\r
@@ -158,7 +178,6 @@ public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationR
                return getPropertyFlexible(environment, accessInputVariable(environment, contextVariable), name, type);\r
        }\r
 \r
-\r
        @Override\r
        protected Expression getVariableAccessExpression(\r
                        ReadGraph graph,\r
@@ -172,8 +191,26 @@ public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationR
                                        contextVariable,\r
                                        name,\r
                                        property.type == null ? Types.metaVar(Kinds.STAR) : property.type);\r
-               else\r
+               else {\r
+                       \r
+//                     if(context.propertyMap.containsKey(name)) {\r
+//                             \r
+//                             org.simantics.scl.compiler.elaboration.expressions.Variable parametersVariable = new org.simantics.scl.compiler.elaboration.expressions.Variable("context", COMMAND_CONTEXT);\r
+//                             \r
+//                             Environment environment = context.runtimeEnvironment.getEnvironment();\r
+//                             \r
+////                           return new EApply(\r
+////                           new EConstant(environment.getValue(FROM_DYNAMIC), Types.STRING),\r
+//                             return new EApply(\r
+//                                     new EConstant(environment.getValue(CONTEXT_VARIABLE), Types.DYNAMIC),\r
+//                                     new EVariable(parametersVariable),\r
+//                                     new ELiteral(new StringConstant(name)));\r
+//                             \r
+//                     }\r
+                       \r
                        return getSpecialVariableAccessExpression(graph, context, contextVariable, name);\r
+                       \r
+               }\r
        }\r
 \r
        protected Expression getSpecialVariableAccessExpression(ReadGraph graph,\r
@@ -191,16 +228,42 @@ public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationR
 \r
        @Override\r
        public int hashCode() {\r
-               return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode();\r
+               final int prime = 31;\r
+               int result = 1;\r
+               result = prime * result + ((context == null) ? 0 : context.hashCode());\r
+               return result;\r
        }\r
 \r
        @Override\r
        public boolean equals(Object obj) {\r
-               if(this == obj)\r
+               if (this == obj)\r
                        return true;\r
-               if(obj == null || obj.getClass() != getClass())\r
+               if (obj == null)\r
+                       return false;\r
+               if (getClass() != obj.getClass())\r
                        return false;\r
-               ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest)obj;\r
-               return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);\r
+               ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest) obj;\r
+               if (context == null) {\r
+                       if (other.context != null)\r
+                               return false;\r
+               } else if (!context.equals(other.context))\r
+                       return false;\r
+               return true;\r
        }\r
+\r
+//     @Override\r
+//     public int hashCode() {\r
+//             return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode();\r
+//     }\r
+//\r
+//     @Override\r
+//     public boolean equals(Object obj) {\r
+//             if(this == obj)\r
+//                     return true;\r
+//             if(obj == null || obj.getClass() != getClass())\r
+//                     return false;\r
+//             ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest)obj;\r
+//             return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);\r
+//     }\r
+       \r
 }\r
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementJSON.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementJSON.java
new file mode 100644 (file)
index 0000000..ffeb83f
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************\r
+ * Copyright (c) 2016 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.g2d.diagram.participant;\r
+\r
+import java.util.Optional;\r
+\r
+import org.simantics.g2d.canvas.ICanvasParticipant;\r
+import org.simantics.g2d.element.IElement;\r
+\r
+/**\r
+ * @author Antti Villberg\r
+ */\r
+public interface ElementJSON extends ICanvasParticipant {\r
+       \r
+       /**\r
+        * @param element\r
+        * @return JSON that describes the provided diagram element\r
+        */\r
+       public Optional<String> getJSON(IElement element);\r
+\r
+}\r
index 977f2be251388501e00d0f4a5a4996dab1d9c667..a35b65cccd6aba1451bcc154da9bb2ce47492afe 100644 (file)
@@ -557,6 +557,7 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos
             ConnectionNode holder = e.getHint(sgKey);\r
             if (holder == null) {\r
                 holder = parentNode.addNode(ElementUtils.generateNodeId(e), ConnectionNode.class);\r
+                holder.setTransferableProvider(new ElementTransferableProvider(getContext(), e));\r
                 e.setHint(sgKey, holder);\r
                 holder.setZIndex(parentNode.getNodeCount() + 1);\r
             }\r
@@ -566,6 +567,7 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos
             SingleElementNode holder = e.getHint(sgKey);\r
             if (holder == null) {\r
                 holder = parentNode.addNode(ElementUtils.generateNodeId(e), SingleElementNode.class);\r
+                holder.setTransferableProvider(new ElementTransferableProvider(getContext(), e));\r
                 e.setHint(sgKey, holder);\r
                 holder.setZIndex(parentNode.getNodeCount() + 1);\r
             }\r
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementTransferableProvider.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementTransferableProvider.java
new file mode 100644 (file)
index 0000000..6d07496
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************\r
+ * Copyright (c) 2016 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.g2d.diagram.participant;\r
+\r
+import java.awt.datatransfer.Transferable;\r
+\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.scenegraph.g2d.nodes.TransferableProvider;\r
+import org.simantics.ui.dnd.PlaintextTransfer;\r
+\r
+/**\r
+ * @author Antti Villberg, Tuukka Lehtonen\r
+ */\r
+public class ElementTransferableProvider implements TransferableProvider {\r
+\r
+       final private ICanvasContext context;\r
+       final private IElement element;\r
+       \r
+       public ElementTransferableProvider(ICanvasContext context, IElement element) {\r
+               this.context = context;\r
+               this.element = element;\r
+       }\r
+       \r
+       @Override\r
+       public Transferable create() {\r
+               ElementJSON converter = context.getAtMostOneItemOfClass(ElementJSON.class);\r
+               if (converter == null)\r
+                       return null;\r
+               return converter.getJSON(element).map(PlaintextTransfer::new).orElse(null);\r
+       }\r
+\r
+}\r
index a062eb76bfb1a00a52fd924d7c54f462a3e5222e..8a0ee6ef1715ee91477976e6eac24440c2745033 100644 (file)
@@ -11,6 +11,7 @@ import org.simantics.databoard.binding.Binding;
 import org.simantics.databoard.type.Datatype;\r
 import org.simantics.db.exception.DatabaseException;\r
 import org.simantics.db.layer0.variable.NodeSupport;\r
+import org.simantics.modeling.ModelingResources;\r
 import org.simantics.scl.compiler.types.Type;\r
 import org.simantics.simulator.variable.Realm;\r
 import org.simantics.simulator.variable.exceptions.NodeManagerException;\r
@@ -272,6 +273,6 @@ public class SCLNodeManager extends AbstractNodeManager<String> {
     \r
     @Override\r
     public String getPropertyURI(String parent, String property) {\r
-        return "http://www.simantics.org/Modeling-1.2/CommandSession/hasValue";\r
+        return ModelingResources.URIs.SCLCommandSession_hasValue;\r
     }\r
 }\r
index d1f6e6ef2da50f32399b0b914d4bc02692738e21..ac0e36f73804b8c171db1282dabe05707c6097b9 100644 (file)
@@ -20,10 +20,12 @@ import java.awt.dnd.DragSourceDragEvent;
 import java.awt.dnd.DragSourceDropEvent;\r
 import java.awt.dnd.DragSourceEvent;\r
 import java.awt.dnd.DragSourceListener;\r
+import java.awt.event.InputEvent;\r
 import java.awt.geom.Point2D;\r
 import java.util.ArrayList;\r
 import java.util.Arrays;\r
 import java.util.Comparator;\r
+import java.util.List;\r
 \r
 import org.simantics.scenegraph.INode;\r
 import org.simantics.scenegraph.g2d.G2DFocusManager;\r
@@ -31,6 +33,7 @@ import org.simantics.scenegraph.g2d.G2DSceneGraph;
 import org.simantics.scenegraph.g2d.IG2DNode;\r
 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;\r
 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin;\r
+import org.simantics.scenegraph.g2d.events.adapter.AWTMouseEventAdapter;\r
 import org.simantics.scenegraph.g2d.events.command.CommandEvent;\r
 
 /**\r
@@ -44,6 +47,8 @@ public class NodeEventHandler implements IEventHandler {
     private static final boolean DEBUG_EVENTS       = false;\r
     private static final boolean DEBUG_HANDLER_SORT = false;\r
 \r
+    private static final IEventHandler[] NONE = {};\r
+\r
     public static class TreePreOrderComparator implements Comparator<IEventHandler> {\r
 \r
         static enum Order {\r
@@ -146,120 +151,129 @@ public class NodeEventHandler implements IEventHandler {
     TreePreOrderComparator COMPARATOR = new TreePreOrderComparator(TreePreOrderComparator.Order.DESCENDING);\r
 \r
     /**\r
-     * FocusEvents are propagated to event handlers in undefined order.\r
+     * {@link FocusEvent} are propagated first to the scene graph focus node,\r
+     * then to event handler nodes in scene graph tree pre-order.\r
      */\r
-    protected ListenerList<IEventHandler> focusListeners         = new ListenerList<IEventHandler>(IEventHandler.class);\r
+    protected List<IEventHandler>         focusListeners         = new ArrayList<IEventHandler>();\r
+    protected IEventHandler[]             sortedFocusListeners   = null;\r
 \r
     /**\r
-     * TimeEvents are propagated to events handlers in an undefined order.\r
+     * {@link TimeEvent} are propagated first to the scene graph focus node,\r
+     * then to event handler nodes in scene graph tree pre-order.\r
      */\r
-    protected ListenerList<IEventHandler> timeListeners          = new ListenerList<IEventHandler>(IEventHandler.class);\r
+    protected List<IEventHandler>         timeListeners          = new ArrayList<IEventHandler>();\r
+    protected IEventHandler[]             sortedTimeListeners    = null;\r
 \r
     /**\r
-     * CommandEvents are propagated first to the scene graph focus node, then to\r
-     * event handler nodes in scene graph tree pre-order.\r
+     * {@link CommandEvent} are propagated first to the scene graph focus node,\r
+     * then to event handler nodes in scene graph tree pre-order.\r
      */\r
-    protected ListenerList<IEventHandler> commandListeners       = new ListenerList<IEventHandler>(IEventHandler.class);\r
+    protected List<IEventHandler>         commandListeners       = new ArrayList<IEventHandler>();\r
     protected IEventHandler[]             sortedCommandListeners = null;\r
 \r
     /**\r
-     * KeyEvents are propagated first to the scene graph focus node, then to\r
-     * event handler nodes in scene graph tree pre-order.\r
+     * {@link KeyEvent} are propagated first to the scene graph focus node, then\r
+     * to event handler nodes in scene graph tree pre-order.\r
      */\r
-    protected ListenerList<IEventHandler> keyListeners           = new ListenerList<IEventHandler>(IEventHandler.class);\r
+    protected List<IEventHandler>         keyListeners           = new ArrayList<IEventHandler>();\r
     protected IEventHandler[]             sortedKeyListeners     = null;\r
 \r
     /**\r
-     * MouseEvents are propagated first to the scene graph focus node, then to\r
-     * event handler nodes in scene graph tree pre-order.\r
+     * {@link MouseEvent} are propagated first to the scene graph focus node,\r
+     * then to event handler nodes in scene graph tree pre-order.\r
      */\r
-    protected ListenerList<IEventHandler> mouseListeners         = new ListenerList<IEventHandler>(IEventHandler.class);\r
+    protected List<IEventHandler>         mouseListeners         = new ArrayList<IEventHandler>();\r
     protected IEventHandler[]             sortedMouseListeners   = null;\r
+\r
+    /**\r
+     * {@link MouseDragBegin} events are propagated first to the scene graph focus node, then\r
+     * to event handler nodes in scene graph tree pre-order.\r
+     */\r
+    protected List<IEventHandler>         mouseDragBeginListeners = new ArrayList<IEventHandler>();\r
+    protected IEventHandler[]             sortedMouseDragBeginListeners = null;\r
 
     /**\r
      * The scene graph this instance handles event propagation for.\r
      */\r
     protected G2DSceneGraph               sg;\r
-    \r
-    protected DragSource ds = new DragSource();\r
+\r
+    /**\r
+     * For proper initiation of native DnD operations within this AWT-based\r
+     * scenegraph system.\r
+     */\r
+    protected DragSource                  ds = new DragSource();\r
 
     public NodeEventHandler(G2DSceneGraph sg) {\r
         this.sg = sg;
     }
 \r
+    @SuppressWarnings("unused")\r
     private IEventHandler[] sort(IEventHandler[] sort) {\r
         if (DEBUG_HANDLER_SORT)\r
-            debug("sort " + sort.length + " handlers");\r
-        IEventHandler[] copy = Arrays.copyOf(sort, sort.length);\r
-        Arrays.sort(copy, COMPARATOR);\r
-        return copy;\r
+            debug("copy sort " + sort.length + " handlers");\r
+        return sortInplace(Arrays.copyOf(sort, sort.length));\r
     }\r
-    \r
-    public void setRootPane(Component rootPane) {\r
-       \r
-       final DragSourceListener dsl = new DragSourceListener() {\r
-                       \r
-                       @Override\r
-                       public void dropActionChanged(DragSourceDragEvent dsde) {\r
-                       }\r
-                       \r
-                       @Override\r
-                       public void dragOver(DragSourceDragEvent dsde) {\r
-                       }\r
-                       \r
-                       @Override\r
-                       public void dragExit(DragSourceEvent dse) {\r
-                       }\r
-                       \r
-                       @Override\r
-                       public void dragEnter(DragSourceDragEvent dsde) {\r
-                       }\r
-                       \r
-                       @Override\r
-                       public void dragDropEnd(DragSourceDropEvent dsde) {\r
-                       }\r
-               };\r
-               ds.createDefaultDragGestureRecognizer(rootPane, DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK, new DragGestureListener() {\r
-                       \r
-                       @Override\r
-                       public void dragGestureRecognized(DragGestureEvent dge) {\r
-                               MouseDragBegin event = new MouseDragBegin(NodeEventHandler.this,\r
-                                               0, 0, 0, 0, 0,\r
-                                               new Point2D.Double(),new Point2D.Double(),\r
-                                               new Point2D.Double(),new Point2D.Double());\r
-                               handleMouseEvent(event, EventTypes.MouseDragBegin);\r
-                               if(event.transferable != null) {\r
-                                       ds.startDrag(dge, null, event.transferable, dsl);\r
-                                       if (DEBUG_EVENTS)\r
-                                               debug("dragGestureRecognized: startDrag " + event.transferable);\r
-                               }\r
-                       }\r
-               });\r
-               ds.addDragSourceListener(dsl);\r
-       \r
+\r
+    private IEventHandler[] sortInplace(IEventHandler[] sort) {\r
+        if (DEBUG_HANDLER_SORT)\r
+            debug("in-place sort " + sort.length + " handlers");\r
+        Arrays.sort(sort, COMPARATOR);\r
+        return sort;\r
     }\r
 \r
-//    @Override
-//    public void mouseReleased(MouseEvent event) {
-//        Point op = event.getPoint();
-//        for (MouseListener l : mouseListeners.getListeners()) {
-//            MouseEvent e = (MouseEvent) NodeUtil.transformEvent(event,(IG2DNode) l);
-//            l.mouseReleased(e);
-//            event.translatePoint((int)(op.getX()-event.getX()), (int)(op.getY()-event.getY()));
-//            if (e.isConsumed())
-//                break;
-//        }
-//    }
-//
-//    @Override
-//    public void mouseMoved(MouseEvent event) {
-//        for (MouseMotionListener l : mouseMotionListeners.getListeners()) {
-//            MouseEvent e = (MouseEvent) NodeUtil.transformEvent(event,(IG2DNode) l);
-//            l.mouseMoved(e);
-//            if (e.isConsumed())
-//                break;
-//        }
-//    }
+    public void setRootPane(Component rootPane) {\r
+        final DragSourceListener dsl = new DragSourceListener() {\r
+            @Override\r
+            public void dropActionChanged(DragSourceDragEvent dsde) {\r
+            }\r
+            @Override\r
+            public void dragOver(DragSourceDragEvent dsde) {\r
+            }\r
+            @Override\r
+            public void dragExit(DragSourceEvent dse) {\r
+            }\r
+            @Override\r
+            public void dragEnter(DragSourceDragEvent dsde) {\r
+            }\r
+            @Override\r
+            public void dragDropEnd(DragSourceDropEvent dsde) {\r
+            }\r
+        };\r
+        DragGestureListener dgl = new DragGestureListener() {\r
+            @Override\r
+            public void dragGestureRecognized(DragGestureEvent dge) {\r
+                InputEvent ie = dge.getTriggerEvent();\r
+                if (ie instanceof java.awt.event.MouseEvent) {\r
+                    java.awt.event.MouseEvent e = (java.awt.event.MouseEvent) ie;\r
+                    Point2D controlPos = AWTMouseEventAdapter.getControlPosition(e);\r
+                    MouseDragBegin event = new MouseDragBegin(NodeEventHandler.this,\r
+                            e.getWhen(), 0,\r
+                            AWTMouseEventAdapter.getButtonStatus(e),\r
+                            AWTMouseEventAdapter.getStateMask(e),\r
+                            AWTMouseEventAdapter.getMouseButton(e),\r
+                            // TODO: fix canvas position if necessary\r
+                            new Point2D.Double(),\r
+                            controlPos,\r
+                            controlPos,\r
+                            AWTMouseEventAdapter.getScreenPosition(e));\r
+\r
+                    // Send MouseDragBegin to the scenegraph and see\r
+                    // if anyone sets event.transferable to start DnD.\r
+                    handleMouseDragBeginEvent(event, EventTypes.MouseDragBegin);\r
+                    if (event.transferable != null) {\r
+                        ds.startDrag(dge, null, event.transferable, dsl);\r
+                        if (DEBUG_EVENTS)\r
+                            debug("dragGestureRecognized: startDrag " + event.transferable);\r
+                    }\r
+                }\r
+            }\r
+        };\r
+        ds.createDefaultDragGestureRecognizer(\r
+                rootPane,\r
+                DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK,\r
+                dgl);\r
+        ds.addDragSourceListener(dsl);\r
+    }\r
 
     public boolean mousePressed(MouseButtonPressedEvent event) {\r
         G2DFocusManager.INSTANCE.clearFocus();\r
@@ -283,47 +297,65 @@ public class NodeEventHandler implements IEventHandler {
         }\r
     }\r
 \r
-    private boolean handleMouseEvent(MouseEvent e, int eventType) {\r
-        IEventHandler[] sorted = sortedMouseListeners;\r
-        if (sorted == null)\r
-            sortedMouseListeners = sorted = sort(mouseListeners.getListeners());\r
-        return handleEvent(e, sg.getFocusNode(), sorted);\r
-    }\r
-\r
     private boolean handleEvent(Event e, IG2DNode focusNode, IEventHandler[] handlers) {\r
+        int typeMask = EventTypes.toTypeMask(e);\r
         if (focusNode instanceof IEventHandler) {\r
             IEventHandler h = (IEventHandler) focusNode;\r
-            if (eats(h.getEventMask(), EventTypes.toTypeMask(e))) {\r
+            if (eats(h.getEventMask(), typeMask)) {\r
                 if (h.handleEvent(e))\r
                     return true;\r
             }\r
         }\r
         for (IEventHandler l : handlers) {\r
-            if (l.handleEvent(e))\r
-                return true;\r
+            if (eats(l.getEventMask(), typeMask)) {\r
+                if (l.handleEvent(e))\r
+                    return true;\r
+            }\r
         }\r
         return false;\r
     }\r
 \r
+    private boolean handleMouseEvent(MouseEvent e, int eventType) {\r
+        IEventHandler[] sorted = sortedMouseListeners;\r
+        if (sorted == null)\r
+            sortedMouseListeners = sorted = sortInplace(mouseListeners.toArray(NONE));\r
+        return handleEvent(e, sg.getFocusNode(), sorted);\r
+    }\r
+\r
+    private boolean handleMouseDragBeginEvent(MouseEvent e, int eventType) {\r
+        IEventHandler[] sorted = sortedMouseDragBeginListeners;\r
+        if (sorted == null)\r
+            sortedMouseDragBeginListeners = sorted = sortInplace(mouseDragBeginListeners.toArray(NONE));\r
+        // Give null for focusNode because we want to propagate\r
+        // this event in scene tree pre-order only.\r
+        return handleEvent(e, null, sorted);\r
+    }\r
+\r
     private boolean handleFocusEvent(FocusEvent e) {\r
-        return handleEvent(e, null, focusListeners.getListeners());\r
+        IEventHandler[] sorted = sortedFocusListeners;\r
+        if (sorted == null)\r
+            sortedFocusListeners = sorted = sortInplace(focusListeners.toArray(NONE));\r
+        return handleEvent(e, null, sorted);\r
     }\r
 \r
     private boolean handleTimeEvent(TimeEvent e) {\r
-        return handleEvent(e, null, timeListeners.getListeners());\r
+        IEventHandler[] sorted = sortedTimeListeners;\r
+        if (sorted == null)\r
+            sortedTimeListeners = sorted = sortInplace(timeListeners.toArray(NONE));\r
+        return handleEvent(e, null, sorted);\r
     }\r
 \r
     private boolean handleCommandEvent(CommandEvent e) {\r
         IEventHandler[] sorted = sortedCommandListeners;\r
         if (sorted == null)\r
-            sortedCommandListeners = sorted = sort(commandListeners.getListeners());\r
+            sortedCommandListeners = sorted = sortInplace(commandListeners.toArray(NONE));\r
         return handleEvent(e, sg.getFocusNode(), sorted);\r
     }\r
 \r
     private boolean handleKeyEvent(KeyEvent e) {\r
         IEventHandler[] sorted = sortedKeyListeners;\r
         if (sorted == null)\r
-            sortedKeyListeners = sorted = sort(keyListeners.getListeners());\r
+            sortedKeyListeners = sorted = sortInplace(keyListeners.toArray(NONE));\r
         return handleEvent(e, sg.getFocusNode(), sorted);\r
     }\r
 
@@ -350,11 +382,13 @@ public class NodeEventHandler implements IEventHandler {
             case EventTypes.KeyReleased:\r
                 return handleKeyEvent((KeyEvent) e);\r
 \r
+            case EventTypes.MouseDragBegin:\r
+                return handleMouseDragBeginEvent((MouseEvent) e, eventType);\r
+\r
             case EventTypes.MouseButtonPressed:\r
             case EventTypes.MouseButtonReleased:\r
             case EventTypes.MouseClick:\r
             case EventTypes.MouseDoubleClick:\r
-            case EventTypes.MouseDragBegin:\r
             case EventTypes.MouseEnter:\r
             case EventTypes.MouseExit:\r
             case EventTypes.MouseMoved:\r
@@ -378,17 +412,23 @@ public class NodeEventHandler implements IEventHandler {
         }\r
         if (eats(mask, EventTypes.FocusMask)) {\r
             focusListeners.add(item);\r
+            sortedFocusListeners = null;\r
         }\r
         if (eats(mask, EventTypes.KeyMask)) {\r
             keyListeners.add(item);\r
             sortedKeyListeners = null;\r
         }\r
-        if (eats(mask, EventTypes.MouseMask)) {\r
+        if (eats(mask, EventTypes.MouseDragBeginMask)) {\r
+            mouseDragBeginListeners.add(item);\r
+            sortedMouseDragBeginListeners = null;\r
+        }\r
+        if (eats(mask, EventTypes.MouseMask & ~EventTypes.MouseDragBeginMask)) {\r
             mouseListeners.add(item);\r
             sortedMouseListeners = null;\r
         }\r
         if (eats(mask, EventTypes.TimeMask)) {\r
             timeListeners.add(item);\r
+            sortedTimeListeners = null;\r
         }\r
     }\r
 \r
@@ -404,17 +444,23 @@ public class NodeEventHandler implements IEventHandler {
         }\r
         if (eats(mask, EventTypes.FocusMask)) {\r
             removed |= focusListeners.remove(item);\r
+            sortedFocusListeners = null;\r
         }\r
         if (eats(mask, EventTypes.KeyMask)) {\r
             removed |= keyListeners.remove(item);\r
             sortedKeyListeners = null;\r
         }\r
-        if (eats(mask, EventTypes.MouseMask)) {\r
+        if (eats(mask, EventTypes.MouseDragBeginMask)) {\r
+            removed |= mouseDragBeginListeners.remove(item);\r
+            sortedMouseDragBeginListeners = null;\r
+        }\r
+        if (eats(mask, EventTypes.MouseMask & ~EventTypes.MouseDragBeginMask)) {\r
             removed |= mouseListeners.remove(item);\r
             sortedMouseListeners = null;\r
         }\r
         if (eats(mask, EventTypes.TimeMask)) {\r
             removed |= timeListeners.remove(item);\r
+            sortedTimeListeners = null;\r
         }\r
         return removed;\r
     }\r
index 97d0e01f97ccf1a12ebe1757905fd2ef56cf6f44..85f56a34f09e315d288c1be2b290f1d272a57cb0 100644 (file)
@@ -71,17 +71,17 @@ public class AWTMouseEventAdapter extends AbstractEventAdapter implements MouseL
         super(sender, queue);\r
     }\r
 \r
-    private Point2D getControlPosition(MouseEvent e)\r
+    public static Point2D getControlPosition(MouseEvent e)\r
     {\r
         return new Point2D.Double(e.getX(), e.getY());\r
     }\r
 \r
-    private Point2D getScreenPosition(MouseEvent e)\r
+    public static Point2D getScreenPosition(MouseEvent e)\r
     {\r
         return e.getLocationOnScreen();\r
     }\r
 \r
-    private static int getStateMask(MouseEvent e) {\r
+    public static int getStateMask(MouseEvent e) {\r
         int modifiers = e.getModifiersEx();\r
         int stateMask = 0;\r
         if((modifiers & InputEvent.CTRL_DOWN_MASK) != 0)\r
@@ -95,7 +95,7 @@ public class AWTMouseEventAdapter extends AbstractEventAdapter implements MouseL
         return stateMask;\r
     }\r
 \r
-    private int getMouseButton(MouseEvent e)\r
+    public static int getMouseButton(MouseEvent e)\r
     {\r
         int awtMouseButton = e.getButton();\r
         if (awtMouseButton == MouseEvent.BUTTON1)\r
@@ -115,7 +115,7 @@ public class AWTMouseEventAdapter extends AbstractEventAdapter implements MouseL
      * @param e\r
      * @return\r
      */\r
-    private int getButtonStatus(MouseEvent e) {\r
+    public static int getButtonStatus(MouseEvent e) {\r
         int modex = e.getModifiersEx();\r
         int status = 0;\r
         status |= (modex & MouseEvent.BUTTON1_DOWN_MASK) != 0 ? org.simantics.scenegraph.g2d.events.MouseEvent.LEFT_MASK : 0;\r
index 128b0df90f931d871846dc71faf42d32cb57de2f..927619e02100f452329638522af2c804eb669ffe 100644 (file)
@@ -14,9 +14,12 @@ package org.simantics.scenegraph.g2d.nodes;
 import java.awt.Color;\r
 import java.awt.Composite;\r
 import java.awt.Stroke;\r
+import java.awt.geom.Point2D;\r
 \r
+import org.simantics.diagram.connection.RouteGraph;\r
 import org.simantics.scenegraph.INode;\r
 import org.simantics.scenegraph.g2d.IG2DNode;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent;\r
 import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode;\r
 import org.simantics.scenegraph.utils.InitValueSupport;\r
 import org.simantics.scenegraph.utils.NodeUtil;\r
@@ -126,4 +129,25 @@ public class ConnectionNode extends SingleElementNode implements InitValueSuppor
         }\r
     }\r
 \r
+    @Override\r
+    protected boolean hitTest(MouseEvent event) {\r
+        if (!super.hitTest(event))\r
+            return false;\r
+\r
+        Point2D pos = NodeUtil.worldToLocal(this, event.controlPosition, new Point2D.Double());\r
+        double tolerance = 0.5;\r
+        // TODO: change tolerance based on zoom level\r
+\r
+        for (IG2DNode child : getSortedNodes()) {\r
+            if (child instanceof RouteGraphNode) {\r
+                RouteGraphNode rgn = (RouteGraphNode) child;\r
+                RouteGraph rg = rgn.getRouteGraph();\r
+                Object pick = rg.pickLine(pos.getX(), pos.getY(), tolerance);\r
+                if (pick != null)\r
+                    return true;\r
+            }\r
+        }\r
+        return false;\r
+    }\r
+\r
 }\r
index dc40036a7ff794c19dc0a62a34c1cebef715334b..c6a8b950e0e8a6f22218bb70d0637fc2c45360cd 100644 (file)
@@ -14,20 +14,35 @@ package org.simantics.scenegraph.g2d.nodes;
 import java.awt.AlphaComposite;\r
 import java.awt.Composite;\r
 import java.awt.Graphics2D;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
 \r
 import org.simantics.scenegraph.g2d.IG2DNode;\r
+import org.simantics.scenegraph.g2d.events.EventTypes;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin;\r
 import org.simantics.scenegraph.utils.InitValueSupport;\r
+import org.simantics.scenegraph.utils.NodeUtil;\r
 \r
 public class SingleElementNode extends TransformNode implements InitValueSupport {\r
-    /**\r
-     * \r
-     */\r
+\r
     private static final long serialVersionUID = -4982578347433716440L;\r
 \r
+    private TransferableProvider transferableProvider;\r
     protected Composite composite;\r
     protected Boolean visible = Boolean.TRUE;\r
     protected Boolean hidden = Boolean.FALSE;\r
 \r
+    public void setTransferableProvider(TransferableProvider transferableProvider) {\r
+        if (transferableProvider != this.transferableProvider) {\r
+            if (this.transferableProvider != null)\r
+                removeEventHandler(this);\r
+            if (transferableProvider != null)\r
+                addEventHandler(this);\r
+            this.transferableProvider = transferableProvider;\r
+        }\r
+    }\r
+\r
     @Override\r
     public boolean validate() {\r
         return visible && !hidden;\r
@@ -97,34 +112,6 @@ public class SingleElementNode extends TransformNode implements InitValueSupport
         return sb.toString();\r
     }\r
 \r
-//    private INode findChild(String key) {\r
-//\r
-//     INode result = getNode(key);\r
-//     if(result != null) return result;\r
-//\r
-//     for(Map.Entry<String, IG2DNode> entry : children.entrySet()) {\r
-//\r
-//             if(!(entry.getValue() instanceof SingleElementNode)) {\r
-//                     if(entry.getKey().startsWith(key)) return entry.getValue();\r
-//             }\r
-//\r
-//     }\r
-//\r
-//     for(IG2DNode node : getNodes()) {\r
-//\r
-//             if(node instanceof SingleElementNode) {\r
-//\r
-//                     result = ((SingleElementNode)node).findChild(key);\r
-//                     if(result != null) return result;\r
-//\r
-//             }\r
-//\r
-//     }\r
-//\r
-//     return null;\r
-//\r
-//    }\r
-\r
     protected Composite alphaComposite = null;\r
 \r
     @PropertySetter("alpha")\r
@@ -133,26 +120,6 @@ public class SingleElementNode extends TransformNode implements InitValueSupport
         this.alphaComposite = alphaComposite;\r
     }\r
 \r
-//    public void setValue(String key, Object value) {\r
-//\r
-//        if ("alpha".equals(key)) {\r
-//             Float val = Float.parseFloat((String)value);\r
-//             alphaComposite = AlphaComposite.getInstance(AlphaComposite. SRC_OVER, val);\r
-//        } else {\r
-//\r
-//             String[] parts = key.split("\\.");\r
-//             if(parts.length != 2) return;\r
-//\r
-//             INode child = findChild(parts[0]);\r
-//\r
-//             if(child == null) return;\r
-//\r
-////           child.setValue(parts[1], value);\r
-//\r
-//        }\r
-//\r
-//    }\r
-\r
     @Override\r
     public void initValues() {\r
         alphaComposite = null;\r
@@ -163,4 +130,43 @@ public class SingleElementNode extends TransformNode implements InitValueSupport
         }\r
     }\r
 \r
+    @Override\r
+    public void cleanup() {\r
+        if (transferableProvider != null) {\r
+            removeEventHandler(this);\r
+            transferableProvider = null;\r
+        }\r
+        super.cleanup();\r
+    }\r
+\r
+    protected boolean isDragStartEvent(MouseEvent e) {\r
+        return e.isControlDown();\r
+    }\r
+\r
+    protected boolean hitTest(MouseEvent event) {\r
+        Rectangle2D bounds = super.getBoundsInLocal(false);\r
+        if (bounds == null)\r
+            return false;\r
+        Point2D localPos = NodeUtil.worldToLocal(this, event.controlPosition, new Point2D.Double());\r
+        double x = localPos.getX();\r
+        double y = localPos.getY();\r
+        boolean hit = bounds.contains(x, y);\r
+        return hit;\r
+    }\r
+\r
+    @Override\r
+    protected boolean mouseDragged(MouseDragBegin e) {\r
+        if (transferableProvider == null\r
+                || !isDragStartEvent(e)\r
+                || !hitTest(e))\r
+            return false;\r
+        e.transferable = transferableProvider.create();\r
+        return e.transferable != null;\r
+    }\r
+\r
+    @Override\r
+    public int getEventMask() {\r
+        return EventTypes.MouseDragBeginMask;\r
+    }\r
+\r
 }\r
diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TransferableProvider.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TransferableProvider.java
new file mode 100644 (file)
index 0000000..36ef357
--- /dev/null
@@ -0,0 +1,9 @@
+package org.simantics.scenegraph.g2d.nodes;\r
+\r
+import java.awt.datatransfer.Transferable;\r
+\r
+public interface TransferableProvider {\r
+\r
+       public Transferable create();\r
+       \r
+}\r
index 914f84a1afe90a7ac49948cb4f70d7a89909056e..54ec348cb46252226c74aac1acac6a5c96efde0a 100644 (file)
@@ -6,6 +6,7 @@ import java.awt.datatransfer.DataFlavor;
 import java.awt.datatransfer.Transferable;\r
 import java.awt.datatransfer.UnsupportedFlavorException;\r
 import java.io.IOException;\r
+import java.util.Collection;\r
 import java.util.HashMap;\r
 import java.util.Map;\r
 \r
@@ -21,6 +22,14 @@ public class MultiTransferable implements Transferable, ClipboardOwner {
                }\r
        }\r
 \r
+       public MultiTransferable(Collection<Transferable> tr) {\r
+               for(Transferable t : tr) {\r
+                       for(DataFlavor f : t.getTransferDataFlavors()) {\r
+                               transferables.put(f, t);\r
+                       }\r
+               }\r
+       }\r
+\r
        @Override\r
        public void lostOwnership(Clipboard arg0, Transferable arg1) {\r
                for(Transferable t : transferables.values())\r
@@ -44,4 +53,9 @@ public class MultiTransferable implements Transferable, ClipboardOwner {
                return transferables.containsKey(arg0);\r
        }\r
 \r
+       @Override\r
+       public String toString() {\r
+               return "MultiTransferable " + transferables.toString();\r
+       }\r
+\r
 }\r
index b54413a93af4b584ba333a45fb1375972ff4172f..855051ed1f540615fac5e0088ce565c0dbac6b61 100644 (file)
@@ -3,32 +3,38 @@ package org.simantics.ui.dnd;
 import java.awt.datatransfer.DataFlavor;\r
 import java.awt.datatransfer.Transferable;\r
 import java.awt.datatransfer.UnsupportedFlavorException;\r
+import java.io.ByteArrayInputStream;\r
 import java.io.IOException;\r
 \r
 public class PlaintextTransfer implements Transferable {\r
        \r
        final String content;\r
        \r
+       final DataFlavor flavor = DataFlavor.getTextPlainUnicodeFlavor();\r
+       final DataFlavor[] flavors = new DataFlavor[] { flavor };\r
+       final String flavorCharset = flavor.getParameter("charset");\r
+       \r
        public PlaintextTransfer(String content) {\r
                this.content = content;\r
        }\r
 \r
        @Override\r
        public Object getTransferData(DataFlavor arg0) throws UnsupportedFlavorException, IOException {\r
-               if(DataFlavor.getTextPlainUnicodeFlavor().equals(arg0)) {\r
-                       return content;\r
+               if(flavor.equals(arg0)) {\r
+                       byte[] bytes = content.getBytes(flavorCharset);\r
+                       return new ByteArrayInputStream(bytes);\r
                }\r
                return null;\r
        }\r
 \r
        @Override\r
        public DataFlavor[] getTransferDataFlavors() {\r
-               return new DataFlavor[] { DataFlavor.getTextPlainUnicodeFlavor() };\r
+               return flavors;\r
        }\r
 \r
        @Override\r
        public boolean isDataFlavorSupported(DataFlavor arg0) {\r
-               return(DataFlavor.getTextPlainUnicodeFlavor().equals(arg0));\r
+               return flavor.equals(arg0);\r
        }\r
 \r
 }\r
diff --git a/bundles/org.simantics.utils.ui.workbench/src/org/simantics/utils/ui/workbench/dialogs/ColorDialog.java b/bundles/org.simantics.utils.ui.workbench/src/org/simantics/utils/ui/workbench/dialogs/ColorDialog.java
new file mode 100644 (file)
index 0000000..ab61e6d
--- /dev/null
@@ -0,0 +1,137 @@
+package org.simantics.utils.ui.workbench.dialogs;\r
+\r
+import java.io.IOException;\r
+import java.util.Deque;\r
+import java.util.LinkedList;\r
+\r
+import org.eclipse.core.runtime.preferences.InstanceScope;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.preference.IPersistentPreferenceStore;\r
+import org.eclipse.jface.preference.IPreferenceStore;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Group;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.ui.IMemento;\r
+import org.eclipse.ui.preferences.ScopedPreferenceStore;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+import org.simantics.utils.ui.color.Color;\r
+import org.simantics.utils.ui.workbench.StringMemento;\r
+\r
+/**\r
+ * ColorDialog that keeps track used colors.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class ColorDialog extends org.simantics.utils.ui.color.ColorDialog{\r
+       \r
+       public ColorDialog(Shell parentShell) {\r
+               super(parentShell);\r
+       }\r
+\r
+    \r
+    protected Control createDialogArea(Composite parent) {\r
+       initRecent();\r
+       Composite composite = (Composite)super.createDialogArea(parent);\r
+               Group recentGroup = new Group(composite, SWT.NONE);\r
+               recentGroup.setText("Recent colors");\r
+               GridLayoutFactory.fillDefaults().numColumns(8).spacing(2, 2).margins(4, 4).applyTo(recentGroup);\r
+               int i = 0;\r
+               for (Color c : recentColors) {\r
+                       i++;\r
+                       createColorButton(recentGroup, c);\r
+               }\r
+               org.eclipse.swt.graphics.Color c = Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);\r
+               Color color = new Color(c.getRGB());\r
+               for ( ; i < MAX_RECENT_COLORS; i++) {\r
+                       Button button = createColorButton(recentGroup, color);\r
+                       button.setEnabled(false);\r
+               }\r
+               return composite;\r
+    }\r
+    \r
+    @Override\r
+    protected Point getInitialSize() {\r
+        return new Point(400, 450);\r
+    }\r
+    \r
+       private static final int MAX_RECENT_COLORS = 8;\r
+       \r
+       public static final String  RECENT_COLORS = "RECENT_COLORS";\r
+\r
+    private static final String TAG_COLORS                = "color";\r
+    private static final String R_ATTR_NAME               = "r";\r
+    private static final String G_ATTR_NAME               = "g";\r
+    private static final String B_ATTR_NAME               = "b";\r
+    \r
+    private static final String PLUGIN_ID = "org.simantics.utils.ui.workbench";\r
+    \r
+    protected Deque<Color> recentColors;\r
+    \r
+    private void initRecent() {\r
+        IPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, PLUGIN_ID);\r
+        String recentString = store.getString(RECENT_COLORS);\r
+        recentColors = decodeColors(recentString);\r
+    }\r
+    \r
+    private void storeRecent() {\r
+       Color color = getColor();\r
+       recentColors.remove(color);\r
+       recentColors.addFirst(color);\r
+       while(recentColors.size() > MAX_RECENT_COLORS)\r
+               recentColors.removeLast();\r
+       \r
+       IPersistentPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, PLUGIN_ID);\r
+       store.putValue(RECENT_COLORS, encodeColors(recentColors));\r
+       \r
+       if (store.needsSaving())\r
+               try { \r
+                       store.save();\r
+               } catch (IOException e) {\r
+                       ExceptionUtils.logError(e);\r
+               }\r
+    }\r
+    \r
+    @Override\r
+       protected void okPressed() {\r
+               storeRecent();\r
+               super.okPressed();\r
+       }\r
+    \r
+    public static Deque<Color> decodeColors(String recentColorsPref) {\r
+        Deque<Color> result = new LinkedList<Color>();\r
+        try {\r
+            StringMemento sm = new StringMemento(recentColorsPref);\r
+            for (IMemento m : sm.getChildren(TAG_COLORS)) {\r
+               try {\r
+                       int r = m.getInteger(R_ATTR_NAME);\r
+                       int g = m.getInteger(G_ATTR_NAME);\r
+                       int b = m.getInteger(B_ATTR_NAME);\r
+                       Color c = new Color(r, g, b);\r
+                       result.add(c);\r
+                } catch (Exception e) {\r
+                       \r
+                }\r
+                \r
+            }\r
+        } catch (IllegalArgumentException e) {\r
+        }\r
+        return result;\r
+    }\r
+    \r
+    public static String encodeColors(Deque<Color> recentColors) {\r
+        StringMemento sm = new StringMemento();\r
+        for (Color c : recentColors) {\r
+            IMemento m = sm.createChild(TAG_COLORS);\r
+            m.putInteger(R_ATTR_NAME, c.getR());\r
+            m.putInteger(G_ATTR_NAME, c.getG());\r
+            m.putInteger(B_ATTR_NAME, c.getB());\r
+        }\r
+        return sm.toString();\r
+    }\r
+}\r
index b1f67289065c7a99d60ad339fb4b4727a6a59c56..da0251da1063a153601574d1a891488e35bafc5a 100644 (file)
@@ -52,14 +52,14 @@ public class Color implements Comparable<Color>{
         this.h = h;\r
         this.s = s;\r
         this.v = v;\r
-        updateRGB();    \r
+        updateRGB();   \r
     }\r
     \r
     public Color(double h, double s, double v) {\r
         this.h = (float)h;\r
         this.s = (float)s;\r
         this.v = (float)v;\r
-        updateRGB();     \r
+        updateRGB();    \r
     }\r
     \r
     public Color(RGB rgb) {\r
@@ -223,7 +223,8 @@ public class Color implements Comparable<Color>{
         }\r
 \r
         if (s == 0.f) {\r
-            h = Float.NaN; // saturation is 0 -> achromatic color\r
+            //h = Float.NaN; // saturation is 0 -> achromatic color\r
+               h = 0.f;\r
         } else {\r
             if (tr == v) {\r
                 h = 60.f * (tg - tb);\r
@@ -248,14 +249,9 @@ public class Color implements Comparable<Color>{
      */\r
     private void updateRGB() {\r
         if (s == 0.f) {\r
-            //if (Float.isNaN(h)) {\r
-                h = Float.NaN;\r
-                r = floatToInt(v);\r
-                g = floatToInt(v);\r
-                b = floatToInt(v);\r
-            //} else {\r
-            //    throw new RuntimeException("Saturation is 0 -> Hue must be undefined");\r
-            //}\r
+            r = floatToInt(v);\r
+            g = floatToInt(v);\r
+            b = floatToInt(v);\r
         } else {\r
             while (h < 0.f)\r
                h+= 360.f;\r
index bae10b93586e926a5e33e6ca20b87cda1fb5de3e..7e86056af3b749dfc745c352fb0b5d20c6142b60 100644 (file)
  *******************************************************************************/\r
 package org.simantics.utils.ui.color;\r
 \r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
 import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
 import org.eclipse.swt.events.MouseEvent;\r
 import org.eclipse.swt.events.MouseListener;\r
+import org.eclipse.swt.events.MouseMoveListener;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.GC;\r
 import org.eclipse.swt.graphics.Rectangle;\r
-import org.eclipse.swt.layout.GridData;\r
 import org.eclipse.swt.layout.GridLayout;\r
-import org.eclipse.swt.widgets.Canvas;\r
+import org.eclipse.swt.widgets.Button;\r
 import org.eclipse.swt.widgets.Composite;\r
 import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.TabFolder;\r
+import org.eclipse.swt.widgets.TabItem;\r
 import org.eclipse.swt.widgets.Text;\r
 \r
 /**\r
@@ -32,160 +41,525 @@ import org.eclipse.swt.widgets.Text;
 public class ColorComposite extends Composite{\r
        \r
        \r
-       private Color color = new Color(255,255,255);\r
+       private Color color;\r
        private ColorGradient rGradient;\r
        private ColorGradient gGradient;\r
        private ColorGradient bGradient;\r
+       private ColorGradient hGradient;\r
+       private ColorGradient sGradient;\r
+       private ColorGradient vGradient;\r
        private ColorGradient colorGradient;\r
        \r
+       TabFolder tabFolder;\r
+       \r
        Text rText;\r
        Text gText;\r
        Text bText;\r
-       ColorGradientCanvas rCanvas;\r
-       ColorGradientCanvas gCanvas;\r
-       ColorGradientCanvas bCanvas;\r
+       IntGradientWidget rCanvas;\r
+       IntGradientWidget gCanvas;\r
+       IntGradientWidget bCanvas;\r
        ColorGradientCanvas colorCanvas;\r
        \r
+       Text hText;\r
+       Text sText;\r
+       Text vText;\r
+       GradientWidget hCanvas;\r
+       GradientWidget sCanvas;\r
+       GradientWidget vCanvas;\r
+       \r
+       Button dynamicButton;\r
+       \r
+       boolean dynamic = true;\r
+       \r
        \r
        public ColorComposite(Composite parent, int style) {\r
                super(parent,style);\r
-               updateGradients();\r
                \r
                GridLayout layout = new GridLayout();\r
-               layout.makeColumnsEqualWidth = false;\r
-               layout.numColumns = 3;\r
+               layout.makeColumnsEqualWidth = true;\r
+               layout.numColumns = 1;\r
                this.setLayout(layout);\r
                \r
                colorCanvas = new ColorGradientCanvas(this,SWT.BORDER|SWT.HORIZONTAL);\r
-               GridData colorCanvasData = new GridData();\r
-               colorCanvasData.horizontalSpan = 3;\r
-               colorCanvasData.heightHint = 32;\r
-               colorCanvasData.widthHint = 600;\r
-               colorCanvasData.grabExcessHorizontalSpace = true;\r
-               colorCanvas.setLayoutData(colorCanvasData);\r
-               \r
-               //layout data used with labels\r
-               GridData labelData = new GridData();\r
-               labelData.widthHint = 30;\r
-               //layout data used with gradients\r
-               GridData gradientData = new GridData();\r
-               gradientData.grabExcessHorizontalSpace = true;\r
-               gradientData.heightHint = 16;\r
-               gradientData.widthHint = 500;\r
-               //layout data used with texts\r
-               GridData textData = new GridData();\r
-               textData.widthHint = 30;\r
-               \r
-               \r
-               //Composite rComposite = new Composite(this,SWT.NONE);\r
-               //Layout rLayout = new FillLayout(SWT.HORIZONTAL);\r
-               //rComposite.setLayout(rLayout);\r
-               Label rLabel = new Label(this,SWT.NONE);\r
+               \r
+               tabFolder = new TabFolder(this, SWT.NONE);\r
+               \r
+               TabItem rgbTab = new TabItem(tabFolder, SWT.NONE);\r
+               rgbTab.setText("RGB");\r
+               Composite rgbComposite = new Composite(tabFolder, SWT.NONE);\r
+               \r
+               rgbTab.setControl(rgbComposite);\r
+               \r
+               Label rLabel = new Label(rgbComposite,SWT.NONE);\r
                rLabel.setText("Red");\r
-               rLabel.setLayoutData(labelData);\r
-               rCanvas = new ColorGradientCanvas(this,SWT.BORDER|SWT.HORIZONTAL);\r
-               rCanvas.setLayoutData(gradientData);\r
-               rText = new Text(this,SWT.BORDER);\r
-               rText.setLayoutData(textData);\r
-               rCanvas.addMouseListener(new ColorSelectListener(rCanvas) {\r
+               rCanvas = new IntGradientWidget(rgbComposite,SWT.BORDER|SWT.HORIZONTAL){\r
+                       @Override\r
+                       protected void updatePosition(int value) {\r
+                               Color newColor = new Color(value,color.getG(),color.getB());\r
+                               setColor(newColor);\r
+                       }\r
+               };\r
+               rText = new Text(rgbComposite,SWT.BORDER);\r
+               rText.addModifyListener(new IntColorModifyListener() {\r
+                       \r
+                       @Override\r
                        void setValue(int value) {\r
                                Color newColor = new Color(value,color.getG(),color.getB());\r
-                               updateColor(newColor);\r
-                       };\r
+                               setColor(newColor);\r
+                       }\r
                });\r
                \r
-               //Composite gComposite = new Composite(this,SWT.NONE);\r
-               //Layout gLayout = new FillLayout(SWT.HORIZONTAL);\r
-               //gComposite.setLayout(gLayout);\r
-               Label gLabel = new Label(this,SWT.NONE);\r
+               Label gLabel = new Label(rgbComposite,SWT.NONE);\r
                gLabel.setText("Green");\r
-               gLabel.setLayoutData(labelData);\r
-               gCanvas = new ColorGradientCanvas(this,SWT.BORDER|SWT.HORIZONTAL);\r
-               gCanvas.setLayoutData(gradientData);\r
-               gText = new Text(this,SWT.BORDER);\r
-               gText.setLayoutData(textData);\r
-               gCanvas.addMouseListener(new ColorSelectListener(gCanvas) {\r
+               gCanvas = new IntGradientWidget(rgbComposite,SWT.BORDER|SWT.HORIZONTAL) {\r
+                       @Override\r
+                       protected void updatePosition(int value) {\r
+                               Color newColor = new Color(color.getR(),value,color.getB());\r
+                               setColor(newColor);\r
+                       }\r
+               };\r
+               gText = new Text(rgbComposite,SWT.BORDER);\r
+               gText.addModifyListener(new IntColorModifyListener() {\r
+                       \r
+                       @Override\r
                        void setValue(int value) {\r
                                Color newColor = new Color(color.getR(),value,color.getB());\r
-                               updateColor(newColor);\r
-                       };\r
+                               setColor(newColor);\r
+                       }\r
                });\r
                \r
-               //Composite bComposite = new Composite(this,SWT.NONE);\r
-               //Layout bLayout = new FillLayout(SWT.HORIZONTAL);\r
-               //bComposite.setLayout(bLayout);\r
-               Label bLabel = new Label(this,SWT.NONE);\r
+               Label bLabel = new Label(rgbComposite,SWT.NONE);\r
                bLabel.setText("Blue");\r
-               bLabel.setLayoutData(labelData);\r
-               bCanvas = new ColorGradientCanvas(this,SWT.BORDER|SWT.HORIZONTAL);\r
-               bCanvas.setLayoutData(gradientData);\r
-               bText = new Text(this,SWT.BORDER);\r
-               bText.setLayoutData(textData);\r
-               bCanvas.addMouseListener(new ColorSelectListener(bCanvas) {\r
+               bCanvas = new IntGradientWidget(rgbComposite,SWT.BORDER|SWT.HORIZONTAL) {\r
+                       @Override\r
+                       protected void updatePosition(int value) {\r
+                               Color newColor = new Color(color.getR(),color.getG(),value);\r
+                               setColor(newColor);\r
+                       }\r
+               };\r
+               bText = new Text(rgbComposite,SWT.BORDER);\r
+               bText.addModifyListener(new IntColorModifyListener() {\r
+                       \r
+                       @Override\r
                        void setValue(int value) {\r
                                Color newColor = new Color(color.getR(),color.getG(),value);\r
-                               updateColor(newColor);\r
-                       };\r
+                               setColor(newColor);\r
+                       }\r
                });\r
-               updateWidgets();\r
                \r
-       }\r
-       \r
-       private abstract class ColorSelectListener implements MouseListener {\r
-               private Canvas canvas;\r
+               TabItem hsvTab = new TabItem(tabFolder, SWT.NONE);\r
+               hsvTab.setText("HSV");\r
+               Composite hsvComposite = new Composite(tabFolder, SWT.NONE);\r
                \r
-               public ColorSelectListener(Canvas canvas) {\r
-                       this.canvas = canvas;\r
-               }\r
-               public void mouseDoubleClick(MouseEvent e) {\r
-                                               \r
-               }\r
-               public void mouseDown(MouseEvent e) {\r
-                       Rectangle r = this.canvas.getBounds();\r
-                       double d = (double)e.x / (double)r.width;\r
-                       int value = (int)(d * 255);\r
-                       if (value < 0)\r
-                               value = 0;\r
-                       if (value > 255)\r
-                               value = 255;\r
-                       setValue(value);\r
+               hsvTab.setControl(hsvComposite);\r
+               \r
+               Label hLabel = new Label(hsvComposite,SWT.NONE);\r
+               hLabel.setText("Hue");\r
+               hCanvas = new GradientWidget(hsvComposite,SWT.BORDER|SWT.HORIZONTAL) {\r
+                       @Override\r
+                       protected boolean updatePosition(double d) {\r
+                               Color newColor = new Color(d*360.0,color.getS(),color.getV());\r
+                               setColor(newColor);\r
+                               return true;\r
+                       }\r
                        \r
-               }\r
-               public void mouseUp(MouseEvent e) {\r
+                       @Override\r
+                       protected void setPosition(double d) {\r
+                               super.setPosition(d/360.0);\r
+                       }\r
+               };\r
+               hText = new Text(hsvComposite,SWT.BORDER);\r
+               hText.addModifyListener(new DoubleColorModifyListener(0.,360.) {\r
+                       \r
+                       @Override\r
+                       void setValue(double value) {\r
+                               Color newColor = new Color(value,color.getS(),color.getV());\r
+                               setColor(newColor);\r
+                       }\r
+               });\r
+               \r
+               Label sLabel = new Label(hsvComposite,SWT.NONE);\r
+               sLabel.setText("Saturation");\r
+               sCanvas = new GradientWidget(hsvComposite,SWT.BORDER|SWT.HORIZONTAL) {\r
+                       @Override\r
+                       protected boolean updatePosition(double d) {\r
+                               Color newColor = new Color(color.getH(),d,color.getV());\r
+                               setColor(newColor);\r
+                               return true;\r
+                       }\r
+               };\r
+               sText = new Text(hsvComposite,SWT.BORDER);\r
+               sText.addModifyListener(new DoubleColorModifyListener(0.,1.) {\r
+                       \r
+                       @Override\r
+                       void setValue(double value) {\r
+                               Color newColor = new Color(color.getH(),value,color.getV());\r
+                               setColor(newColor);\r
+                       }\r
+               });\r
+               \r
+               Label vLabel = new Label(hsvComposite,SWT.NONE);\r
+               vLabel.setText("Value");\r
+               vCanvas = new GradientWidget(hsvComposite,SWT.BORDER|SWT.HORIZONTAL) {\r
+                       @Override\r
+                       protected boolean updatePosition(double d) {\r
+                               Color newColor = new Color(color.getH(),color.getS(),d);\r
+                               setColor(newColor);\r
+                               return true;\r
+                       }\r
+               };\r
+               vText = new Text(hsvComposite,SWT.BORDER);\r
+               vText.addModifyListener(new DoubleColorModifyListener(0.,1.) {\r
+                       \r
+                       @Override\r
+                       void setValue(double value) {\r
+                               Color newColor = new Color(color.getH(),color.getS(),value);\r
+                               setColor(newColor);\r
+                       }\r
+               });\r
+               \r
+               TabItem settingsTab = new TabItem(tabFolder, SWT.NONE);\r
+               settingsTab.setText("Settings");\r
+               Composite settingsComposite = new Composite(tabFolder, SWT.NONE);\r
+               \r
+               settingsTab.setControl(settingsComposite);\r
+               \r
+               dynamicButton = new Button(settingsComposite, SWT.CHECK);\r
+               dynamicButton.setText("Dynamic widgets");\r
+               dynamicButton.setSelection(dynamic);\r
+               dynamicButton.addSelectionListener(new SelectionAdapter() {\r
+                       @Override\r
+                       public void widgetSelected(SelectionEvent e) {\r
+                               dynamic = dynamicButton.getSelection();\r
+                               updateWidgets();\r
+                       }\r
+               });\r
+\r
+               GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).applyTo(rgbComposite);\r
+               GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).applyTo(hsvComposite);\r
+               GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).applyTo(settingsComposite);\r
+               GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(rgbComposite);\r
+               GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(hsvComposite);\r
+               GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(settingsComposite);\r
+               GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(tabFolder);\r
+               \r
+               GridDataFactory.fillDefaults().hint(-1, 32).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(colorCanvas);\r
+               GridDataFactory.fillDefaults().hint(-1, 16).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(rCanvas);\r
+               GridDataFactory.fillDefaults().hint(-1, 16).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(gCanvas);\r
+               GridDataFactory.fillDefaults().hint(-1, 16).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(bCanvas);\r
+               GridDataFactory.fillDefaults().hint(-1, 16).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(hCanvas);\r
+               GridDataFactory.fillDefaults().hint(-1, 16).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(sCanvas);\r
+               GridDataFactory.fillDefaults().hint(-1, 16).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(vCanvas);\r
+               GridDataFactory.fillDefaults().hint(20, 15).grab(false, false).applyTo(rText);\r
+               GridDataFactory.fillDefaults().hint(20, 15).grab(false, false).applyTo(gText);\r
+               GridDataFactory.fillDefaults().hint(20, 15).grab(false, false).applyTo(bText);\r
+               GridDataFactory.fillDefaults().hint(20, 15).grab(false, false).applyTo(hText);\r
+               GridDataFactory.fillDefaults().hint(20, 15).grab(false, false).applyTo(sText);\r
+               GridDataFactory.fillDefaults().hint(20, 15).grab(false, false).applyTo(vText);\r
+               \r
+               if (color == null)\r
+                       setColor(new Color(255,255,255));\r
+               else\r
+                       setColor(color);\r
+       }\r
+       \r
+       private abstract class IntColorModifyListener implements ModifyListener {\r
+               boolean modify = false;\r
+               @Override\r
+               public void modifyText(ModifyEvent e) {\r
+                       if (internalUpdate)\r
+                               return;\r
+                       if (modify)\r
+                               return;\r
+                       modify = true;\r
+                       Text text = (Text)e.widget;\r
+                       try {\r
+                               int value = Integer.parseInt(text.getText());\r
+                               if (value < 0)\r
+                                       value = 0;\r
+                               if (value > 255)\r
+                                       value = 255;\r
+                               setValue(value);\r
+                       } catch (NumberFormatException err) {\r
+                               \r
+                       }\r
+                       modify = false;\r
                        \r
                }\r
                \r
                abstract void setValue(int value);\r
        }\r
+\r
+       private abstract class DoubleColorModifyListener implements ModifyListener {\r
+               boolean modify = false;\r
+               double min;\r
+               double max;\r
+               \r
+               public DoubleColorModifyListener( double min, double max) {\r
+                       this.min = min;\r
+                       this.max = max;\r
+               }\r
+               \r
+               @Override\r
+               public void modifyText(ModifyEvent e) {\r
+                       if (internalUpdate)\r
+                               return;\r
+                       if (modify)\r
+                               return;\r
+                       modify = true;\r
+                       Text text = (Text)e.widget;\r
+                       try {\r
+                               double value = Integer.parseInt(text.getText());\r
+                               if (value < min) {\r
+                                       value = min;\r
+                               } else if (value > max)\r
+                                       value = max;\r
+                               setValue(value);\r
+                       } catch (NumberFormatException err) {\r
+                               \r
+                       }\r
+                       modify = false;                 \r
+               }\r
+\r
+               \r
+               abstract void setValue(double value);\r
+       }\r
        \r
-       private void updateColor(Color color) {\r
+       public void setColor(Color color) {\r
                this.color = color;\r
                updateWidgets();\r
        }\r
        \r
+       public Color getColor() {\r
+               return color;\r
+       }\r
+       \r
        private void updateGradients() {\r
-               rGradient = new ColorGradient(new ColorValue[]{\r
-                                       new ColorValue(new Color(0,color.getG(),color.getB()),0.0),\r
-                                       new ColorValue(new Color(255,color.getG(),color.getB()),1.0)});\r
-               gGradient = new ColorGradient(new ColorValue[]{\r
-                               new ColorValue(new Color(color.getR(),0,color.getB()),0.0),\r
-                               new ColorValue(new Color(color.getR(),255,color.getB()),1.0)});\r
-               bGradient = new ColorGradient(new ColorValue[]{\r
-                               new ColorValue(new Color(color.getR(),color.getG(),0),0.0),\r
-                               new ColorValue(new Color(color.getR(),color.getG(),255),1.0)});\r
+               if (dynamic) {\r
+                       rGradient = new ColorGradient(new ColorValue[]{\r
+                                               new ColorValue(new Color(0,color.getG(),color.getB()),0.0),\r
+                                               new ColorValue(new Color(255,color.getG(),color.getB()),1.0)});\r
+                       gGradient = new ColorGradient(new ColorValue[]{\r
+                                       new ColorValue(new Color(color.getR(),0,color.getB()),0.0),\r
+                                       new ColorValue(new Color(color.getR(),255,color.getB()),1.0)});\r
+                       bGradient = new ColorGradient(new ColorValue[]{\r
+                                       new ColorValue(new Color(color.getR(),color.getG(),0),0.0),\r
+                                       new ColorValue(new Color(color.getR(),color.getG(),255),1.0)});\r
+                       // hue is interpolated along the shortest route, using just 0 and 360 would result in constant color. \r
+                       hGradient = new ColorGradient(new ColorValue[]{\r
+                                       new ColorValue(new Color(0.0,color.getS(),color.getV()),0.0),\r
+                                       new ColorValue(new Color(90.0,color.getS(),color.getV()),0.25),\r
+                                       new ColorValue(new Color(180.0,color.getS(),color.getV()),0.5),\r
+                                       new ColorValue(new Color(270.0,color.getS(),color.getV()),0.75),\r
+                                       new ColorValue(new Color(360.0,color.getS(),color.getV()),1.0)}, ColorGradient.HSV);\r
+                       sGradient = new ColorGradient(new ColorValue[]{\r
+                                       new ColorValue(new Color(color.getH(),0.0,color.getV()),0.0),\r
+                                       new ColorValue(new Color(color.getH(),1.0,color.getV()),1.0)}, ColorGradient.HSV);\r
+                       vGradient = new ColorGradient(new ColorValue[]{\r
+                                       new ColorValue(new Color(color.getH(),color.getS(),0.0),0.0),\r
+                                       new ColorValue(new Color(color.getH(),color.getS(),1.0),1.0)}, ColorGradient.HSV);\r
+               } else {\r
+                       rGradient = new ColorGradient(new ColorValue[]{\r
+                                       new ColorValue(new Color(0,0,0),0.0),\r
+                                       new ColorValue(new Color(255,0,0),1.0)});\r
+                       gGradient = new ColorGradient(new ColorValue[]{\r
+                                       new ColorValue(new Color(0,0,0),0.0),\r
+                                       new ColorValue(new Color(0,255,0),1.0)});\r
+                       bGradient = new ColorGradient(new ColorValue[]{\r
+                                       new ColorValue(new Color(0,0,0),0.0),\r
+                                       new ColorValue(new Color(0,0,255),1.0)});\r
+                       // hue is interpolated along the shortest route, using just 0 and 360 would result in constant color. \r
+                       hGradient = new ColorGradient(new ColorValue[]{\r
+                                       new ColorValue(new Color(0.0,1.0,1.0),0.0),\r
+                                       new ColorValue(new Color(90.0,1.0,1.0),0.25),\r
+                                       new ColorValue(new Color(180.0,1.0,1.0),0.5),\r
+                                       new ColorValue(new Color(270.0,1.0,1.0),0.75),\r
+                                       new ColorValue(new Color(360.0,1.0,1.0),1.0)}, ColorGradient.HSV);\r
+                       sGradient = new ColorGradient(new ColorValue[]{\r
+                                       new ColorValue(new Color(color.getH(),0.0,1.0),0.0),\r
+                                       new ColorValue(new Color(color.getH(),1.0,1.0),1.0)}, ColorGradient.HSV);\r
+                       vGradient = new ColorGradient(new ColorValue[]{\r
+                                       new ColorValue(new Color(color.getH(),1.0,0.0),0.0),\r
+                                       new ColorValue(new Color(color.getH(),1.0,1.0),1.0)}, ColorGradient.HSV);\r
+               }\r
+               \r
                colorGradient = new ColorGradient(new ColorValue[]{\r
                                new ColorValue(new Color(color.getR(),color.getG(),color.getB()),0.0)});\r
        \r
        }\r
        \r
+       private boolean internalUpdate = false;\r
+       \r
        private void updateWidgets() {\r
+               if (internalUpdate)\r
+                       return;\r
+               internalUpdate = true;\r
                updateGradients();\r
                rCanvas.setGradient(rGradient);\r
                gCanvas.setGradient(gGradient);\r
                bCanvas.setGradient(bGradient);\r
+               hCanvas.setGradient(hGradient);\r
+               sCanvas.setGradient(sGradient);\r
+               vCanvas.setGradient(vGradient);\r
                colorCanvas.setGradient(colorGradient);\r
-               rText.setText(Integer.toString(color.getR()));\r
-               gText.setText(Integer.toString(color.getG()));\r
-               bText.setText(Integer.toString(color.getB()));  \r
+               \r
+               rCanvas.setPosition(color.getR());\r
+               gCanvas.setPosition(color.getG());\r
+               bCanvas.setPosition(color.getB());\r
+               hCanvas.setPosition(color.getH());\r
+               sCanvas.setPosition(color.getS());\r
+               vCanvas.setPosition(color.getV());\r
+               \r
+               if(!rText.isFocusControl())\r
+                       rText.setText(Integer.toString(color.getR()));\r
+               if(!gText.isFocusControl())\r
+                       gText.setText(Integer.toString(color.getG()));\r
+               if(!bText.isFocusControl())\r
+                       bText.setText(Integer.toString(color.getB()));\r
+               if(!hText.isFocusControl())\r
+                       hText.setText(Double.toString(color.getH()));\r
+               if(!sText.isFocusControl())\r
+                       sText.setText(Double.toString(color.getS()));\r
+               if(!vText.isFocusControl())\r
+                       vText.setText(Double.toString(color.getV()));   \r
+               internalUpdate = false;\r
+       }\r
+       \r
+       private abstract static class IntGradientWidget extends GradientWidget {\r
+\r
+               public IntGradientWidget(Composite parent, int style) {\r
+                       super(parent, style);\r
+               }\r
+               \r
+               @Override\r
+               protected boolean updatePosition(double d) {\r
+                       int value = (int)(d * 255);\r
+                       if (value < 0)\r
+                               value = 0;\r
+                       if (value > 255)\r
+                               value = 255;\r
+                       updatePosition(value);\r
+                       return true;\r
+               }\r
+               protected abstract void updatePosition(int value);\r
+               \r
+               protected void setPosition(int value) {\r
+                       double d = ((double)value)/255.0;\r
+                       setPosition(d);\r
+               }\r
+               \r
+       }\r
+       \r
+       private abstract static class GradientWidget extends ColorGradientCanvas {\r
+\r
+               int pos = -1;\r
+               double posD = -1.0;\r
+               \r
+               int size = 8;\r
+               int sized2 = 4;\r
+               \r
+               \r
+               \r
+               public GradientWidget(Composite parent, int style) {\r
+                       super(parent, style);\r
+                       this.addMouseListener(new MouseListener() {                     \r
+                               @Override\r
+                               public void mouseDown(MouseEvent e) {\r
+                                       if (e.button == 1) {\r
+                                               update(e);\r
+                                       }\r
+                               }\r
+                               \r
+                               @Override\r
+                               public void mouseUp(MouseEvent e) {}\r
+                               @Override\r
+                               public void mouseDoubleClick(MouseEvent e) {}\r
+                       });\r
+                       this.addMouseMoveListener(new MouseMoveListener() {\r
+                               \r
+                               @Override\r
+                               public void mouseMove(MouseEvent e) {\r
+                                       if ((e.stateMask & SWT.BUTTON1)>0) {\r
+                                               update(e);\r
+                                       }\r
+                               }\r
+                       });\r
+               }\r
+               \r
+               protected void update(MouseEvent e) {\r
+                       Rectangle r = getClientArea();\r
+                       double d;\r
+                       if ((style & SWT.HORIZONTAL) > 0) {\r
+                               d = (double)e.x / (double)r.width;\r
+                       } else {\r
+                               d = (double)e.y / (double)r.height;\r
+                       }\r
+                       if (d < 0.0)\r
+                               d = 0.0;\r
+                       else if (d > 1.0)\r
+                               d = 1.0;\r
+                       if (updatePosition(d)) {\r
+                               if ((style & SWT.HORIZONTAL) > 0) {\r
+                                       pos = (int)(d*((double)r.width));\r
+                               } else {\r
+                                       pos = (int)(d*((double)r.height));\r
+                               }\r
+                               posD = d;\r
+                       }\r
+               }\r
+               \r
+               protected abstract boolean updatePosition(double d);\r
+               \r
+               protected void setPosition(double d) {\r
+                       if (d == posD)\r
+                               return;\r
+                       _setPosition(d);                                                \r
+               }\r
+               \r
+               private void _setPosition(double d) {\r
+                       Rectangle r = getClientArea();\r
+                       posD = d;\r
+                       if (posD >= 0.0) {\r
+                               if ((style & SWT.HORIZONTAL) > 0) {\r
+                                       pos = (int)(d * (double)r.width);\r
+                               } else {\r
+                                       pos = (int)(d * (double)r.height);\r
+                               }\r
+                       } else {\r
+                               pos = -1;\r
+                       }\r
+               }\r
+               \r
+               Rectangle prevClip;\r
+               @Override\r
+               protected void paintGradient(GC gc, Rectangle clip) {\r
+                       super.paintGradient(gc, clip);\r
+                       if (!clip.equals(prevClip)) {\r
+                               prevClip = clip;\r
+                               _setPosition(posD);\r
+                       }\r
+                       \r
+                       if (pos >= 0) {\r
+                               org.eclipse.swt.graphics.Color white = new org.eclipse.swt.graphics.Color(gc.getDevice(), 255,255,255);\r
+                               org.eclipse.swt.graphics.Color black = new org.eclipse.swt.graphics.Color(gc.getDevice(), 0, 0, 0);\r
+                               gc.setForeground(black);\r
+                               gc.setBackground(white);\r
+                               int x;\r
+                               int y;\r
+                               if ((style & SWT.HORIZONTAL) > 0) {\r
+                                       x = pos;\r
+                                       y = clip.height / 2;\r
+                               } else {\r
+                                       x = clip.width / 2;\r
+                                       y = pos;\r
+                               }\r
+                               gc.fillOval(x-sized2, y-sized2, size, size);\r
+                               gc.drawOval(x-sized2, y-sized2, size, size);\r
+                               \r
+                               white.dispose();\r
+                               black.dispose();\r
+                       }\r
+               }\r
+               \r
        }\r
 }\r
diff --git a/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorDialog.java b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorDialog.java
new file mode 100644 (file)
index 0000000..195a16c
--- /dev/null
@@ -0,0 +1,84 @@
+package org.simantics.utils.ui.color;\r
+\r
+import org.eclipse.jface.dialogs.Dialog;\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Group;\r
+import org.eclipse.swt.widgets.Shell;\r
+\r
+public class ColorDialog extends Dialog{\r
+       protected ColorComposite colorComposite;\r
+       protected Color value;\r
+       \r
+       public ColorDialog(Shell parentShell) {\r
+               super(parentShell);     \r
+       }\r
+       \r
+       @Override\r
+       protected void configureShell(Shell newShell) {\r
+               super.configureShell(newShell);\r
+               newShell.setText("Color");\r
+       }\r
+\r
+       \r
+       public void setInitialValue(Color initialValue) {\r
+               this.value = new Color(initialValue);\r
+       }\r
+       \r
+       @Override\r
+    protected Point getInitialSize() {\r
+        return new Point(400, 400);\r
+    }\r
+       \r
+       @Override\r
+       protected Control createDialogArea(Composite parent) {\r
+               Composite composite = new Composite(parent, SWT.NONE);\r
+               GridLayoutFactory.fillDefaults().numColumns(1).margins(6, 0).applyTo(composite);\r
+               GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(composite);\r
+               colorComposite = new ColorComposite(composite, 0);\r
+        GridData childData = new GridData(GridData.FILL_BOTH);\r
+        colorComposite.setLayoutData(childData); \r
+        if (value != null)\r
+               colorComposite.setColor(value);\r
+        Group builtinGroup = new Group(composite, SWT.NONE);\r
+        builtinGroup.setText("System colors");\r
+        GridLayoutFactory.fillDefaults().numColumns(8).spacing(2, 2).margins(4, 4).applyTo(builtinGroup);\r
+        for (int i = SWT.COLOR_WHITE; i <= SWT.COLOR_DARK_GRAY; i++) {\r
+               org.eclipse.swt.graphics.Color c = Display.getCurrent().getSystemColor(i);\r
+               Color color = new Color(c.getRGB());\r
+               createColorButton(builtinGroup, color);\r
+        }\r
+        \r
+\r
+        return composite;\r
+       }\r
+       \r
+       protected Button createColorButton(Composite parent, Color color) {\r
+               Button button = new Button(parent, SWT.PUSH);\r
+       button.setImage(ColorIconCreator.createImage(color, 32, SWT.BORDER));\r
+       button.setData(color);\r
+       button.addSelectionListener(new SelectionAdapter() {\r
+               @Override\r
+               public void widgetSelected(SelectionEvent e) {\r
+                       colorComposite.setColor(color);\r
+               }\r
+               });\r
+       return button;\r
+       }\r
+\r
+       \r
+       public Color getColor() {\r
+               return colorComposite.getColor();\r
+       }\r
+       \r
+\r
+}\r
index 56195ce0c4cd5c643d89d513e25a59d761e76226..5fc3d747c26790cbd3795676312eeb39c4126322 100644 (file)
@@ -14,6 +14,7 @@ package org.simantics.utils.ui.color;
 import java.util.ArrayList;\r
 import java.util.Collection;\r
 import java.util.Collections;\r
+import java.util.List;\r
 \r
 import org.eclipse.swt.SWT;\r
 import org.eclipse.swt.graphics.Color;\r
@@ -266,7 +267,7 @@ public class ColorGradient {
         return type;\r
     }\r
     \r
-    public Collection<ColorValue> getColorValues() {\r
+    public List<ColorValue> getColorValues() {\r
         return values;\r
     }\r
     \r
diff --git a/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorGradientAdjustingCanvas.java b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorGradientAdjustingCanvas.java
new file mode 100644 (file)
index 0000000..ea8983f
--- /dev/null
@@ -0,0 +1,258 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.utils.ui.color;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.ISelectionProvider;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.MouseEvent;\r
+import org.eclipse.swt.events.MouseListener;\r
+import org.eclipse.swt.events.MouseMoveListener;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.GC;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.graphics.Rectangle;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+\r
+/**\r
+ * \r
+ * Canvas that shows color gradients and color positions.\r
+ * Without READ_ONLY style the canvas allows user to drag color positions.\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public class ColorGradientAdjustingCanvas extends ColorGradientCanvas implements ISelectionProvider{\r
+       \r
+       ColorValue[] values;\r
+       int last;\r
+       int coords[];\r
+       int size = 8;\r
+       int sized2 = 4;\r
+       int width;\r
+       int height;\r
+       \r
+       int selectedValueIndex = -1;\r
+       \r
+       public ColorGradientAdjustingCanvas(Composite parent, int style) {\r
+               super(parent,style|SWT.DOUBLE_BUFFERED|SWT.NO_BACKGROUND);\r
+               addMouseListener(new MouseListener() {\r
+                       \r
+                       @Override\r
+                       public void mouseUp(MouseEvent e) {\r
+                               \r
+                       }\r
+                       \r
+                       @Override\r
+                       public void mouseDown(MouseEvent e) {\r
+                               // store and reset selection\r
+                               int prev = selectedValueIndex;\r
+                               selectedValueIndex = -1;\r
+                               \r
+                               // locate closest ColorValue, and select it.\r
+                               int d = Integer.MAX_VALUE;\r
+                               for (int i = 0; i <= last; i++) {\r
+                                       int x = coords[i*2];\r
+                               int y = coords[i*2+1];\r
+                               int dx = Math.abs(x - e.x);\r
+                               int dy = Math.abs(y - e.y);\r
+                               if ((dx < size) &&\r
+                                       (dy < size)) {\r
+                                       int dd = dx+dy;\r
+                                       if (dd < d) {\r
+                                               selectedValueIndex = i;\r
+                                               d = dd;\r
+                                       }\r
+                               }\r
+                               }\r
+                               // if selection was changed, update it.\r
+                               if (prev != selectedValueIndex) {\r
+                                       updateSelection();\r
+                                       redraw();\r
+                               }\r
+                       }\r
+                       \r
+                       @Override\r
+                       public void mouseDoubleClick(MouseEvent e) {\r
+                               \r
+                       }\r
+               });\r
+               if ((style&SWT.READ_ONLY) == 0) {\r
+                       addMouseMoveListener(new MouseMoveListener() {\r
+                               \r
+                               @Override\r
+                               public void mouseMove(MouseEvent e) {\r
+                                       if ((e.stateMask & SWT.BUTTON1)>0) {\r
+                                               if (selectedValueIndex > 0 && selectedValueIndex < last) {\r
+                                                       double d;\r
+                                                       if ((ColorGradientAdjustingCanvas.this.style | SWT.HORIZONTAL) > 0) {\r
+                                                               d = (double)e.x/(double)width;\r
+                                                       } else {\r
+                                                               d = (double)e.y/(double)height;\r
+                                                       }\r
+                                                       double r = max-min;\r
+                                                       d *= r;\r
+                                                       d += min;\r
+                                                       double offset = r*0.015;\r
+                                                       if (d <= values[selectedValueIndex-1].getValue()+offset)\r
+                                                               d = values[selectedValueIndex-1].getValue()+offset;\r
+                                                       else if (d >= values[selectedValueIndex+1].getValue()-offset)\r
+                                                               d = values[selectedValueIndex+1].getValue()-offset;\r
+                                                       values[selectedValueIndex]._setValue(d);\r
+                                                       calculateCoords(width, height);\r
+                                                       redraw();\r
+                                               }\r
+                                       }\r
+                                       \r
+                               }\r
+                       });\r
+               }\r
+\r
+       }\r
+       \r
+       public void setGradient(ColorGradient gradient) {\r
+               int prevSize = 0;\r
+               if (values != null)\r
+                       prevSize = values.length;\r
+               \r
+               values = gradient.getColorValueArray();\r
+               last = values.length-1;\r
+               coords = new int[values.length*2];\r
+               super.setGradient(gradient);\r
+               if (selectedValueIndex >= 0 && prevSize != values.length) {\r
+                       selectedValueIndex = -1;\r
+                       updateSelection();\r
+               } else {\r
+                       updateSelection();\r
+               }\r
+       }\r
+       \r
+       double min;\r
+       double max;\r
+       \r
+       private void calculateCoords(int width, int height) {\r
+               this.width = width;\r
+               this.height = height;\r
+               \r
+               min = values[0].getValue();\r
+               max = values[last].getValue();\r
+               \r
+               if ((ColorGradientAdjustingCanvas.this.style & SWT.HORIZONTAL) > 0) {\r
+                       for (int i = 0; i <= last ; i++) {\r
+                               int y = height / 2;\r
+                               double d =  values[i].getValue();\r
+                               int x = (int)(((d-min)/(max-min))*(double)width);\r
+                               coords[i*2] = x;\r
+                               coords[i*2+1] = y;\r
+                       }\r
+               } else {\r
+                       for (int i = 0; i <= last ; i++) {\r
+                               int x = width / 2;\r
+                               double d =  values[i].getValue();\r
+                               int y = (int)(((d-min)/(max-min))*(double)height);\r
+                               coords[i*2] = x;\r
+                               coords[i*2+1] = y;\r
+                       }\r
+               }\r
+       }\r
+\r
+       \r
+       @Override\r
+       protected void paintGradient(GC gc, Rectangle clip) {\r
+               if (values != null && values.length > 0) {\r
+                       Image image = gradient.getGradientImage(clip.width,clip.height,ColorGradientAdjustingCanvas.this.style);\r
+                       gc.drawImage(image, 0, 0);\r
+                       image.dispose();        \r
+                       calculateCoords(clip.width, clip.height);\r
+\r
+                       Color white = new Color(gc.getDevice(), 255,255,255);\r
+                       Color yellow = new Color(gc.getDevice(), 255,230,0);\r
+                       Color black = new Color(gc.getDevice(), 0, 0, 0);\r
+                       for (int i = 0; i <= last ; i++) {\r
+                               int x = coords[i*2];\r
+                               int y = coords[i*2+1];\r
+                               gc.setForeground(black);\r
+                               if (selectedValueIndex == i)\r
+                                       gc.setBackground(yellow);\r
+                               else\r
+                                       gc.setBackground(white);\r
+                               if (i == 0 || i == last ) {\r
+                                       gc.fillRectangle(x-sized2, y-sized2, size, size);\r
+                                       gc.drawRectangle(x-sized2, y-sized2, size, size);\r
+                               } else {\r
+                                       gc.fillOval(x-sized2, y-sized2, size, size);\r
+                                       gc.drawOval(x-sized2, y-sized2, size, size);\r
+                               }\r
+                       }\r
+                       \r
+                       white.dispose();\r
+                       black.dispose();\r
+                       yellow.dispose();\r
+               } else {\r
+                       gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));\r
+                       gc.fillRectangle(clip);\r
+               }\r
+       }\r
+       \r
+       private ISelection selection = new StructuredSelection();\r
+       private List<ISelectionChangedListener> listeners = new ArrayList<>();\r
+\r
+       @Override\r
+       public void addSelectionChangedListener(ISelectionChangedListener listener) {\r
+               listeners.add(listener);\r
+       }\r
+\r
+       @Override\r
+       public ISelection getSelection() {\r
+       return selection;\r
+       }\r
+\r
+       @Override\r
+       public void removeSelectionChangedListener(ISelectionChangedListener listener) {\r
+               listeners.remove(listener);\r
+       }\r
+\r
+       @Override\r
+       public void setSelection(ISelection selection) {\r
+               ColorValue value = (ColorValue)((StructuredSelection)selection).getFirstElement();\r
+               selectedValueIndex = gradient.getColorValues().indexOf(value);\r
+       }\r
+       \r
+       private void updateSelection() {\r
+               if (selectedValueIndex < 0)\r
+                       selection = new StructuredSelection();\r
+               else\r
+                       selection = new StructuredSelection(values[selectedValueIndex]);\r
+               \r
+               for (ISelectionChangedListener l : listeners) {\r
+                       l.selectionChanged(new SelectionChangedEvent(this, selection));\r
+               }\r
+       }\r
+       \r
+       public int getPointSize() {\r
+               return size;\r
+       }\r
+       \r
+       public void setPointSize(int size) {\r
+               this.size = size;\r
+               this.sized2 = size/2;\r
+       }\r
+       \r
+\r
+}\r
index 356de7ad0358d401f92cbd3240c74f454a081ad1..27daeeb717dd647d018e1f9b07feeeec4c270c4a 100644 (file)
@@ -33,29 +33,35 @@ public class ColorGradientCanvas extends Canvas{
        int style;\r
        \r
        public ColorGradientCanvas(Composite parent, int style) {\r
-               // FIXME : use xor operation to get SWT.HORIZONTAL and SWT.VERTICAL\r
-               // out of style when it's passed to parent\r
-               super(parent,SWT.BORDER);\r
+               super(parent,(style|SWT.BORDER)&(~(SWT.VERTICAL|SWT.HORIZONTAL)));\r
                this.style = style & (SWT.VERTICAL | SWT.HORIZONTAL) ;\r
-               addPaintListener(new PaintListener() {\r
+               addPaintListener(createPaintListener());\r
+       }\r
+       \r
+       public void setGradient(ColorGradient gradient) {\r
+               this.gradient = gradient;\r
+               this.redraw();\r
+       }       \r
+       \r
+       protected PaintListener createPaintListener() {\r
+               return new PaintListener() {\r
                public void paintControl(PaintEvent e) {\r
                        GC gc = e.gc;\r
                        Rectangle clip = gc.getClipping();\r
-                       if (gradient != null) {\r
-                               Image image = gradient.getGradientImage(clip.width,clip.height,ColorGradientCanvas.this.style);\r
-                               gc.drawImage(image, 0, 0);\r
-                               image.dispose();                \r
-                       } else {\r
-                               gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));\r
-                               gc.fillRectangle(clip);\r
-                       }\r
+                       paintGradient(gc, clip);\r
                }\r
-           });\r
+           };\r
        }\r
        \r
-       public void setGradient(ColorGradient gradient) {\r
-               this.gradient = gradient;\r
-               this.redraw();\r
-       }               \r
+       protected void paintGradient(GC gc, Rectangle clip) {\r
+               if (gradient != null) {\r
+                       Image image = gradient.getGradientImage(clip.width,clip.height,ColorGradientCanvas.this.style);\r
+                       gc.drawImage(image, 0, 0);\r
+                       image.dispose();                \r
+               } else {\r
+                       gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));\r
+                       gc.fillRectangle(clip);\r
+               }\r
+       }\r
 \r
 }\r
index f8a52bc70f9997d13495834eeb147699c78cd502..77b7668d1eb3653599af774b96b2f3b1ad8eb68e 100644 (file)
@@ -43,7 +43,6 @@ import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Button;\r
 import org.eclipse.swt.widgets.ColorDialog;\r
 import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Group;\r
 import org.eclipse.swt.widgets.Table;\r
 import org.eclipse.swt.widgets.TableColumn;\r
 import org.eclipse.swt.widgets.TableItem;\r
@@ -272,7 +271,7 @@ public class ColorGradientComposite extends Composite implements ISelectionChang
        public void dispose() {\r
                for (Image i : images.values())\r
                        i.dispose();\r
-               \r
+               super.dispose();\r
        }\r
        \r
        public void setGradient(ColorGradient gradient) {\r
diff --git a/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorGradientComposite2.java b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorGradientComposite2.java
new file mode 100644 (file)
index 0000000..497407b
--- /dev/null
@@ -0,0 +1,258 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.utils.ui.color;\r
+\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.graphics.RGB;\r
+import org.eclipse.swt.layout.FillLayout;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+\r
+/**\r
+ * Widget to create and edit color gradients\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public class ColorGradientComposite2 extends Composite implements ISelectionChangedListener{   \r
+       \r
+       private ColorGradientAdjustingCanvas gradientComposite;\r
+       private Button addButton;\r
+       private Button editButton;\r
+       private Button removeButton;\r
+       private Button rgbButton;\r
+       private Button hsvButton;\r
+       private int type = ColorGradient.RGB;\r
+       \r
+       private ArrayList<ColorValue> values = new ArrayList<ColorValue>();\r
+       \r
+       public ColorGradientComposite2(Composite parent, int style) {\r
+               super(parent,style);\r
+               GridLayout layout = new GridLayout(2,false);\r
+           this.setLayout(layout);\r
+           gradientComposite = new ColorGradientAdjustingCanvas(this,SWT.HORIZONTAL);\r
+           \r
+           gradientComposite.addSelectionChangedListener(this);\r
+           \r
+           Composite typeComposite = new Composite(this, SWT.NONE);\r
+           \r
+           typeComposite.setLayout(new GridLayout(1,false));\r
+           rgbButton = new Button(typeComposite,SWT.RADIO);\r
+           rgbButton.setSelection(true);\r
+           rgbButton.addSelectionListener(new SelectionListener() {\r
+               public void widgetDefaultSelected(SelectionEvent e) {\r
+                       widgetSelected(e);\r
+               }\r
+               public void widgetSelected(SelectionEvent e) {\r
+                       rgbButton.setSelection(true);\r
+                       hsvButton.setSelection(false);\r
+                       type = ColorGradient.RGB;\r
+                       gradientComposite.setGradient(new ColorGradient(values,type));\r
+               }\r
+           });\r
+           rgbButton.setText("RGB");\r
+           hsvButton = new Button(typeComposite,SWT.RADIO);\r
+           hsvButton.addSelectionListener(new SelectionListener() {\r
+               public void widgetDefaultSelected(SelectionEvent e) {\r
+                       widgetSelected(e);\r
+               }\r
+               public void widgetSelected(SelectionEvent e) {\r
+                       hsvButton.setSelection(true);\r
+                       rgbButton.setSelection(false);\r
+                       type = ColorGradient.HSV;\r
+                       gradientComposite.setGradient(new ColorGradient(values,type));\r
+               }\r
+           });\r
+           hsvButton.setText("HSV"); \r
+           \r
+           Composite buttonComposite = new Composite(this,SWT.NONE);\r
+\r
+           buttonComposite.setLayout(new FillLayout(SWT.HORIZONTAL));\r
+           \r
+           addButton = new Button(buttonComposite,SWT.PUSH);\r
+           addButton.setText("Add new color");\r
+           addButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { \r
+               public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {    \r
+                       RGB rgb = openDialog(null);\r
+                if (rgb != null) {\r
+                    Color c = new Color(rgb.red,rgb.green,rgb.blue);\r
+                    Double value;\r
+                    if (values.size() == 0) {\r
+                       value = 0.0;\r
+                    } else if (values.size() == 1) {\r
+                       value = 100.0;\r
+                    } else {\r
+                       StructuredSelection selection = (StructuredSelection)gradientComposite.getSelection();\r
+                       if (selection.size() == 1) {\r
+                               // add new color next to the selection\r
+                               ColorValue v = (ColorValue)selection.getFirstElement();\r
+                               int index = values.indexOf(v);\r
+                               if (index == values.size() -1) {\r
+                                       index--;\r
+                               }\r
+                               value = (values.get(index+1).getValue()-values.get(index).getValue())*0.5;\r
+                               value += values.get(index).getValue();\r
+                       } else {\r
+                               // add new color to largest gap\r
+                               int index = 0;\r
+                               double r = 0.0;\r
+                               for (int i = 0; i < values.size() -1; i++) {\r
+                                       double v1 = values.get(i).getValue();\r
+                                       double v2 = values.get(i+1).getValue();\r
+                                       double vr = v2 -v1;\r
+                                       if (vr > r) {\r
+                                               r=vr;\r
+                                               index = i;\r
+                                       }\r
+                               }\r
+                               value = values.get(index).getValue() + r *0.5;\r
+                       }\r
+                    }\r
+                    addColor(c,value);\r
+                }\r
+            }\r
+        });\r
+           editButton = new Button(buttonComposite,SWT.PUSH);\r
+           editButton.setText("Edit color");\r
+           editButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { \r
+               public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {    \r
+               \r
+                       Object obj = ((StructuredSelection)gradientComposite.getSelection()).getFirstElement();\r
+                       if (obj == null)\r
+                               return;\r
+                       if (obj instanceof ColorValue) {\r
+                               RGB rgb = openDialog(((ColorValue)obj).getColor().getRgb());\r
+                    if (rgb != null) {\r
+                       modifyColorValueColor((ColorValue)obj,rgb);\r
+                    }\r
+                       }                       \r
+                       \r
+               }\r
+        });\r
+           editButton.setEnabled(false);\r
+           removeButton = new Button(buttonComposite,SWT.PUSH);\r
+           removeButton.setText("Remove color");\r
+           removeButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { \r
+               public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {    \r
+                       Object o = ((StructuredSelection)gradientComposite.getSelection()).getFirstElement();\r
+                       if (o == null)\r
+                               return;\r
+                       if (o instanceof ColorValue) {\r
+                               values.remove(o);\r
+                               updateWidgets();\r
+                       }                       \r
+                       \r
+               }\r
+        });\r
+           removeButton.setEnabled(false);\r
+           \r
+           GridDataFactory.fillDefaults().span(1, 1).grab(true, false).align(SWT.FILL, SWT.CENTER).hint(SWT.DEFAULT, 32).applyTo(gradientComposite);\r
+           GridDataFactory.fillDefaults().grab(false, true).align(SWT.LEFT, SWT.FILL).applyTo(typeComposite);\r
+           GridDataFactory.fillDefaults().span(1, 1).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(buttonComposite);  \r
+       }\r
+       \r
+       protected RGB openDialog(RGB selection) {\r
+//             ColorDialog dialog = new ColorDialog(ColorGradientComposite2.this.getShell(), SWT.NONE);\r
+//        if (selection != null)\r
+//             dialog.setRGB(selection);\r
+//        RGB rgb = dialog.open();\r
+//        return rgb;\r
+               org.simantics.utils.ui.color.ColorDialog dialog = new org.simantics.utils.ui.color.ColorDialog(getShell());\r
+               if (selection != null) {\r
+                       Color color = new Color(selection);\r
+                       dialog.setInitialValue(color);\r
+               }\r
+               if (dialog.open() == org.simantics.utils.ui.color.ColorDialog.OK) {\r
+                       Color color = dialog.getColor();\r
+                       return color.getRgb();\r
+               }\r
+               return null;\r
+       }\r
+\r
+       public void addColor(Color color, double value) {\r
+               addColor(new ColorValue(color,value));\r
+       }\r
+       \r
+       public void addColor(ColorValue value) {\r
+               values.add(value);\r
+               updateWidgets();\r
+       }\r
+       \r
+       private void updateWidgets() {\r
+               Collections.sort(values,new ColorValueComparator());    \r
+               gradientComposite.setGradient(new ColorGradient(values,type));\r
+       }\r
+\r
+       public ColorGradient getGradient() {\r
+               return new ColorGradient(values,type);\r
+       }\r
+\r
+       public void dispose() {\r
+               super.dispose();\r
+       }\r
+       \r
+       public void setGradient(ColorGradient gradient) {\r
+               values.clear();\r
+               type = gradient.getType();\r
+               for (ColorValue value : gradient.getColorValues())\r
+                       addColor(value);\r
+               if (type == ColorGradient.HSV) {\r
+                       rgbButton.setSelection(false);\r
+                       hsvButton.setSelection(true);\r
+               } else if (type == ColorGradient.RGB) {\r
+                       hsvButton.setSelection(false);\r
+                       rgbButton.setSelection(true);\r
+               }\r
+               \r
+       }\r
+       \r
+       private void modifyColorValueColor(ColorValue cValue, RGB rgb) {\r
+               values.remove(cValue);;\r
+               Color newColor = new Color(rgb.red,rgb.green,rgb.blue);\r
+               ColorValue newCValue = new ColorValue(newColor,cValue.getValue());\r
+               values.add(newCValue);\r
+               updateWidgets();\r
+       }\r
+       \r
+       /**\r
+        * Enables and disables "Edit color" and "Remove color" buttons depending on selected item\r
+        */\r
+       public void selectionChanged(SelectionChangedEvent event) {\r
+               Object obj = ((IStructuredSelection)event.getSelection()).getFirstElement();\r
+               if (obj == null) {\r
+                       editButton.setEnabled(false);\r
+                       removeButton.setEnabled(false);\r
+               } else {\r
+                       editButton.setEnabled(true);\r
+                       int index = values.indexOf(obj);\r
+                       if (index > 0 && index < values.size() -1)\r
+                               removeButton.setEnabled(true);\r
+                       else\r
+                               removeButton.setEnabled(false);\r
+               }\r
+       }\r
+       \r
+}\r
+\r
+       \r
index be63557904d2baf3bef34c103bbf1bae231287b3..80f41c8a31e6a64abe8b3a28f0f7c8a4a90895c6 100644 (file)
@@ -40,6 +40,10 @@ public class ColorValue {
         return value;\r
     }\r
     \r
+    public void _setValue(double value) {\r
+        this.value = value;\r
+    }\r
+    \r
     @Override\r
     public int hashCode() {        \r
         return color.hashCode() ^ new Double(value).hashCode();\r