KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > user > client > ui > DockPanel


1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.user.client.ui;
17
18 import com.google.gwt.user.client.DOM;
19 import com.google.gwt.user.client.Element;
20
21 import java.util.ArrayList JavaDoc;
22 import java.util.Iterator JavaDoc;
23
24 /**
25  * A panel that lays its child widgets out "docked" at its outer edges, and
26  * allows its last widget to take up the remaining space in its center.
27  *
28  * <p>
29  * <img class='gallery' SRC='DockPanel.png'/>
30  * </p>
31  */

32 public class DockPanel extends CellPanel implements HasAlignment {
33
34   /**
35    * DockPanel layout constant, used in
36    * {@link DockPanel#add(Widget, DockPanel.DockLayoutConstant)}.
37    */

38   public static class DockLayoutConstant {
39     private DockLayoutConstant() {
40     }
41   }
42
43   /*
44    * This class is package-protected for use with DockPanelTest.
45    */

46   static class LayoutData {
47     public DockLayoutConstant direction;
48     public String JavaDoc hAlign = "left";
49     public String JavaDoc height = "";
50     public Element td;
51     public String JavaDoc vAlign = "top";
52     public String JavaDoc width = "";
53
54     public LayoutData(DockLayoutConstant dir) {
55       direction = dir;
56     }
57   }
58
59   private static class TmpRow {
60     public int center;
61     public Element tr;
62   }
63
64   /**
65    * Specifies that a widget be added at the center of the dock.
66    */

67   public static final DockLayoutConstant CENTER = new DockLayoutConstant();
68
69   /**
70    * Specifies that a widget be added at the east edge of the dock.
71    */

72   public static final DockLayoutConstant EAST = new DockLayoutConstant();
73
74   /**
75    * Specifies that a widget be added at the north edge of the dock.
76    */

77   public static final DockLayoutConstant NORTH = new DockLayoutConstant();
78
79   /**
80    * Specifies that a widget be added at the south edge of the dock.
81    */

82   public static final DockLayoutConstant SOUTH = new DockLayoutConstant();
83
84   /**
85    * Specifies that a widget be added at the west edge of the dock.
86    */

87   public static final DockLayoutConstant WEST = new DockLayoutConstant();
88
89   private HorizontalAlignmentConstant horzAlign = ALIGN_LEFT;
90   private VerticalAlignmentConstant vertAlign = ALIGN_TOP;
91   private Widget center;
92   private ArrayList JavaDoc children = new ArrayList JavaDoc();
93
94   /**
95    * Creates an empty dock panel.
96    */

97   public DockPanel() {
98     DOM.setElementPropertyInt(getTable(), "cellSpacing", 0);
99     DOM.setElementPropertyInt(getTable(), "cellPadding", 0);
100   }
101
102   /**
103    * Adds a widget to the specified edge of the dock. If the widget is already a
104    * child of this panel, this method behaves as though {@link #remove(Widget)}
105    * had already been called.
106    *
107    * @param widget the widget to be added
108    * @param direction the widget's direction in the dock
109    *
110    * @throws IllegalArgumentException when adding to the {@link #CENTER} and
111    * there is already a different widget there
112    */

113   public void add(Widget widget, DockLayoutConstant direction) {
114     if (widget.getParent() == this) {
115       remove(widget);
116     }
117
118     // Ensure that a second 'center' widget is not being added.
119
if (direction == CENTER) {
120       if (center != null) {
121         throw new IllegalArgumentException JavaDoc(
122             "Only one CENTER widget may be added");
123       }
124       center = widget;
125     }
126
127     LayoutData layout = new LayoutData(direction);
128     widget.setLayoutData(layout);
129     setCellHorizontalAlignment(widget, horzAlign);
130     setCellVerticalAlignment(widget, vertAlign);
131
132     // Store the child widget in the local child list, which is used by
133
// realizeTable().
134
children.add(widget);
135     realizeTable(widget);
136   }
137
138   public HorizontalAlignmentConstant getHorizontalAlignment() {
139     return horzAlign;
140   }
141
142   public VerticalAlignmentConstant getVerticalAlignment() {
143     return vertAlign;
144   }
145
146   /**
147    * Gets the layout direction of the given child widget.
148    *
149    * @param w the widget to be queried
150    * @return the widget's layout direction, or <code>null</code> if it is not
151    * a child of this panel
152    */

153   public DockLayoutConstant getWidgetDirection(Widget w) {
154     if (w.getParent() != this) {
155       return null;
156     }
157     return ((LayoutData) w.getLayoutData()).direction;
158   }
159
160   public boolean remove(Widget w) {
161     // Clear the center widget.
162
if (w == center) {
163       center = null;
164     }
165
166     boolean ret = super.remove(w);
167     if (ret) {
168       children.remove(w);
169       realizeTable(null);
170     }
171     return ret;
172   }
173
174   public void setCellHeight(Widget w, String JavaDoc height) {
175     LayoutData data = (LayoutData) w.getLayoutData();
176     data.height = height;
177     if (data.td != null) {
178       DOM.setStyleAttribute(data.td, "height", data.height);
179     }
180   }
181
182   public void setCellHorizontalAlignment(Widget w,
183       HorizontalAlignmentConstant align) {
184     LayoutData data = (LayoutData) w.getLayoutData();
185     data.hAlign = align.getTextAlignString();
186     if (data.td != null) {
187       DOM.setElementProperty(data.td, "align", data.hAlign);
188     }
189   }
190
191   public void setCellVerticalAlignment(Widget w, VerticalAlignmentConstant align) {
192     LayoutData data = (LayoutData) w.getLayoutData();
193     data.vAlign = align.getVerticalAlignString();
194     if (data.td != null) {
195       DOM.setStyleAttribute(data.td, "verticalAlign", data.vAlign);
196     }
197   }
198
199   public void setCellWidth(Widget w, String JavaDoc width) {
200     LayoutData data = (LayoutData) w.getLayoutData();
201     data.width = width;
202     if (data.td != null) {
203       DOM.setStyleAttribute(data.td, "width", data.width);
204     }
205   }
206
207   /**
208    * Sets the default horizontal alignment to be used for widgets added to this
209    * panel. It only applies to widgets added after this property is set.
210    *
211    * @see HasHorizontalAlignment#setHorizontalAlignment(HasHorizontalAlignment.HorizontalAlignmentConstant)
212    */

213   public void setHorizontalAlignment(HorizontalAlignmentConstant align) {
214     horzAlign = align;
215   }
216
217   /**
218    * Sets the default vertical alignment to be used for widgets added to this
219    * panel. It only applies to widgets added after this property is set.
220    *
221    * @see HasVerticalAlignment#setVerticalAlignment(HasVerticalAlignment.VerticalAlignmentConstant)
222    */

223   public void setVerticalAlignment(VerticalAlignmentConstant align) {
224     vertAlign = align;
225   }
226
227   /**
228    * Used by {@link #realizeTable(Widget)} to ensure that super.add() is called
229    * at the right time for newly added widgets.
230    *
231    * @param parent the parent element (always a TD)
232    * @param child the child element to be added
233    * @param beingAdded the widget that is currently being added to the
234    * DockPanel, if any
235    */

236   private void appendAndMaybeAdopt(Element parent, Element child,
237       Widget beingAdded) {
238     if (beingAdded != null) {
239       // If beingAdded is specified, and the child element is beingAdded's
240
// element, then call super.add() on its behalf.
241
if (DOM.compare(child, beingAdded.getElement())) {
242         super.add(beingAdded, parent);
243         return;
244       }
245     }
246
247     // Normal case -- just append it.
248
DOM.appendChild(parent, child);
249   }
250
251   /**
252    * Creates the table representing the DockPanel. This method uses the local
253    * list of children in {@link #children}, because when add() is called, the
254    * superclass' child list doesn't yet contain the new child.
255    *
256    * @param beingAdded if a widget is being added, it must be specified here.
257    * This allows the method to take care of calling super.add() on its
258    * behalf, at the right time.
259    */

260   private void realizeTable(Widget beingAdded) {
261     Element bodyElem = getBody();
262     while (DOM.getChildCount(bodyElem) > 0) {
263       DOM.removeChild(bodyElem, DOM.getChild(bodyElem, 0));
264     }
265
266     int rowCount = 1, colCount = 1;
267     for (Iterator JavaDoc it = children.iterator(); it.hasNext();) {
268       Widget child = (Widget) it.next();
269       DockLayoutConstant dir = ((LayoutData) child.getLayoutData()).direction;
270       if ((dir == NORTH) || (dir == SOUTH)) {
271         ++rowCount;
272       } else if ((dir == EAST) || (dir == WEST)) {
273         ++colCount;
274       }
275     }
276
277     TmpRow[] rows = new TmpRow[rowCount];
278     for (int i = 0; i < rowCount; ++i) {
279       rows[i] = new TmpRow();
280       rows[i].tr = DOM.createTR();
281       DOM.appendChild(bodyElem, rows[i].tr);
282     }
283
284     int westCol = 0, eastCol = colCount - 1;
285     int northRow = 0, southRow = rowCount - 1;
286     Element centerTd = null;
287
288     for (Iterator JavaDoc it = children.iterator(); it.hasNext();) {
289       Widget child = (Widget) it.next();
290       LayoutData layout = (LayoutData) child.getLayoutData();
291
292       Element td = DOM.createTD();
293       layout.td = td;
294       DOM.setElementProperty(layout.td, "align", layout.hAlign);
295       DOM.setStyleAttribute(layout.td, "verticalAlign", layout.vAlign);
296       DOM.setElementProperty(layout.td, "width", layout.width);
297       DOM.setElementProperty(layout.td, "height", layout.height);
298
299       if (layout.direction == NORTH) {
300         DOM.insertChild(rows[northRow].tr, td, rows[northRow].center);
301         appendAndMaybeAdopt(td, child.getElement(), beingAdded);
302         DOM.setElementPropertyInt(td, "colSpan", eastCol - westCol + 1);
303         ++northRow;
304       } else if (layout.direction == SOUTH) {
305         DOM.insertChild(rows[southRow].tr, td, rows[southRow].center);
306         appendAndMaybeAdopt(td, child.getElement(), beingAdded);
307         DOM.setElementPropertyInt(td, "colSpan", eastCol - westCol + 1);
308         --southRow;
309       } else if (layout.direction == WEST) {
310         TmpRow row = rows[northRow];
311         DOM.insertChild(row.tr, td, row.center++);
312         appendAndMaybeAdopt(td, child.getElement(), beingAdded);
313         DOM.setElementPropertyInt(td, "rowSpan", southRow - northRow + 1);
314         ++westCol;
315       } else if (layout.direction == EAST) {
316         TmpRow row = rows[northRow];
317         DOM.insertChild(row.tr, td, row.center);
318         appendAndMaybeAdopt(td, child.getElement(), beingAdded);
319         DOM.setElementPropertyInt(td, "rowSpan", southRow - northRow + 1);
320         --eastCol;
321       } else if (layout.direction == CENTER) {
322         // Defer adding the center widget, so that it can be added after all
323
// the others are complete.
324
centerTd = td;
325       }
326     }
327
328     // If there is a center widget, add it at the end (centerTd is guaranteed
329
// to be initialized because it will have been set in the CENTER case in
330
// the above loop).
331
if (center != null) {
332       TmpRow row = rows[northRow];
333       DOM.insertChild(row.tr, centerTd, row.center);
334       appendAndMaybeAdopt(centerTd, center.getElement(), beingAdded);
335     }
336   }
337 }
338
Popular Tags