1
28 package demo.view.uml;
29
30 import y.geom.YDimension;
31 import y.view.AbstractCustomNodePainter;
32 import y.view.GenericNodeRealizer;
33 import y.view.Graph2DView;
34 import y.view.HitInfo;
35 import y.view.MouseInputEditor;
36 import y.view.NodeLabel;
37 import y.view.NodeRealizer;
38 import y.view.YRenderingHints;
39
40 import java.awt.AlphaComposite;
41 import java.awt.Color;
42 import java.awt.Composite;
43 import java.awt.Graphics2D;
44 import java.awt.Shape;
45 import java.awt.Stroke;
46 import java.awt.geom.AffineTransform;
47 import java.awt.geom.Rectangle2D;
48
49
52 class UmlClassConfiguration extends AbstractCustomNodePainter
53 implements GenericNodeRealizer.GenericMouseInputEditorProvider,
54 GenericNodeRealizer.GenericSizeConstraintProvider {
55 private UmlClassButton[] buttons;
56
57 public UmlClassConfiguration() {
58 buttons = new UmlClassButton[] {
59 new UmlClassOpenCloseSectionButton(true),
60 new UmlClassOpenCloseSectionButton(false),
61 new UmlClassOpenCloseClassButton(),
62 new UmlClassAddItemButton(true),
63 new UmlClassAddItemButton(false),
64 new UmlClassRemoveItemButton(true),
65 new UmlClassRemoveItemButton(false)
66 };
67 }
68
69
72 protected void paintNode(final NodeRealizer context, final Graphics2D graphics, final boolean sloppy) {
73 final Color fillColor = context.getFillColor();
74 final Color fillColor2 = context.getFillColor2();
75 final Color lineColor = context.getLineColor();
76 final boolean selected = useSelectionStyle(context, graphics);
77
78 final Composite orgComposite = graphics.getComposite();
80 final AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, UmlRealizerFactory.getNodeOpacity(context));
81 graphics.setComposite(composite);
82
83 final Rectangle2D.Double rect = context.getBoundingBox();
85 final Color backgroundColor = selected && sloppy ? createSelectionColor(fillColor) : fillColor;
86 graphics.setColor(backgroundColor);
87 graphics.fill(rect);
88
89 final NodeLabel nameLabel = UmlClassLabelSupport.getNameLabel(context);
91 UmlClassLabelSupport.getLabelArea(context, nameLabel, rect);
92 final Color nameColor = selected && sloppy ? createSelectionColor(fillColor2) : fillColor2;
93 graphics.setColor(nameColor);
94 graphics.fill(rect);
95
96 if (!sloppy) {
97 if (UmlClassLabelSupport.getModel(context).areSectionsVisible()) {
98
99 final NodeLabel attributeCaptionLabel = UmlClassLabelSupport.getAttributeCaptionLabel(context);
101 UmlClassLabelSupport.getLabelArea(context, attributeCaptionLabel, rect);
102 graphics.setColor(fillColor2);
103 graphics.fill(rect);
104
105 final NodeLabel operationCaptionLabel = UmlClassLabelSupport.getOperationCaptionLabel(context);
107 UmlClassLabelSupport.getLabelArea(context, operationCaptionLabel, rect);
108 graphics.setColor(fillColor2);
109 graphics.fill(rect);
110
111 final NodeLabel selectedLabel = UmlClassLabelSupport.getSelectedLabel(context);
113 if (selectedLabel != null) {
114 UmlClassLabelSupport.getLabelArea(context, selectedLabel, rect);
115 final Color selectedLabelColor = new Color(
116 lineColor.getRed(),
117 lineColor.getGreen(),
118 lineColor.getBlue(),
119 (int) (UmlRealizerFactory.getSelectionOpacity(context) * 255));
120 graphics.setColor(selectedLabelColor);
121 graphics.fill(rect);
122 }
123 }
124
125 for (int i = 0; i < buttons.length; i++) {
127 final UmlClassButton button = buttons[i];
128 button.paint(context, graphics);
129 }
130 }
131
132 rect.setFrame(context.getX(), context.getY(), context.getWidth(), context.getHeight());
134 final Color outlineColor = selected && sloppy ? createSelectionColor(fillColor2) : fillColor2;
135 graphics.setColor(outlineColor);
136 graphics.setStroke(context.getLineType());
137 graphics.draw(rect);
138
139 graphics.setComposite(orgComposite);
140 }
141
142
154 public void paintAnimatedNode(
155 final NodeRealizer context,
156 final Graphics2D graphics,
157 final double fixedOffset,
158 final double movingOffset,
159 final double state
160 ) {
161 final Shape clip = graphics.getClip();
162 final Color color = graphics.getColor();
163 final Stroke stroke = graphics.getStroke();
164 final AffineTransform transform = graphics.getTransform();
165 try {
166 paintAnimatedNodeImpl(context, graphics, fixedOffset, movingOffset, state);
167 } finally {
168 graphics.setClip(clip);
169 graphics.setColor(color);
170 graphics.setStroke(stroke);
171 graphics.setTransform(transform);
172 }
173 }
174
175 private void paintAnimatedNodeImpl(
176 final NodeRealizer context,
177 final Graphics2D graphics,
178 final double fixedOffset,
179 final double movingOffset,
180 final double state
181 ) {
182 final double offset = fixedOffset + (movingOffset - fixedOffset) * state;
183 final double lineWidth = UmlRealizerFactory.LINE_EDGE_CREATION_BUTTON_OUTLINE.getLineWidth();
184
185 final Rectangle2D clipRect = new Rectangle2D.Double(
187 context.getX() - lineWidth * 0.5,
188 context.getY() - lineWidth * 0.5,
189 context.getWidth() + lineWidth,
190 offset - (context.getY() - lineWidth * 0.5));
191 graphics.setClip(clipRect);
192 paintNode(context, graphics, false);
193 paintText(context, graphics);
194
195 clipRect.setFrame(
197 context.getX() - lineWidth * 0.5,
198 offset,
199 context.getWidth() + lineWidth,
200 context.getY() + context.getHeight() + lineWidth * 0.5 - movingOffset);
201 graphics.setClip(clipRect);
202
203 graphics.translate(0, -(movingOffset - offset));
205 paintNode(context, graphics, false);
206 paintText(context, graphics);
207 }
208
209
212 private static boolean useSelectionStyle(
213 final NodeRealizer context,
214 final Graphics2D gfx
215 ) {
216 return context.isSelected() && YRenderingHints.isSelectionPaintingEnabled(gfx);
217 }
218
219
222 public MouseInputEditor findMouseInputEditor(
223 final NodeRealizer context,
224 final Graph2DView view,
225 final double x,
226 final double y,
227 final HitInfo hitInfo
228 ) {
229 if (context instanceof GenericNodeRealizer && isDetailed(view)) {
230 for (int i = 0; i < buttons.length; i++) {
231 final UmlClassButton button = buttons[i];
232 if (button.contains(context, x, y)) {
233 return button.getMouseInputEditor(context, view);
234 }
235 }
236 }
237 return null;
238 }
239
240
243 private static boolean isDetailed(final Graph2DView view) {
244 return view.getZoom() > view.getPaintDetailThreshold();
245 }
246
247
250 public YDimension getMinimumSize(final NodeRealizer context) {
251 double minY = context.getY();
252 double minX = context.getX();
253
254 double maxY = getMaxYOfLabel(UmlClassLabelSupport.getNameLabel(context));
255 double maxX = getNameLabelMaxX(context);
256 if (UmlClassLabelSupport.getModel(context).areSectionsVisible()) {
257 maxX = Math.max(maxX, getCaptionLabelMaxX(UmlClassLabelSupport.getAttributeCaptionLabel(context)));
258 maxX = Math.max(maxX, getCaptionLabelMaxX(UmlClassLabelSupport.getOperationCaptionLabel(context)));
259 for (int i = 1; i < context.labelCount(); i++) {
260 final NodeLabel label = context.getLabel(i);
261 maxX = Math.max(maxX, getMaxXOfLabel(label));
262 maxY = Math.max(maxY, getMaxYOfLabel(label));
263 }
264 }
265 final double INSET_RIGHT = 10;
266 final double INSET_BOTTOM = UmlClassLabelSupport.getModel(context).areSectionsVisible() ? 5 : 0;
267 return new YDimension(maxX - minX + INSET_RIGHT, maxY - minY + INSET_BOTTOM);
268 }
269
270
273 private double getMaxXOfLabel(final NodeLabel label) {
274 return label.getLocation().getX() + label.getWidth();
275 }
276
277
280 private double getMaxYOfLabel(final NodeLabel label) {
281 return label.getLocation().getY() + label.getHeight();
282 }
283
284
287 private double getNameLabelMaxX(final NodeRealizer context) {
288 final NodeLabel label = UmlClassLabelSupport.getNameLabel(context);
289 return label.getLocation().getX() +
290 label.getWidth() +
291 UmlClassOpenCloseClassButton.ICON_SIZE +
292 UmlClassOpenCloseClassButton.ICON_GAP;
293 }
294
295
298 private double getCaptionLabelMaxX(final NodeLabel label) {
299 return label.getLocation().getX() +
300 label.getWidth() +
301 UmlClassAddItemButton.ICON_SIZE +
302 UmlClassAddItemButton.ICON_GAP +
303 UmlClassRemoveItemButton.ICON_SIZE +
304 UmlClassRemoveItemButton.ICON_GAP;
305 }
306
307
310 public YDimension getMaximumSize(final NodeRealizer context) {
311 return new YDimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
312 }
313
314 }
315