1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in 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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.utils.ui.color;
\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.ModifyEvent;
\r
18 import org.eclipse.swt.events.ModifyListener;
\r
19 import org.eclipse.swt.events.MouseEvent;
\r
20 import org.eclipse.swt.events.MouseListener;
\r
21 import org.eclipse.swt.events.MouseMoveListener;
\r
22 import org.eclipse.swt.events.SelectionAdapter;
\r
23 import org.eclipse.swt.events.SelectionEvent;
\r
24 import org.eclipse.swt.graphics.GC;
\r
25 import org.eclipse.swt.graphics.Rectangle;
\r
26 import org.eclipse.swt.layout.GridLayout;
\r
27 import org.eclipse.swt.widgets.Button;
\r
28 import org.eclipse.swt.widgets.Composite;
\r
29 import org.eclipse.swt.widgets.Label;
\r
30 import org.eclipse.swt.widgets.TabFolder;
\r
31 import org.eclipse.swt.widgets.TabItem;
\r
32 import org.eclipse.swt.widgets.Text;
\r
36 * Widget to edit colors
\r
38 * @author Marko Luukkainen
\r
41 public class ColorComposite extends Composite{
\r
44 private Color color;
\r
45 private ColorGradient rGradient;
\r
46 private ColorGradient gGradient;
\r
47 private ColorGradient bGradient;
\r
48 private ColorGradient hGradient;
\r
49 private ColorGradient sGradient;
\r
50 private ColorGradient vGradient;
\r
51 private ColorGradient colorGradient;
\r
53 TabFolder tabFolder;
\r
58 IntGradientWidget rCanvas;
\r
59 IntGradientWidget gCanvas;
\r
60 IntGradientWidget bCanvas;
\r
61 ColorGradientCanvas colorCanvas;
\r
66 GradientWidget hCanvas;
\r
67 GradientWidget sCanvas;
\r
68 GradientWidget vCanvas;
\r
70 Button dynamicButton;
\r
72 boolean dynamic = true;
\r
75 public ColorComposite(Composite parent, int style) {
\r
76 super(parent,style);
\r
78 GridLayout layout = new GridLayout();
\r
79 layout.makeColumnsEqualWidth = true;
\r
80 layout.numColumns = 1;
\r
81 this.setLayout(layout);
\r
83 colorCanvas = new ColorGradientCanvas(this,SWT.BORDER|SWT.HORIZONTAL);
\r
85 tabFolder = new TabFolder(this, SWT.NONE);
\r
87 TabItem rgbTab = new TabItem(tabFolder, SWT.NONE);
\r
88 rgbTab.setText("RGB");
\r
89 Composite rgbComposite = new Composite(tabFolder, SWT.NONE);
\r
91 rgbTab.setControl(rgbComposite);
\r
93 Label rLabel = new Label(rgbComposite,SWT.NONE);
\r
94 rLabel.setText("Red");
\r
95 rCanvas = new IntGradientWidget(rgbComposite,SWT.BORDER|SWT.HORIZONTAL){
\r
97 protected void updatePosition(int value) {
\r
98 Color newColor = new Color(value,color.getG(),color.getB());
\r
102 rText = new Text(rgbComposite,SWT.BORDER);
\r
103 rText.addModifyListener(new IntColorModifyListener() {
\r
106 void setValue(int value) {
\r
107 Color newColor = new Color(value,color.getG(),color.getB());
\r
108 setColor(newColor);
\r
112 Label gLabel = new Label(rgbComposite,SWT.NONE);
\r
113 gLabel.setText("Green");
\r
114 gCanvas = new IntGradientWidget(rgbComposite,SWT.BORDER|SWT.HORIZONTAL) {
\r
116 protected void updatePosition(int value) {
\r
117 Color newColor = new Color(color.getR(),value,color.getB());
\r
118 setColor(newColor);
\r
121 gText = new Text(rgbComposite,SWT.BORDER);
\r
122 gText.addModifyListener(new IntColorModifyListener() {
\r
125 void setValue(int value) {
\r
126 Color newColor = new Color(color.getR(),value,color.getB());
\r
127 setColor(newColor);
\r
131 Label bLabel = new Label(rgbComposite,SWT.NONE);
\r
132 bLabel.setText("Blue");
\r
133 bCanvas = new IntGradientWidget(rgbComposite,SWT.BORDER|SWT.HORIZONTAL) {
\r
135 protected void updatePosition(int value) {
\r
136 Color newColor = new Color(color.getR(),color.getG(),value);
\r
137 setColor(newColor);
\r
140 bText = new Text(rgbComposite,SWT.BORDER);
\r
141 bText.addModifyListener(new IntColorModifyListener() {
\r
144 void setValue(int value) {
\r
145 Color newColor = new Color(color.getR(),color.getG(),value);
\r
146 setColor(newColor);
\r
150 TabItem hsvTab = new TabItem(tabFolder, SWT.NONE);
\r
151 hsvTab.setText("HSV");
\r
152 Composite hsvComposite = new Composite(tabFolder, SWT.NONE);
\r
154 hsvTab.setControl(hsvComposite);
\r
156 Label hLabel = new Label(hsvComposite,SWT.NONE);
\r
157 hLabel.setText("Hue");
\r
158 hCanvas = new GradientWidget(hsvComposite,SWT.BORDER|SWT.HORIZONTAL) {
\r
160 protected boolean updatePosition(double d) {
\r
161 Color newColor = new Color(d*360.0,color.getS(),color.getV());
\r
162 setColor(newColor);
\r
167 protected void setPosition(double d) {
\r
168 super.setPosition(d/360.0);
\r
171 hText = new Text(hsvComposite,SWT.BORDER);
\r
172 hText.addModifyListener(new DoubleColorModifyListener(0.,360.) {
\r
175 void setValue(double value) {
\r
176 Color newColor = new Color(value,color.getS(),color.getV());
\r
177 setColor(newColor);
\r
181 Label sLabel = new Label(hsvComposite,SWT.NONE);
\r
182 sLabel.setText("Saturation");
\r
183 sCanvas = new GradientWidget(hsvComposite,SWT.BORDER|SWT.HORIZONTAL) {
\r
185 protected boolean updatePosition(double d) {
\r
186 Color newColor = new Color(color.getH(),d,color.getV());
\r
187 setColor(newColor);
\r
191 sText = new Text(hsvComposite,SWT.BORDER);
\r
192 sText.addModifyListener(new DoubleColorModifyListener(0.,1.) {
\r
195 void setValue(double value) {
\r
196 Color newColor = new Color(color.getH(),value,color.getV());
\r
197 setColor(newColor);
\r
201 Label vLabel = new Label(hsvComposite,SWT.NONE);
\r
202 vLabel.setText("Value");
\r
203 vCanvas = new GradientWidget(hsvComposite,SWT.BORDER|SWT.HORIZONTAL) {
\r
205 protected boolean updatePosition(double d) {
\r
206 Color newColor = new Color(color.getH(),color.getS(),d);
\r
207 setColor(newColor);
\r
211 vText = new Text(hsvComposite,SWT.BORDER);
\r
212 vText.addModifyListener(new DoubleColorModifyListener(0.,1.) {
\r
215 void setValue(double value) {
\r
216 Color newColor = new Color(color.getH(),color.getS(),value);
\r
217 setColor(newColor);
\r
221 TabItem settingsTab = new TabItem(tabFolder, SWT.NONE);
\r
222 settingsTab.setText("Settings");
\r
223 Composite settingsComposite = new Composite(tabFolder, SWT.NONE);
\r
225 settingsTab.setControl(settingsComposite);
\r
227 dynamicButton = new Button(settingsComposite, SWT.CHECK);
\r
228 dynamicButton.setText("Dynamic widgets");
\r
229 dynamicButton.setSelection(dynamic);
\r
230 dynamicButton.addSelectionListener(new SelectionAdapter() {
\r
232 public void widgetSelected(SelectionEvent e) {
\r
233 dynamic = dynamicButton.getSelection();
\r
238 GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).applyTo(rgbComposite);
\r
239 GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).applyTo(hsvComposite);
\r
240 GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).applyTo(settingsComposite);
\r
241 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(rgbComposite);
\r
242 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(hsvComposite);
\r
243 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(settingsComposite);
\r
244 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(tabFolder);
\r
246 GridDataFactory.fillDefaults().hint(-1, 32).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(colorCanvas);
\r
247 GridDataFactory.fillDefaults().hint(-1, 16).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(rCanvas);
\r
248 GridDataFactory.fillDefaults().hint(-1, 16).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(gCanvas);
\r
249 GridDataFactory.fillDefaults().hint(-1, 16).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(bCanvas);
\r
250 GridDataFactory.fillDefaults().hint(-1, 16).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(hCanvas);
\r
251 GridDataFactory.fillDefaults().hint(-1, 16).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(sCanvas);
\r
252 GridDataFactory.fillDefaults().hint(-1, 16).grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(vCanvas);
\r
253 GridDataFactory.fillDefaults().hint(20, 15).grab(false, false).applyTo(rText);
\r
254 GridDataFactory.fillDefaults().hint(20, 15).grab(false, false).applyTo(gText);
\r
255 GridDataFactory.fillDefaults().hint(20, 15).grab(false, false).applyTo(bText);
\r
256 GridDataFactory.fillDefaults().hint(20, 15).grab(false, false).applyTo(hText);
\r
257 GridDataFactory.fillDefaults().hint(20, 15).grab(false, false).applyTo(sText);
\r
258 GridDataFactory.fillDefaults().hint(20, 15).grab(false, false).applyTo(vText);
\r
261 setColor(new Color(255,255,255));
\r
266 private abstract class IntColorModifyListener implements ModifyListener {
\r
267 boolean modify = false;
\r
269 public void modifyText(ModifyEvent e) {
\r
270 if (internalUpdate)
\r
275 Text text = (Text)e.widget;
\r
277 int value = Integer.parseInt(text.getText());
\r
283 } catch (NumberFormatException err) {
\r
290 abstract void setValue(int value);
\r
293 private abstract class DoubleColorModifyListener implements ModifyListener {
\r
294 boolean modify = false;
\r
298 public DoubleColorModifyListener( double min, double max) {
\r
304 public void modifyText(ModifyEvent e) {
\r
305 if (internalUpdate)
\r
310 Text text = (Text)e.widget;
\r
312 double value = Integer.parseInt(text.getText());
\r
315 } else if (value > max)
\r
318 } catch (NumberFormatException err) {
\r
325 abstract void setValue(double value);
\r
328 public void setColor(Color color) {
\r
329 this.color = color;
\r
333 public Color getColor() {
\r
337 private void updateGradients() {
\r
339 rGradient = new ColorGradient(new ColorValue[]{
\r
340 new ColorValue(new Color(0,color.getG(),color.getB()),0.0),
\r
341 new ColorValue(new Color(255,color.getG(),color.getB()),1.0)});
\r
342 gGradient = new ColorGradient(new ColorValue[]{
\r
343 new ColorValue(new Color(color.getR(),0,color.getB()),0.0),
\r
344 new ColorValue(new Color(color.getR(),255,color.getB()),1.0)});
\r
345 bGradient = new ColorGradient(new ColorValue[]{
\r
346 new ColorValue(new Color(color.getR(),color.getG(),0),0.0),
\r
347 new ColorValue(new Color(color.getR(),color.getG(),255),1.0)});
\r
348 // hue is interpolated along the shortest route, using just 0 and 360 would result in constant color.
\r
349 hGradient = new ColorGradient(new ColorValue[]{
\r
350 new ColorValue(new Color(0.0,color.getS(),color.getV()),0.0),
\r
351 new ColorValue(new Color(90.0,color.getS(),color.getV()),0.25),
\r
352 new ColorValue(new Color(180.0,color.getS(),color.getV()),0.5),
\r
353 new ColorValue(new Color(270.0,color.getS(),color.getV()),0.75),
\r
354 new ColorValue(new Color(360.0,color.getS(),color.getV()),1.0)}, ColorGradient.HSV);
\r
355 sGradient = new ColorGradient(new ColorValue[]{
\r
356 new ColorValue(new Color(color.getH(),0.0,color.getV()),0.0),
\r
357 new ColorValue(new Color(color.getH(),1.0,color.getV()),1.0)}, ColorGradient.HSV);
\r
358 vGradient = new ColorGradient(new ColorValue[]{
\r
359 new ColorValue(new Color(color.getH(),color.getS(),0.0),0.0),
\r
360 new ColorValue(new Color(color.getH(),color.getS(),1.0),1.0)}, ColorGradient.HSV);
\r
362 rGradient = new ColorGradient(new ColorValue[]{
\r
363 new ColorValue(new Color(0,0,0),0.0),
\r
364 new ColorValue(new Color(255,0,0),1.0)});
\r
365 gGradient = new ColorGradient(new ColorValue[]{
\r
366 new ColorValue(new Color(0,0,0),0.0),
\r
367 new ColorValue(new Color(0,255,0),1.0)});
\r
368 bGradient = new ColorGradient(new ColorValue[]{
\r
369 new ColorValue(new Color(0,0,0),0.0),
\r
370 new ColorValue(new Color(0,0,255),1.0)});
\r
371 // hue is interpolated along the shortest route, using just 0 and 360 would result in constant color.
\r
372 hGradient = new ColorGradient(new ColorValue[]{
\r
373 new ColorValue(new Color(0.0,1.0,1.0),0.0),
\r
374 new ColorValue(new Color(90.0,1.0,1.0),0.25),
\r
375 new ColorValue(new Color(180.0,1.0,1.0),0.5),
\r
376 new ColorValue(new Color(270.0,1.0,1.0),0.75),
\r
377 new ColorValue(new Color(360.0,1.0,1.0),1.0)}, ColorGradient.HSV);
\r
378 sGradient = new ColorGradient(new ColorValue[]{
\r
379 new ColorValue(new Color(color.getH(),0.0,1.0),0.0),
\r
380 new ColorValue(new Color(color.getH(),1.0,1.0),1.0)}, ColorGradient.HSV);
\r
381 vGradient = new ColorGradient(new ColorValue[]{
\r
382 new ColorValue(new Color(color.getH(),1.0,0.0),0.0),
\r
383 new ColorValue(new Color(color.getH(),1.0,1.0),1.0)}, ColorGradient.HSV);
\r
386 colorGradient = new ColorGradient(new ColorValue[]{
\r
387 new ColorValue(new Color(color.getR(),color.getG(),color.getB()),0.0)});
\r
391 private boolean internalUpdate = false;
\r
393 private void updateWidgets() {
\r
394 if (internalUpdate)
\r
396 internalUpdate = true;
\r
398 rCanvas.setGradient(rGradient);
\r
399 gCanvas.setGradient(gGradient);
\r
400 bCanvas.setGradient(bGradient);
\r
401 hCanvas.setGradient(hGradient);
\r
402 sCanvas.setGradient(sGradient);
\r
403 vCanvas.setGradient(vGradient);
\r
404 colorCanvas.setGradient(colorGradient);
\r
406 rCanvas.setPosition(color.getR());
\r
407 gCanvas.setPosition(color.getG());
\r
408 bCanvas.setPosition(color.getB());
\r
409 hCanvas.setPosition(color.getH());
\r
410 sCanvas.setPosition(color.getS());
\r
411 vCanvas.setPosition(color.getV());
\r
413 if(!rText.isFocusControl())
\r
414 rText.setText(Integer.toString(color.getR()));
\r
415 if(!gText.isFocusControl())
\r
416 gText.setText(Integer.toString(color.getG()));
\r
417 if(!bText.isFocusControl())
\r
418 bText.setText(Integer.toString(color.getB()));
\r
419 if(!hText.isFocusControl())
\r
420 hText.setText(Double.toString(color.getH()));
\r
421 if(!sText.isFocusControl())
\r
422 sText.setText(Double.toString(color.getS()));
\r
423 if(!vText.isFocusControl())
\r
424 vText.setText(Double.toString(color.getV()));
\r
425 internalUpdate = false;
\r
428 private abstract static class IntGradientWidget extends GradientWidget {
\r
430 public IntGradientWidget(Composite parent, int style) {
\r
431 super(parent, style);
\r
435 protected boolean updatePosition(double d) {
\r
436 int value = (int)(d * 255);
\r
441 updatePosition(value);
\r
444 protected abstract void updatePosition(int value);
\r
446 protected void setPosition(int value) {
\r
447 double d = ((double)value)/255.0;
\r
453 private abstract static class GradientWidget extends ColorGradientCanvas {
\r
456 double posD = -1.0;
\r
463 public GradientWidget(Composite parent, int style) {
\r
464 super(parent, style);
\r
465 this.addMouseListener(new MouseListener() {
\r
467 public void mouseDown(MouseEvent e) {
\r
468 if (e.button == 1) {
\r
474 public void mouseUp(MouseEvent e) {}
\r
476 public void mouseDoubleClick(MouseEvent e) {}
\r
478 this.addMouseMoveListener(new MouseMoveListener() {
\r
481 public void mouseMove(MouseEvent e) {
\r
482 if ((e.stateMask & SWT.BUTTON1)>0) {
\r
489 protected void update(MouseEvent e) {
\r
490 Rectangle r = getClientArea();
\r
492 if ((style & SWT.HORIZONTAL) > 0) {
\r
493 d = (double)e.x / (double)r.width;
\r
495 d = (double)e.y / (double)r.height;
\r
501 if (updatePosition(d)) {
\r
502 if ((style & SWT.HORIZONTAL) > 0) {
\r
503 pos = (int)(d*((double)r.width));
\r
505 pos = (int)(d*((double)r.height));
\r
511 protected abstract boolean updatePosition(double d);
\r
513 protected void setPosition(double d) {
\r
519 private void _setPosition(double d) {
\r
520 Rectangle r = getClientArea();
\r
523 if ((style & SWT.HORIZONTAL) > 0) {
\r
524 pos = (int)(d * (double)r.width);
\r
526 pos = (int)(d * (double)r.height);
\r
533 Rectangle prevClip;
\r
535 protected void paintGradient(GC gc, Rectangle clip) {
\r
536 super.paintGradient(gc, clip);
\r
537 if (!clip.equals(prevClip)) {
\r
539 _setPosition(posD);
\r
543 org.eclipse.swt.graphics.Color white = new org.eclipse.swt.graphics.Color(gc.getDevice(), 255,255,255);
\r
544 org.eclipse.swt.graphics.Color black = new org.eclipse.swt.graphics.Color(gc.getDevice(), 0, 0, 0);
\r
545 gc.setForeground(black);
\r
546 gc.setBackground(white);
\r
549 if ((style & SWT.HORIZONTAL) > 0) {
\r
551 y = clip.height / 2;
\r
553 x = clip.width / 2;
\r
556 gc.fillOval(x-sized2, y-sized2, size, size);
\r
557 gc.drawOval(x-sized2, y-sized2, size, size);
\r