1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.custom.tabbedpane;
20
21 import java.util.Iterator;
22 import java.util.List;
23
24 import javax.faces.component.PartialStateHolder;
25 import javax.faces.component.StateHolder;
26 import javax.faces.component.UIComponent;
27 import javax.faces.component.UIForm;
28 import javax.faces.component.UINamingContainer;
29 import javax.faces.component.behavior.ClientBehaviorHolder;
30 import javax.faces.component.html.HtmlPanelGroup;
31 import javax.faces.context.FacesContext;
32 import javax.faces.el.EvaluationException;
33 import javax.faces.el.MethodBinding;
34 import javax.faces.event.AbortProcessingException;
35 import javax.faces.event.FacesEvent;
36 import javax.faces.event.PhaseId;
37
38 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
39 import org.apache.myfaces.component.AlignProperty;
40 import org.apache.myfaces.component.AttachedDeltaWrapper;
41 import org.apache.myfaces.component.DataProperties;
42 import org.apache.myfaces.component.EventAware;
43 import org.apache.myfaces.component.PanelProperties;
44 import org.apache.myfaces.component.UniversalProperties;
45 import org.apache.myfaces.component.UserRoleAware;
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 public abstract class AbstractHtmlPanelTabbedPane
62 extends HtmlPanelGroup
63 implements UniversalProperties, EventAware, PanelProperties,
64 AlignProperty, DataProperties, UserRoleAware, ClientBehaviorHolder
65
66 {
67
68
69 public static final String COMPONENT_TYPE = "org.apache.myfaces.HtmlPanelTabbedPane";
70 public static final String COMPONENT_FAMILY = "javax.faces.Panel";
71 private static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.TabbedPane";
72 private static final int DEFAULT_SELECTEDINDEX = 0;
73 private static final boolean DEFAULT_SERVER_SIDE_TAB_SWITCH = false;
74
75 private MethodBinding _tabChangeListener = null;
76 private static final int DEFAULT_BORDER = Integer.MIN_VALUE;
77
78 public void decode(FacesContext context)
79 {
80 super.decode(context);
81 }
82
83 public void processDecodes(javax.faces.context.FacesContext context)
84 {
85 if (context == null) throw new NullPointerException("context");
86 decode(context);
87
88 int tabIdx = 0;
89 int selectedIndex = getSelectedIndex();
90
91 Iterator it = getFacetsAndChildren();
92
93 while (it.hasNext())
94 {
95 UIComponent childOrFacet = getUIComponent((UIComponent) it.next());
96 if (childOrFacet instanceof HtmlPanelTab) {
97 if (isClientSide() || selectedIndex == tabIdx) {
98 childOrFacet.processDecodes(context);
99 }
100 tabIdx++;
101 } else {
102 childOrFacet.processDecodes(context);
103 }
104 }
105 }
106
107 public void processValidators(FacesContext context)
108 {
109 if (context == null) throw new NullPointerException("context");
110 if (!isRendered()) return;
111
112 int tabIdx = 0;
113 int selectedIndex = getSelectedIndex();
114
115 Iterator it = getFacetsAndChildren();
116
117 while (it.hasNext())
118 {
119 UIComponent childOrFacet = getUIComponent((UIComponent) it.next());
120 if (childOrFacet instanceof HtmlPanelTab) {
121 if (isClientSide() || selectedIndex == tabIdx) {
122 childOrFacet.processValidators(context);
123 }
124 tabIdx++;
125 } else {
126 childOrFacet.processValidators(context);
127 }
128 }
129 }
130
131 public void processUpdates(FacesContext context)
132 {
133 if (context == null) throw new NullPointerException("context");
134 if (!isRendered()) return;
135
136 int tabIdx = 0;
137 int selectedIndex = getSelectedIndex();
138
139 Iterator it = getFacetsAndChildren();
140
141 while (it.hasNext())
142 {
143 UIComponent childOrFacet = getUIComponent((UIComponent) it.next());
144 if (childOrFacet instanceof HtmlPanelTab) {
145 if (isClientSide() || selectedIndex == tabIdx) {
146 childOrFacet.processUpdates(context);
147 }
148 tabIdx++;
149 } else {
150 childOrFacet.processUpdates(context);
151 }
152 }
153 }
154
155 private UIComponent getUIComponent(UIComponent uiComponent)
156 {
157
158 if (uiComponent instanceof UINamingContainer || uiComponent instanceof UIForm)
159 {
160 List children = uiComponent.getChildren();
161 for (int i = 0, len = children.size(); i < len; i++)
162 {
163 uiComponent = getUIComponent((UIComponent)children.get(i));
164 }
165 }
166 return uiComponent;
167 }
168
169 public void addTabChangeListener(TabChangeListener listener)
170 {
171 addFacesListener(listener);
172 }
173
174 public void removeTabChangeListener(TabChangeListener listener)
175 {
176 removeFacesListener(listener);
177 }
178
179
180
181
182
183
184
185
186
187
188
189
190 public MethodBinding getTabChangeListener()
191 {
192 return _tabChangeListener;
193 }
194
195 private boolean _isSetTabChangeListener()
196 {
197 Boolean value = (Boolean) getStateHelper().get(PropertyKeys.tabChangeListenerSet);
198 return value == null ? false : value;
199 }
200
201 public void setTabChangeListener(MethodBinding tabChangeListener)
202 {
203 _tabChangeListener = tabChangeListener;
204 }
205
206 public Object saveState(FacesContext facesContext)
207 {
208 if (initialStateMarked())
209 {
210 boolean nullDelta = true;
211 Object parentSaved = super.saveState(facesContext);
212 Object tabChangeListenerSaved = null;
213 if (!_isSetTabChangeListener() &&
214 _tabChangeListener != null && _tabChangeListener instanceof PartialStateHolder)
215 {
216
217 StateHolder holder = (StateHolder) _tabChangeListener;
218 if (!holder.isTransient())
219 {
220 Object attachedState = holder.saveState(facesContext);
221 if (attachedState != null)
222 {
223 nullDelta = false;
224 }
225 tabChangeListenerSaved = new AttachedDeltaWrapper(_tabChangeListener.getClass(),
226 attachedState);
227 }
228 }
229 else if (_isSetTabChangeListener() || _tabChangeListener != null)
230 {
231
232 tabChangeListenerSaved = saveAttachedState(facesContext,_tabChangeListener);
233 nullDelta = false;
234 }
235 if (parentSaved == null && nullDelta)
236 {
237
238 return null;
239 }
240
241 Object[] values = new Object[2];
242 values[0] = parentSaved;
243 values[1] = tabChangeListenerSaved;
244 return values;
245 }
246 else
247 {
248 Object[] values = new Object[2];
249 values[0] = super.saveState(facesContext);
250 values[1] = saveAttachedState(facesContext,_tabChangeListener);
251 return values;
252 }
253 }
254
255 public void restoreState(FacesContext facesContext, Object state)
256 {
257 if (state == null)
258 {
259 return;
260 }
261
262 Object[] values = (Object[])state;
263 super.restoreState(facesContext,values[0]);
264 if (values[1] instanceof AttachedDeltaWrapper)
265 {
266
267 ((StateHolder)_tabChangeListener).restoreState(facesContext, ((AttachedDeltaWrapper) values[1]).getWrappedStateObject());
268 }
269 else
270 {
271
272 _tabChangeListener = (javax.faces.el.MethodBinding) restoreAttachedState(facesContext,values[1]);
273 }
274 }
275
276 public void broadcast(FacesEvent event) throws AbortProcessingException
277 {
278 if (event instanceof TabChangeEvent)
279 {
280 TabChangeEvent tabChangeEvent = (TabChangeEvent)event;
281 if (tabChangeEvent.getComponent() == this)
282 {
283 setSelectedIndex(tabChangeEvent.getNewTabIndex());
284 getFacesContext().renderResponse();
285 }
286 }
287 super.broadcast(event);
288
289 MethodBinding tabChangeListenerBinding = getTabChangeListener();
290 if (tabChangeListenerBinding != null)
291 {
292 try
293 {
294 tabChangeListenerBinding.invoke(getFacesContext(), new Object[]{event});
295 }
296 catch (EvaluationException e)
297 {
298 Throwable cause = e.getCause();
299 if (cause != null && cause instanceof AbortProcessingException)
300 {
301 throw (AbortProcessingException)cause;
302 }
303 else
304 {
305 throw e;
306 }
307 }
308 }
309 }
310
311
312
313
314
315 public boolean isClientSide()
316 {
317 return !isServerSideTabSwitch();
318 }
319
320
321
322
323 @JSFProperty(
324 tagExcluded = true)
325 public abstract String getActiveTabVar();
326
327
328
329
330
331
332
333 @JSFProperty
334 public abstract Boolean getActivePanelTabVar();
335
336
337
338
339
340 @JSFProperty(
341 defaultValue = "0")
342 public abstract int getSelectedIndex();
343
344 public abstract void setSelectedIndex(int selectedIndex);
345
346
347
348
349
350 @JSFProperty
351 public abstract String getActiveTabStyleClass();
352
353
354
355
356
357 @JSFProperty
358 public abstract String getInactiveTabStyleClass();
359
360
361
362
363
364 @JSFProperty
365 public abstract String getActiveSubStyleClass();
366
367
368
369
370
371 @JSFProperty
372 public abstract String getInactiveSubStyleClass();
373
374
375
376
377
378 @JSFProperty
379 public abstract String getTabContentStyleClass();
380
381
382
383
384
385 @JSFProperty
386 public abstract String getDisabledTabStyleClass();
387
388
389
390
391
392 @JSFProperty(
393 defaultValue = "false")
394 public abstract boolean isServerSideTabSwitch();
395
396 public boolean getServerSideTabSwitch()
397 {
398 return isServerSideTabSwitch();
399 }
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415 @JSFProperty(
416 defaultValue = "true")
417 public abstract boolean isImmediateTabChange();
418
419 public void queueEvent(FacesEvent event)
420 {
421 if (event != null && event instanceof TabChangeEvent)
422 {
423 if (isImmediateTabChange())
424 {
425 event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
426 }
427 else
428 {
429 event.setPhaseId(PhaseId.INVOKE_APPLICATION);
430 }
431 }
432 super.queueEvent(event);
433 }
434
435 enum PropertyKeys
436 {
437 tabChangeListenerSet
438 }
439 }