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.g2d.elementclass.button;
14 import java.awt.AlphaComposite;
16 import java.awt.FontMetrics;
17 import java.awt.Graphics2D;
18 import java.awt.geom.Line2D;
19 import java.awt.geom.Rectangle2D;
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;
42 public class ToggleButtonClass {
44 public static final ElementClass BUTTON_CLASS =
48 Resizeable.UNCONSTRICTED,
49 DefaultTransform.INSTANCE,
50 ToggleButtonPaint.INSTANCE,
51 Stateful.ENABLED_BY_DEFAULT
56 static class ToggleButtonPaint implements SceneGraph {
57 private static final long serialVersionUID = 1114908644204400590L;
58 public static final ToggleButtonPaint INSTANCE = new ToggleButtonPaint();
60 public static final Key SG_NODE = new SceneGraphNodeKey(Node.class, "SUB_SG_NODE");
64 public void cleanup(IElement e) {
65 Node node = e.removeHint(SG_NODE);
71 public void init(IElement e, G2DParentNode parent) {
72 ToggleButtonNode node = (ToggleButtonNode) e.getHint(SG_NODE);
74 node = parent.addNode(ToggleButtonNode.class);
75 e.setHint(SG_NODE, node);
76 e.addKeyHintListener(AbstractTogglable.TOGGLE_KEY, new HintListenerAdapter() {
79 public void hintChanged(IHintObservable sender, Key key, Object oldValue,
81 if (sender instanceof IElement) {
82 ToggleButtonNode node = (ToggleButtonNode) ((IElement)sender).getHint(SG_NODE);
83 node.setToggle((Boolean)newValue);
88 e.addKeyHintListener(ElementHints.KEY_TEXT, new HintListenerAdapter() {
91 public void hintChanged(IHintObservable sender, Key key, Object oldValue,
93 if (sender instanceof IElement) {
94 ToggleButtonNode node = (ToggleButtonNode) ((IElement)sender).getHint(SG_NODE);
95 node.buttonText = (String)newValue;
101 e.addKeyHintListener(AbstractClickable.PRESS_STATUS_KEY, new HintListenerAdapter() {
104 public void hintChanged(IHintObservable sender, Key key, Object oldValue,
106 if (sender instanceof IElement) {
107 ToggleButtonNode node = (ToggleButtonNode) ((IElement)sender).getHint(SG_NODE);
108 node.status = (PressStatus)newValue;
115 Rectangle2D rect = ElementUtils.getElementBounds(e);
116 ButtonColorProfile colors = ButtonColorProfile.DEFAULT;
117 double height = rect.getHeight();
118 boolean enabled = isEnabled(e);
120 // FIXME: context not supported by scenegraph
121 PressStatus status = PressStatus.NORMAL;//ElementUtils.getPressStatus(e, ctx);
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);
131 System.out.println("ToggleButtonClass.init " + e + " " + status + " " + checked);
132 node.init(status, rect, enabled, checked, colors, font, selFont, buttonText);
134 // e.addKeyHintListener(AbstractClickable.PRESS_STATUS_KEY, new HintListenerAdapter() {
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);
149 public static class ToggleButtonNode extends G2DNode {
153 private static final long serialVersionUID = -7968142805282971747L;
155 PressStatus status = null;
156 Rectangle2D rect = null;
157 Boolean enabled = null;
158 Boolean checked = null;
159 ButtonColorProfile colors = null;
162 String buttonText = null;
163 boolean toggle = false;
166 public Rectangle2D getBoundsInLocal() {
170 @SyncField("pressStatus") void setPressStatus(PressStatus pressStatus) {
171 this.status = pressStatus;
174 @SyncField("toggle") void setToggle(Boolean toggle) {
175 this.checked = toggle;
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;
182 this.enabled = enabled;
183 this.checked = checked;
184 this.colors = colors;
186 this.selFont = selFont;
187 this.buttonText = buttonText;
191 public void render(Graphics2D g) {
194 drawNormal(g, rect, enabled, checked, colors, font, selFont, buttonText);
197 drawHeld(g, rect, enabled, colors, font, selFont, buttonText);
200 drawPressed(g, rect, enabled, colors, font, selFont, buttonText);
203 drawHover(g, rect, enabled, colors, font, selFont, buttonText);
208 protected void drawNormal(Graphics2D g, Rectangle2D rect, boolean enabled, boolean checked, ButtonColorProfile colors, Font font, Font selectedFont, String text)
211 drawPressed(g, rect, enabled, colors, font, selectedFont, text);
214 g.translate(rect.getX(), rect.getY());
215 double width = rect.getWidth();
216 double height = rect.getHeight();
218 g.setColor(colors.BACKGROUND);
219 g.fill(new Rectangle2D.Double(0, 0, width-1, height-1));
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);
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);
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);
235 g.setColor(colors.TEXT_BLACK);
236 FontMetrics fm = g.getFontMetrics(font);
237 Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
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);
244 Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
246 g.setFont(selectedFont);
248 FontMetrics fm = g.getFontMetrics(selectedFont);
249 Rectangle2D stringRect = fm.getStringBounds(text, g);
250 float x = ((float)((width - 4) / 2)) - ((float)stringRect.getWidth()) / 2;
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);
256 g.setColor(colors.TEXT_BLACK);
257 g.drawString(text, x, (float)height-6);
261 protected void drawHeld(Graphics2D g, Rectangle2D rect, boolean enabled, ButtonColorProfile colors, Font font, Font selectedFont, String text)
263 g.translate(rect.getX(), rect.getY());
264 double width = rect.getWidth();
265 double height = rect.getHeight();
267 g.setColor(colors.BACKGROUND);
268 g.fill(new Rectangle2D.Double(0, 0, width-1, height-1));
270 Line2D line = new Line2D.Double();
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);
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);
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);
284 g.setColor(colors.TEXT_BLACK);
285 FontMetrics fm = g.getFontMetrics(font);
286 Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
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);
295 protected void drawPressed(Graphics2D g, Rectangle2D rect, boolean enabled, ButtonColorProfile colors, Font font, Font selectedFont, String text)
297 g.translate(rect.getX(), rect.getY());
298 double width = rect.getWidth();
299 double height = rect.getHeight();
301 g.setColor(colors.SELECTEDBACKGROUND);
302 g.fill(new Rectangle2D.Double(0, 0, width-1, height-1));
304 Line2D line = new Line2D.Double();
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);
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);
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);
319 g.setColor(colors.TEXT_BLACK);
321 FontMetrics fm = g.getFontMetrics(font);
322 Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
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);
329 Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
331 g.setFont(selectedFont);
333 FontMetrics fm = g.getFontMetrics(selectedFont);
334 Rectangle2D stringRect = fm.getStringBounds(text, g);
335 float x = ((float)((width - 4) / 2)) - ((float)stringRect.getWidth()) / 2;
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);
341 g.setColor(colors.TEXT_BLACK);
342 g.drawString(text, x+1, (float)height-6+1);
347 protected void drawHover(Graphics2D g, Rectangle2D rect, boolean enabled, ButtonColorProfile colors, Font font, Font selectedFont, String text)
350 drawPressed(g, rect, enabled, colors, font, selectedFont, text);
353 g.translate(rect.getX(), rect.getY());
354 double width = rect.getWidth();
355 double height = rect.getHeight();
357 g.setColor(colors.HOVERBACKGROUND);
358 g.fill(new Rectangle2D.Double(0, 0, width-1, height-1));
360 //g.setStroke(HOVER_STROKE);
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);
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);
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);
376 g.setColor(colors.TEXT_BLACK);
377 FontMetrics fm = g.getFontMetrics(font);
378 Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
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);
385 Rectangle2D clipRect = new Rectangle2D.Double(2, 2, width-4, height-4);
387 g.setFont(selectedFont);
389 FontMetrics fm = g.getFontMetrics(selectedFont);
390 Rectangle2D stringRect = fm.getStringBounds(text, g);
391 float x = ((float)((width - 4) / 2)) - ((float)stringRect.getWidth()) / 2;
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);
397 g.setColor(colors.TEXT_BLACK);
398 g.drawString(text, x, (float)height-6);
404 protected ButtonColorProfile getColorProfile(IElement e)
406 return ButtonColorProfile.DEFAULT;
409 protected boolean isToggleButton()
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);
420 public boolean isChecked(IElement e){
421 Boolean b = e.getHint(AbstractTogglable.TOGGLE_KEY);