1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.9. 
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-2011 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  package demo.io.graphml;
15  
16  import y.option.OptionHandler;
17  import y.view.Graph2D;
18  import y.view.NodeRealizer;
19  import y.view.SizeConstraintProvider;
20  import y.view.NodeLabel;
21  import y.base.NodeCursor;
22  import y.base.Node;
23  import y.geom.YDimension;
24  
25  import java.awt.font.FontRenderContext;
26  import java.awt.geom.AffineTransform;
27  
28  /**
29   * This module adjusts the size of nodes to match the
30   * size of their label text.
31   */
32  public class NodeSizeAdapter extends y.module.YModule 
33  {
34    static final String MIN_WIDTH             = "MIN_WIDTH";
35    static final String IGNORE_WIDTHS         = "IGNORE_WIDTHS";
36    static final String ADAPT_TO_MAXIMUM_NODE = "ADAPT_TO_MAXIMUM_NODE";
37    static final String NODE_SIZE_ADAPTER     = "NODE_SIZE_ADAPTER";
38    static final String ONLY_SELECTION        = "ONLY_SELECTION";
39    static final String VERTICAL_SPACE        = "VERTICAL_SPACE";
40    static final String IGNORE_HEIGHTS        = "IGNORE_HEIGHTS";
41    static final String MIN_HEIGHT            = "MIN_HEIGHT";
42    static final String HORIZON_SPACE         = "HORIZON_SPACE";
43  
44    private int vSpace        = 5;
45    private int hSpace        = 5;
46    private int minWidth      = 10;
47    private int minHeight     = 30;
48    private boolean selectionOnly = false;
49    private boolean adaptToMax    = false;
50    private boolean ignoreHeight  = true;
51    private boolean ignoreWidth   = false;
52  
53    double currentMaxH = 0;
54    double currentMaxW = 0;
55  
56    public NodeSizeAdapter()
57    {
58      super(NodeSizeAdapter.NODE_SIZE_ADAPTER,
59            "yWorks GmbH",
60            "Adjusts the size of nodes to match the " +
61            "size of their label text.");
62    }
63  
64    protected OptionHandler createOptionHandler()
65    {
66      OptionHandler op = new OptionHandler(getModuleName());
67  
68      op.addInt(NodeSizeAdapter.VERTICAL_SPACE, vSpace, 1, 20);
69      op.addInt(NodeSizeAdapter.MIN_HEIGHT, minHeight, 5, 100 );
70      op.addBool(NodeSizeAdapter.IGNORE_HEIGHTS, ignoreHeight);
71      op.addInt(NodeSizeAdapter.HORIZON_SPACE, hSpace, 1, 20);
72      op.addInt(NodeSizeAdapter.MIN_WIDTH, minWidth, 5, 100 );
73      op.addBool(NodeSizeAdapter.IGNORE_WIDTHS, ignoreWidth);
74      op.addBool(NodeSizeAdapter.ADAPT_TO_MAXIMUM_NODE, adaptToMax);
75      op.addBool(NodeSizeAdapter.ONLY_SELECTION, false);
76  
77      return op;
78    }
79  
80    protected void init()
81    {
82      OptionHandler op = getOptionHandler();
83  
84      vSpace = op.getInt(NodeSizeAdapter.VERTICAL_SPACE);
85      minHeight = op.getInt(NodeSizeAdapter.MIN_HEIGHT);
86      ignoreHeight = op.getBool(NodeSizeAdapter.IGNORE_HEIGHTS);
87      hSpace = op.getInt(NodeSizeAdapter.HORIZON_SPACE);
88      minWidth = op.getInt(NodeSizeAdapter.MIN_WIDTH);
89      ignoreWidth = op.getBool(NodeSizeAdapter.IGNORE_WIDTHS);
90      adaptToMax = op.getBool(NodeSizeAdapter.ADAPT_TO_MAXIMUM_NODE);
91      selectionOnly = op.getBool(NodeSizeAdapter.ONLY_SELECTION);
92    }
93  
94    protected void mainrun()
95    {
96      Graph2D graph = getGraph2D();
97      NodeCursor nc;
98      if( selectionOnly )               // only selected nodes
99        nc = graph.selectedNodes();
100     else                              // all nodes
101       nc = graph.nodes();
102     adapt(nc,adaptToMax);
103     getGraph2D().updateViews();
104   }
105 
106   public void adaptMax()
107   {
108     Graph2D graph = getGraph2D();
109 
110     NodeCursor nc;
111     if( selectionOnly )               // only selected nodes
112       nc = graph.selectedNodes();
113     else                              // all nodes
114       nc = graph.nodes();
115     for( ; nc.ok(); nc.next() )
116     {
117       NodeRealizer nr = graph.getRealizer(nc.node());
118       if( !ignoreHeight )
119         nr.setHeight( currentMaxH );
120       if( !ignoreWidth )
121         nr.setWidth( currentMaxW );
122     }
123   }
124 
125   //---------------------------------------------------------------------------
126   /**
127    * Adapts the size of a list of nodes
128    */
129   public void adapt(NodeCursor nc,boolean adaptToMax)
130   {
131     currentMaxW = currentMaxH = 0;
132     for (;nc.ok();nc.next())
133     {
134       adapt(nc.node());
135     }
136     if( adaptToMax )
137       adaptMax();
138   }
139 
140   static FontRenderContext defaultFRC =
141     new FontRenderContext(new AffineTransform(),false,false);
142 
143   //---------------------------------------------------------------------------
144   /**
145    * Adapts the size of a single node
146    */
147   public void adapt(Node n)
148   {
149     NodeRealizer nr = getGraph2D().getRealizer(n);
150     adapt(nr);
151   }
152 
153 
154   /**
155    * Adapts the size of a single node
156    */
157   public void adapt(NodeRealizer nr) {
158     double minWidth = this.minWidth;
159     double minHeight = this.minHeight;
160     double maxWidth = Double.POSITIVE_INFINITY;
161     double maxHeight = Double.POSITIVE_INFINITY;
162     final SizeConstraintProvider scp = nr.getSizeConstraintProvider();
163     if (scp != null) {
164       final YDimension min = scp.getMinimumSize();
165       if (min != null) {
166         if (minWidth < min.width) {
167           minWidth = min.width;
168         }
169         if (minHeight < min.height) {
170           minHeight = min.height;
171         }
172       }
173       final YDimension max = scp.getMaximumSize();
174       if (max != null) {
175         maxWidth = max.width;
176         maxHeight = max.height;
177       }
178     }
179 
180     final NodeLabel nl = nr.getLabel();
181 
182     if (!ignoreWidth) {
183       double width = nl.getWidth() + 2 * hSpace;
184       if (width < minWidth) {
185         width = minWidth;
186       }
187       if (width > maxWidth) {
188         width = maxWidth;
189       }
190       nr.setWidth(width);
191       if (width > currentMaxW) {
192         currentMaxW = width;
193       }
194     }
195     if (!ignoreHeight) {
196       double height = nl.getHeight() + 2 * vSpace;
197       if (height < minHeight) {
198         height = minHeight;
199       }
200       if (height > maxHeight) {
201         height = maxHeight;
202       }
203       nr.setHeight(height);
204       if (height > currentMaxH) {
205         currentMaxH = height;
206       }
207     }
208   }
209 
210   //---------------------------------------------------------------------------
211   public void setIgnore(boolean width,boolean height)
212   {
213     ignoreHeight = height;
214     ignoreWidth = width;
215   }
216 
217 }
218