]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/button/ToggleButtonClass.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / elementclass / button / ToggleButtonClass.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.g2d.elementclass.button;
13
14 import java.awt.AlphaComposite;
15 import java.awt.Font;
16 import java.awt.FontMetrics;
17 import java.awt.Graphics2D;
18 import java.awt.geom.Line2D;
19 import java.awt.geom.Rectangle2D;
20
21 import org.simantics.g2d.element.ElementClass;
22 import org.simantics.g2d.element.ElementHints;
23 import org.simantics.g2d.element.ElementUtils;
24 import org.simantics.g2d.element.IElement;
25 import org.simantics.g2d.element.SceneGraphNodeKey;
26 import org.simantics.g2d.element.handler.Clickable.PressStatus;
27 import org.simantics.g2d.element.handler.SceneGraph;
28 import org.simantics.g2d.element.handler.Stateful;
29 import org.simantics.g2d.element.handler.Text;
30 import org.simantics.g2d.element.handler.Togglable;
31 import org.simantics.g2d.element.handler.impl.AbstractClickable;
32 import org.simantics.g2d.element.handler.impl.AbstractTogglable;
33 import org.simantics.g2d.element.handler.impl.DefaultTransform;
34 import org.simantics.g2d.element.handler.impl.Resizeable;
35 import org.simantics.scenegraph.Node;
36 import org.simantics.scenegraph.g2d.G2DNode;
37 import org.simantics.scenegraph.g2d.G2DParentNode;
38 import org.simantics.utils.datastructures.hints.HintListenerAdapter;
39 import org.simantics.utils.datastructures.hints.IHintContext.Key;
40 import org.simantics.utils.datastructures.hints.IHintObservable;
41
42 public class ToggleButtonClass {
43
44     public static final ElementClass BUTTON_CLASS =
45         ElementClass.compile(
46                 Togglable.INSTANCE,
47                 Text.INSTANCE,
48                 Resizeable.UNCONSTRICTED,
49                 DefaultTransform.INSTANCE,
50                 ToggleButtonPaint.INSTANCE,
51                 Stateful.ENABLED_BY_DEFAULT
52         );
53     
54
55
56     static class ToggleButtonPaint implements SceneGraph {
57         private static final long serialVersionUID = 1114908644204400590L;
58         public static final ToggleButtonPaint INSTANCE = new ToggleButtonPaint();
59
60         public static final Key SG_NODE = new SceneGraphNodeKey(Node.class, "SUB_SG_NODE");
61
62         
63         @Override
64         public void cleanup(IElement e) {
65             Node node = e.removeHint(SG_NODE);
66             if (node != null)
67                 node.remove();
68         }
69
70         @Override
71         public void init(IElement e, G2DParentNode parent) {
72             ToggleButtonNode node = (ToggleButtonNode) e.getHint(SG_NODE);
73             if (node == null) {
74                 node = parent.addNode(ToggleButtonNode.class);
75                 e.setHint(SG_NODE, node);
76                 e.addKeyHintListener(AbstractTogglable.TOGGLE_KEY, new HintListenerAdapter() {
77                                 
78                                 @Override
79                                 public void hintChanged(IHintObservable sender, Key key, Object oldValue,
80                                                 Object newValue) {
81                                         if (sender instanceof IElement) {
82                                                 ToggleButtonNode node = (ToggleButtonNode) ((IElement)sender).getHint(SG_NODE);
83                                                 node.setToggle((Boolean)newValue);
84                                                 node.repaint();
85                                         }
86                                 }
87                         });
88                 e.addKeyHintListener(ElementHints.KEY_TEXT, new HintListenerAdapter() {
89                                 
90                                 @Override
91                                 public void hintChanged(IHintObservable sender, Key key, Object oldValue,
92                                                 Object newValue) {
93                                         if (sender instanceof IElement) {
94                                                 ToggleButtonNode node = (ToggleButtonNode) ((IElement)sender).getHint(SG_NODE);
95                                                 node.buttonText = (String)newValue;
96                                                 node.repaint();
97                                         }
98                                         
99                                 }
100                         });
101                 e.addKeyHintListener(AbstractClickable.PRESS_STATUS_KEY, new HintListenerAdapter() {
102                                         
103                                         @Override
104                                         public void hintChanged(IHintObservable sender, Key key, Object oldValue,
105                                                         Object newValue) {
106                                                 if (sender instanceof IElement) {
107                                                         ToggleButtonNode node = (ToggleButtonNode) ((IElement)sender).getHint(SG_NODE);
108                                                         node.status = (PressStatus)newValue;
109                                                         node.repaint();
110                                                 }
111                                         }
112                                 });
113             }
114
115             Rectangle2D                 rect = ElementUtils.getElementBounds(e);
116             ButtonColorProfile  colors = ButtonColorProfile.DEFAULT;
117             double                              height = rect.getHeight();
118             boolean                             enabled = isEnabled(e);
119
120             // FIXME: context not supported by scenegraph
121             PressStatus                 status = PressStatus.NORMAL;//ElementUtils.getPressStatus(e, ctx);
122
123             Font                                font = new Font("Tahoma", 0, (int) height-6);
124             Font                                selFont = new Font("Tahoma", Font.BOLD, (int) height-6);
125             Text                                text = e.getElementClass().getAtMostOneItemOfClass(Text.class);
126             String                              buttonText = null;
127             if (text!=null) buttonText = text.getText(e);
128             if (buttonText==null) buttonText = "";
129             boolean checked = isChecked(e);
130
131             System.out.println("ToggleButtonClass.init " + e + " " + status + " " + checked);
132             node.init(status, rect, enabled, checked, colors, font, selFont, buttonText);
133             
134 //            e.addKeyHintListener(AbstractClickable.PRESS_STATUS_KEY, new HintListenerAdapter() {
135 //                              
136 //                              @Override
137 //                              public void hintChanged(IHintObservable sender, Key key, Object oldValue,
138 //                                              Object newValue) {
139 //                                      if (sender instanceof IElement) {
140 //                                              ToggleButtonNode node = (ToggleButtonNode) ((IElement)sender).getHint(SG_NODE);
141 //                                              node.setPressStatus((PressStatus)newValue);
142 //                                              node.repaint();
143 //                                      }
144 //                              }
145 //                      });
146             
147         }
148
149         public static class ToggleButtonNode extends G2DNode {
150             /**
151              * 
152              */
153             private static final long serialVersionUID = -7968142805282971747L;
154
155             PressStatus status = null;
156             Rectangle2D rect = null;
157             Boolean enabled = null;
158             Boolean checked = null;
159             ButtonColorProfile colors = null;
160             Font font = null;
161             Font selFont = null;
162             String buttonText = null;
163             boolean toggle = false;
164
165             @Override
166             public Rectangle2D getBoundsInLocal() {
167                 return rect;
168             }
169             
170             @SyncField("pressStatus") void setPressStatus(PressStatus pressStatus) { 
171                 this.status = pressStatus; 
172             }
173             
174             @SyncField("toggle") void setToggle(Boolean toggle) { 
175                 this.checked = toggle; 
176             }
177
178             public void init(PressStatus status, Rectangle2D rect, boolean enabled, boolean checked,
179                     ButtonColorProfile colors, Font font, Font selFont, String buttonText) {
180                 this.status = status;
181                 this.rect = rect;
182                 this.enabled = enabled;
183                 this.checked = checked;
184                 this.colors = colors;
185                 this.font = font;
186                 this.selFont = selFont;
187                 this.buttonText = buttonText;
188             }
189
190             @Override
191             public void render(Graphics2D g) {
192                  switch (status) {
193                     case NORMAL:
194                         drawNormal(g, rect, enabled, checked, colors, font, selFont, buttonText);
195                         break;
196                     case HELD:
197                         drawHeld(g, rect, enabled, colors, font, selFont, buttonText);
198                         break;
199                     case PRESSED:
200                         drawPressed(g, rect, enabled, colors, font, selFont, buttonText);
201                         break;
202                     case HOVER:
203                         drawHover(g, rect, enabled, colors, font, selFont, buttonText);
204                         break;
205                 }
206             }
207
208             protected void drawNormal(Graphics2D g, Rectangle2D rect, boolean enabled, boolean checked, ButtonColorProfile colors, Font font, Font selectedFont, String text)
209             {
210                 if(checked) {
211                     drawPressed(g, rect, enabled, colors, font, selectedFont, text);
212                     return;
213                 }
214                 g.translate(rect.getX(), rect.getY());
215                 double width = rect.getWidth();
216                 double height = rect.getHeight();
217
218                 g.setColor(colors.BACKGROUND);
219                 g.fill(new Rectangle2D.Double(0, 0, width-1, height-1));
220
221                 g.setColor(colors.BORDER1);
222                 Line2D line = new Line2D.Double();
223                 line.setLine(0, 0, width-1, 0);         g.draw(line);
224                 line.setLine(0, 0, 0, height-1);        g.draw(line);
225
226                 g.setColor(colors.BORDER2);
227                 line.setLine(1, height-2, width-2, height-2);   g.draw(line);
228                 line.setLine(width-2, height-2, width-2, 1);    g.draw(line);
229
230                 g.setColor(colors.BORDER3);
231                 line.setLine(0, height-1, width-1, height-1);   g.draw(line);
232                 line.setLine(width-1, height-1, width-1, 0);    g.draw(line);
233
234                 if (enabled) {
235                     g.setColor(colors.TEXT_BLACK);
236                     FontMetrics fm = g.getFontMetrics(font);
237                     Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
238                     g.clip(clipRect);
239                     g.setFont(font);
240                     Rectangle2D stringRect = fm.getStringBounds(text, g);
241                     float x = ((float)((width - 4) / 2)) - ((float)stringRect.getWidth()) / 2;
242                     g.drawString(text, x, (float)height-6);
243                 } else {
244                     Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
245                     g.clip(clipRect);
246                     g.setFont(selectedFont);
247
248                     FontMetrics fm = g.getFontMetrics(selectedFont);
249                     Rectangle2D stringRect = fm.getStringBounds(text, g);
250                     float x = ((float)((width - 4) / 2)) - ((float)stringRect.getWidth()) / 2;
251
252                     g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
253                     g.setColor(colors.TEXT_WHITE);
254                     g.drawString(text, x+1, (float)height-6+1);
255
256                     g.setColor(colors.TEXT_BLACK);
257                     g.drawString(text, x, (float)height-6);
258                 }
259             }
260
261             protected void drawHeld(Graphics2D g, Rectangle2D rect, boolean enabled, ButtonColorProfile colors, Font font, Font selectedFont, String text)
262             {
263                 g.translate(rect.getX(), rect.getY());
264                 double width = rect.getWidth();
265                 double height = rect.getHeight();
266
267                 g.setColor(colors.BACKGROUND);
268                 g.fill(new Rectangle2D.Double(0, 0, width-1, height-1));
269
270                 Line2D line = new Line2D.Double();
271
272                 g.setColor(colors.BORDER3);
273                 line.setLine(0, 0, width-2, 0); g.draw(line);
274                 line.setLine(0, 0, 0, height-2); g.draw(line);
275
276                 g.setColor(colors.BORDER2);
277                 line.setLine(1, 1, width-3, 1); g.draw(line);
278                 line.setLine(1, 1, 1, height-3); g.draw(line);
279
280                 g.setColor(colors.BORDER1);
281                 line.setLine(0, height-1, width-1, height-1); g.draw(line);
282                 line.setLine(width-1, height-1, width-1, 0); g.draw(line);
283
284                 g.setColor(colors.TEXT_BLACK);
285                 FontMetrics fm = g.getFontMetrics(font);
286                 Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
287                 g.clip(clipRect);
288                 g.setFont(font);
289                 Rectangle2D     stringRect = fm.getStringBounds(text, g);
290                 float x = ((float)((width - 4) / 2)) - ((float)stringRect.getWidth()) / 2;
291                 g.drawString(text, x+1, (float)height-6+1);
292             }
293
294
295             protected void drawPressed(Graphics2D g, Rectangle2D rect, boolean enabled, ButtonColorProfile colors, Font font, Font selectedFont, String text)
296             {
297                 g.translate(rect.getX(), rect.getY());
298                 double width = rect.getWidth();
299                 double height = rect.getHeight();
300
301                 g.setColor(colors.SELECTEDBACKGROUND);
302                 g.fill(new Rectangle2D.Double(0, 0, width-1, height-1));
303
304                 Line2D line = new Line2D.Double();
305
306                 g.setColor(colors.BORDER3);
307                 line.setLine(0, 0, width-2, 0); g.draw(line);
308                 line.setLine(0, 0, 0, height-2); g.draw(line);
309
310                 g.setColor(colors.BORDER2);
311                 line.setLine(1, 1, width-3, 1); g.draw(line);
312                 line.setLine(1, 1, 1, height-3); g.draw(line);
313
314                 g.setColor(colors.BORDER1);
315                 line.setLine(0, height-1, width-1, height-1); g.draw(line);
316                 line.setLine(width-1, height-1, width-1, 0); g.draw(line);
317
318                 if (enabled) {
319                     g.setColor(colors.TEXT_BLACK);
320
321                     FontMetrics fm = g.getFontMetrics(font);
322                     Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
323                     g.clip(clipRect);
324                     g.setFont(font);
325                     Rectangle2D stringRect = fm.getStringBounds(text, g);
326                     float x = ((float)((width - 4) / 2)) - ((float)stringRect.getWidth()) / 2;
327                     g.drawString(text, x+1, (float)height-6+1);
328                 } else {
329                     Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
330                     g.clip(clipRect);
331                     g.setFont(selectedFont);
332
333                     FontMetrics fm = g.getFontMetrics(selectedFont);
334                     Rectangle2D stringRect = fm.getStringBounds(text, g);
335                     float x = ((float)((width - 4) / 2)) - ((float)stringRect.getWidth()) / 2;
336
337                     g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
338                     g.setColor(colors.TEXT_WHITE);
339                     g.drawString(text, x+2, (float)height-6+2);
340
341                     g.setColor(colors.TEXT_BLACK);
342                     g.drawString(text, x+1, (float)height-6+1);
343                 }
344
345             }
346
347             protected void drawHover(Graphics2D g, Rectangle2D rect, boolean enabled, ButtonColorProfile colors, Font font, Font selectedFont, String text)
348             {
349                 if(checked) {
350                     drawPressed(g, rect, enabled, colors, font, selectedFont, text);
351                     return;
352                 }
353                 g.translate(rect.getX(), rect.getY());
354                 double width = rect.getWidth();
355                 double height = rect.getHeight();
356
357                 g.setColor(colors.HOVERBACKGROUND);
358                 g.fill(new Rectangle2D.Double(0, 0, width-1, height-1));
359
360                 //g.setStroke(HOVER_STROKE);
361
362                 g.setColor(colors.BORDER1);
363                 Line2D line = new Line2D.Double();
364                 line.setLine(0, 0, width-1, 0);         g.draw(line);
365                 line.setLine(0, 0, 0, height-1);        g.draw(line);
366
367                 g.setColor(colors.BORDER2);
368                 line.setLine(1, height-2, width-2, height-2);   g.draw(line);
369                 line.setLine(width-2, height-2, width-2, 1);    g.draw(line);
370
371                 g.setColor(colors.BORDER3);
372                 line.setLine(0, height-1, width-1, height-1);   g.draw(line);
373                 line.setLine(width-1, height-1, width-1, 0);    g.draw(line);
374
375                 if (enabled) {
376                     g.setColor(colors.TEXT_BLACK);
377                     FontMetrics fm = g.getFontMetrics(font);
378                     Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
379                     g.clip(clipRect);
380                     g.setFont(font);
381                     Rectangle2D stringRect = fm.getStringBounds(text, g);
382                     float x = ((float)((width - 4) / 2)) - ((float)stringRect.getWidth()) / 2;
383                     g.drawString(text, x, (float)height-6);
384                 } else {
385                     Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
386                     g.clip(clipRect);
387                     g.setFont(selectedFont);
388
389                     FontMetrics fm = g.getFontMetrics(selectedFont);
390                     Rectangle2D stringRect = fm.getStringBounds(text, g);
391                     float x = ((float)((width - 4) / 2)) - ((float)stringRect.getWidth()) / 2;
392
393                     g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
394                     g.setColor(colors.TEXT_WHITE);
395                     g.drawString(text, x+1, (float)height-6+1);
396
397                     g.setColor(colors.TEXT_BLACK);
398                     g.drawString(text, x, (float)height-6);
399                 }
400             }
401
402         }
403
404         protected ButtonColorProfile getColorProfile(IElement e)
405         {
406             return ButtonColorProfile.DEFAULT;
407         }
408
409         protected boolean isToggleButton()
410         {
411             return false;
412         }
413
414         public boolean isEnabled(IElement e) {
415             Stateful enabled = e.getElementClass().getAtMostOneItemOfClass(Stateful.class);
416             if (enabled==null) return true;
417             return enabled.isEnabled(e);
418         }
419
420         public boolean isChecked(IElement e){
421             Boolean b = e.getHint(AbstractTogglable.TOGGLE_KEY);
422             if (b == null)
423                 return false;
424             return b;
425         }
426     }
427 }