1
28 package demo.view.uml;
29
30 import y.base.NodeList;
31 import y.geom.YDimension;
32 import y.view.Graph2D;
33 import y.view.Graph2DView;
34 import y.view.LineType;
35 import y.view.NodeLabel;
36 import y.view.NodeRealizer;
37
38 import java.awt.Color;
39 import java.awt.Graphics2D;
40 import java.awt.RenderingHints;
41 import java.awt.Shape;
42 import java.awt.geom.GeneralPath;
43 import java.awt.geom.Rectangle2D;
44
45
48 class UmlClassOpenCloseSectionButton extends UmlClassButton {
49 private static final double ICON_SIZE = 12;
50 private static final double GAP = 5;
51
52 private final boolean isAttributeSection;
53
54
57 public UmlClassOpenCloseSectionButton(final boolean attributeSection) {
58 isAttributeSection = attributeSection;
59 }
60
61
64 public void paint(final NodeRealizer context, final Graphics2D graphics) {
65 if (isVisible(context)) {
66 final Object orgRenderingHint = graphics.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
67 graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
68 try {
69 final Rectangle2D area = getButtonArea(context);
70 paintButton(context, graphics, area);
71 paintIcon(context, graphics, area);
72 } finally {
73 graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, orgRenderingHint);
74 }
75 }
76 }
77
78
82 protected boolean isVisible(final NodeRealizer context) {
83 return UmlClassLabelSupport.getModel(context).areSectionsVisible();
84 }
85
86
89 protected Rectangle2D getButtonArea(final NodeRealizer context) {
90 final NodeLabel label = getCaptionLabel(context);
91 return new Rectangle2D.Double(
92 context.getX() + GAP,
93 label.getLocation().getY() + (label.getHeight() - ICON_SIZE) * 0.5,
94 ICON_SIZE,
95 ICON_SIZE);
96 }
97
98
99 private NodeLabel getCaptionLabel(final NodeRealizer context) {
100 if (isAttributeSection) {
101 return UmlClassLabelSupport.getAttributeCaptionLabel(context);
102 } else {
103 return UmlClassLabelSupport.getOperationCaptionLabel(context);
104 }
105 }
106
107
110 private void paintButton(final NodeRealizer context, final Graphics2D graphics, final Rectangle2D area) {
111 final Color color = getButtonColor(context);
112 graphics.setColor(color);
113 graphics.fill(area);
114 }
115
116
119 private Color getButtonColor(final NodeRealizer context) {
120 return isMouseOverButton(context) ?
121 UmlRealizerFactory.COLOR_BUTTON_BACKGROUND_ACTIVE :
122 UmlRealizerFactory.COLOR_BUTTON_BACKGROUND_BLANK;
123 }
124
125
129 private boolean isMouseOverButton(final NodeRealizer context) {
130 final int button = UmlRealizerFactory.getMouseOverButton(context);
131 return ((button == UmlRealizerFactory.BUTTON_OPEN_CLOSE_ATTRIBUTE_SECTION) && isAttributeSection) ||
132 ((button == UmlRealizerFactory.BUTTON_OPEN_CLOSE_OPERATION_SECTION) && !isAttributeSection);
133 }
134
135
138 private void paintIcon(final NodeRealizer context, final Graphics2D graphics, final Rectangle2D area) {
139 final Shape shape = getIconShape(context, area);
140 graphics.setColor(UmlRealizerFactory.COLOR_BUTTON_FOREGROUND_ENABLED);
141 graphics.setStroke(LineType.LINE_1);
142 graphics.draw(shape);
143 }
144
145
146 private Shape getIconShape(final NodeRealizer context, final Rectangle2D area) {
147 if (isAttributeSection) {
148 return UmlClassLabelSupport.getModel(context).areAttributesVisible() ? getMinusShape(area) : getPlusShape(area);
149 } else {
150 return UmlClassLabelSupport.getModel(context).areOperationsVisible() ? getMinusShape(area) : getPlusShape(area);
151 }
152 }
153
154
157 private Shape getMinusShape(final Rectangle2D area) {
158 final float minX = (float) (area.getX() + area.getWidth() * 0.25);
159 final float maxX = (float) (area.getX() + area.getWidth() * 0.75);
160 final float midY = (float) (area.getY() + area.getHeight() * 0.5);
161
162 final GeneralPath icon = new GeneralPath();
163 icon.moveTo(minX, midY);
164 icon.lineTo(maxX, midY);
165 return icon;
166 }
167
168
171 private Shape getPlusShape(final Rectangle2D area) {
172 final float minX = (float) (area.getX() + area.getWidth() * 0.25);
173 final float midX = (float) (area.getX() + area.getWidth() * 0.5);
174 final float maxX = (float) (area.getX() + area.getWidth() * 0.75);
175 final float minY = (float) (area.getY() + area.getHeight() * 0.25);
176 final float midY = (float) (area.getY() + area.getHeight() * 0.5);
177 final float maxY = (float) (area.getY() + area.getHeight() * 0.75);
178
179 final GeneralPath icon = new GeneralPath();
180 icon.moveTo(minX, midY);
181 icon.lineTo(maxX, midY);
182 icon.moveTo(midX, minY);
183 icon.lineTo(midX, maxY);
184 return icon;
185 }
186
187
190 protected void buttonClicked(final NodeRealizer context, final Graph2DView view) {
191 final Graph2D graph = view.getGraph2D();
192 graph.firePreEvent();
193 try {
194 graph.backupRealizers(new NodeList(context.getNode()).nodes());
195 graph.backupRealizers(context.getNode().edges());
196 if (isAttributeSection) {
197 final boolean areAttributesOpened = UmlClassLabelSupport.getModel(context).areAttributesVisible();
198 final UmlClassAnimation attributeAnimation = new OpenCloseAttributeSectionAnimation(
199 view,
200 context,
201 areAttributesOpened);
202 attributeAnimation.play();
203 } else {
204 final boolean areOperationsOpened = UmlClassLabelSupport.getModel(context).areOperationsVisible();
205 final UmlClassAnimation operationAnimation = new OpenCloseOperationSectionAnimation(
206 view,
207 context,
208 areOperationsOpened);
209 operationAnimation.play();
210 }
211 } finally {
212 graph.firePostEvent();
213 }
214 }
215
216
217 protected void buttonEntered(final NodeRealizer context, final Graph2DView view) {
218 if (isAttributeSection) {
219 UmlRealizerFactory.setMouseOverButton(context, UmlRealizerFactory.BUTTON_OPEN_CLOSE_ATTRIBUTE_SECTION);
220 } else {
221 UmlRealizerFactory.setMouseOverButton(context, UmlRealizerFactory.BUTTON_OPEN_CLOSE_OPERATION_SECTION);
222 }
223 view.updateView();
224 }
225
226
229 private static class OpenCloseAttributeSectionAnimation extends UmlClassAnimation {
230 private OpenCloseAttributeSectionAnimation(
231 final Graph2DView view,
232 final NodeRealizer context,
233 final boolean isClosing
234 ) {
235 super(view, context, isClosing);
236 }
237
238
241 protected void close() {
242 UmlClassLabelSupport.getModel(context).setAttributesVisible(false);
243 UmlClassLabelSupport.updateAllLabels(context);
244 UmlClassLabelSupport.updateRealizerSize(context);
245 }
246
247
250 protected void open() {
251 UmlClassLabelSupport.getModel(context).setAttributesVisible(true);
252 UmlClassLabelSupport.updateAllLabels(context);
253 UmlClassLabelSupport.updateRealizerSize(context);
254 }
255
256
259 protected YDimension getClosedSize() {
260 final boolean isVisible = UmlClassLabelSupport.getModel(context).areAttributesVisible();
261 UmlClassLabelSupport.getModel(context).setAttributesVisible(false);
262 UmlClassLabelSupport.updateAllLabels(context);
263 UmlClassLabelSupport.updateRealizerSize(context);
264 final YDimension dimension = new YDimension(context.getWidth(), context.getHeight());
265 UmlClassLabelSupport.getModel(context).setAttributesVisible(isVisible);
266 UmlClassLabelSupport.updateAllLabels(context);
267 UmlClassLabelSupport.updateRealizerSize(context);
268 return dimension;
269 }
270
271
274 protected double getFixedY() {
275 final NodeLabel label = UmlClassLabelSupport.getAttributeCaptionLabel(context);
276 return label.getLocation().getY() + label.getHeight();
277 }
278
279
282 protected double getMovingY() {
283 final NodeLabel label = UmlClassLabelSupport.getOperationCaptionLabel(context);
284 return label.getLocation().getY() - UmlClassLabelSupport.SECTION_GAP;
285 }
286
287
292 protected void stateUpdated(final double state) {
293 UmlRealizerFactory.setAttributeButtonOpacity(context, (float) state);
294 }
295 }
296
297
300 private static class OpenCloseOperationSectionAnimation extends UmlClassAnimation {
301 private OpenCloseOperationSectionAnimation(
302 final Graph2DView view,
303 final NodeRealizer context,
304 final boolean isClosing
305 ) {
306 super(view, context, isClosing);
307 }
308
309
312 protected void close() {
313 UmlClassLabelSupport.getModel(context).setOperationsVisible(false);
314 UmlClassLabelSupport.updateAllLabels(context);
315 UmlClassLabelSupport.updateRealizerSize(context);
316 }
317
318
321 protected void open() {
322 UmlClassLabelSupport.getModel(context).setOperationsVisible(true);
323 UmlClassLabelSupport.updateAllLabels(context);
324 UmlClassLabelSupport.updateRealizerSize(context);
325 }
326
327
330 protected YDimension getClosedSize() {
331 final boolean isVisible = UmlClassLabelSupport.getModel(context).areOperationsVisible();
332 UmlClassLabelSupport.getModel(context).setOperationsVisible(false);
333 UmlClassLabelSupport.updateAllLabels(context);
334 UmlClassLabelSupport.updateRealizerSize(context);
335 final YDimension dimension = new YDimension(context.getWidth(), context.getHeight());
336 UmlClassLabelSupport.getModel(context).setOperationsVisible(isVisible);
337 UmlClassLabelSupport.updateAllLabels(context);
338 UmlClassLabelSupport.updateRealizerSize(context);
339 return dimension;
340 }
341
342
345 protected double getFixedY() {
346 final NodeLabel label = UmlClassLabelSupport.getOperationCaptionLabel(context);
347 return label.getLocation().getY() + label.getHeight();
348 }
349
350
353 protected double getMovingY() {
354 double fixedY = getFixedY();
355 for (int i = 0; i < context.labelCount(); i++) {
356 final NodeLabel label = context.getLabel(i);
357 fixedY = Math.max(fixedY, label.getLocation().getY() + label.getHeight());
358 }
359 return fixedY;
360 }
361
362
367 protected void stateUpdated(final double state) {
368 UmlRealizerFactory.setOperationButtonOpacity(context, (float) state);
369 }
370 }
371 }