001: /*
002: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
003: *
004: * "The contents of this file are subject to the Mozilla Public License
005: * Version 1.1 (the "License"); you may not use this file except in
006: * compliance with the License. You may obtain a copy of the License at
007: * http://www.mozilla.org/MPL/
008: *
009: * Software distributed under the License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
011: * License for the specific language governing rights and limitations under
012: * the License.
013: *
014: * The Original Code is ICEfaces 1.5 open source software code, released
015: * November 5, 2006. The Initial Developer of the Original Code is ICEsoft
016: * Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
017: * 2004-2006 ICEsoft Technologies Canada, Corp. All Rights Reserved.
018: *
019: * Contributor(s): _____________________.
020: *
021: * Alternatively, the contents of this file may be used under the terms of
022: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
023: * License), in which case the provisions of the LGPL License are
024: * applicable instead of those above. If you wish to allow use of your
025: * version of this file only under the terms of the LGPL License and not to
026: * allow others to use your version of this file under the MPL, indicate
027: * your decision by deleting the provisions above and replace them with
028: * the notice and other provisions required by the LGPL License. If you do
029: * not delete the provisions above, a recipient may use your version of
030: * this file under either the MPL or the LGPL License."
031: *
032: */
033:
034: package com.icesoft.faces.component.panelstack;
035:
036: import com.icesoft.faces.component.CSS_DEFAULT;
037: import com.icesoft.faces.component.ext.taglib.Util;
038:
039: import javax.faces.component.html.HtmlPanelGroup;
040: import javax.faces.component.UIComponent;
041: import javax.faces.context.FacesContext;
042: import javax.faces.el.ValueBinding;
043: import javax.faces.event.PhaseId;
044: import java.util.Iterator;
045:
046: /**
047: * Manage a stack of JSF components and allow for one child component to be
048: * choosen for rendering. The behaviour is similar to the CardLayout of Java
049: * Swing. Property <code>selectedPanel</code> defines the id of the child to be
050: * rendered. If no child panel is selected or if the selected panel can not be
051: * found the first child is rendered.
052: *
053: * @version beta 1.0
054: */
055: public class PanelStack extends HtmlPanelGroup {
056:
057: public static final String COMPONENT_TYPE = "com.icesoft.faces.PanelStack";
058: public static final String COMPONENT_FAMILY = "javax.faces.Panel";
059: private static final String DEFAULT_RENDERER_TYPE = "com.icesoft.faces.PanelStack";
060: private String style = null;
061: private String selectedPanel = null;
062: private String styleClass = null;
063: private String renderedOnUserRole = null;
064:
065: public PanelStack() {
066: setRendererType(DEFAULT_RENDERER_TYPE);
067: }
068:
069: /**
070: * <p>Return the value of the <code>COMPONENT_FAMILY</code> of this
071: * component.</p>
072: */
073: public String getFamily() {
074: return COMPONENT_FAMILY;
075: }
076:
077: /**
078: * <p>Set the value of the <code>style</code> property.</p>
079: */
080: public void setStyle(String style) {
081: this .style = style;
082: }
083:
084: /**
085: * <p>Return the value of the <code>style</code> property.</p>
086: */
087: public String getStyle() {
088: if (style != null) {
089: return style;
090: }
091: ValueBinding vb = getValueBinding("style");
092: return vb != null ? (String) vb.getValue(getFacesContext())
093: : null;
094: }
095:
096: /**
097: * <p>Set the value of the <code>selectedPanel</code> property.</p>
098: */
099: public void setSelectedPanel(String selectedPanel) {
100: this .selectedPanel = selectedPanel;
101: }
102:
103: /**
104: * <p>Return the value of the <code>selectedPanel</code> property.</p>
105: */
106: public String getSelectedPanel() {
107: if (selectedPanel != null) {
108: return selectedPanel;
109: }
110: ValueBinding vb = getValueBinding("selectedPanel");
111: return vb != null ? (String) vb.getValue(getFacesContext())
112: : null;
113: }
114:
115: /**
116: * <p>Return the value of the <code>rendered</code> property.</p>
117: */
118: public boolean isRendered() {
119: if (!Util.isRenderedOnUserRole(this )) {
120: return false;
121: }
122: return super .isRendered();
123: }
124:
125: /**
126: * <p>Set the value of the <code>styleClass</code> property.</p>
127: */
128: public void setStyleClass(String styleClass) {
129: this .styleClass = styleClass;
130: }
131:
132: /**
133: * <p>Return the value of the <code>styleClass</code> property.</p>
134: */
135: public String getStyleClass() {
136: return Util.getQualifiedStyleClass(this , styleClass,
137: CSS_DEFAULT.PANEL_STACK_BASE, "styleClass");
138: }
139:
140: /**
141: * <p>Set the value of the <code>renderedOnUserRole</code> property.</p>
142: */
143: public void setRenderedOnUserRole(String renderedOnUserRole) {
144: this .renderedOnUserRole = renderedOnUserRole;
145: }
146:
147: /**
148: * <p>Return the value of the <code>renderedOnUserRole</code> property.</p>
149: */
150: public String getRenderedOnUserRole() {
151: if (renderedOnUserRole != null) {
152: return renderedOnUserRole;
153: }
154: ValueBinding vb = getValueBinding("renderedOnUserRole");
155: return vb != null ? (String) vb.getValue(getFacesContext())
156: : null;
157: }
158:
159: /**
160: * <p>Return the value of the <code>rowClass</code> property.</p>
161: */
162: public String getRowClass() {
163: return Util.getQualifiedStyleClass(this ,
164: CSS_DEFAULT.PANEL_STACK_ROW);
165: }
166:
167: /**
168: * <p>Return the value of the <code>columnName</code> property.</p>
169: */
170: public String getColumnClass() {
171: return Util.getQualifiedStyleClass(this ,
172: CSS_DEFAULT.PANEL_STACK_COL);
173: }
174:
175: /**
176: * <p>Gets the state of the instance as a <code>Serializable</code>
177: * Object.</p>
178: */
179: public Object saveState(FacesContext context) {
180: Object values[] = new Object[4];
181: values[0] = super .saveState(context);
182: values[1] = selectedPanel;
183: values[2] = styleClass;
184: values[3] = style;
185: return ((Object) (values));
186: }
187:
188: /**
189: * <p>Perform any processing required to restore the state from the entries
190: * in the state Object.</p>
191: */
192: public void restoreState(FacesContext context, Object state) {
193: Object values[] = (Object[]) state;
194: super .restoreState(context, values[0]);
195: selectedPanel = (String) values[1];
196: styleClass = (String) values[2];
197: style = (String) values[3];
198: }
199:
200: public static final String LAST_SELECTED_PANEL = "PanelStack-lastPanel";
201:
202: /**
203: * @param context
204: * @param phaseId
205: */
206: public void applyPhase(FacesContext context, PhaseId phaseId) {
207: if (context == null) {
208: throw new NullPointerException(
209: "Null context in PanelTabSet");
210: }
211: Iterator it = getFacetsAndChildren();
212:
213: while (it.hasNext()) {
214: UIComponent childOrFacet = (UIComponent) it.next();
215: String selectedPanel = getSelectedPanel();
216: String lastSelectedPanel = (String) context
217: .getExternalContext().getRequestMap().get(
218: LAST_SELECTED_PANEL + getClientId(context));
219: boolean changed = !selectedPanel.equals(lastSelectedPanel);
220: if (lastSelectedPanel == null)
221: changed = false;
222: if (selectedPanel.equals(childOrFacet.getId())) {
223: if (!(changed && phaseId == PhaseId.APPLY_REQUEST_VALUES)) {
224: applyPhase(context, childOrFacet, phaseId);
225: }
226: }
227: }
228:
229: }
230:
231: /**
232: * @param context
233: * @param component
234: * @param phaseId
235: */
236: public void applyPhase(FacesContext context, UIComponent component,
237: PhaseId phaseId) {
238: if (phaseId == PhaseId.APPLY_REQUEST_VALUES) {
239: component.processDecodes(context);
240: } else if (phaseId == PhaseId.PROCESS_VALIDATIONS) {
241: component.processValidators(context);
242: } else if (phaseId == PhaseId.UPDATE_MODEL_VALUES) {
243: component.processUpdates(context);
244: } else {
245: throw new IllegalArgumentException();
246: }
247: }
248:
249: /* (non-Javadoc)
250: * @see javax.faces.component.UIComponent#processDecodes(javax.faces.context.FacesContext)
251: */
252: public void processDecodes(javax.faces.context.FacesContext context) {
253:
254: if (context == null) {
255: throw new NullPointerException("context");
256: }
257:
258: if (!isRendered()) {
259: return;
260: }
261:
262: decode(context);
263: applyPhase(context, PhaseId.APPLY_REQUEST_VALUES);
264: }
265:
266: /* (non-Javadoc)
267: * @see javax.faces.component.UIComponent#processValidators(javax.faces.context.FacesContext)
268: */
269: public void processValidators(FacesContext context) {
270:
271: if (context == null) {
272: throw new NullPointerException();
273: }
274: if (!isRendered()) {
275: return;
276: }
277: applyPhase(context, PhaseId.PROCESS_VALIDATIONS);
278: }
279:
280: /* (non-Javadoc)
281: * @see javax.faces.component.UIComponent#processUpdates(javax.faces.context.FacesContext)
282: */
283: public void processUpdates(FacesContext context) {
284:
285: if (context == null) {
286: throw new NullPointerException();
287: }
288: if (!isRendered()) {
289: return;
290: }
291: applyPhase(context, PhaseId.UPDATE_MODEL_VALUES);
292: }
293:
294: }
|