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 75 2006-10-24 23:00:51Z 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.ktreemap;
34  
35  import java.util.ArrayList;
36  import java.util.List;
37  
38  import org.eclipse.swt.graphics.Rectangle;
39  
40  /**
41   * Abtract class with the method which split the elements of a KTreeMap.
42   * <p>
43   * The split is done by dichotomy. We split the elements in 2 groups with a
44   * defined strategy (for example : take care of the weight of the elements)
45   * <p>
46   *
47   * @author Laurent Dutheil
48   */
49  
50  public abstract class SplitStrategy {
51    /**
52     * calculate the positions for all the elements of the root.
53     *
54     * @param root the root to calculate
55     */
56    public void calculatePositions(TreeMapNode root) {
57      if (root == null) {
58        return;
59      }
60  
61      List<TreeMapNode> children = root.getChildren();
62      if (children != null) {
63        calculatePositionsRec(root.getBounds(), this.sumWeight(children),
64            children);
65      }
66    }
67  
68    /**
69     * split the elements of a JTreeMap.
70     *
71     * @param v Vector with the elements to split (arg IN)
72     * @param v1 first Vector of the split (arg OUT)
73     * @param v2 second Vector of the split (arg OUT)
74     */
75    public abstract void splitElements(List<TreeMapNode> v, List<TreeMapNode> v1,
76        List<TreeMapNode> v2);
77  
78    /**
79     * Sum the weight of elements. <BR>
80     * You can override this method if you want to apply a coef on the weights or
81     * to cancel the effect of weight on the strategy.
82     *
83     * @param children List with the elements to sum
84     * @return the sum of the weight of elements
85     */
86    public double sumWeight(List<TreeMapNode> children) {
87      double d = 0.0;
88      if (children != null) {
89        for (TreeMapNode node : children) {
90          d += node.getWeight();
91        }
92      }
93      return d;
94    }
95  
96    protected void calculatePositionsRec(Rectangle bounds, double weight0,
97        List<TreeMapNode> children) {
98  
99      // if the Vector contains only one element
100     if (children.size() == 1) {
101       TreeMapNode f = children.get(0);
102       if (f.isLeaf()) {
103         // if this is a leaf, we display with the border
104         int w = bounds.width - TreeMapNode.getBorder();
105         if (w < 0) {
106           w = 0;
107         }
108         int h = bounds.height - TreeMapNode.getBorder();
109         if (h < 0) {
110           h = 0;
111         }
112         Rectangle newBounds = new Rectangle(bounds.x + TreeMapNode.getBorder(),
113             bounds.y + TreeMapNode.getBorder(), w, h);
114         f.setBounds(newBounds);
115       } else {
116         // if this is not a leaf, calculation for the children
117         f.setBounds(bounds);
118 
119         int bSub;
120         if (TreeMapNode.getBorder() > 1) {
121           bSub = 2;
122         } else if (TreeMapNode.getBorder() == 1) {
123           bSub = 1;
124         } else {
125           bSub = 0;
126         }
127 
128         int w = bounds.width - bSub;
129         if (w < 0) {
130           w = 0;
131         }
132         int h = bounds.height - bSub;
133         if (h < 0) {
134           h = 0;
135         }
136 
137         TreeMapNode.setBorder(TreeMapNode.getBorder() - bSub);
138         Rectangle newBounds = new Rectangle(bounds.x + bSub, bounds.y + bSub,
139             w, h);
140         calculatePositionsRec(newBounds, 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       List<TreeMapNode> group1 = new ArrayList<TreeMapNode>();
147       List<TreeMapNode> group2 = new ArrayList<TreeMapNode>();
148       double weight1, weight2; // weights of the groups
149       this.splitElements(children, group1, group2);
150       weight1 = this.sumWeight(group1);
151       weight2 = this.sumWeight(group2);
152 
153       int w1, w2, h1, h2;
154       int x2, y2;
155       // if width is greater than height, we split the width
156       if (bounds.width > bounds.height) {
157         w1 = (int)(bounds.width * weight1 / weight0);
158         w2 = bounds.width - w1;
159         h1 = bounds.height;
160         h2 = bounds.height;
161         x2 = bounds.x + w1;
162         y2 = bounds.y;
163       } else {
164         // else we split the height
165         w1 = bounds.width;
166         w2 = bounds.width;
167         h1 = (int)(bounds.height * weight1 / weight0);
168         h2 = bounds.height - h1;
169         x2 = bounds.x;
170         y2 = bounds.y + h1;
171       }
172       // calculation for the new two Vectors
173       Rectangle bounds1 = new Rectangle(bounds.x, bounds.y, w1, h1);
174       calculatePositionsRec(bounds1, weight1, group1);
175       Rectangle bounds2 = new Rectangle(x2, y2, w2, h2);
176       calculatePositionsRec(bounds2, weight2, group2);
177     }
178   }
179 
180   /**
181    * Sort the elements by descending weight.
182    *
183    * @param v Vector with the elements to be sorted
184    */
185   protected void sortList(List<TreeMapNode> v) {
186     TreeMapNode tmn;
187     // we use the bubble sort
188     for (int i = 0; i < v.size(); i++) {
189       for (int j = v.size() - 1; j > i; j--) {
190         if ((v.get(j)).getWeight() > (v.get(j - 1)).getWeight()) {
191           tmn = (v.get(j));
192           v.set(j, v.get(j - 1));
193           v.set(j - 1, tmn);
194         }
195       }
196     }
197   }
198 }
199 /*
200  *                 ObjectLab is supporing JTreeMap
201  * 
202  * Based in London, we are world leaders in the design and development 
203  * of bespoke applications for the securities financing markets.
204  * 
205  * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
206  *           ___  _     _           _   _          _
207  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
208  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
209  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
210  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
211  *                   |__/
212  *
213  *                     www.ObjectLab.co.uk
214  */