KickJava   Java API By Example, From Geeks To Geeks.

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


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 import com.google.gwt.user.client.Event;
21
22 /**
23  * A panel that stacks its children vertically, displaying only one at a time,
24  * with a header for each child which the user can click to display.
25  * <p>
26  * <img class='gallery' SRC='StackPanel.png'/>
27  * </p>
28  * <h3>CSS Style Rules</h3>
29  * <ul class='css'>
30  * <li>.gwt-StackPanel { the panel itself }</li>
31  * <li>.gwt-StackPanel .gwt-StackPanelItem { unselected items }</li>
32  * <li>.gwt-StackPanel .gwt-StackPanelItem-selected { selected items }</li>
33  * </ul>
34  * <p>
35  * <h3>Example</h3>
36  * {@example com.google.gwt.examples.StackPanelExample}
37  * </p>
38  */

39 public class StackPanel extends ComplexPanel {
40
41   private Element body;
42   private int visibleStack = -1;
43
44   /**
45    * Creates an empty stack panel.
46    */

47   public StackPanel() {
48     Element table = DOM.createTable();
49     setElement(table);
50
51     body = DOM.createTBody();
52     DOM.appendChild(table, body);
53     DOM.setElementPropertyInt(table, "cellSpacing", 0);
54     DOM.setElementPropertyInt(table, "cellPadding", 0);
55
56     DOM.sinkEvents(table, Event.ONCLICK);
57     setStyleName("gwt-StackPanel");
58   }
59
60   /**
61    * Adds a new child with the given widget.
62    *
63    * @param w the widget to be added
64    */

65   public void add(Widget w) {
66     insert(w, getWidgetCount());
67   }
68
69   /**
70    * Adds a new child with the given widget and header.
71    *
72    * @param w the widget to be added
73    * @param stackText the header text associated with this widget
74    */

75   public void add(Widget w, String JavaDoc stackText) {
76     add(w, stackText, false);
77   }
78
79   /**
80    * Adds a new child with the given widget and header, optionally interpreting
81    * the header as HTML.
82    *
83    * @param w the widget to be added
84    * @param stackText the header text associated with this widget
85    * @param asHTML <code>true</code> to treat the specified text as HTML
86    */

87   public void add(Widget w, String JavaDoc stackText, boolean asHTML) {
88     add(w);
89     setStackText(getWidgetCount() - 1, stackText, asHTML);
90   }
91
92   /**
93    * Gets the currently selected child index.
94    *
95    * @return selected child
96    */

97   public int getSelectedIndex() {
98     return visibleStack;
99   }
100
101   /**
102    * Inserts a widget before the specified index.
103    *
104    * @param w the widget to be inserted
105    * @param beforeIndex the index before which it will be inserted
106    * @throws IndexOutOfBoundsException if <code>beforeIndex</code> is out of
107    * range
108    */

109   public void insert(Widget w, int beforeIndex) {
110     // header
111
Element trh = DOM.createTR();
112     Element tdh = DOM.createTD();
113     DOM.appendChild(trh, tdh);
114
115     // body
116
Element trb = DOM.createTR();
117     Element tdb = DOM.createTD();
118     DOM.appendChild(trb, tdb);
119
120     beforeIndex = super.insert(w, tdb, beforeIndex);
121     // DOM indices are 2x logical indices; 2 dom elements per stack item
122
int effectiveIndex = beforeIndex * 2;
123     // this ordering puts the body below the header
124
DOM.insertChild(body, trb, effectiveIndex);
125     DOM.insertChild(body, trh, effectiveIndex);
126
127     // header styling
128
setStyleName(tdh, "gwt-StackPanelItem", true);
129     DOM.setElementPropertyInt(tdh, "__owner", hashCode());
130     DOM.setElementProperty(tdh, "height", "1px");
131
132     // body styling
133
DOM.setElementProperty(tdb, "height", "100%");
134     DOM.setElementProperty(tdb, "vAlign", "top");
135
136     // Update indices of all elements to the right.
137
updateIndicesFrom(beforeIndex);
138
139     // Correct visible stack for new location.
140
if (visibleStack == -1) {
141       showStack(0);
142     } else {
143       setStackVisible(beforeIndex, false);
144       if (visibleStack >= beforeIndex) {
145         ++visibleStack;
146       }
147     }
148   }
149
150   public void onBrowserEvent(Event event) {
151     if (DOM.eventGetType(event) == Event.ONCLICK) {
152       Element target = DOM.eventGetTarget(event);
153       int index = findDividerIndex(target);
154       if (index != -1) {
155         showStack(index);
156       }
157     }
158   }
159
160   public boolean remove(int index) {
161     return remove(getWidget(index), index);
162   }
163
164   public boolean remove(Widget child) {
165     return remove(child, getWidgetIndex(child));
166   }
167
168   /**
169    * Sets the text associated with a child by its index.
170    *
171    * @param index the index of the child whose text is to be set
172    * @param text the text to be associated with it
173    */

174   public void setStackText(int index, String JavaDoc text) {
175     setStackText(index, text, false);
176   }
177
178   /**
179    * Sets the text associated with a child by its index.
180    *
181    * @param index the index of the child whose text is to be set
182    * @param text the text to be associated with it
183    * @param asHTML <code>true</code> to treat the specified text as HTML
184    */

185   public void setStackText(int index, String JavaDoc text, boolean asHTML) {
186     if (index >= getWidgetCount()) {
187       return;
188     }
189
190     Element td = DOM.getChild(DOM.getChild(body, index * 2), 0);
191     if (asHTML) {
192       DOM.setInnerHTML(td, text);
193     } else {
194       DOM.setInnerText(td, text);
195     }
196   }
197
198   /**
199    * Shows the widget at the specified child index.
200    *
201    * @param index the index of the child to be shown
202    */

203   public void showStack(int index) {
204     if ((index >= getWidgetCount()) || (index == visibleStack)) {
205       return;
206     }
207
208     if (visibleStack >= 0) {
209       setStackVisible(visibleStack, false);
210     }
211
212     visibleStack = index;
213     setStackVisible(visibleStack, true);
214   }
215
216   private int findDividerIndex(Element elem) {
217     while ((elem != null) && !DOM.compare(elem, getElement())) {
218       String JavaDoc expando = DOM.getElementProperty(elem, "__index");
219       if (expando != null) {
220         // Make sure it belongs to me!
221
int ownerHash = DOM.getElementPropertyInt(elem, "__owner");
222         if (ownerHash == hashCode()) {
223           // Yes, it's mine.
224
return Integer.parseInt(expando);
225         } else {
226           // It must belong to some nested StackPanel.
227
return -1;
228         }
229       }
230       elem = DOM.getParent(elem);
231     }
232     return -1;
233   }
234
235   private boolean remove(Widget child, int index) {
236     // TODO: is this check really necessary?
237
if (child.getParent() != this) {
238       return false;
239     }
240
241     // Correct visible stack for new location.
242
if (visibleStack == index) {
243       visibleStack = -1;
244     } else if (visibleStack > index) {
245       --visibleStack;
246     }
247
248     // Calculate which internal table elements to remove.
249
int rowIndex = 2 * index;
250     Element tr = DOM.getChild(body, rowIndex);
251     DOM.removeChild(body, tr);
252     tr = DOM.getChild(body, rowIndex);
253     DOM.removeChild(body, tr);
254     super.remove(child);
255
256     // Update indices of all elements to the right.
257
updateIndicesFrom(rowIndex);
258
259     return true;
260   }
261
262   private void setStackVisible(int index, boolean visible) {
263     // Get the first table row containing the widget's selector item.
264
Element tr = DOM.getChild(body, (index * 2));
265     if (tr == null) {
266       return;
267     }
268
269     // Style the stack selector item.
270
Element td = DOM.getFirstChild(tr);
271     setStyleName(td, "gwt-StackPanelItem-selected", visible);
272
273     // Show/hide the contained widget.
274
tr = DOM.getChild(body, (index * 2) + 1);
275     UIObject.setVisible(tr, visible);
276     getWidget(index).setVisible(visible);
277   }
278
279   private void updateIndicesFrom(int beforeIndex) {
280     for (int i = beforeIndex, c = getWidgetCount(); i < c; ++i) {
281       Element childTR = DOM.getChild(body, i * 2);
282       Element childTD = DOM.getFirstChild(childTR);
283       DOM.setElementPropertyInt(childTD, "__index", i);
284     }
285   }
286
287 }
288
Popular Tags