001: /* Tab.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Tue Jul 12 10:43:18 2005, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2005 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zul;
020:
021: import java.util.Set;
022: import java.util.Iterator;
023:
024: import org.zkoss.zk.ui.Component;
025: import org.zkoss.zk.ui.UiException;
026: import org.zkoss.zk.ui.event.Events;
027: import org.zkoss.zk.ui.ext.client.Selectable;
028:
029: import org.zkoss.zul.impl.LabelImageElement;
030:
031: /**
032: * A tab.
033: *
034: * @author tomyeh
035: */
036: public class Tab extends LabelImageElement {
037: private boolean _selected;
038: /** Whether to show a close button. */
039: private boolean _closable;
040:
041: private boolean _disabled;
042:
043: public Tab() {
044: }
045:
046: public Tab(String label) {
047: setLabel(label);
048: }
049:
050: public Tab(String label, String image) {
051: setLabel(label);
052: setImage(image);
053: }
054:
055: /** Returns whether this tab is closable.
056: * If closable, a button is displayed and the onClose event is sent
057: * if an user clicks the button.
058: * <p>Default: false.
059: */
060: public boolean isClosable() {
061: return _closable;
062: }
063:
064: /** Sets whether this tab is closable.
065: * If closable, a button is displayed and the onClose event is sent
066: * if an user clicks the button.
067: * <p>Default: false.
068: * <p>You can intercept the default behavior by either overriding
069: * {@link #onClose}, or listening the onClose event.
070: */
071: public void setClosable(boolean closable) {
072: if (_closable != closable) {
073: _closable = closable;
074: invalidate(); //re-init is required
075: }
076: }
077:
078: /** Process the onClose event sent when the close button is pressed.
079: * <p>Default: detach itself and the corresponding {@link Tabpanel}.
080: */
081: public void onClose() {
082: if (_selected) {
083: final Tabs tabs = (Tabs) getParent();
084: if (tabs != null) {
085: for (Iterator it = tabs.getChildren().iterator(); it
086: .hasNext();) {
087: final Tab t = (Tab) it.next();
088: if (t != this ) {
089: t.setSelected(true);
090: break;
091: }
092: }
093: }
094: }
095:
096: final Tabpanel panel = getLinkedPanel();
097: if (panel != null)
098: panel.detach();
099: detach();
100: }
101:
102: /** Returns the tabbox owns this component.
103: */
104: public Tabbox getTabbox() {
105: final Tabs tabs = (Tabs) getParent();
106: return tabs != null ? tabs.getTabbox() : null;
107: }
108:
109: /** Returns the panel associated with this tab.
110: */
111: public Tabpanel getLinkedPanel() {
112: final int j = getIndex();
113: if (j >= 0) {
114: final Tabbox tabbox = getTabbox();
115: if (tabbox != null) {
116: final Tabpanels tabpanels = tabbox.getTabpanels();
117: if (tabpanels != null
118: && tabpanels.getChildren().size() > j)
119: return (Tabpanel) tabpanels.getChildren().get(j);
120: }
121: }
122: return null;
123: }
124:
125: /** Returns whether this tab is selected.
126: */
127: public final boolean isSelected() {
128: return _selected;
129: }
130:
131: /** Sets whether this tab is selected.
132: */
133: public void setSelected(boolean selected) {
134: if (_selected != selected) {
135: final Tabbox tabbox = (Tabbox) getTabbox();
136: if (tabbox != null) {
137: //Note: we don't update it here but let its parent does the job
138: tabbox.setSelectedTab(this );
139: } else {
140: _selected = selected;
141: invalidate();
142: }
143: }
144: }
145:
146: /** Returns whether this tab is disabled.
147: * <p>Default: false.
148: * @since 3.0.0
149: */
150: public final boolean isDisabled() {
151: return _disabled;
152: }
153:
154: /** Sets whether this tab is disabled. If a tab is disabled,
155: * then it cann't be selected or closed by user,
156: * but it still can be controlled by server side program.
157: * @since 3.0.0
158: */
159: public void setDisabled(boolean disabled) {
160: if (_disabled != disabled) {
161: _disabled = disabled;
162: smartUpdate("z.disabled", _disabled);
163: }
164: }
165:
166: /** Updates _selected directly without updating the client.
167: */
168: /*package*/void setSelectedDirectly(boolean selected) {
169: _selected = selected;
170: }
171:
172: /** Returns the index of this panel, or -1 if it doesn't belong to any
173: * tabs.
174: */
175: public int getIndex() {
176: final Tabs tabs = (Tabs) getParent();
177: if (tabs == null)
178: return -1;
179: int j = 0;
180: for (Iterator it = tabs.getChildren().iterator();; ++j)
181: if (it.next() == this )
182: return j;
183: }
184:
185: //-- super --//
186: public String getOuterAttrs() {
187: final StringBuffer sb = new StringBuffer(64).append(super
188: .getOuterAttrs());
189: appendAsapAttr(sb, Events.ON_SELECT);
190:
191: final String clkattrs = getAllOnClickAttrs(false);
192: if (clkattrs != null)
193: sb.append(clkattrs);
194: return sb.toString();
195: }
196:
197: /** Returns the style class.
198: * Note:
199: * 1) if not specified (or setSclass(null))<br/>
200: * 1.1) if not disabled ,"tab" is assumed; <br/>
201: * 1.2) if disabled ,"tabdis" is assumed; <br/>
202: * 2) if selected, it appends "sel" to step 1. <br/>
203: */
204: public String getSclass() {
205: String scls = super .getSclass();
206: if (scls == null)
207: scls = "tab";
208: if (isDisabled())
209: scls = scls + "dis";
210: return isSelected() ? scls + "sel" : scls;
211: }
212:
213: //-- Component --//
214: public void invalidate() {
215: final Tabbox tabbox = getTabbox();
216: if (tabbox != null && "accordion".equals(tabbox.getMold()))
217: tabbox.invalidate();
218: else
219: super .invalidate();
220: }
221:
222: /** No child is allowed.
223: */
224: public boolean isChildable() {
225: return false;
226: }
227:
228: public void setParent(Component parent) {
229: if (parent != null && !(parent instanceof Tabs))
230: throw new UiException("Wrong parent: " + parent);
231: super .setParent(parent);
232: }
233:
234: //-- ComponentCtrl --//
235: protected Object newExtraCtrl() {
236: return new ExtraCtrl();
237: }
238:
239: /** A utility class to implement {@link #getExtraCtrl}.
240: * It is used only by component developers.
241: */
242: protected class ExtraCtrl extends LabelImageElement.ExtraCtrl
243: implements Selectable {
244: //-- Selectable --//
245: public void selectItemsByClient(Set selItems) {
246: if (selItems == null || selItems.size() != 1)
247: throw new UiException(
248: "Exactly one selected tab is required: "
249: + selItems); //debug purpose
250:
251: final Tabbox tabbox = getTabbox();
252: if (tabbox != null)
253: tabbox.selectTabDirectly((Tab) selItems.iterator()
254: .next(), true);
255: }
256: }
257: }
|