1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sf.magicproject.ui.layout;
20
21 import java.awt.BorderLayout;
22 import java.awt.Component;
23 import java.awt.Container;
24 import java.awt.Dimension;
25 import java.awt.LayoutManager2;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30
31 import net.sf.magicproject.clickable.targetable.card.AbstractCard;
32 import net.sf.magicproject.clickable.targetable.card.MCard;
33 import net.sf.magicproject.zone.ZoneSector;
34
35 /***
36 * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
37 * @since 0.91
38 */
39 public class SectorLayout implements LayoutManager2, java.io.Serializable {
40 /***
41 * Constructs a border layout with the horizontal gaps between components. The
42 * horizontal gap is specified by <code>hgap</code>.
43 *
44 * @see #getHgap()
45 * @see #setHgap(int)
46 * @serial
47 */
48 int hgap;
49
50 /***
51 * Constructs a border layout with the vertical gaps between components. The
52 * vertical gap is specified by <code>vgap</code>.
53 *
54 * @see #getVgap()
55 * @see #setVgap(int)
56 * @serial
57 */
58 int vgap;
59
60 private final Map<Object, ZoneSector> sectors;
61
62 private static final List<AbstractCard> EMPTY_LIST = new ArrayList<AbstractCard>(
63 0);
64
65
66
67
68 private static final long serialVersionUID = -8658291919501921765L;
69
70 /***
71 * Constructs a new border layout with no gaps between components.
72 *
73 * @param sectors
74 * defined sectors.
75 */
76 public SectorLayout(List<ZoneSector> sectors) {
77 this(5, 5, sectors);
78 }
79
80 /***
81 * Constructs a border layout with the specified gaps between components. The
82 * horizontal gap is specified by <code>hgap</code> and the vertical gap is
83 * specified by <code>vgap</code>.
84 *
85 * @param hgap
86 * the horizontal gap.
87 * @param vgap
88 * the vertical gap.
89 * @param sectors
90 * defined sectors.
91 */
92 public SectorLayout(int hgap, int vgap, List<ZoneSector> sectors) {
93 this.hgap = hgap;
94 this.vgap = vgap;
95 this.sectors = new HashMap<Object, ZoneSector>();
96 for (ZoneSector zoneSector : sectors) {
97 this.sectors.put(zoneSector.getConstraint(), zoneSector);
98 }
99 }
100
101 /***
102 * Returns the horizontal gap between components.
103 *
104 * @return the horizontal gap.
105 * @since JDK1.1
106 */
107 public int getHgap() {
108 return hgap;
109 }
110
111 /***
112 * Sets the horizontal gap between components.
113 *
114 * @param hgap
115 * the horizontal gap between components
116 * @since JDK1.1
117 */
118 public void setHgap(int hgap) {
119 this.hgap = hgap;
120 }
121
122 /***
123 * Returns the vertical gap between components.
124 *
125 * @return the vertical gap.
126 * @since JDK1.1
127 */
128 public int getVgap() {
129 return vgap;
130 }
131
132 /***
133 * Sets the vertical gap between components.
134 *
135 * @param vgap
136 * the vertical gap between components
137 * @since JDK1.1
138 */
139 public void setVgap(int vgap) {
140 this.vgap = vgap;
141 }
142
143 public void addLayoutComponent(Component comp, Object constraints) {
144
145 }
146
147 public void addLayoutComponent(String name, Component comp) {
148
149 }
150
151 public void removeLayoutComponent(Component comp) {
152
153 }
154
155 /***
156 * Determines the minimum size of the <code>target</code> container using
157 * this layout manager.
158 * <p>
159 * This method is called when a container calls its
160 * <code>getMinimumSize</code> method. Most applications do not call this
161 * method directly.
162 *
163 * @param target
164 * the container in which to do the layout.
165 * @return the minimum dimensions needed to lay out the subcomponents of the
166 * specified container.
167 * @see java.awt.Container
168 * @see net.sf.magicproject.ui.layout.SectorLayout#preferredLayoutSize
169 * @see java.awt.Container#getMinimumSize()
170 */
171 public Dimension minimumLayoutSize(Container target) {
172 return new Dimension(0, 0);
173 }
174
175 /***
176 * Determines the preferred size of the <code>target</code> container using
177 * this layout manager, based on the components in the container.
178 * <p>
179 * Most applications do not call this method directly. This method is called
180 * when a container calls its <code>getPreferredSize</code> method.
181 *
182 * @param target
183 * the container in which to do the layout.
184 * @return the preferred dimensions to lay out the subcomponents of the
185 * specified container.
186 * @see java.awt.Container
187 * @see net.sf.magicproject.ui.layout.SectorLayout#minimumLayoutSize
188 * @see java.awt.Container#getPreferredSize()
189 */
190 public Dimension preferredLayoutSize(Container target) {
191 return target.getSize();
192 }
193
194 /***
195 * Returns the maximum dimensions for this layout given the components in the
196 * specified target container.
197 *
198 * @param target
199 * the component which needs to be laid out
200 * @return the maximum dimensions for this layout
201 * @see Container
202 * @see #minimumLayoutSize
203 * @see #preferredLayoutSize
204 */
205 public Dimension maximumLayoutSize(Container target) {
206 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
207 }
208
209 /***
210 * Returns the alignment along the x axis. This specifies how the component
211 * would like to be aligned relative to other components. The value should be
212 * a number between 0 and 1 where 0 represents alignment along the origin, 1
213 * is aligned the furthest away from the origin, 0.5 is centered, etc.
214 *
215 * @param parent
216 * @return the alignment along the x axis.
217 */
218 public float getLayoutAlignmentX(Container parent) {
219 return 0.5f;
220 }
221
222 /***
223 * Returns the alignment along the y axis. This specifies how the component
224 * would like to be aligned relative to other components. The value should be
225 * a number between 0 and 1 where 0 represents alignment along the origin, 1
226 * is aligned the furthest away from the origin, 0.5 is centered, etc.
227 *
228 * @param parent
229 * @return the alignment along the y axis.
230 */
231 public float getLayoutAlignmentY(Container parent) {
232 return 0.5f;
233 }
234
235 /***
236 * Invalidates the layout, indicating that if the layout manager has cached
237 * information it should be discarded.
238 *
239 * @param target
240 */
241 public void invalidateLayout(Container target) {
242
243 }
244
245 private List<AbstractCard> getCards(Object constraint) {
246 ZoneSector sector = sectors.get(constraint);
247 if (sector == null) {
248 return EMPTY_LIST;
249 }
250 return sector.getCards();
251 }
252
253 /***
254 * Lays out the container argument using this border layout.
255 * <p>
256 * This method actually reshapes the components in the specified container in
257 * order to satisfy the constraints of this <code>SectorLayout</code>
258 * object. The <code>NORTH</code> and <code>SOUTH</code> components, if
259 * any, are placed at the top and bottom of the container, respectively. The
260 * <code>WEST</code> and <code>EAST</code> components are then placed on
261 * the left and right, respectively. Finally, the <code>CENTER</code> object
262 * is placed in any remaining space in the middle.
263 * <p>
264 * Most applications do not call this method directly. This method is called
265 * when a container calls its <code>doLayout</code> method.
266 *
267 * @param target
268 * the container in which to do the layout.
269 * @see java.awt.Container
270 * @see java.awt.Container#doLayout()
271 */
272 public void layoutContainer(Container target) {
273 synchronized (target.getTreeLock()) {
274 int height = target.getHeight();
275 int width = target.getWidth();
276
277
278 int yw = 0;
279 int xw = 0;
280 int maxWidth = 0;
281 for (AbstractCard card : getCards(BorderLayout.WEST)) {
282 if (card instanceof MCard && ((MCard) card).getMUI().isAutoAlign) {
283 int cardHeight = card.getHeight();
284 if (yw + cardHeight + vgap >= height) {
285 yw = 0;
286 xw += maxWidth + hgap;
287 maxWidth = card.getWidth();
288 card.setLocation(xw, yw);
289 } else {
290 if (card.getWidth() > maxWidth) {
291 maxWidth = card.getWidth();
292 }
293 card.setLocation(xw, yw);
294 }
295 yw += cardHeight + vgap;
296 }
297 }
298 xw += maxWidth + hgap;
299
300
301 int ye = vgap;
302 int xe = width - hgap;
303 maxWidth = 0;
304 for (AbstractCard card : getCards(BorderLayout.EAST)) {
305 if (((MCard) card).getMUI().isAutoAlign) {
306 int cardHeight = card.getHeight();
307 if (ye + cardHeight + vgap >= height) {
308 ye = 0;
309 xe -= maxWidth + hgap;
310 maxWidth = card.getWidth();
311 card.setLocation(xe - card.getWidth(), ye);
312 } else {
313 if (card.getWidth() > maxWidth) {
314 maxWidth = card.getWidth();
315 }
316 card.setLocation(xe - card.getWidth(), ye);
317 }
318 ye += cardHeight + vgap;
319 }
320 }
321 xe -= maxWidth + hgap;
322
323
324 int yn = vgap;
325 int xn = (xe - xw) / 2;
326 maxWidth = 0;
327 int maxHeightN = 0;
328 int count = 0;
329 int requiredSpace = 0;
330 int scaledHgap = hgap;
331 for (AbstractCard card : getCards(BorderLayout.NORTH)) {
332 if (((MCard) card).getMUI().isAutoAlign) {
333 count++;
334 requiredSpace += card.getWidth();
335 if (card.getHeight() > maxHeightN)
336 maxHeightN = card.getHeight();
337 }
338 }
339 requiredSpace += count * hgap;
340 if (count > 1) {
341 if (requiredSpace + xw > xe) {
342 scaledHgap = (xe - xw - requiredSpace) / (count - 1);
343 xn = xw;
344 } else {
345 xn = (xe - xw - requiredSpace) / 2;
346 }
347 }
348 for (AbstractCard card : getCards(BorderLayout.NORTH)) {
349 if (((MCard) card).getMUI().isAutoAlign) {
350 card.setLocation(xn, yn);
351 xn += card.getWidth() + scaledHgap;
352 }
353 }
354 yn += maxHeightN + vgap;
355
356
357 int ys = height - vgap;
358 int xs = (xe - xw) / 2;
359 maxWidth = 0;
360 int maxHeightS = 0;
361 count = 0;
362 requiredSpace = 0;
363 scaledHgap = hgap;
364 for (AbstractCard card : getCards(BorderLayout.SOUTH)) {
365 if (((MCard) card).getMUI().isAutoAlign) {
366 count++;
367 requiredSpace += card.getWidth();
368 if (card.getHeight() > maxHeightS)
369 maxHeightS = card.getHeight();
370 }
371 }
372 if (count > 1) {
373 if (requiredSpace + xw > xe) {
374 scaledHgap = (xe - xw - requiredSpace) / (count - 1);
375 xs = xw;
376 } else {
377 xs = (xe - xw - requiredSpace) / 2;
378 }
379 }
380 for (AbstractCard card : getCards(BorderLayout.SOUTH)) {
381 if (((MCard) card).getMUI().isAutoAlign) {
382 card.setLocation(xs, ys - card.getHeight());
383 xs += card.getWidth() + scaledHgap;
384 }
385 }
386 ys -= maxHeightS + vgap;
387
388
389 maxWidth = 0;
390 int maxHeightC = 0;
391 requiredSpace = 0;
392 int requiredHeight = 0;
393 scaledHgap = hgap;
394 int tmpX = 0;
395 List<Integer> lineWidths = new ArrayList<Integer>();
396 for (AbstractCard card : getCards(BorderLayout.CENTER)) {
397 if (((MCard) card).getMUI().isAutoAlign) {
398 if (tmpX + card.getWidth() + hgap + xw >= xe) {
399
400 lineWidths.add(tmpX);
401 tmpX = 0;
402
403 requiredHeight += maxHeightC + vgap;
404 maxHeightC = card.getHeight();
405 } else if (card.getHeight() > maxHeightC) {
406
407 maxHeightC = card.getHeight();
408 }
409 tmpX += card.getWidth() + hgap;
410 }
411 }
412 lineWidths.add(tmpX);
413
414 if (!lineWidths.isEmpty()) {
415 int yc = (ys - yn) / 2;
416 if (yn + requiredHeight > ys) {
417
418 yc = yn;
419 } else {
420 yc = (ys - yn - requiredHeight) / 2;
421 }
422 int lastLine = 0;
423 int lineWidth = lineWidths.get(0);
424 int xc = (xe - xw - lineWidth) / 2;
425 maxHeightC = 0;
426 for (AbstractCard card : getCards(BorderLayout.CENTER)) {
427 if (((MCard) card).getMUI().isAutoAlign) {
428 if (xc + card.getWidth() + hgap + xw >= xe) {
429 lineWidth = lineWidths.get(++lastLine);
430 xc = (xe - xw - lineWidth) / 2;
431 yc += maxHeightC + vgap;
432 maxHeightC = card.getHeight();
433 } else {
434 if (card.getHeight() > maxHeightC) {
435 maxHeightC = card.getHeight();
436 }
437 }
438 card.setLocation(xc, yc);
439 xc += card.getWidth() + hgap;
440 }
441 }
442 }
443 }
444 }
445
446 /***
447 * Returns a string representation of the state of this border layout.
448 *
449 * @return a string representation of this border layout.
450 */
451 @Override
452 public String toString() {
453 return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]";
454 }
455
456 }