1
28 package demo.view.uml;
29
30 import y.base.NodeList;
31 import y.geom.YDimension;
32 import y.geom.YPoint;
33 import y.view.Graph2D;
34 import y.view.Graph2DView;
35 import y.view.LineType;
36 import y.view.NodeLabel;
37 import y.view.NodeRealizer;
38
39 import java.awt.AlphaComposite;
40 import java.awt.Color;
41 import java.awt.Composite;
42 import java.awt.Graphics2D;
43 import java.awt.RenderingHints;
44 import java.awt.Shape;
45 import java.awt.geom.Ellipse2D;
46 import java.awt.geom.GeneralPath;
47 import java.awt.geom.Rectangle2D;
48 import java.beans.PropertyChangeEvent;
49 import java.beans.PropertyChangeListener;
50
51
54 class UmlClassAddItemButton extends UmlClassButton{
55 public static final double ICON_SIZE = 12;
56 public static final double ICON_GAP = 5;
57
58 private final boolean isAttributeSection;
59
60
63 public UmlClassAddItemButton(final boolean attributeSection) {
64 isAttributeSection = attributeSection;
65 }
66
67
70 public void paint(final NodeRealizer context, final Graphics2D graphics) {
71 if (isVisible(context)) {
72 final Composite orgComposite = graphics.getComposite();
74 final AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getButtonOpacity(context));
75 graphics.setComposite(composite);
76
77 final Rectangle2D area = getButtonArea(context);
78 paintBackground(context, graphics, area);
79 paintIcon(graphics, area);
80
81 graphics.setComposite(orgComposite);
82 }
83 }
84
85
89 protected boolean isVisible(final NodeRealizer context) {
90 final boolean areClassDetailsVisible = UmlClassLabelSupport.getModel(context).areSectionsVisible();
91 final boolean isSectionVisible =
92 isAttributeSection && UmlClassLabelSupport.getModel(context).areAttributesVisible() ||
93 !isAttributeSection && UmlClassLabelSupport.getModel(context).areOperationsVisible();
94 return isSectionVisible && areClassDetailsVisible;
95 }
96
97
100 protected Rectangle2D getButtonArea(final NodeRealizer context) {
101 final NodeLabel label = getCaptionLabel(context);
102 return new Rectangle2D.Double(
103 context.getX() + context.getWidth() - 2* ICON_SIZE - 2* ICON_GAP,
104 label.getLocation().getY() + (label.getHeight() - ICON_SIZE) * 0.5,
105 ICON_SIZE,
106 ICON_SIZE);
107 }
108
109
110 private NodeLabel getCaptionLabel(final NodeRealizer context) {
111 if (isAttributeSection) {
112 return UmlClassLabelSupport.getAttributeCaptionLabel(context);
113 } else {
114 return UmlClassLabelSupport.getOperationCaptionLabel(context);
115 }
116 }
117
118
121 private void paintBackground(final NodeRealizer context, final Graphics2D graphics, final Rectangle2D area) {
122 final Color color = isMouseOverButton(context) ?
123 UmlRealizerFactory.COLOR_BUTTON_BACKGROUND_ACTIVE :
124 UmlRealizerFactory.COLOR_BUTTON_BACKGROUND_BLANK;
125 final Shape shape = new Ellipse2D.Double(area.getX(), area.getY(), area.getWidth(), area.getHeight());
126 graphics.setColor(color);
127 graphics.fill(shape);
128 }
129
130
131 private float getButtonOpacity(final NodeRealizer context) {
132 if (isAttributeSection) {
133 return UmlRealizerFactory.getAttributeButtonOpacity(context);
134 } else {
135 return UmlRealizerFactory.getOperationButtonOpacity(context);
136 }
137 }
138
139
143 private boolean isMouseOverButton(final NodeRealizer context) {
144 final int button = UmlRealizerFactory.getMouseOverButton(context);
145 return ((button == UmlRealizerFactory.BUTTON_ADD_ATTRIBUTE) && isAttributeSection) ||
146 ((button == UmlRealizerFactory.BUTTON_ADD_OPERATION) && !isAttributeSection);
147 }
148
149
152 private void paintIcon(final Graphics2D graphics, final Rectangle2D area) {
153 final Object orgRenderingHint = graphics.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
154 graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
155 try {
156 final Shape shape = getIconShape(area);
157 final Color color = UmlRealizerFactory.COLOR_BUTTON_FOREGROUND_ENABLED;
158 graphics.setColor(color);
159 graphics.setStroke(LineType.LINE_1);
160 graphics.draw(shape);
161 } finally {
162 graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, orgRenderingHint);
163 }
164 }
165
166
169 private Shape getIconShape(final Rectangle2D area) {
170 final float minX = (float) (area.getX() + area.getWidth() * 0.25);
171 final float midX = (float) (area.getX() + area.getWidth() * 0.5);
172 final float maxX = (float) (area.getX() + area.getWidth() * 0.75);
173 final float minY = (float) (area.getY() + area.getHeight() * 0.25);
174 final float midY = (float) (area.getY() + area.getHeight() * 0.5);
175 final float maxY = (float) (area.getY() + area.getHeight() * 0.75);
176
177 final GeneralPath icon = new GeneralPath();
178 icon.moveTo(minX, midY);
179 icon.lineTo(maxX, midY);
180 icon.moveTo(midX, minY);
181 icon.lineTo(midX, maxY);
182 return icon;
183 }
184
185
188 protected void buttonClicked(final NodeRealizer context, final Graph2DView view) {
189 if (getButtonOpacity(context) == UmlRealizerFactory.OPAQUE) {
190 final Graph2D graph = view.getGraph2D();
191 graph.firePreEvent();
192 try {
193 graph.backupRealizers(new NodeList(context.getNode()).nodes());
195 graph.backupRealizers(context.getNode().edges());
196 final UmlClassAnimation animation = new AddItemAnimation(view, context, false);
197 animation.play();
198
199 final NodeLabel label = UmlClassLabelSupport.getSelectedLabel(context);
201 final YPoint location = label.getTextLocation();
202 view.openLabelEditor(label, location.getX(), location.getY(), new TextChangeHandler(view), true, true);
203
204 } finally {
205 graph.firePostEvent();
206 }
207 }
208 }
209
210
211 protected void buttonEntered(final NodeRealizer context, final Graph2DView view) {
212 if (isAttributeSection) {
213 UmlRealizerFactory.setMouseOverButton(context, UmlRealizerFactory.BUTTON_ADD_ATTRIBUTE);
214 } else {
215 UmlRealizerFactory.setMouseOverButton(context, UmlRealizerFactory.BUTTON_ADD_OPERATION);
216 }
217 view.updateView(getButtonArea(context));
218 }
219
220
224 private class TextChangeHandler implements PropertyChangeListener {
225 private final Graph2DView view;
226
227 public TextChangeHandler(final Graph2DView view) {
228 this.view = view;
229 }
230
231
235 public void propertyChange(PropertyChangeEvent e) {
236 final Object source = e.getSource();
237 if (source instanceof NodeLabel) {
238 final NodeLabel label = (NodeLabel) source;
239 final NodeRealizer realizer = view.getGraph2D().getRealizer(label.getNode());
240
241 UmlClassLabelSupport.updateLabelText(realizer, label);
243 UmlClassLabelSupport.selectLabel(realizer, label);
244
245 if ("".equals(label.getText())) {
247 label.setText(" ");
248 final UmlClassAnimation animation = new UmlClassRemoveItemButton.RemoveItemAnimation(view, realizer, true);
249 animation.play();
250 } else {
251 UmlClassLabelSupport.updateRealizerSize(realizer);
252 }
253 }
254 }
255 }
256
257
260 private class AddItemAnimation extends UmlClassAnimation {
261 final double closedHeight;
262
263 private AddItemAnimation(final Graph2DView view, final NodeRealizer context, final boolean isClosing) {
264 super(view, context, isClosing);
265 closedHeight = context.getHeight();
266 }
267
268
269 protected void open() {
270 if (isAttributeSection) {
271 UmlClassLabelSupport.addAttribute(context);
272 } else {
273 UmlClassLabelSupport.addOperation(context);
274 }
275 }
276
277
280 protected void close() {
281 }
282
283
286 protected YDimension getClosedSize() {
287 return new YDimension(context.getWidth(), closedHeight);
288 }
289
290
293 protected double getFixedY() {
294 final NodeLabel label = UmlClassLabelSupport.getSelectedLabel(context);
295 return label.getLocation().getY();
296 }
297
298
301 protected double getMovingY() {
302 final NodeLabel label = UmlClassLabelSupport.getSelectedLabel(context);
303 return label.getLocation().getY() + label.getHeight();
304 }
305 }
306
307 }
308