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