1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.6. 
4    ** 
5    ** yWorks proprietary/confidential. Use is subject to license terms.
6    **
7    ** Redistribution of this file or of an unauthorized byte-code version
8    ** of this file is strictly forbidden.
9    **
10   ** Copyright (c) 2000-2008 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  package demo.view.realizer;
15  
16  import java.awt.Font;
17  import java.awt.Graphics2D;
18  import java.awt.Rectangle;
19  import java.awt.Shape;
20  import java.io.IOException;
21  import java.io.ObjectInputStream;
22  import java.io.ObjectOutputStream;
23  
24  import javax.swing.JFrame;
25  import javax.swing.JRootPane;
26  
27  import y.util.D;
28  import y.util.YVersion;
29  import y.view.EditMode;
30  import y.view.Graph2DView;
31  import y.view.NodeLabel;
32  import y.view.NodeRealizer;
33  import y.view.ShapeNodeRealizer;
34  import y.view.YLabel;
35  
36  
37  /**
38   * NodeRealizer implementation that represents a UML Class Node.
39   * This node realizer displays the following properties of a class
40   * in UML notation:
41   * <ul>
42   *  <li>class name
43   *  <li>sterotype property
44   *  <li>constraint property
45   *  <li>attribute list
46   *  <li>method list
47   * </ul>
48   * Executing this class will display a sample instance of this realizer.
49   */
50  public class UMLClassNodeRealizer extends ShapeNodeRealizer
51  {
52    private NodeLabel aLabel; //attributeLabel
53    private NodeLabel mLabel; //methodLabel
54    private boolean clipContent;
55    private boolean omitDetails;
56    private String stereotype = "";
57    private String constraint = "";
58  
59    private static NodeLabel constraintLabel = new NodeLabel(); 
60    private static NodeLabel stereotypeLabel = new NodeLabel();
61  
62    /**
63     * Instantiates a new UMLNodeRealizer.
64     */ 
65    public UMLClassNodeRealizer()
66    {
67      init();
68    }
69    
70    void init()
71    {
72      setShapeType(RECT_3D);
73      
74      getLabel().setModel(NodeLabel.INTERNAL);
75      getLabel().setPosition(NodeLabel.TOP);
76      
77      getLabel().setFontSize(13);
78      getLabel().setFontStyle(Font.BOLD);
79          
80      aLabel = new NodeLabel();
81      aLabel.bindRealizer(this);
82      aLabel.setAlignment(YLabel.ALIGN_LEFT);
83      aLabel.setModel(NodeLabel.FREE);
84      
85      mLabel = new NodeLabel();
86      mLabel.bindRealizer(this);
87      mLabel.setAlignment(YLabel.ALIGN_LEFT);
88      mLabel.setModel(NodeLabel.FREE);
89      
90      clipContent = true;
91      omitDetails = false;
92    }
93    
94    /**
95     * Instantiates a new UMLNodeRealzier as a copy of a given 
96     * realizer.
97     */ 
98    public UMLClassNodeRealizer(NodeRealizer r)
99    {
100     super(r);
101     if(r instanceof UMLClassNodeRealizer)
102     {
103       UMLClassNodeRealizer cnr = (UMLClassNodeRealizer)r;
104       aLabel = (NodeLabel)cnr.aLabel.clone();
105       aLabel.bindRealizer(this);
106       mLabel = (NodeLabel)cnr.mLabel.clone();
107       mLabel.bindRealizer(this);
108       constraint = cnr.constraint;
109       stereotype = cnr.stereotype;
110       clipContent = cnr.clipContent;
111       omitDetails = cnr.omitDetails;  
112     }
113     else
114       init();
115   }
116   
117   /**
118    * Returns a UMLNodERealizer that is a copy of the given 
119    * realizer.
120    */ 
121   public NodeRealizer createCopy(NodeRealizer r)
122   {
123     return new UMLClassNodeRealizer(r);
124   }
125     
126   
127   //////////////////////////////////////////////////////////////////////////////
128   // SETTER & GETTER ///////////////////////////////////////////////////////////
129   //////////////////////////////////////////////////////////////////////////////
130   
131   
132   /**
133    * Set the class name to be displayed by this realizer.
134    */
135   public void setClassName(String name)
136   {
137     setLabelText(name);
138   }
139   
140   /**
141    * Returns the class name to be displayed by this realizer.
142    */
143   public String getClassName()
144   {
145     return getLabelText();
146   }
147   
148   
149   /**
150    * Sets the constraint property of this realizer.
151    */
152   public void setConstraint(String constraint)
153   {
154     this.constraint = constraint;
155   }
156 
157   
158   /**
159    * Sets the stereotype property of this realizer.
160    */
161   public void setStereotype(String stereotype)
162   {
163     this.stereotype = stereotype;
164   }
165   
166   
167   /**
168    * Returns the constraint property of this realizer.
169    */
170   public String getConstraint()
171   {
172     return constraint;
173   }
174 
175   /**
176    * Returns the stereotype property of this realizer.
177    */
178   public String getStereotype()
179   {
180     return stereotype;
181   }
182   
183   
184   /**
185    * Returns the node label that represents all added
186    * method strings.
187    */
188   public NodeLabel getMethodLabel()
189   {
190     return mLabel;
191   }
192   
193   /**
194    * Returns the node label that represents all added
195    * attribute strings.
196    */
197   public NodeLabel getAttributeLabel()
198   {
199     return aLabel;
200   }
201   
202   /**
203    * Returns whether or not the display of the labels should be
204    * clipped with the bounding box of the realizer.
205    */
206   public boolean getClipContent()
207   {
208     return clipContent;
209   }
210  
211   /**
212    * Sets whether or not the display of the labels should be
213    * clipped with the bounding box of the realizer.
214    */
215   public void setClipContent(boolean clipping)
216   {
217     clipContent = clipping;
218   }
219   
220  
221   /**
222    * Set whether or not this realizer should omit details when being displayed.
223    */
224   public void setOmitDetails(boolean b)
225   {
226     omitDetails = b;
227   }
228   
229   
230   /**
231    * Returns whether or not this realizer should omit details when being displayed.
232    */ 
233   public boolean getOmitDetails()
234   {
235     return omitDetails;
236   }
237   
238   private void addToLabel(NodeLabel l, String s)
239   {
240     if(l.getText().length() > 0)
241       l.setText(l.getText() + '\n' + s);
242     else
243       l.setText(s);
244   }
245   
246   
247   /**
248    * Adds a class method label to this realizer.
249    */ 
250   public void addMethod(String method)
251   {
252     addToLabel(mLabel,method);
253   }
254   
255   /**
256    * Adds a class attribute label to this realizer.
257    */ 
258   public void addAttribute(String attr)
259   {
260     addToLabel(aLabel,attr);
261   }
262   
263   /**
264    * Set the size of this realizer automatically. This method will apapt the size
265    * of this realzier so that the labels defined for it will fit within its 
266    * bounding box.
267    */
268   public void fitContent()
269   {
270     double height = 3.0;
271     double width = getLabel().getWidth()+10;
272     
273     if(stereotype.length() > 0)
274     {
275       NodeLabel l = new NodeLabel();
276       l.setText("<<" + getStereotype() + ">>");
277       l.setModel(NodeLabel.FREE);
278       l.bindRealizer( this );
279       height += l.getHeight() + 5;
280       width = Math.max(l.getWidth()+10, width);
281     }
282     
283     height += getLabel().getHeight()+3;
284 
285     if(constraint.length() > 0)
286     {
287       NodeLabel l = new NodeLabel();
288       l.setText("{" + getConstraint() + "}");
289       l.setModel(NodeLabel.FREE);
290       height += l.getHeight() + 5;
291       width = Math.max(l.getWidth()+10, width);
292     }
293     
294     if(!omitDetails && !(aLabel.getText().equals("") && mLabel.getText().equals("")))
295     {
296       height += 3;
297       height += aLabel.getHeight()+3;
298       width = Math.max(aLabel.getWidth()+10 ,width);
299       height += 3;
300       height += mLabel.getHeight()+3;
301       width = Math.max(mLabel.getWidth()+10 ,width);
302     }
303     
304     setSize(width, height);
305   }
306   
307   
308   //////////////////////////////////////////////////////////////////////////////
309   // GRAPHICS  /////////////////////////////////////////////////////////////////
310   //////////////////////////////////////////////////////////////////////////////
311   
312   /**
313    * Paint the labels associated with this realizer.
314    */
315   public void paintText(Graphics2D gfx)
316   {    
317     Shape oldClip = null;
318     if(clipContent)
319     {
320       oldClip = gfx.getClip();
321       gfx.clip(getBoundingBox());//Rect((int)x,(int)y,(int)width,(int)height);
322     }
323     
324     double yoff = 3.0;
325     
326     if(stereotype.length() > 0)
327     {
328       NodeLabel l = new NodeLabel();
329       l.setText("<<" + getStereotype() + ">>");
330       l.setModel(NodeLabel.FREE);
331       l.setOffset( (getWidth()-l.getWidth())/2.0, yoff);
332       l.bindRealizer( this );
333       l.paint(gfx);
334       yoff += l.getHeight() + 5;
335     }
336     
337     NodeLabel label = getLabel();
338     label.setOffset((getWidth()-label.getWidth())/2.0,yoff);
339     label.paint(gfx);
340     yoff += label.getHeight()+3;
341 
342     if(constraint.length() > 0)
343     {
344       NodeLabel l = new NodeLabel();
345       l.setText("{" + getConstraint() + "}");
346       l.setModel(NodeLabel.FREE);
347       l.setOffset( getWidth()-l.getWidth() - 5.0, yoff);
348       l.bindRealizer( this );
349       l.paint(gfx);
350       yoff += l.getHeight() + 5;
351     }
352     
353     if(!omitDetails && !(aLabel.getText().equals("") && mLabel.getText().equals("")))
354     {
355       gfx.setColor(getLineColor());
356       gfx.drawLine((int)x+1,(int)(y+yoff),(int)(x+width-1),(int)(y+yoff));
357       yoff += 3;
358       aLabel.setOffset(3,yoff);
359       aLabel.paint(gfx);
360       yoff += aLabel.getHeight()+3;
361       gfx.drawLine((int)x+1,(int)(y+yoff),(int)(x+width-1),(int)(y+yoff));
362       yoff += 3;
363       mLabel.setOffset(3,yoff);
364       mLabel.paint(gfx);
365     }
366     
367     if(clipContent)
368     {
369       gfx.setClip(oldClip);
370     }
371   }
372   
373   //////////////////////////////////////////////////////////////////////////////
374   // SERIALIZATION /////////////////////////////////////////////////////////////
375   //////////////////////////////////////////////////////////////////////////////
376   
377   /**
378    * Serialization routine that allows this realizer to be written out
379    * in YGF graph format.
380    */ 
381   public void write(ObjectOutputStream out) throws IOException 
382   {
383     out.writeByte(YVersion.VERSION_1);
384     super.write(out);
385     aLabel.write( out );
386     mLabel.write( out );
387     out.writeBoolean(clipContent);
388     out.writeBoolean(omitDetails);
389     out.writeObject(getStereotype());
390     out.writeObject(getConstraint());
391   }
392   
393   
394   /**
395    * Deserialization routine that allows this realizer to be read in
396    * from YGF graph format.
397    */ 
398   public void read(ObjectInputStream in) throws IOException, ClassNotFoundException 
399   {
400     switch(in.readByte()) {
401     case YVersion.VERSION_1:
402       super.read(in);
403       init();
404       aLabel.read(in);
405       mLabel.read(in);
406       clipContent = in.readBoolean();
407       omitDetails = in.readBoolean();
408       stereotype = (String)in.readObject();
409       constraint = (String)in.readObject();
410       break;
411     default:
412       D.fatal("Unsupported Format");
413     }
414   }
415 
416 
417 
418   public static void addContentTo( final JRootPane rootPane )
419   {
420     final UMLClassNodeRealizer r = new UMLClassNodeRealizer();
421     r.setClassName("com.mycompany.MyClass");
422     r.setConstraint("abstract");
423     r.setStereotype("factory");
424     r.addAttribute("-graph");
425     r.addAttribute("-id");
426     r.addMethod("+setGraph(Graph)");
427     r.addMethod("+getGraph():Graph");
428     r.addMethod("+setID(int)");
429     r.addMethod("+getID():int");
430     r.fitContent();
431 
432     final Graph2DView view = new Graph2DView();
433     view.getGraph2D().setDefaultNodeRealizer(r.createCopy());
434     view.getGraph2D().createNode();
435     view.addViewMode(new EditMode());
436     view.fitContent();
437 
438     rootPane.setContentPane(view);
439   }
440 
441   /**
442    * Launcher method. Execute this class to see a sample instantiation of
443    * this node realizer in action.
444    */
445   public static void main(String[] args)
446   {
447     final JFrame frame = new JFrame();
448     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
449     addContentTo(frame.getRootPane());
450     frame.pack();
451     frame.setLocationRelativeTo(null);
452     frame.setVisible(true);
453   }
454 }
455 
456