]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorComposite.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / color / ColorComposite.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.utils.ui.color;
13
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;
33
34 /**
35  * 
36  * Widget to edit colors
37  * 
38  * @author Marko Luukkainen
39  *
40  */
41 public class ColorComposite extends Composite{
42         
43         
44         private Color color;
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;
52         
53         TabFolder tabFolder;
54         
55         Text rText;
56         Text gText;
57         Text bText;
58         IntGradientWidget rCanvas;
59         IntGradientWidget gCanvas;
60         IntGradientWidget bCanvas;
61         ColorGradientCanvas colorCanvas;
62         
63         Text hText;
64         Text sText;
65         Text vText;
66         GradientWidget hCanvas;
67         GradientWidget sCanvas;
68         GradientWidget vCanvas;
69         
70         Button dynamicButton;
71         
72         boolean dynamic = true;
73         
74         
75         public ColorComposite(Composite parent, int style) {
76                 super(parent,style);
77                 
78                 GridLayout layout = new GridLayout();
79                 layout.makeColumnsEqualWidth = true;
80                 layout.numColumns = 1;
81                 this.setLayout(layout);
82                 
83                 colorCanvas = new ColorGradientCanvas(this,SWT.BORDER|SWT.HORIZONTAL);
84                 
85                 tabFolder = new TabFolder(this, SWT.NONE);
86                 
87                 TabItem rgbTab = new TabItem(tabFolder, SWT.NONE);
88                 rgbTab.setText("RGB");
89                 Composite rgbComposite = new Composite(tabFolder, SWT.NONE);
90                 
91                 rgbTab.setControl(rgbComposite);
92                 
93                 Label rLabel = new Label(rgbComposite,SWT.NONE);
94                 rLabel.setText("Red");
95                 rCanvas = new IntGradientWidget(rgbComposite,SWT.BORDER|SWT.HORIZONTAL){
96                         @Override
97                         protected void updatePosition(int value) {
98                                 Color newColor = new Color(value,color.getG(),color.getB());
99                                 setColor(newColor);
100                         }
101                 };
102                 rText = new Text(rgbComposite,SWT.BORDER);
103                 rText.addModifyListener(new IntColorModifyListener() {
104                         
105                         @Override
106                         void setValue(int value) {
107                                 Color newColor = new Color(value,color.getG(),color.getB());
108                                 setColor(newColor);
109                         }
110                 });
111                 
112                 Label gLabel = new Label(rgbComposite,SWT.NONE);
113                 gLabel.setText("Green");
114                 gCanvas = new IntGradientWidget(rgbComposite,SWT.BORDER|SWT.HORIZONTAL) {
115                         @Override
116                         protected void updatePosition(int value) {
117                                 Color newColor = new Color(color.getR(),value,color.getB());
118                                 setColor(newColor);
119                         }
120                 };
121                 gText = new Text(rgbComposite,SWT.BORDER);
122                 gText.addModifyListener(new IntColorModifyListener() {
123                         
124                         @Override
125                         void setValue(int value) {
126                                 Color newColor = new Color(color.getR(),value,color.getB());
127                                 setColor(newColor);
128                         }
129                 });
130                 
131                 Label bLabel = new Label(rgbComposite,SWT.NONE);
132                 bLabel.setText("Blue");
133                 bCanvas = new IntGradientWidget(rgbComposite,SWT.BORDER|SWT.HORIZONTAL) {
134                         @Override
135                         protected void updatePosition(int value) {
136                                 Color newColor = new Color(color.getR(),color.getG(),value);
137                                 setColor(newColor);
138                         }
139                 };
140                 bText = new Text(rgbComposite,SWT.BORDER);
141                 bText.addModifyListener(new IntColorModifyListener() {
142                         
143                         @Override
144                         void setValue(int value) {
145                                 Color newColor = new Color(color.getR(),color.getG(),value);
146                                 setColor(newColor);
147                         }
148                 });
149                 
150                 TabItem hsvTab = new TabItem(tabFolder, SWT.NONE);
151                 hsvTab.setText("HSV");
152                 Composite hsvComposite = new Composite(tabFolder, SWT.NONE);
153                 
154                 hsvTab.setControl(hsvComposite);
155                 
156                 Label hLabel = new Label(hsvComposite,SWT.NONE);
157                 hLabel.setText("Hue");
158                 hCanvas = new GradientWidget(hsvComposite,SWT.BORDER|SWT.HORIZONTAL) {
159                         @Override
160                         protected boolean updatePosition(double d) {
161                                 Color newColor = new Color(d*360.0,color.getS(),color.getV());
162                                 setColor(newColor);
163                                 return true;
164                         }
165                         
166                         @Override
167                         protected void setPosition(double d) {
168                                 super.setPosition(d/360.0);
169                         }
170                 };
171                 hText = new Text(hsvComposite,SWT.BORDER);
172                 hText.addModifyListener(new DoubleColorModifyListener(0.,360.) {
173                         
174                         @Override
175                         void setValue(double value) {
176                                 Color newColor = new Color(value,color.getS(),color.getV());
177                                 setColor(newColor);
178                         }
179                 });
180                 
181                 Label sLabel = new Label(hsvComposite,SWT.NONE);
182                 sLabel.setText("Saturation");
183                 sCanvas = new GradientWidget(hsvComposite,SWT.BORDER|SWT.HORIZONTAL) {
184                         @Override
185                         protected boolean updatePosition(double d) {
186                                 Color newColor = new Color(color.getH(),d,color.getV());
187                                 setColor(newColor);
188                                 return true;
189                         }
190                 };
191                 sText = new Text(hsvComposite,SWT.BORDER);
192                 sText.addModifyListener(new DoubleColorModifyListener(0.,1.) {
193                         
194                         @Override
195                         void setValue(double value) {
196                                 Color newColor = new Color(color.getH(),value,color.getV());
197                                 setColor(newColor);
198                         }
199                 });
200                 
201                 Label vLabel = new Label(hsvComposite,SWT.NONE);
202                 vLabel.setText("Value");
203                 vCanvas = new GradientWidget(hsvComposite,SWT.BORDER|SWT.HORIZONTAL) {
204                         @Override
205                         protected boolean updatePosition(double d) {
206                                 Color newColor = new Color(color.getH(),color.getS(),d);
207                                 setColor(newColor);
208                                 return true;
209                         }
210                 };
211                 vText = new Text(hsvComposite,SWT.BORDER);
212                 vText.addModifyListener(new DoubleColorModifyListener(0.,1.) {
213                         
214                         @Override
215                         void setValue(double value) {
216                                 Color newColor = new Color(color.getH(),color.getS(),value);
217                                 setColor(newColor);
218                         }
219                 });
220                 
221                 TabItem settingsTab = new TabItem(tabFolder, SWT.NONE);
222                 settingsTab.setText("Settings");
223                 Composite settingsComposite = new Composite(tabFolder, SWT.NONE);
224                 
225                 settingsTab.setControl(settingsComposite);
226                 
227                 dynamicButton = new Button(settingsComposite, SWT.CHECK);
228                 dynamicButton.setText("Dynamic widgets");
229                 dynamicButton.setSelection(dynamic);
230                 dynamicButton.addSelectionListener(new SelectionAdapter() {
231                         @Override
232                         public void widgetSelected(SelectionEvent e) {
233                                 dynamic = dynamicButton.getSelection();
234                                 updateWidgets();
235                         }
236                 });
237
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);
245                 
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);
259                 
260                 if (color == null)
261                         setColor(new Color(255,255,255));
262                 else
263                         setColor(color);
264         }
265         
266         private abstract class IntColorModifyListener implements ModifyListener {
267                 boolean modify = false;
268                 @Override
269                 public void modifyText(ModifyEvent e) {
270                         if (internalUpdate)
271                                 return;
272                         if (modify)
273                                 return;
274                         modify = true;
275                         Text text = (Text)e.widget;
276                         try {
277                                 int value = Integer.parseInt(text.getText());
278                                 if (value < 0)
279                                         value = 0;
280                                 if (value > 255)
281                                         value = 255;
282                                 setValue(value);
283                         } catch (NumberFormatException err) {
284                                 
285                         }
286                         modify = false;
287                         
288                 }
289                 
290                 abstract void setValue(int value);
291         }
292
293         private abstract class DoubleColorModifyListener implements ModifyListener {
294                 boolean modify = false;
295                 double min;
296                 double max;
297                 
298                 public DoubleColorModifyListener( double min, double max) {
299                         this.min = min;
300                         this.max = max;
301                 }
302                 
303                 @Override
304                 public void modifyText(ModifyEvent e) {
305                         if (internalUpdate)
306                                 return;
307                         if (modify)
308                                 return;
309                         modify = true;
310                         Text text = (Text)e.widget;
311                         try {
312                                 double value = Integer.parseInt(text.getText());
313                                 if (value < min) {
314                                         value = min;
315                                 } else if (value > max)
316                                         value = max;
317                                 setValue(value);
318                         } catch (NumberFormatException err) {
319                                 
320                         }
321                         modify = false;                 
322                 }
323
324                 
325                 abstract void setValue(double value);
326         }
327         
328         public void setColor(Color color) {
329                 this.color = color;
330                 updateWidgets();
331         }
332         
333         public Color getColor() {
334                 return color;
335         }
336         
337         private void updateGradients() {
338                 if (dynamic) {
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);
361                 } else {
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);
384                 }
385                 
386                 colorGradient = new ColorGradient(new ColorValue[]{
387                                 new ColorValue(new Color(color.getR(),color.getG(),color.getB()),0.0)});
388         
389         }
390         
391         private boolean internalUpdate = false;
392         
393         private void updateWidgets() {
394                 if (internalUpdate)
395                         return;
396                 internalUpdate = true;
397                 updateGradients();
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);
405                 
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());
412                 
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;
426         }
427         
428         private abstract static class IntGradientWidget extends GradientWidget {
429
430                 public IntGradientWidget(Composite parent, int style) {
431                         super(parent, style);
432                 }
433                 
434                 @Override
435                 protected boolean updatePosition(double d) {
436                         int value = (int)(d * 255);
437                         if (value < 0)
438                                 value = 0;
439                         if (value > 255)
440                                 value = 255;
441                         updatePosition(value);
442                         return true;
443                 }
444                 protected abstract void updatePosition(int value);
445                 
446                 protected void setPosition(int value) {
447                         double d = ((double)value)/255.0;
448                         setPosition(d);
449                 }
450                 
451         }
452         
453         private abstract static class GradientWidget extends ColorGradientCanvas {
454
455                 int pos = -1;
456                 double posD = -1.0;
457                 
458                 int size = 8;
459                 int sized2 = 4;
460                 
461                 
462                 
463                 public GradientWidget(Composite parent, int style) {
464                         super(parent, style);
465                         this.addMouseListener(new MouseListener() {                     
466                                 @Override
467                                 public void mouseDown(MouseEvent e) {
468                                         if (e.button == 1) {
469                                                 update(e);
470                                         }
471                                 }
472                                 
473                                 @Override
474                                 public void mouseUp(MouseEvent e) {}
475                                 @Override
476                                 public void mouseDoubleClick(MouseEvent e) {}
477                         });
478                         this.addMouseMoveListener(new MouseMoveListener() {
479                                 
480                                 @Override
481                                 public void mouseMove(MouseEvent e) {
482                                         if ((e.stateMask & SWT.BUTTON1)>0) {
483                                                 update(e);
484                                         }
485                                 }
486                         });
487                 }
488                 
489                 protected void update(MouseEvent e) {
490                         Rectangle r = getClientArea();
491                         double d;
492                         if ((style & SWT.HORIZONTAL) > 0) {
493                                 d = (double)e.x / (double)r.width;
494                         } else {
495                                 d = (double)e.y / (double)r.height;
496                         }
497                         if (d < 0.0)
498                                 d = 0.0;
499                         else if (d > 1.0)
500                                 d = 1.0;
501                         if (updatePosition(d)) {
502                                 if ((style & SWT.HORIZONTAL) > 0) {
503                                         pos = (int)(d*((double)r.width));
504                                 } else {
505                                         pos = (int)(d*((double)r.height));
506                                 }
507                                 posD = d;
508                         }
509                 }
510                 
511                 protected abstract boolean updatePosition(double d);
512                 
513                 protected void setPosition(double d) {
514                         if (d == posD)
515                                 return;
516                         _setPosition(d);                                                
517                 }
518                 
519                 private void _setPosition(double d) {
520                         Rectangle r = getClientArea();
521                         posD = d;
522                         if (posD >= 0.0) {
523                                 if ((style & SWT.HORIZONTAL) > 0) {
524                                         pos = (int)(d * (double)r.width);
525                                 } else {
526                                         pos = (int)(d * (double)r.height);
527                                 }
528                         } else {
529                                 pos = -1;
530                         }
531                 }
532                 
533                 Rectangle prevClip;
534                 @Override
535                 protected void paintGradient(GC gc, Rectangle clip) {
536                         super.paintGradient(gc, clip);
537                         if (!clip.equals(prevClip)) {
538                                 prevClip = clip;
539                                 _setPosition(posD);
540                         }
541                         
542                         if (pos >= 0) {
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);
547                                 int x;
548                                 int y;
549                                 if ((style & SWT.HORIZONTAL) > 0) {
550                                         x = pos;
551                                         y = clip.height / 2;
552                                 } else {
553                                         x = clip.width / 2;
554                                         y = pos;
555                                 }
556                                 gc.fillOval(x-sized2, y-sized2, size, size);
557                                 gc.drawOval(x-sized2, y-sized2, size, size);
558                                 
559                                 white.dispose();
560                                 black.dispose();
561                         }
562                 }
563                 
564         }
565 }