1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
\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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.jfreechart.chart.properties;
\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
49 * Composite for selecting a color for a chart component
\r
51 * @author Teemu Lempinen
\r
54 public class ColorPicker extends Composite implements Widget {
\r
56 Button defaultColor, customColor, color;
\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
62 * @param parent Composite
\r
63 * @param context ISessionContext
\r
64 * @param support WidgetSupport
\r
65 * @param style SWT style
\r
67 public ColorPicker(Composite parent, ISessionContext context, WidgetSupport support, int style) {
\r
68 super(parent, style);
\r
69 support.register(this);
\r
71 GridLayoutFactory.fillDefaults().numColumns(4).applyTo(this);
\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
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
84 GridDataFactory.fillDefaults().applyTo(customColor.getWidget());
\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
94 * Method for finding the resource for which the color is selected.
\r
96 * @param graph ReadGraph
\r
97 * @param input input from WidgetSupport
\r
99 * @throws DatabaseException
\r
101 protected Resource getResource(ReadGraph graph, Resource input) throws DatabaseException {
\r
106 * Method for getting the relation with which the g2d.Color is related to a resource
\r
108 * @param graph ReadGraph
\r
109 * @return Color relation
\r
110 * @throws DatabaseException
\r
112 protected Resource getColorRelation(ReadGraph graph) throws DatabaseException {
\r
113 JFreeChartResource jfree = JFreeChartResource.getInstance(graph);
\r
114 return jfree.color;
\r
119 public void setInput(ISessionContext context, Object input) {
\r
120 final Resource resource = AdaptionUtils.adaptToSingle(input, Resource.class);
\r
122 // Create a listener to define the enabled state of the color chooser button
\r
123 context.getSession().asyncRequest(new Read<Boolean>() {
\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
132 }, new Listener<Boolean>() {
\r
135 public void execute(Boolean result) {
\r
136 if(!color.getWidget().isDisposed()) {
\r
137 color.getWidget().getDisplay().asyncExec(new RunnableWithObject(result) {
\r
139 public void run() {
\r
140 if(!color.getWidget().isDisposed())
\r
141 color.getWidget().setEnabled((Boolean)getObject());
\r
148 public void exception(Throwable t) {
\r
149 t.printStackTrace();
\r
153 public boolean isDisposed() {
\r
154 return color.getWidget().isDisposed();
\r
160 * Get a colored image to be displayed in the color chooser button
\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
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
178 * ImageFactory returning an image for color button
\r
179 * @author Teemu Lempinen
\r
182 private class ColorImageFactoryFactory extends ReadFactoryImpl<Resource, Image> {
\r
186 public ColorImageFactoryFactory(Button button) {
\r
188 this.button = button;
\r
191 public Object getIdentity(Object inputContents) {
\r
192 return new Triple<Object, Class<?>, Button>(inputContents, getClass(), button);
\r
196 public Image perform(ReadGraph graph, Resource input) throws DatabaseException {
\r
197 if(button.getWidget().isDisposed())
\r
199 Display device = button.getWidget().getDisplay();
\r
202 RGB rgb = getColor(graph, getResource(graph, input));
\r
203 return getColorPickerImage(device, rgb.red, rgb.green, rgb.blue);
\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
215 private RGB getColor(ReadGraph graph, Resource input) throws DatabaseException{
\r
216 float[] colorComponents = graph.getPossibleRelatedValue(input, getColorRelation(graph));
\r
218 if(colorComponents == null)
\r
219 rgb = new RGB(0, 0, 255);
\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
229 * SelectionListener for color button.
\r
231 * @author Teemu Lempinen
\r
234 private class ColorSelectionListener extends SelectionListenerImpl<Resource> {
\r
236 private SelectionEvent e;
\r
241 * @param context ISessionContext
\r
243 public ColorSelectionListener(ISessionContext context) {
\r
248 public void widgetSelected(SelectionEvent e) {
\r
249 if(color.getWidget().isDisposed())
\r
251 // Save the event for coordinates
\r
253 super.widgetSelected(e);
\r
257 public void apply(WriteGraph graph, Resource input) throws DatabaseException {
\r
258 if(color.getWidget().isDisposed())
\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
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
278 SimanticsUI.getSession().asyncRequest(new WriteRequest() {
\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
298 * SelectionFactory for default and custom color radio buttons
\r
299 * @author Teemu Lempinen
\r
302 private class DefaultColorSelectionFactory extends ReadFactoryImpl<Resource, Boolean> {
\r
304 private Boolean isCustom;
\r
308 * @param isCustom Is this custom button?
\r
310 public DefaultColorSelectionFactory(Boolean isCustom) {
\r
312 this.isCustom = isCustom;
\r
316 public Object getIdentity(Object inputContents) {
\r
317 return new Triple<Resource, Object, Boolean>((Resource) inputContents, getClass(), isCustom);
\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
327 } else if(r != null && isCustom) {
\r
328 // color definition and custom button -> selected
\r
337 * SelectionListener for default and custom radio buttons
\r
339 * @author Teemu Lempinen
\r
342 private class DefaultColorSelectionListener extends SelectionListenerImpl<Resource> {
\r
344 private SelectionEvent e;
\r
346 public DefaultColorSelectionListener(ISessionContext context) {
\r
351 public void widgetSelected(SelectionEvent e) {
\r
353 super.widgetSelected(e);
\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
368 // Default selected, remove color definition
\r
369 graph.deny(resource, getColorRelation(graph));
\r