View Javadoc

1   /*
2    * ObjectLab, http://www.objectlab.co.uk/open is supporting JTreeMap.
3    * 
4    * Based in London, we are world leaders in the design and development 
5    * of bespoke applications for the securities financing markets.
6    * 
7    * <a href="http://www.objectlab.co.uk/open">Click here to learn more</a>
8    *           ___  _     _           _   _          _
9    *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
10   *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
11   *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
12   *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
13   *                   |__/
14   *
15   *                     www.ObjectLab.co.uk
16   *
17   * $Id: SplitStrategy.java 74 2006-10-24 22:19:05Z benoitx $
18   * 
19   * Copyright 2006 the original author or authors.
20   *
21   * Licensed under the Apache License, Version 2.0 (the "License"); you may not
22   * use this file except in compliance with the License. You may obtain a copy of
23   * the License at
24   *
25   * http://www.apache.org/licenses/LICENSE-2.0
26   *
27   * Unless required by applicable law or agreed to in writing, software
28   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
29   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
30   * License for the specific language governing permissions and limitations under
31   * the License.
32   */
33  package net.sf.jtreemap.swing;
34  
35  import java.io.Serializable;
36  import java.util.Iterator;
37  import java.util.Vector;
38  
39  /**
40   * Abtract class with the method which split the elements of a JTreeMap.
41   * <p>
42   * The split is done by dichotomy. We split the elements in 2 groups with a
43   * defined strategy (for example : take care of the weight of the elements)
44   * <p>
45   * 
46   * @author Laurent Dutheil
47   */
48  
49  public abstract class SplitStrategy implements Serializable {
50      /**
51       * calculate the positions for all the elements of the root.
52       * 
53       * @param root
54       *            the root to calculate
55       */
56      public void calculatePositions(final TreeMapNode root) {
57          if (root == null) {
58              return;
59          }
60  
61          final Vector<TreeMapNode> v = root.getChildren();
62          if (v != null) {
63              calculatePositionsRec(root.getX(), root.getY(), root.getWidth(), root.getHeight(), this.sumWeight(v), v);
64          }
65      }
66  
67      /**
68       * split the elements of a JTreeMap.
69       * 
70       * @param v
71       *            Vector with the elements to split (arg IN)
72       * @param v1
73       *            first Vector of the split (arg OUT)
74       * @param v2
75       *            second Vector of the split (arg OUT)
76       */
77      public abstract void splitElements(Vector<TreeMapNode> v, Vector<TreeMapNode> v1, Vector<TreeMapNode> v2);
78  
79      /**
80       * Sum the weight of elements. <BR>
81       * You can override this method if you want to apply a coef on the weights
82       * or to cancel the effect of weight on the strategy.
83       * 
84       * @param v
85       *            Vector with the elements to sum
86       * @return the sum of the weight of elements
87       */
88      public double sumWeight(final Vector<TreeMapNode> v) {
89          double d = 0.0;
90          if (v != null) {
91              final int size = v.size();
92  
93              for (int i = 0; i < size; i++) {
94                  d += (v.elementAt(i)).getWeight();
95              }
96          }
97          return d;
98      }
99  
100     protected void calculatePositionsRec(final int x0, final int y0, final int w0, final int h0, final double weight0,
101             final Vector<TreeMapNode> v) {
102 
103         // if the Vector contains only one element
104         if (v.size() == 1) {
105             final TreeMapNode f = v.elementAt(0);
106             if (f.isLeaf()) {
107                 // if this is a leaf, we display with the border
108                 int w = w0 - TreeMapNode.getBorder();
109                 if (w < 0) {
110                     w = 0;
111                 }
112                 int h = h0 - TreeMapNode.getBorder();
113                 if (h < 0) {
114                     h = 0;
115                 }
116                 f.setDimension(x0 + TreeMapNode.getBorder(), y0 + TreeMapNode.getBorder(), w, h);
117             } else {
118                 // if this is not a leaf, calculation for the children
119                 f.setDimension(x0, y0, w0, h0);
120 
121                 int bSub;
122                 if (TreeMapNode.getBorder() > 1) {
123                     bSub = 2;
124                 } else if (TreeMapNode.getBorder() == 1) {
125                     bSub = 1;
126                 } else {
127                     bSub = 0;
128                 }
129 
130                 int w = w0 - bSub;
131                 if (w < 0) {
132                     w = 0;
133                 }
134                 int h = h0 - bSub;
135                 if (h < 0) {
136                     h = 0;
137                 }
138 
139                 TreeMapNode.setBorder(TreeMapNode.getBorder() - bSub);
140                 calculatePositionsRec(x0 + bSub, y0 + bSub, w, h, weight0, f.getChildren());
141                 TreeMapNode.setBorder(TreeMapNode.getBorder() + bSub);
142             }
143         } else {
144             // if there is more than one element
145             // we split the Vector according to the selected strategy
146             final Vector<TreeMapNode> v1 = new Vector<TreeMapNode>();
147             final Vector<TreeMapNode> v2 = new Vector<TreeMapNode>();
148             double weight1;
149             double weight2; // poids des 2 vecteurs
150             this.splitElements(v, v1, v2);
151             weight1 = this.sumWeight(v1);
152             weight2 = this.sumWeight(v2);
153 
154             int w1;
155             int w2;
156             int h1;
157             int h2;
158             int x2;
159             int y2;
160             // if width is greater than height, we split the width
161             if (w0 > h0) {
162                 w1 = (int) (w0 * weight1 / weight0);
163                 w2 = w0 - w1;
164                 h1 = h0;
165                 h2 = h0;
166                 x2 = x0 + w1;
167                 y2 = y0;
168             } else {
169                 // else we split the height
170                 w1 = w0;
171                 w2 = w0;
172                 h1 = (int) (h0 * weight1 / weight0);
173                 h2 = h0 - h1;
174                 x2 = x0;
175                 y2 = y0 + h1;
176             }
177             // calculation for the new two Vectors
178             calculatePositionsRec(x0, y0, w1, h1, weight1, v1);
179             calculatePositionsRec(x2, y2, w2, h2, weight2, v2);
180         }
181     }
182 
183     /**
184      * Sort the elements by descending weight.
185      * 
186      * @param v
187      *            Vector with the elements to be sorted
188      */
189     protected void sortVector(final Vector<TreeMapNode> v) {
190         TreeMapNode tmn;
191         // we use the bubble sort
192         for (int i = 0; i < v.size(); i++) {
193             for (int j = v.size() - 1; j > i; j--) {
194                 if ((v.elementAt(j)).getWeight() > (v.elementAt(j - 1)).getWeight()) {
195                     tmn = (v.elementAt(j));
196                     v.setElementAt(v.elementAt(j - 1), j);
197                     v.setElementAt(tmn, j - 1);
198                 }
199             }
200         }
201 
202     }
203 
204     protected void workOutWeight(final Vector<TreeMapNode> v1, final Vector<TreeMapNode> v2, final Vector<TreeMapNode> vClone,
205             final double sumWeight) {
206         double memWeight = 0.0;
207         double elemWeight = 0.0;
208         for (final Iterator<TreeMapNode> i = vClone.iterator(); i.hasNext();) {
209             TreeMapNode tmn = i.next();
210             elemWeight = tmn.getWeight();
211             // if adding the current element pass the middle of total weight
212             if (memWeight + elemWeight >= sumWeight / 2) {
213                 // we look at the finest split (the nearest of the middle of
214                 // weight)
215                 if (((sumWeight / 2) - memWeight) > ((memWeight + elemWeight) - (sumWeight / 2))) {
216                     // if it is after the add, we add the element to the first
217                     // Vector
218                     memWeight += elemWeight;
219                     v1.addElement(tmn);
220                 } else {
221                     // we must have at least 1 element in the first vector
222                     if (v1.isEmpty()) {
223                         v1.addElement(tmn);
224                     } else {
225                         // if it is before the add, we add the element to the
226                         // second Vector
227                         v2.addElement(tmn);
228                     }
229                 }
230                 // then we fill the second Vector qith the rest of elements
231                 while (i.hasNext()) {
232                     tmn = i.next();
233                     v2.addElement(tmn);
234                 }
235             } else {
236                 // we add in the first vector while we don't reach the middle of
237                 // weight
238                 memWeight += elemWeight;
239                 v1.addElement(tmn);
240             }
241         }
242     }
243 }
244 /*
245  *                 ObjectLab is supporing JTreeMap
246  * 
247  * Based in London, we are world leaders in the design and development 
248  * of bespoke applications for the securities financing markets.
249  * 
250  * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
251  *           ___  _     _           _   _          _
252  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
253  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
254  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
255  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
256  *                   |__/
257  *
258  *                     www.ObjectLab.co.uk
259  */