001: /**
002: * Copyright 2006-2007 Webmedia Group Ltd.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: **/package org.araneaframework.uilib.tab;
016:
017: import java.util.Collections;
018: import java.util.Comparator;
019: import java.util.Map;
020: import java.util.TreeMap;
021: import org.apache.commons.collections.map.LinkedMap;
022: import org.apache.commons.lang.ClassUtils;
023: import org.apache.commons.lang.StringUtils;
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026: import org.araneaframework.Component;
027: import org.araneaframework.Environment;
028: import org.araneaframework.InputData;
029: import org.araneaframework.Scope;
030: import org.araneaframework.Widget;
031: import org.araneaframework.core.Assert;
032: import org.araneaframework.core.BaseApplicationWidget;
033: import org.araneaframework.core.StandardEnvironment;
034: import org.araneaframework.core.StandardEventListener;
035: import org.araneaframework.core.WidgetFactory;
036:
037: /**
038: * This class represents a UI widget that contains tabs ({@link TabWidget})s.
039: * Only one tab can be selected (active) at a time, such tab is specified with {@link #selectTab(String)}.
040: * When on creation the selected tab is not specified, the first tab is marked as selected.
041: *
042: * Tabs are added with {@link #addTab(String, String, Widget)}, removed
043: * with {@link #removeTab(String)} and disabled (user cannot select them) with {@link #disableTab(String)}.
044: *
045: * By default tabs preserve the addition order and are also presented in that order. When this {@link TabContainerWidget}
046: * has a {@link Comparator} set, it will sort and present the tabs in an order specified by that {@link Comparator}.
047: *
048: * @author Taimo Peelo (taimo@araneaframework.org)
049: * @since 1.1
050: */
051: public class TabContainerWidget extends BaseApplicationWidget implements
052: TabContainerContext, TabRegistrationContext {
053: private static final Log log = LogFactory
054: .getLog(TabContainerWidget.class);
055:
056: public static final String TAB_SELECT_EVENT_ID = "activateTab";
057:
058: protected Map tabs;
059: protected TabWidget selected;
060:
061: /** This is just to make sure that we do not initialize ANY tabs after destroying process has already begun. */
062: protected transient boolean dying = false;
063:
064: protected Environment getChildWidgetEnvironment() throws Exception {
065: Map entries = new LinkedMap(2);
066: entries.put(TabContainerContext.class, this );
067: entries.put(TabRegistrationContext.class, this );
068: return new StandardEnvironment(super
069: .getChildWidgetEnvironment(), entries);
070: }
071:
072: protected void selectFirst() {
073: if (!tabs.isEmpty()) {
074: Map.Entry first = (Map.Entry) tabs.entrySet().iterator()
075: .next();
076: selectTab(first.getKey().toString());
077: }
078: }
079:
080: /* ********************************************
081: * TabContainerContext IMPL
082: **********************************************/
083: public TabContainerWidget() {
084: tabs = new LinkedMap();
085: }
086:
087: public TabContainerWidget(Comparator comparator) {
088: tabs = new TreeMap(comparator);
089: }
090:
091: public void addTab(String id, String labelId, Widget contentWidget) {
092: addWidget(id, new TabWidget(labelId, contentWidget));
093: }
094:
095: public void addTab(String id, String labelId,
096: WidgetFactory contentWidgetFactory) {
097: addWidget(id, new TabWidget(labelId, contentWidgetFactory));
098: }
099:
100: public void addTab(String id, Widget labelWidget,
101: Widget contentWidget) {
102: addWidget(id, new TabWidget(labelWidget, contentWidget));
103: }
104:
105: public void addTab(String id, Widget labelWidget,
106: WidgetFactory contentWidgetFactory) {
107: addWidget(id, new TabWidget(labelWidget, contentWidgetFactory));
108: }
109:
110: public boolean disableTab(String id) {
111: disableWidget(id);
112: return tabs.containsKey(id);
113: }
114:
115: public boolean enableTab(String id) {
116: enableWidget(id);
117: return tabs.containsKey(id);
118: }
119:
120: public boolean removeTab(String id) {
121: boolean result = tabs.containsKey(id);
122: removeWidget(id);
123: return result;
124: }
125:
126: public boolean selectTab(String id) {
127: if (selected != null) {
128: selected.deleselectTab();
129: }
130:
131: if (!StringUtils.isEmpty(id)) {
132: selected = (TabWidget) tabs.get(id);
133: selected.enableTab();
134: } else
135: selected = null;
136:
137: return selected != null;
138: }
139:
140: public boolean isTabSelected(String id) {
141: Assert.notNullParam(this , id, "id");
142: if (selected == null)
143: return false;
144:
145: return id.equals(selected.getScope().getId());
146: }
147:
148: public Widget getSelectedTab() {
149: return selected;
150: }
151:
152: public Map getTabs() {
153: return Collections.unmodifiableMap(tabs);
154: }
155:
156: /* ********************************************
157: * TabRegistrationContext IMPL
158: **********************************************/
159: /**
160: * @see org.araneaframework.uilib.tab.TabRegistrationContext#registerTab(org.araneaframework.uilib.tab.TabWidget)
161: */
162: public TabWidget registerTab(TabWidget tabWidget) {
163: boolean first = tabs.isEmpty();
164: TabWidget result = (TabWidget) tabs.put(tabWidget.getScope()
165: .getId().toString(), tabWidget);
166: if (first && !dying)
167: selectFirst();
168:
169: return result;
170: }
171:
172: /**
173: * @see org.araneaframework.uilib.tab.TabRegistrationContext#unregisterTab(org.araneaframework.uilib.tab.TabWidget)
174: */
175: public TabWidget unregisterTab(TabWidget tabWidget) {
176: TabWidget result = (TabWidget) tabs.remove(tabWidget.getScope()
177: .getId().toString());
178: if (result == selected) {
179: selected = null;
180: if (!dying)
181: selectFirst();
182: }
183:
184: return result;
185: }
186:
187: /****************************************************
188: * Tab selection listener.
189: ****************************************************/
190: protected class SelectionEventListener extends
191: StandardEventListener {
192: public void processEvent(Object eventId, String eventParam,
193: InputData input) throws Exception {
194: if (log.isTraceEnabled()) {
195: log.trace(ClassUtils
196: .getShortClassName(TabContainerWidget.class)
197: + " received tab selection event for tab '"
198: + eventParam + "'.");
199: }
200: selectTab(eventParam);
201: }
202: }
203:
204: /* ********************************************
205: * Overrides for disableWidget()/enableWidget()
206: **********************************************/
207: public void disableWidget(Object key) {
208: if (!tabs.containsKey(key)) {
209: super .disableWidget(key);
210: return;
211: }
212: TabWidget tabWidget = (TabWidget) tabs.get(key);
213: tabWidget.disableTab();
214: }
215:
216: public void enableWidget(Object key) {
217: if (!tabs.containsKey(key)) {
218: super .enableWidget(key);
219: return;
220: }
221:
222: TabWidget tabWidget = (TabWidget) tabs.get(key);
223: tabWidget.enableTab();
224: }
225:
226: /* ****************** COMPONENT LIFECYCLE METHODS ************************** */
227: public Component.Interface _getComponent() {
228: return new ComponentImpl();
229: }
230:
231: protected class ComponentImpl extends
232: BaseApplicationWidget.ComponentImpl {
233: public synchronized void init(Scope scope, Environment env) {
234: super .init(scope, env);
235: addEventListener(TAB_SELECT_EVENT_ID,
236: new SelectionEventListener());
237: }
238:
239: public void destroy() {
240: dying = true;
241: super.destroy();
242: }
243: }
244: }
|