001: /*
002: * MyGWT Widget Library
003: * Copyright(c) 2007, MyGWT.
004: * licensing@mygwt.net
005: *
006: * http://mygwt.net/license
007: */
008: package net.mygwt.ui.client.widget;
009:
010: import net.mygwt.ui.client.Events;
011: import net.mygwt.ui.client.MyDOM;
012: import net.mygwt.ui.client.Style;
013: import net.mygwt.ui.client.widget.layout.StackLayout;
014:
015: import com.google.gwt.user.client.Command;
016: import com.google.gwt.user.client.DOM;
017: import com.google.gwt.user.client.DeferredCommand;
018: import com.google.gwt.user.client.Element;
019: import com.google.gwt.user.client.ui.HorizontalPanel;
020: import com.google.gwt.user.client.ui.WidgetHelper;
021:
022: /**
023: * Represents a tabbed set of pages, each of which contains another widget. Its
024: * child widgets are shown as the user selects the various tabs associated with
025: * them.
026: *
027: * <p>
028: * Important: This component MUST be sized in pixels to render properly. This
029: * can be done directly or by a layout. Percentage based sizes will not work.
030: * </p>
031: *
032: * <dl>
033: * <dt><b>Style:</b></dt>
034: * <dd>TOP</dd>
035: *
036: * <dt><b>Events:</b></dt>
037: *
038: * <dd><b>BeforeAdd</b> : (widget, item, index)<br>
039: * <div>Fires before a item is added or inserted. Listeners can set the
040: * <code>doit</code> field to <code>false</code> to cancel the action.</div>
041: * <ul>
042: * <li>widget : this</li>
043: * <li>item : the item being added</li>
044: * <li>index : the index at which the item will be added</li>
045: * </ul>
046: * </dd>
047: *
048: * <dd><b>BeforeRemove</b> : (widget, item)<br>
049: * <div>Fires before a item is removed. Listeners can set the <code>doit</code>
050: * field to <code>false</code> to cancel the action.</div>
051: * <ul>
052: * <li>widget : this</li>
053: * <li>item : the item being removed</li>
054: * </ul>
055: * </dd>
056: *
057: * <dd><b>Add</b> : (widget, item, index)<br>
058: * <div>Fires after a item has been added or inserted.</div>
059: * <ul>
060: * <li>widget : this</li>
061: * <li>item : the item that was added</li>
062: * <li>index : the index at which the item will be added</li>
063: * </ul>
064: * </dd>
065: *
066: * <dd><b>Remove</b> : (widget, item)<br>
067: * <div>Fires after a item has been removed.</div>
068: * <ul>
069: * <li>widget : this</li>
070: * <li>item : the item being removed</li>
071: * </ul>
072: * </dd>
073: *
074: * <dd><b>SelectionChange</b> : (widget, item)<br>
075: * <div>Fires after a item is selected.</div>
076: * <ul>
077: * <li>widget : this</li>
078: * <li>item : the item that is selected</li>
079: * </ul>
080: * </dd>
081: *
082: * <dd><b>Close</b> : (widget, item)<br>
083: * <div>Fires after a item is closed.</div>
084: * <ul>
085: * <li>widget : this</li>
086: * <li>item : the item that was closed</li>
087: * </ul>
088: * </dd>
089: *
090: * <dt><b>CSS:</b></dt>
091: * <dd>my-tabfolder (the tab folder)</dd>
092: * </dl>
093: *
094: * @see TabItem
095: */
096: public class TabFolder extends Container {
097:
098: boolean bottom;
099: private Element tabPanelWrapper;
100: private HorizontalPanel tabPanel;
101: private WidgetContainer stack;
102: private StackLayout stackLayout;
103: private TabItem selectedItem;
104: private TabItem attachItem;
105: private int defaultWidth = 100;
106:
107: /**
108: * Creates a new tab folder.
109: */
110: public TabFolder() {
111: this (Style.NONE);
112: }
113:
114: /**
115: * Creates a new tab folder.
116: *
117: * @param style the tab folder style.
118: */
119: public TabFolder(int style) {
120: this .style = style;
121: attachChildren = false;
122: }
123:
124: /**
125: * Adds a tab item.
126: *
127: * @param item the item to be added
128: */
129: public void add(TabItem item) {
130: insert(item, getWidgetCount());
131: }
132:
133: /**
134: * Returns the tab item's default width.
135: *
136: * @return the default width
137: */
138: public int getDefaultWidth() {
139: return defaultWidth;
140: }
141:
142: /**
143: * Returns the item at the specified index.
144: *
145: * @param index the index
146: * @return the item
147: */
148: public TabItem getItem(int index) {
149: return (TabItem) items.get(index);
150: }
151:
152: /**
153: * Returns the number of tab items's.
154: *
155: * @return the child count
156: */
157: public int getItemCount() {
158: return items.size();
159: }
160:
161: /**
162: * Returns the selected item.
163: *
164: * @return the selected item.
165: */
166: public TabItem getSelection() {
167: return selectedItem;
168: }
169:
170: /**
171: * Returns the tab folder's style information.
172: *
173: * @return the style bits
174: */
175: public int getStyle() {
176: return style;
177: }
178:
179: /**
180: * Returns the index of the item.
181: *
182: * @param item the item
183: * @return the index
184: */
185: public int indexOf(TabItem item) {
186: return items.indexOf(item);
187: }
188:
189: /**
190: * Inserts a tab item.
191: *
192: * @param item the item to be inserted
193: * @param index the insert postion
194: */
195: public void insert(TabItem item, int index) {
196: if (fireEvent(Events.BeforeAdd, this , item, index)) {
197: item.tabFolder = this ;
198: items.add(index, item);
199: if (rendered) {
200: renderItem(item, index);
201: }
202: fireEvent(Events.Add, this , item, index);
203: }
204: }
205:
206: /**
207: * Returns <code>true</code> if the item is selected.
208: *
209: * @param item the item
210: * @return the selected state
211: */
212: public boolean isSelected(TabItem item) {
213: return selectedItem == item;
214: }
215:
216: public void recalculate() {
217: if (isRendered()) {
218: int h = getOffsetHeight();
219: int w = getOffsetWidth();
220: h -= MyDOM.getBorderWidth(getElement(), Style.LEFT
221: | Style.RIGHT);
222: w -= MyDOM.getBorderWidth(getElement(), Style.TOP
223: | Style.BOTTOM);
224: MyDOM.setWidth(tabPanelWrapper, w, true);
225: h -= tabPanel.getOffsetHeight();
226: stack.setSize(w, h);
227: if (selectedItem != null) {
228: selectedItem.getContainer().layout(true);
229: }
230: }
231: }
232:
233: /**
234: * Removes the tab item.
235: *
236: * @param item the item to be removed
237: */
238: public void remove(TabItem item) {
239: if (fireEvent(Events.BeforeRemove, this , item)) {
240: if (rendered) {
241: tabPanel.remove(item);
242: stack.remove(item.getContainer());
243: }
244:
245: items.remove(item);
246: if (getAutoDispose()) {
247: item.dispose();
248: item.getContainer().dispose();
249: }
250: if (item == selectedItem) {
251: selectedItem = null;
252: if (getItemCount() > 0) {
253: setSelection(getItem(0));
254: }
255: }
256: fireEvent(Events.Remove, this , item);
257: }
258: }
259:
260: /**
261: * Removes all items.
262: */
263: public void removeAll() {
264: int size = getItemCount();
265: for (int i = 0; i < size; i++) {
266: TabItem item = getItem(0);
267: remove(item);
268: }
269: }
270:
271: /**
272: * Specifies the default width for tab items. Default value is 100.
273: *
274: * @param defaultWidth the default width
275: */
276: public void setDefaultWidth(int defaultWidth) {
277: this .defaultWidth = defaultWidth;
278: }
279:
280: /**
281: * Sets the selected tab item.
282: *
283: * @param item the item to be selected
284: */
285: public void setSelection(TabItem item) {
286: if (!isAttached()) {
287: attachItem = item;
288: return;
289: }
290:
291: if (selectedItem != item) {
292: if (selectedItem != null) {
293: selectedItem.setSelected(false);
294: // selectedItem.setEnabled(false);
295: }
296: selectedItem = item;
297: if (item != null) {
298: item.setSelected(true);
299: // item.setEnabled(true);
300: stackLayout.setTopWidget(item.getContainer());
301:
302: DeferredCommand.addCommand(new Command() {
303: public void execute() {
304: stackLayout.layout(stack);
305: }
306: });
307: }
308: fireEvent(Events.SelectionChange, this , selectedItem);
309: }
310: }
311:
312: /**
313: * Sets the tab folder's style. Has no effect if called after the tab folder
314: * has been rendered.
315: *
316: * @param style the style
317: */
318: public void setStyle(int style) {
319: if (!isRendered()) {
320: this .style = style;
321: }
322: }
323:
324: /**
325: * Sets the width for all tab item's.
326: *
327: * @param width the width
328: */
329: public void setTabWidth(int width) {
330: defaultWidth = width;
331: for (int i = 0; i < getWidgetCount(); i++) {
332: TabItem item = getItem(i);
333: MyDOM.setWidth(item.getElement(), width);
334: }
335: }
336:
337: protected void doAttachChildren() {
338: super .doAttachChildren();
339: WidgetHelper.doAttach(tabPanel);
340: WidgetHelper.doAttach(stack);
341: }
342:
343: protected void doDetachChildren() {
344: super .doDetachChildren();
345: WidgetHelper.doDetach(tabPanel);
346: WidgetHelper.doDetach(stack);
347: }
348:
349: protected void onClose(TabItem item) {
350: item.fireEvent(Events.Close);
351: fireEvent(Events.Close, this , item);
352:
353: remove(item);
354:
355: if (item == selectedItem) {
356: setSelection(getItem(0));
357: }
358: }
359:
360: protected void onLoad() {
361: super .onLoad();
362: if (attachItem != null) {
363: setSelection(attachItem);
364: attachItem = null;
365: }
366: }
367:
368: protected void onRender() {
369: setElement(DOM.createDiv());
370: setStyleName("my-tabfolder");
371:
372: tabPanelWrapper = DOM.createDiv();
373: MyDOM.setStyleName(tabPanelWrapper, "my-tabfolder-header");
374:
375: tabPanel = new HorizontalPanel();
376:
377: stack = new WidgetContainer();
378: stack.setStyleAttribute("position", "static");
379: stackLayout = new StackLayout();
380: stack.setLayout(stackLayout);
381:
382: if ((style & Style.BOTTOM) != 0) {
383: bottom = true;
384: // wrapper.add(stack);
385: // wrapper.add(tabWrapper);
386: } else {
387: DOM.appendChild(tabPanelWrapper, tabPanel.getElement());
388: DOM.appendChild(getElement(), tabPanelWrapper);
389: DOM.appendChild(getElement(), stack.getElement());
390: }
391:
392: renderAll();
393: }
394:
395: protected void onResize(int width, int height) {
396: super .onResize(width, height);
397: int h = height;
398: int w = width;
399: h -= MyDOM.getBorderWidth(getElement(), Style.LEFT
400: | Style.RIGHT);
401: w -= MyDOM.getBorderWidth(getElement(), Style.TOP
402: | Style.BOTTOM);
403: MyDOM.setWidth(tabPanelWrapper, w, true);
404: h -= tabPanel.getOffsetHeight();
405: stack.setSize(w, h);
406: if (selectedItem != null) {
407: selectedItem.getContainer().layout(true);
408: }
409: }
410:
411: private void renderAll() {
412: int count = getWidgetCount();
413: for (int i = 0; i < count; i++) {
414: TabItem item = getItem(i);
415: renderItem(item, i);
416: if (i == 0 && attachItem == null) {
417: attachItem = item;
418: }
419: }
420: }
421:
422: private void renderItem(TabItem item, int index) {
423: item.setWidth(defaultWidth + "px");
424: tabPanel.insert(item, index);
425: stack.insert(item.getContainer(), index);
426: }
427:
428: }
|