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