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.jface.resource.ImageDescriptor;
\r
17 import org.eclipse.jface.resource.JFaceResources;
\r
18 import org.eclipse.jface.resource.LocalResourceManager;
\r
19 import org.eclipse.swt.SWT;
\r
20 import org.eclipse.swt.events.SelectionEvent;
\r
21 import org.eclipse.swt.graphics.Point;
\r
22 import org.eclipse.swt.graphics.RGB;
\r
23 import org.eclipse.swt.widgets.ColorDialog;
\r
24 import org.eclipse.swt.widgets.Composite;
\r
25 import org.eclipse.swt.widgets.Display;
\r
26 import org.eclipse.swt.widgets.Shell;
\r
27 import org.simantics.browsing.ui.swt.widgets.Button;
\r
28 import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;
\r
29 import org.simantics.browsing.ui.swt.widgets.impl.SelectionListenerImpl;
\r
30 import org.simantics.browsing.ui.swt.widgets.impl.Widget;
\r
31 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;
\r
32 import org.simantics.db.ReadGraph;
\r
33 import org.simantics.db.Resource;
\r
34 import org.simantics.db.WriteGraph;
\r
35 import org.simantics.db.common.request.WriteRequest;
\r
36 import org.simantics.db.exception.DatabaseException;
\r
37 import org.simantics.db.management.ISessionContext;
\r
38 import org.simantics.db.procedure.Listener;
\r
39 import org.simantics.db.request.Read;
\r
40 import org.simantics.diagram.stubs.G2DResource;
\r
41 import org.simantics.sysdyn.JFreeChartResource;
\r
42 import org.simantics.ui.SimanticsUI;
\r
43 import org.simantics.utils.RunnableWithObject;
\r
44 import org.simantics.utils.datastructures.Triple;
\r
45 import org.simantics.utils.ui.AdaptionUtils;
\r
46 import org.simantics.utils.ui.gfx.ColorImageDescriptor;
\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 this(parent, context, support, style, true);
\r
72 * Create a composite containing radio buttons for default or custom color. Color chooser button is active
\r
73 * when the custom radio button is selected. Color chooser uses {@link ColorDialog} to select a color
\r
75 * @param parent Composite
\r
76 * @param context ISessionContext
\r
77 * @param support WidgetSupport
\r
78 * @param style SWT style
\r
79 * @param defaultColor provide default color widget?
\r
81 public ColorPicker(Composite parent, ISessionContext context, WidgetSupport support, int style, boolean defaultColor) {
\r
82 super(parent, style);
\r
83 support.register(this);
\r
85 if(support.getParameter(WidgetSupport.RESOURCE_MANAGER) == null) {
\r
86 LocalResourceManager resourceManager = new LocalResourceManager(JFaceResources.getResources(), this);
\r
87 support.setParameter(WidgetSupport.RESOURCE_MANAGER, resourceManager);
\r
91 GridLayoutFactory.fillDefaults().numColumns(4).applyTo(this);
\r
93 this.defaultColor = new Button(this, support, SWT.RADIO);
\r
94 this.defaultColor.setText("default");
\r
95 this.defaultColor.setSelectionFactory(new DefaultColorSelectionFactory(false));
\r
96 this.defaultColor.addSelectionListener(new DefaultColorSelectionListener(context));
\r
97 GridDataFactory.fillDefaults().applyTo(this.defaultColor.getWidget());
\r
99 customColor = new Button(this, support, SWT.RADIO);
\r
100 customColor.setText("custom");
\r
101 customColor.setSelectionFactory(new DefaultColorSelectionFactory(true));
\r
102 customColor.addSelectionListener(new DefaultColorSelectionListener(context));
\r
104 GridDataFactory.fillDefaults().applyTo(customColor.getWidget());
\r
106 GridLayoutFactory.fillDefaults().applyTo(this);
\r
110 color = new Button(this, support, SWT.PUSH);
\r
111 color.setImageFactory(new ColorImageFactoryFactory(this));
\r
112 color.addSelectionListener(new ColorSelectionListener(context));
\r
113 color.getWidget().setEnabled(false);
\r
114 GridDataFactory.fillDefaults().applyTo(color.getWidget());
\r
118 * Method for finding the resource for which the color is selected.
\r
120 * @param graph ReadGraph
\r
121 * @param input input from WidgetSupport
\r
123 * @throws DatabaseException
\r
125 protected Resource getResource(ReadGraph graph, Resource input) throws DatabaseException {
\r
130 * Method for getting the relation with which the g2d.Color is related to a resource
\r
132 * @param graph ReadGraph
\r
133 * @return Color relation
\r
134 * @throws DatabaseException
\r
136 protected Resource getColorRelation(ReadGraph graph) throws DatabaseException {
\r
137 JFreeChartResource jfree = JFreeChartResource.getInstance(graph);
\r
138 return jfree.color;
\r
143 public void setInput(ISessionContext context, Object input) {
\r
144 final Resource resource = AdaptionUtils.adaptToSingle(input, Resource.class);
\r
146 // Create a listener to define the enabled state of the color chooser button
\r
147 context.getSession().asyncRequest(new Read<Float[]>() {
\r
150 public Float[] perform(ReadGraph graph) throws DatabaseException {
\r
151 if(graph.hasStatement(getResource(graph, resource), getColorRelation(graph))) {
\r
152 float[] components = graph.getPossibleRelatedValue(getResource(graph, resource), getColorRelation(graph));
\r
153 Float[] result = new Float[components.length];
\r
154 for(int i = 0; i < components.length; i++) result[i] = components[i];
\r
161 }, new Listener<Float[]>() {
\r
164 public void execute(Float[] result) {
\r
165 if(!color.getWidget().isDisposed()) {
\r
166 color.getWidget().getDisplay().asyncExec(new RunnableWithObject(result != null ? true : false) {
\r
168 public void run() {
\r
169 if(!color.getWidget().isDisposed()) {
\r
170 if(!Boolean.TRUE.equals(getObject()))
\r
171 color.getWidget().setEnabled(false);
\r
173 color.getWidget().setEnabled(true);
\r
181 public void exception(Throwable t) {
\r
182 t.printStackTrace();
\r
186 public boolean isDisposed() {
\r
187 return color.getWidget().isDisposed();
\r
194 * ImageFactory returning an image for color button
\r
195 * @author Teemu Lempinen
\r
198 private class ColorImageFactoryFactory extends ReadFactoryImpl<Resource, ImageDescriptor> {
\r
200 private ColorPicker picker;
\r
202 public ColorImageFactoryFactory(ColorPicker colorPicker) {
\r
203 this.picker = colorPicker;
\r
207 public ImageDescriptor perform(ReadGraph graph, Resource input) throws DatabaseException {
\r
208 RGB rgb = getColor(graph, getResource(graph, input));
\r
209 return new ColorImageDescriptor(rgb.red, rgb.green, rgb.blue, 20, 20, false);
\r
214 public Object getIdentity(Object inputContents) {
\r
215 return new Triple<Object, ColorPicker, Class<?>>(inputContents, picker, getClass());
\r
221 * Get RGB from a color literal resource. If resource is not a color resource, return blue (RGB 0, 0, 255)
\r
222 * @param graph ReadGraph
\r
223 * @param input Color literal resource (float[4])
\r
224 * @return RGB color
\r
225 * @throws DatabaseException
\r
227 private RGB getColor(ReadGraph graph, Resource input) throws DatabaseException{
\r
228 float[] colorComponents = graph.getPossibleRelatedValue(input, getColorRelation(graph));
\r
230 if(colorComponents == null)
\r
231 rgb = new RGB(0, 0, 255);
\r
233 rgb = new RGB((int)(colorComponents[0] * 255.0f),
\r
234 (int)(colorComponents[1] * 255.0f),
\r
235 (int)(colorComponents[2] * 255.0f));
\r
241 * SelectionListener for color button.
\r
243 * @author Teemu Lempinen
\r
246 private class ColorSelectionListener extends SelectionListenerImpl<Resource> {
\r
248 private SelectionEvent e;
\r
253 * @param context ISessionContext
\r
255 public ColorSelectionListener(ISessionContext context) {
\r
260 public void widgetSelected(SelectionEvent e) {
\r
261 if(color.getWidget().isDisposed())
\r
263 // Save the event for coordinates
\r
265 super.widgetSelected(e);
\r
269 public void apply(WriteGraph graph, Resource input) throws DatabaseException {
\r
270 if(color.getWidget().isDisposed())
\r
273 final Resource resource = getResource(graph, input);
\r
274 final Display display = color.getWidget().getDisplay();
\r
275 final RGB oldRGB = getColor(graph, resource);
\r
277 display.asyncExec(new RunnableWithObject(oldRGB) {
\r
279 public void run() {
\r
280 // Use color dialog to select a color
\r
281 Shell shell = new Shell(display);
\r
282 ColorDialog cd = new ColorDialog(shell);
\r
283 Point point = color.getWidget().toDisplay(e.x - 150, e.y - 150);
\r
284 cd.getParent().setLocation(point.x, point.y);
\r
285 cd.setText("Select color");
\r
286 cd.setRGB((RGB)getObject());
\r
291 SimanticsUI.getSession().asyncRequest(new WriteRequest() {
\r
294 public void perform(WriteGraph graph) throws DatabaseException {
\r
295 G2DResource g2d = G2DResource.getInstance(graph);
\r
296 float[] components = new float[] {rgb.red / 255.0f, rgb.green / 255.0f, rgb.blue / 255.0f, 1.0f};
\r
297 graph.claimLiteral(resource, getColorRelation(graph), g2d.Color, components);
\r
311 * SelectionFactory for default and custom color radio buttons
\r
312 * @author Teemu Lempinen
\r
315 private class DefaultColorSelectionFactory extends ReadFactoryImpl<Resource, Boolean> {
\r
317 private final Boolean isCustom;
\r
321 * @param isCustom Is this custom button?
\r
323 public DefaultColorSelectionFactory(Boolean isCustom) {
\r
325 this.isCustom = isCustom;
\r
329 public Object getIdentity(Object inputContents) {
\r
330 return new Triple<Resource, Object, Boolean>((Resource) inputContents, getClass(), isCustom);
\r
334 public Boolean perform(ReadGraph graph, Resource input) throws DatabaseException {
\r
335 Resource r = graph.getPossibleObject(getResource(graph, input), getColorRelation(graph));
\r
336 boolean result = false; // Default == not selected
\r
337 if(r == null && !isCustom) {
\r
338 // No color definition and default-button -> selected
\r
340 } else if(r != null && isCustom) {
\r
341 // color definition and custom button -> selected
\r
350 * SelectionListener for default and custom radio buttons
\r
352 * @author Teemu Lempinen
\r
355 private class DefaultColorSelectionListener extends SelectionListenerImpl<Resource> {
\r
357 private SelectionEvent e;
\r
359 public DefaultColorSelectionListener(ISessionContext context) {
\r
364 public void widgetSelected(SelectionEvent e) {
\r
366 super.widgetSelected(e);
\r
370 public void apply(WriteGraph graph, Resource input) throws DatabaseException {
\r
371 Resource resource = getResource(graph, input);
\r
372 if(customColor.getWidget().equals(e.widget)) {
\r
373 // Custom selected. If there is no color already, create a default Blue color
\r
374 G2DResource g2d = G2DResource.getInstance(graph);
\r
375 if(graph.getPossibleObject(resource, getColorRelation(graph)) == null) {
\r
376 float[] components = java.awt.Color.BLUE.getColorComponents(new float[4]);
\r
377 components[3] = 1.0f;
\r
378 graph.claimLiteral(resource, getColorRelation(graph), g2d.Color, components);
\r
381 // Default selected, remove color definition
\r
382 graph.deny(resource, getColorRelation(graph));
\r