]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/elements/TextElementNoBounds.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / elements / TextElementNoBounds.java
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
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.diagram.elements;\r
13 \r
14 import java.awt.Color;\r
15 import java.awt.Font;\r
16 import java.awt.geom.AffineTransform;\r
17 import java.awt.geom.Rectangle2D;\r
18 import java.util.function.Consumer;\r
19 \r
20 import org.simantics.g2d.canvas.ICanvasContext;\r
21 import org.simantics.g2d.diagram.DiagramUtils;\r
22 import org.simantics.g2d.diagram.IDiagram;\r
23 import org.simantics.g2d.element.ElementHints;\r
24 import org.simantics.g2d.element.ElementUtils;\r
25 import org.simantics.g2d.element.IElement;\r
26 import org.simantics.g2d.element.SceneGraphNodeKey;\r
27 import org.simantics.g2d.element.handler.HandleMouseEvent;\r
28 import org.simantics.g2d.element.handler.SceneGraph;\r
29 import org.simantics.g2d.utils.Alignment;\r
30 import org.simantics.scenegraph.g2d.G2DParentNode;\r
31 import org.simantics.scenegraph.g2d.events.MouseEvent;\r
32 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseEnterEvent;\r
33 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent;\r
34 import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
35 \r
36 /**\r
37  * ElementHandler for text elements\r
38  * In-line editing supported.\r
39  * \r
40  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
41  */\r
42 public class TextElementNoBounds implements SceneGraph, HandleMouseEvent {\r
43 \r
44     private static final long serialVersionUID = -148784588840819612L;\r
45 \r
46     public static final TextElementNoBounds INSTANCE         = new TextElementNoBounds();\r
47 \r
48     public static final Key                 SG_NODE          = new SceneGraphNodeKey(TextNode.class, "TEXT_SG_NODE");\r
49     \r
50     protected static final double DEFAULT_PADDING_X = 0.5;\r
51     protected static final double DEFAULT_PADDING_Y = 0.5;\r
52     protected static final double SCALE = 0.235;\r
53 \r
54     protected final double originX;\r
55     protected final double originY;\r
56     protected final Alignment horizontalAlignment;\r
57     protected final Alignment verticalAlignment;\r
58     protected final double borderWidth;\r
59     protected final boolean editable;\r
60     protected final double paddingX;\r
61     protected final double paddingY;\r
62 \r
63 \r
64     public TextElementNoBounds() {\r
65         this(0, 0, Alignment.LEADING, 0);\r
66     }\r
67 \r
68     public TextElementNoBounds(double originX, double originY, Alignment horizontalAlignment) {\r
69         this(originX, originY, horizontalAlignment, 0);\r
70     }\r
71 \r
72     public TextElementNoBounds(double originX, double originY, Alignment horizontalAlignment, double borderWidth) {\r
73         this(originX, originY, horizontalAlignment, borderWidth, DEFAULT_PADDING_X, DEFAULT_PADDING_Y, true);\r
74     }\r
75     \r
76     public TextElementNoBounds(double originX, double originY, Alignment horizontalAlignment, double borderWidth, double paddingX, double paddingY, boolean editable) {\r
77         if (horizontalAlignment == null)\r
78             throw new NullPointerException("null horizontal alignment");\r
79 \r
80         this.originX = originX;\r
81         this.originY = originY;\r
82         this.horizontalAlignment = horizontalAlignment;\r
83         this.verticalAlignment = Alignment.BASELINE;\r
84         this.borderWidth = borderWidth;\r
85         this.editable = editable;\r
86         this.paddingX = paddingX;\r
87         this.paddingY = paddingY;\r
88     }\r
89     \r
90 \r
91     @Override\r
92     public void init(final IElement e, G2DParentNode parent) {\r
93         TextNode node = getOrCreateTextNode(e, parent);\r
94 \r
95         Font font = ElementUtils.getTextFont(e);\r
96         Color color = ElementUtils.getTextColor(e);\r
97         Color fillColor = ElementUtils.getFillColor(e);\r
98         Color borderColor = ElementUtils.getBorderColor(e, Color.BLACK);\r
99         String text = ElementUtils.getText(e);\r
100         AffineTransform at = ElementUtils.getTransform(e);\r
101         Alignment hAlign = ElementUtils.getHintOrDefault(e, ElementHints.KEY_HORIZONTAL_ALIGN, horizontalAlignment);\r
102         Alignment vAlign = ElementUtils.getHintOrDefault(e, ElementHints.KEY_VERTICAL_ALIGN, verticalAlignment);\r
103         Double borderWidth = ElementUtils.getHintOrDefault(e, MonitorClass.KEY_BORDER_WIDTH, this.borderWidth);\r
104 \r
105         node.init(text, font, color, originX, originY, SCALE);\r
106         node.setBackgroundColor(fillColor);\r
107         node.setBorderColor(borderColor);\r
108         node.setHorizontalAlignment((byte) hAlign.ordinal());\r
109         node.setVerticalAlignment((byte) vAlign.ordinal());\r
110         node.setPadding(paddingX, paddingY);\r
111         node.setBorderWidth(borderWidth.floatValue());\r
112         node.setEditable(editable);\r
113         if (at != null)\r
114             node.setTransform(at);\r
115         \r
116         if(Boolean.TRUE.equals(ElementUtils.getHintOrDefault(e, ElementHints.KEY_RESIZABLE, false))) {\r
117             Rectangle2D bounds = e.getHint(ElementHints.KEY_BOUNDS);\r
118             if(bounds != null) {\r
119                 node.setTargetBounds(bounds);\r
120                 node.setWrapText(true);\r
121             }\r
122         }\r
123     }\r
124     \r
125     protected TextNode getOrCreateTextNode(IElement e, G2DParentNode parent) {\r
126         return ElementUtils.getOrCreateNode(e, parent, SG_NODE, "text", TextNode.class, new TextNodeCallBack(e));\r
127     }\r
128     \r
129     private class TextNodeCallBack implements Consumer<TextNode> {\r
130         \r
131         IElement e;\r
132         \r
133         public TextNodeCallBack(IElement e) {\r
134             this.e = e;\r
135         }\r
136         \r
137         @Override\r
138         public void accept(TextNode node) {\r
139             node.setTextListener(new ITextListener() {\r
140                 @Override\r
141                 public void textChanged() {}\r
142 \r
143                 @Override\r
144                 public void textEditingStarted() {}\r
145 \r
146                 @Override\r
147                 public void textEditingCancelled() {\r
148                     TextNode node = (TextNode) e.getHint(SG_NODE);\r
149                     if (node != null)\r
150                         endEdit(node);\r
151                 }\r
152 \r
153                 @Override\r
154                 public void textEditingEnded() {\r
155                     TextNode node = (TextNode) e.getHint(SG_NODE);\r
156                     if (node == null)\r
157                         return;\r
158                     //System.out.println("Node text changed: " + node.getText());\r
159                     ElementUtils.setText(e, node.getText());\r
160                     IDiagram diagram = ElementUtils.getDiagram(e);\r
161                     DiagramUtils.synchronizeHintsToBackend(diagram, e);\r
162                     endEdit(node);\r
163                 }\r
164             });\r
165         }\r
166     }\r
167 \r
168     @Override\r
169     public void cleanup(IElement e) {\r
170         ElementUtils.removePossibleNode(e, SG_NODE);\r
171     }\r
172 \r
173     // FIXME: hazardous with TextElementHandler.INSTANCE\r
174     TextEditActivation editActivation = null;\r
175 \r
176     @Override\r
177     public boolean handleMouseEvent(IElement e, ICanvasContext ctx, MouseEvent me) {\r
178         if (me instanceof MouseEnterEvent) {\r
179             e.setHint(ElementHints.KEY_HOVER, true);\r
180         } else if (me instanceof MouseExitEvent) {\r
181             e.setHint(ElementHints.KEY_HOVER, false);\r
182         }\r
183 \r
184         return false;\r
185     }\r
186 \r
187     protected void endEdit(TextNode node) {\r
188         if (editActivation != null) {\r
189             editActivation.release();\r
190             editActivation = null;\r
191 \r
192             node.setEditMode(false);\r
193             node.repaint();\r
194         }\r
195     }\r
196 \r
197     @Override\r
198     public int hashCode() {\r
199         final int prime = 31;\r
200         int result = 1;\r
201         long temp;\r
202         temp = Double.doubleToLongBits(borderWidth);\r
203         result = prime * result + (int) (temp ^ (temp >>> 32));\r
204         result = prime * result + horizontalAlignment.hashCode();\r
205         temp = Double.doubleToLongBits(originX);\r
206         result = prime * result + (int) (temp ^ (temp >>> 32));\r
207         temp = Double.doubleToLongBits(originY);\r
208         result = prime * result + (int) (temp ^ (temp >>> 32));\r
209         temp = Double.doubleToLongBits(paddingX);\r
210         result = prime * result + (int) (temp ^ (temp >>> 32));\r
211         temp = Double.doubleToLongBits(paddingY);\r
212         result = prime * result + (int) (temp ^ (temp >>> 32));\r
213         return result;\r
214     }\r
215 \r
216     @Override\r
217     public boolean equals(Object obj) {\r
218         if (this == obj)\r
219             return true;\r
220         if (obj == null)\r
221             return false;\r
222         if (getClass() != obj.getClass())\r
223             return false;\r
224         TextElementNoBounds other = (TextElementNoBounds) obj;\r
225         if (Double.doubleToLongBits(borderWidth) != Double.doubleToLongBits(other.borderWidth))\r
226             return false;\r
227         if (horizontalAlignment != other.horizontalAlignment)\r
228             return false;\r
229         if (Double.doubleToLongBits(originX) != Double.doubleToLongBits(other.originX))\r
230             return false;\r
231         if (Double.doubleToLongBits(originY) != Double.doubleToLongBits(other.originY))\r
232             return false;\r
233         if (Double.doubleToLongBits(paddingX) != Double.doubleToLongBits(other.paddingX))\r
234             return false;\r
235         if (Double.doubleToLongBits(paddingY) != Double.doubleToLongBits(other.paddingY))\r
236             return false;\r
237         return true;\r
238     }\r
239     \r
240     \r
241 \r
242 }