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