1   /****************************************************************************
2    * This demo file is part of yFiles for Java 2.14.
3    * Copyright (c) 2000-2017 by yWorks GmbH, Vor dem Kreuzberg 28,
4    * 72070 Tuebingen, Germany. All rights reserved.
5    * 
6    * yFiles demo files exhibit yFiles for Java functionalities. Any redistribution
7    * of demo files in source code or binary form, with or without
8    * modification, is not permitted.
9    * 
10   * Owners of a valid software license for a yFiles for Java version that this
11   * demo is shipped with are allowed to use the demo source code as basis
12   * for their own yFiles for Java powered applications. Use of such programs is
13   * governed by the rights and conditions as set out in the yFiles for Java
14   * license agreement.
15   * 
16   * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
17   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19   * NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21   * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   *
27   ***************************************************************************/
28  package demo.io.graphml;
29  
30  import y.option.OptionHandler;
31  import y.view.Graph2D;
32  import y.view.NodeRealizer;
33  import y.view.SizeConstraintProvider;
34  import y.view.NodeLabel;
35  import y.base.NodeCursor;
36  import y.base.Node;
37  import y.geom.YDimension;
38  
39  import java.awt.font.FontRenderContext;
40  import java.awt.geom.AffineTransform;
41  
42  /**
43   * This module adjusts the size of nodes to match the
44   * size of their label text.
45   */
46  public class NodeSizeAdapter extends y.module.YModule 
47  {
48    static final String MIN_WIDTH             = "MIN_WIDTH";
49    static final String IGNORE_WIDTHS         = "IGNORE_WIDTHS";
50    static final String ADAPT_TO_MAXIMUM_NODE = "ADAPT_TO_MAXIMUM_NODE";
51    static final String NODE_SIZE_ADAPTER     = "NODE_SIZE_ADAPTER";
52    static final String ONLY_SELECTION        = "ONLY_SELECTION";
53    static final String VERTICAL_SPACE        = "VERTICAL_SPACE";
54    static final String IGNORE_HEIGHTS        = "IGNORE_HEIGHTS";
55    static final String MIN_HEIGHT            = "MIN_HEIGHT";
56    static final String HORIZON_SPACE         = "HORIZON_SPACE";
57  
58    private int vSpace        = 5;
59    private int hSpace        = 5;
60    private int minWidth      = 10;
61    private int minHeight     = 30;
62    private boolean selectionOnly = false;
63    private boolean adaptToMax    = false;
64    private boolean ignoreHeight  = true;
65    private boolean ignoreWidth   = false;
66  
67    double currentMaxH = 0;
68    double currentMaxW = 0;
69  
70    public NodeSizeAdapter()
71    {
72      super(NodeSizeAdapter.NODE_SIZE_ADAPTER);
73    }
74  
75    protected OptionHandler createOptionHandler()
76    {
77      OptionHandler op = new OptionHandler(getModuleName());
78  
79      op.addInt(NodeSizeAdapter.VERTICAL_SPACE, vSpace, 1, 20);
80      op.addInt(NodeSizeAdapter.MIN_HEIGHT, minHeight, 5, 100 );
81      op.addBool(NodeSizeAdapter.IGNORE_HEIGHTS, ignoreHeight);
82      op.addInt(NodeSizeAdapter.HORIZON_SPACE, hSpace, 1, 20);
83      op.addInt(NodeSizeAdapter.MIN_WIDTH, minWidth, 5, 100 );
84      op.addBool(NodeSizeAdapter.IGNORE_WIDTHS, ignoreWidth);
85      op.addBool(NodeSizeAdapter.ADAPT_TO_MAXIMUM_NODE, adaptToMax);
86      op.addBool(NodeSizeAdapter.ONLY_SELECTION, false);
87  
88      return op;
89    }
90  
91    protected void init()
92    {
93      OptionHandler op = getOptionHandler();
94  
95      vSpace = op.getInt(NodeSizeAdapter.VERTICAL_SPACE);
96      minHeight = op.getInt(NodeSizeAdapter.MIN_HEIGHT);
97      ignoreHeight = op.getBool(NodeSizeAdapter.IGNORE_HEIGHTS);
98      hSpace = op.getInt(NodeSizeAdapter.HORIZON_SPACE);
99      minWidth = op.getInt(NodeSizeAdapter.MIN_WIDTH);
100     ignoreWidth = op.getBool(NodeSizeAdapter.IGNORE_WIDTHS);
101     adaptToMax = op.getBool(NodeSizeAdapter.ADAPT_TO_MAXIMUM_NODE);
102     selectionOnly = op.getBool(NodeSizeAdapter.ONLY_SELECTION);
103   }
104 
105   protected void mainrun()
106   {
107     Graph2D graph = getGraph2D();
108     NodeCursor nc;
109     if( selectionOnly )               // only selected nodes
110       nc = graph.selectedNodes();
111     else                              // all nodes
112       nc = graph.nodes();
113     adapt(nc,adaptToMax);
114     getGraph2D().updateViews();
115   }
116 
117   public void adaptMax()
118   {
119     Graph2D graph = getGraph2D();
120 
121     NodeCursor nc;
122     if( selectionOnly )               // only selected nodes
123       nc = graph.selectedNodes();
124     else                              // all nodes
125       nc = graph.nodes();
126     for( ; nc.ok(); nc.next() )
127     {
128       NodeRealizer nr = graph.getRealizer(nc.node());
129       if( !ignoreHeight )
130         nr.setHeight( currentMaxH );
131       if( !ignoreWidth )
132         nr.setWidth( currentMaxW );
133     }
134   }
135 
136   //---------------------------------------------------------------------------
137   /**
138    * Adapts the size of a list of nodes
139    */
140   public void adapt(NodeCursor nc,boolean adaptToMax)
141   {
142     currentMaxW = currentMaxH = 0;
143     for (;nc.ok();nc.next())
144     {
145       adapt(nc.node());
146     }
147     if( adaptToMax )
148       adaptMax();
149   }
150 
151   static FontRenderContext defaultFRC =
152     new FontRenderContext(new AffineTransform(),false,false);
153 
154   //---------------------------------------------------------------------------
155   /**
156    * Adapts the size of a single node
157    */
158   public void adapt(Node n)
159   {
160     NodeRealizer nr = getGraph2D().getRealizer(n);
161     adapt(nr);
162   }
163 
164 
165   /**
166    * Adapts the size of a single node
167    */
168   public void adapt(NodeRealizer nr) {
169     double minWidth = this.minWidth;
170     double minHeight = this.minHeight;
171     double maxWidth = Double.POSITIVE_INFINITY;
172     double maxHeight = Double.POSITIVE_INFINITY;
173     final SizeConstraintProvider scp = nr.getSizeConstraintProvider();
174     if (scp != null) {
175       final YDimension min = scp.getMinimumSize();
176       if (min != null) {
177         if (minWidth < min.width) {
178           minWidth = min.width;
179         }
180         if (minHeight < min.height) {
181           minHeight = min.height;
182         }
183       }
184       final YDimension max = scp.getMaximumSize();
185       if (max != null) {
186         maxWidth = max.width;
187         maxHeight = max.height;
188       }
189     }
190 
191     final NodeLabel nl = nr.getLabel();
192 
193     if (!ignoreWidth) {
194       double width = nl.getWidth() + 2 * hSpace;
195       if (width < minWidth) {
196         width = minWidth;
197       }
198       if (width > maxWidth) {
199         width = maxWidth;
200       }
201       nr.setWidth(width);
202       if (width > currentMaxW) {
203         currentMaxW = width;
204       }
205     }
206     if (!ignoreHeight) {
207       double height = nl.getHeight() + 2 * vSpace;
208       if (height < minHeight) {
209         height = minHeight;
210       }
211       if (height > maxHeight) {
212         height = maxHeight;
213       }
214       nr.setHeight(height);
215       if (height > currentMaxH) {
216         currentMaxH = height;
217       }
218     }
219   }
220 
221   //---------------------------------------------------------------------------
222   public void setIgnore(boolean width,boolean height)
223   {
224     ignoreHeight = height;
225     ignoreWidth = width;
226   }
227 
228 }
229