001: package com.icesoft.faces.component.panelcollapsible;
002:
003: import java.util.Map;
004:
005: import javax.faces.application.FacesMessage;
006: import javax.faces.component.UICommand;
007: import javax.faces.context.FacesContext;
008: import javax.faces.el.ValueBinding;
009: import javax.faces.el.EvaluationException;
010: import javax.faces.event.ActionEvent;
011: import javax.faces.event.FacesEvent;
012:
013: import com.icesoft.faces.component.CSS_DEFAULT;
014: import com.icesoft.faces.component.ext.taglib.Util;
015:
016: public class PanelCollapsible extends UICommand {
017: public static final String COMPONENET_TYPE = "com.icesoft.faces.PanelCollapsible";
018: public static final String DEFAULT_RENDERER_TYPE = "com.icesoft.faces.PanelCollapsibleRenderer";
019: public static final String COMPONENT_FAMILY = "javax.faces.Command";
020: private String style;
021: private String styleClass;
022: private boolean disabled = false;
023: private boolean disabledSet = false;
024: private String enabledOnUserRole = null;
025: private String renderedOnUserRole = null;
026: private Boolean toggleOnClick = null;
027:
028: public String getFamily() {
029: return COMPONENT_FAMILY;
030: }
031:
032: public String getRendererType() {
033: return DEFAULT_RENDERER_TYPE;
034: }
035:
036: public void decode(FacesContext context) {
037: super .decode(context);
038: Map map = context.getExternalContext().getRequestParameterMap();
039: String clientId = getClientId(context) + "Expanded";
040: if (map.containsKey(clientId)
041: && !map.get(clientId).toString().equals("")) {
042: boolean exp = Boolean.valueOf(map.get(clientId).toString())
043: .booleanValue();
044: exp = !exp;
045: setExpanded(exp);
046: queueEvent(new ActionEvent(this ));
047: }
048: }
049:
050: public boolean isExpanded() {
051: ValueBinding vb = getValueBinding("expanded");
052: if (vb != null) {
053: if (vb.getValue(getFacesContext()) != null) {
054: return ((Boolean) vb.getValue(getFacesContext()))
055: .booleanValue();
056: }
057: }
058: Object value = getAttributes().get(getMatureClientId());
059: if (value != null) {
060: return ((Boolean) value).booleanValue();
061: }
062: return false;
063: }
064:
065: public void setToggleOnClick(boolean toggleOnClick) {
066: this .toggleOnClick = Boolean.valueOf(toggleOnClick);
067: }
068:
069: public boolean isToggleOnClick() {
070: if (toggleOnClick != null) {
071: return toggleOnClick.booleanValue();
072: }
073: ValueBinding vb = getValueBinding("toggleOnClick");
074: if (vb != null) {
075: return ((Boolean) vb.getValue(getFacesContext()))
076: .booleanValue();
077: }
078: return true;
079: }
080:
081: public void setExpanded(boolean expanded) {
082: //expanded is a core state of this component,
083: //so to make it work with any UIData type of component
084: //the state need to be put inside the map belongs to
085: //this component instance.
086:
087: getAttributes().put(getMatureClientId(),
088: Boolean.valueOf(expanded));
089: }
090:
091: public String getStyle() {
092: if (style != null) {
093: return style;
094: }
095: ValueBinding vb = getValueBinding("style");
096: if (vb != null) {
097: return (String) vb.getValue(getFacesContext());
098: }
099: return null;
100: }
101:
102: public void setStyle(String style) {
103: this .style = style;
104: }
105:
106: public String getStyleClass() {
107: return Util
108: .getQualifiedStyleClass(
109: this ,
110: getCollapsedStyle(styleClass),
111: getCollapsedStyle(CSS_DEFAULT.PANEL_COLLAPSIBLE_DEFAULT_STYLE_CLASS),
112: "styleClass", isDisabled());
113: }
114:
115: public String getHeaderClass() {
116: return Util.getQualifiedStyleClass(this ,
117: CSS_DEFAULT.PANEL_COLLAPSIBLE_HEADER, isDisabled());
118: }
119:
120: public String getContentClass() {
121: return Util.getQualifiedStyleClass(this ,
122: CSS_DEFAULT.PANEL_COLLAPSIBLE_CONTENT, isDisabled());
123: }
124:
125: private String getCollapsedStyle(String style) {
126: if (!isExpanded() && style != null) {
127: style += CSS_DEFAULT.PANEL_COLLAPSIBLE_STATE_COLLAPSED;
128: }
129: return style;
130: }
131:
132: public void setStyleClass(String styleClass) {
133: this .styleClass = styleClass;
134: }
135:
136: /**
137: * @param disabled
138: */
139: public void setDisabled(boolean disabled) {
140: this .disabled = disabled;
141: this .disabledSet = true;
142: }
143:
144: /**
145: * @return the value of disabled
146: */
147: public boolean isDisabled() {
148: if (!Util.isEnabledOnUserRole(this )) {
149: return true;
150: }
151: if (disabledSet) {
152: return disabled;
153: }
154: ValueBinding vb = getValueBinding("disabled");
155: Boolean v = vb != null ? (Boolean) vb
156: .getValue(getFacesContext()) : null;
157: return v != null ? v.booleanValue() : false;
158: }
159:
160: /**
161: * <p>Set the value of the <code>enabledOnUserRole</code> property.</p>
162: */
163: public void setEnabledOnUserRole(String enabledOnUserRole) {
164: this .enabledOnUserRole = enabledOnUserRole;
165: }
166:
167: /**
168: * <p>Return the value of the <code>enabledOnUserRole</code> property.</p>
169: */
170: public String getEnabledOnUserRole() {
171: if (enabledOnUserRole != null) {
172: return enabledOnUserRole;
173: }
174: ValueBinding vb = getValueBinding("enabledOnUserRole");
175: return vb != null ? (String) vb.getValue(getFacesContext())
176: : null;
177: }
178:
179: /**
180: * <p>Set the value of the <code>renderedOnUserRole</code> property.</p>
181: */
182: public void setRenderedOnUserRole(String renderedOnUserRole) {
183: this .renderedOnUserRole = renderedOnUserRole;
184: }
185:
186: /**
187: * <p>Return the value of the <code>renderedOnUserRole</code> property.</p>
188: */
189: public String getRenderedOnUserRole() {
190: if (renderedOnUserRole != null) {
191: return renderedOnUserRole;
192: }
193: ValueBinding vb = getValueBinding("renderedOnUserRole");
194: return vb != null ? (String) vb.getValue(getFacesContext())
195: : null;
196: }
197:
198: /**
199: * <p>Return the value of the <code>rendered</code> property.</p>
200: */
201: public boolean isRendered() {
202: if (!Util.isRenderedOnUserRole(this )) {
203: return false;
204: }
205: return super .isRendered();
206: }
207:
208: /* (non-Javadoc)
209: * @see javax.faces.component.UIComponent#processDecodes(javax.faces.context.FacesContext)
210: */
211: public void processDecodes(javax.faces.context.FacesContext context) {
212: if (isExpanded()) {
213: super .processDecodes(context);
214: }
215: decode(context);
216: }
217:
218: /* (non-Javadoc)
219: * @see javax.faces.component.UIComponent#processValidators(javax.faces.context.FacesContext)
220: */
221: public void processValidators(FacesContext context) {
222: if (isExpanded()) {
223: super .processValidators(context);
224: }
225: }
226:
227: /* (non-Javadoc)
228: * @see javax.faces.component.UIComponent#processUpdates(javax.faces.context.FacesContext)
229: */
230: public void processUpdates(FacesContext context) {
231: if (isExpanded()) {
232: super .processUpdates(context);
233: }
234: ValueBinding vb = getValueBinding("expanded");
235: //Let bean to know that the component's expanded state
236: //has been changed by the decode method.
237: if (vb != null) {
238: try {
239: vb.setValue(context, getAttributes().get(
240: getClientId(getFacesContext())));
241: return;
242: } catch (EvaluationException e) {
243: String messageStr = e.getMessage();
244: FacesMessage message = null;
245: if (null == messageStr) {
246: messageStr = "Conversion error";
247: } else {
248: message = new FacesMessage(messageStr);
249: }
250: message.setSeverity(FacesMessage.SEVERITY_ERROR);
251: context.addMessage(getClientId(context), message);
252: } catch (Exception e) {
253: String messageStr = e.getMessage();
254: FacesMessage message = null;
255: if (null == messageStr) {
256: messageStr = "Conversion error";
257: }
258: message = new FacesMessage(messageStr);
259: message.setSeverity(FacesMessage.SEVERITY_ERROR);
260: context.addMessage(getClientId(context), message);
261:
262: }
263: }
264: }
265:
266: public void queueEvent(FacesEvent e) {
267: // ICE-1956 UICommand subclasses shouldn't call super.queueEvent
268: // on ActionEvents or else the immediate flag is ignored
269: if ((e instanceof ActionEvent)
270: && !this .equals(e.getComponent())
271: && getParent() != null) {
272: getParent().queueEvent(e);
273: } else {
274: super .queueEvent(e);
275: }
276: }
277:
278: public Object saveState(FacesContext context) {
279: Object[] state = new Object[7];
280: state[0] = super .saveState(context);
281: state[1] = style;
282: state[2] = styleClass;
283: state[3] = Boolean.valueOf(disabled);
284: state[4] = enabledOnUserRole;
285: state[5] = renderedOnUserRole;
286: state[6] = toggleOnClick;
287:
288: return state;
289: }
290:
291: public void restoreState(FacesContext context, Object stateIn) {
292: Object[] state = (Object[]) stateIn;
293: super .restoreState(context, state[0]);
294: style = (String) state[1];
295: styleClass = (String) state[2];
296: disabled = ((Boolean) state[3]).booleanValue();
297: enabledOnUserRole = (String) state[4];
298: renderedOnUserRole = (String) state[5];
299: toggleOnClick = (Boolean) state[6];
300: }
301:
302: //At the time of the creation of the component both JSP and facelets
303: //returns incomplete client-id. So we want to keep the initial state of the
304: //component and later we want to replace it with the client-id so when this
305: //component is inside the dataTable it work for each row properly.
306: private String getMatureClientId() {
307: String clientId = getClientId(getFacesContext());
308: if (clientId != null && clientId.indexOf(':') >= 0) {
309: if (getAttributes().containsKey("expandedState")) {
310: getAttributes().put(clientId,
311: getAttributes().get("expandedState"));
312: getAttributes().remove("expandedState");
313: }
314: return clientId;
315: }
316: return "expandedState";
317: }
318: }
|