]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
2901c2700a9b9096a95d1171180d00712dcfd2ef
[simantics/sysdyn.git] /
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.jfreechart.chart.properties;\r
13 \r
14 import org.eclipse.jface.layout.GridDataFactory;\r
15 import org.eclipse.jface.layout.GridLayoutFactory;\r
16 import org.eclipse.swt.SWT;\r
17 import org.eclipse.swt.events.SelectionEvent;\r
18 import org.eclipse.swt.graphics.Color;\r
19 import org.eclipse.swt.graphics.Device;\r
20 import org.eclipse.swt.graphics.GC;\r
21 import org.eclipse.swt.graphics.Image;\r
22 import org.eclipse.swt.graphics.Point;\r
23 import org.eclipse.swt.graphics.RGB;\r
24 import org.eclipse.swt.widgets.ColorDialog;\r
25 import org.eclipse.swt.widgets.Composite;\r
26 import org.eclipse.swt.widgets.Display;\r
27 import org.eclipse.swt.widgets.Shell;\r
28 import org.simantics.browsing.ui.swt.widgets.Button;\r
29 import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
30 import org.simantics.browsing.ui.swt.widgets.impl.SelectionListenerImpl;\r
31 import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
32 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
33 import org.simantics.db.ReadGraph;\r
34 import org.simantics.db.Resource;\r
35 import org.simantics.db.WriteGraph;\r
36 import org.simantics.db.common.request.WriteRequest;\r
37 import org.simantics.db.exception.DatabaseException;\r
38 import org.simantics.db.management.ISessionContext;\r
39 import org.simantics.db.procedure.Listener;\r
40 import org.simantics.db.request.Read;\r
41 import org.simantics.diagram.stubs.G2DResource;\r
42 import org.simantics.sysdyn.JFreeChartResource;\r
43 import org.simantics.ui.SimanticsUI;\r
44 import org.simantics.ui.utils.AdaptionUtils;\r
45 import org.simantics.utils.RunnableWithObject;\r
46 import org.simantics.utils.datastructures.Triple;\r
47 \r
48 /**\r
49  * Composite for selecting a color for a chart component\r
50  * \r
51  * @author Teemu Lempinen\r
52  *\r
53  */\r
54 public class ColorPicker extends Composite implements Widget {\r
55 \r
56     Button defaultColor, customColor, color;\r
57 \r
58     /**\r
59      * Create a composite containing radio buttons for default or custom color. Color chooser button is active\r
60      * when the custom radio button is selected. Color chooser uses {@link ColorDialog} to select a color \r
61      * \r
62      * @param parent Composite\r
63      * @param context ISessionContext\r
64      * @param support WidgetSupport\r
65      * @param style SWT style\r
66      */\r
67     public ColorPicker(Composite parent, ISessionContext context, WidgetSupport support, int style) {\r
68         super(parent, style);\r
69         support.register(this);\r
70         \r
71         GridLayoutFactory.fillDefaults().numColumns(4).applyTo(this);\r
72 \r
73         defaultColor = new Button(this, support, SWT.RADIO);\r
74         defaultColor.setText("default");\r
75         defaultColor.setSelectionFactory(new DefaultColorSelectionFactory(false));\r
76         defaultColor.addSelectionListener(new DefaultColorSelectionListener(context));\r
77         GridDataFactory.fillDefaults().applyTo(defaultColor.getWidget());\r
78 \r
79         customColor = new Button(this, support, SWT.RADIO);\r
80         customColor.setText("custom");\r
81         customColor.setSelectionFactory(new DefaultColorSelectionFactory(true));\r
82         customColor.addSelectionListener(new DefaultColorSelectionListener(context));\r
83         \r
84         GridDataFactory.fillDefaults().applyTo(customColor.getWidget());\r
85 \r
86         color = new Button(this, support, SWT.NONE);\r
87         GridDataFactory.fillDefaults().applyTo(color.getWidget());\r
88         color.setImageFactory(new ColorImageFactoryFactory(color));\r
89         color.addSelectionListener(new ColorSelectionListener(context));\r
90         color.getWidget().setEnabled(false);\r
91     }\r
92 \r
93     /**\r
94      * Method for finding the resource for which the color is selected. \r
95      * \r
96      * @param graph ReadGraph\r
97      * @param input input from WidgetSupport\r
98      * @return\r
99      * @throws DatabaseException\r
100      */\r
101     protected Resource getResource(ReadGraph graph, Resource input) throws DatabaseException {\r
102         return input;\r
103     }\r
104     \r
105     /**\r
106      * Method for getting the relation with which the g2d.Color is related to a resource\r
107      * \r
108      * @param graph ReadGraph\r
109      * @return Color relation\r
110      * @throws DatabaseException\r
111      */\r
112     protected Resource getColorRelation(ReadGraph graph) throws DatabaseException {\r
113         JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
114         return jfree.color;\r
115     }\r
116     \r
117     \r
118     @Override\r
119     public void setInput(ISessionContext context, Object input) {\r
120         final Resource resource = AdaptionUtils.adaptToSingle(input, Resource.class);\r
121         \r
122         // Create a listener to define the enabled state of the color chooser button\r
123         context.getSession().asyncRequest(new Read<Boolean>() {\r
124 \r
125             @Override\r
126             public Boolean perform(ReadGraph graph) throws DatabaseException {\r
127                 // if there is a color definition, the color chooser is active\r
128                 Boolean result = graph.hasStatement(getResource(graph, resource), getColorRelation(graph));\r
129                 return result;\r
130             }\r
131             \r
132         }, new Listener<Boolean>() {\r
133 \r
134             @Override\r
135             public void execute(Boolean result) {\r
136                 if(!color.getWidget().isDisposed()) {\r
137                     color.getWidget().getDisplay().asyncExec(new RunnableWithObject(result) {\r
138                         @Override\r
139                         public void run() {\r
140                             if(!color.getWidget().isDisposed())\r
141                                 color.getWidget().setEnabled((Boolean)getObject());\r
142                         }\r
143                     });\r
144                 }\r
145             }\r
146 \r
147             @Override\r
148             public void exception(Throwable t) {\r
149                 t.printStackTrace();\r
150             }\r
151 \r
152             @Override\r
153             public boolean isDisposed() {\r
154                 return color.getWidget().isDisposed();\r
155             }\r
156         });\r
157     }\r
158     \r
159     /**\r
160      * Get a colored image to be displayed in the color chooser button\r
161      * \r
162      * @param device SWT Device\r
163      * @param red Red 0-255\r
164      * @param green Green 0-255\r
165      * @param blue Blue 0-255\r
166      * @return\r
167      */\r
168     private Image getColorPickerImage(Device device, int red, int green, int blue) {\r
169         Image image = new Image(device, 20, 20);\r
170         GC gc = new GC (image);\r
171         gc.setBackground (new Color(device, red, green, blue));\r
172         gc.fillRectangle (image.getBounds ());\r
173         gc.dispose ();\r
174         return image;\r
175     }\r
176 \r
177     /**\r
178      * ImageFactory returning an image for color button\r
179      * @author Teemu Lempinen\r
180      *\r
181      */\r
182     private class ColorImageFactoryFactory extends ReadFactoryImpl<Resource, Image> {\r
183         \r
184         Button button;\r
185         \r
186         public ColorImageFactoryFactory(Button button) {\r
187             super();\r
188             this.button = button;\r
189         }\r
190         \r
191         public Object getIdentity(Object inputContents) {\r
192             return new Triple<Object, Class<?>, Button>(inputContents, getClass(), button);\r
193         }\r
194 \r
195         @Override\r
196         public Image perform(ReadGraph graph, Resource input) throws DatabaseException {\r
197             if(button.getWidget().isDisposed())\r
198                 return null;\r
199             Display device = button.getWidget().getDisplay();\r
200             if(device == null)\r
201                 return null;\r
202             RGB rgb = getColor(graph, getResource(graph, input));\r
203             return getColorPickerImage(device, rgb.red, rgb.green, rgb.blue);\r
204         }\r
205 \r
206     }\r
207 \r
208     /**\r
209      * Get RGB from a color literal resource. If resource is not a color resource, return blue (RGB 0, 0, 255)\r
210      * @param graph ReadGraph\r
211      * @param input Color literal resource (float[4])\r
212      * @return RGB color\r
213      * @throws DatabaseException\r
214      */\r
215     private RGB getColor(ReadGraph graph, Resource input) throws DatabaseException{\r
216         float[] colorComponents = graph.getPossibleRelatedValue(input, getColorRelation(graph));\r
217         RGB rgb;\r
218         if(colorComponents == null)\r
219             rgb = new RGB(0, 0, 255);\r
220         else\r
221             rgb = new RGB((int)(colorComponents[0] * 255.0f), \r
222                     (int)(colorComponents[1] * 255.0f), \r
223                     (int)(colorComponents[2] * 255.0f));\r
224         return rgb;\r
225     }\r
226 \r
227 \r
228     /**\r
229      * SelectionListener for color button. \r
230      * \r
231      * @author Teemu Lempinen\r
232      *\r
233      */\r
234     private class ColorSelectionListener extends SelectionListenerImpl<Resource> {\r
235 \r
236         private SelectionEvent e;\r
237         private RGB rgb;\r
238         \r
239         /**\r
240          * \r
241          * @param context ISessionContext\r
242          */\r
243         public ColorSelectionListener(ISessionContext context) {\r
244             super(context);\r
245         }\r
246 \r
247         @Override\r
248         public void widgetSelected(SelectionEvent e) {\r
249             if(color.getWidget().isDisposed())\r
250                 return;\r
251             // Save the event for coordinates\r
252             this.e = e;\r
253             super.widgetSelected(e);\r
254         }\r
255 \r
256         @Override\r
257         public void apply(WriteGraph graph, Resource input) throws DatabaseException {\r
258             if(color.getWidget().isDisposed())\r
259                 return;\r
260             \r
261             final Resource resource = getResource(graph, input);\r
262             final Display display = color.getWidget().getDisplay();\r
263             final RGB oldRGB = getColor(graph, resource);\r
264             \r
265             display.asyncExec(new RunnableWithObject(oldRGB) {\r
266                 public void run() {\r
267                     // Use color dialog to select a color\r
268                     Shell shell = new Shell(display);\r
269                     ColorDialog cd = new ColorDialog(shell);\r
270                     Point point = color.getWidget().toDisplay(e.x - 150, e.y - 150);\r
271                     cd.getParent().setLocation(point.x, point.y);\r
272                     cd.setText("Select color");\r
273                     cd.setRGB((RGB)getObject());\r
274                     rgb = cd.open();\r
275                     if(rgb == null)\r
276                         return;\r
277                     \r
278                     SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
279                         \r
280                         @Override\r
281                         public void perform(WriteGraph graph) throws DatabaseException {\r
282                             G2DResource g2d = G2DResource.getInstance(graph);\r
283                             float[] components = new float[] {(float)rgb.red / 255.0f,  (float)rgb.green / 255.0f, (float)rgb.blue / 255.0f, 1.0f};\r
284                             graph.claimLiteral(resource, getColorRelation(graph), g2d.Color, components);                            \r
285                         }\r
286                     });\r
287                     \r
288                 }\r
289             });\r
290             \r
291             \r
292 \r
293         }\r
294 \r
295     }\r
296 \r
297     /**\r
298      * SelectionFactory for default and custom color radio buttons\r
299      * @author Teemu Lempinen\r
300      *\r
301      */\r
302     private class DefaultColorSelectionFactory extends ReadFactoryImpl<Resource, Boolean> {\r
303 \r
304         private Boolean isCustom;\r
305 \r
306         /**\r
307          * \r
308          * @param isCustom Is this custom button?\r
309          */\r
310         public DefaultColorSelectionFactory(Boolean isCustom) {\r
311             super();\r
312             this.isCustom = isCustom;\r
313         }\r
314 \r
315         @Override\r
316         public Object getIdentity(Object inputContents) {\r
317             return new Triple<Resource, Object, Boolean>((Resource) inputContents, getClass(), isCustom);\r
318         }\r
319 \r
320         @Override\r
321         public Boolean perform(ReadGraph graph, Resource input) throws DatabaseException {\r
322             Resource r = graph.getPossibleObject(getResource(graph, input), getColorRelation(graph));\r
323             boolean result = false; // Default == not selected\r
324             if(r == null && !isCustom) {\r
325                 // No color definition and default-button -> selected\r
326                 result =  true;\r
327             } else if(r != null && isCustom) {\r
328                 // color definition and custom button -> selected\r
329                 result =  true;\r
330             }\r
331             return result;\r
332         }\r
333 \r
334     }\r
335 \r
336     /**\r
337      * SelectionListener for default and custom radio buttons\r
338      * \r
339      * @author Teemu Lempinen\r
340      *\r
341      */\r
342     private class DefaultColorSelectionListener extends SelectionListenerImpl<Resource> {\r
343 \r
344         private SelectionEvent e;\r
345 \r
346         public DefaultColorSelectionListener(ISessionContext context) {\r
347             super(context);\r
348         }\r
349 \r
350         @Override\r
351         public void widgetSelected(SelectionEvent e) {\r
352             this.e = e; \r
353             super.widgetSelected(e);\r
354         }\r
355 \r
356         @Override\r
357         public void apply(WriteGraph graph, Resource input) throws DatabaseException {\r
358             Resource resource = getResource(graph, input);\r
359             if(customColor.getWidget().equals(e.widget)) {\r
360                 // Custom selected. If there is no color already, create a default Blue color\r
361                 G2DResource g2d = G2DResource.getInstance(graph);\r
362                 if(graph.getPossibleObject(resource, getColorRelation(graph)) == null) {\r
363                     float[] components = java.awt.Color.BLUE.getColorComponents(new float[4]);\r
364                     components[3] = 1.0f;\r
365                     graph.claimLiteral(resource, getColorRelation(graph), g2d.Color, components);\r
366                 }\r
367             } else {\r
368                 // Default selected, remove color definition\r
369                 graph.deny(resource, getColorRelation(graph));\r
370             }\r
371         }\r
372     }\r
373 \r
374 \r
375 }\r