View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.custom.collapsiblepanel;
20  
21  import java.io.IOException;
22  import java.util.Iterator;
23  
24  import javax.faces.component.UIComponent;
25  import javax.faces.component.UIInput;
26  import javax.faces.component.behavior.ClientBehaviorHolder;
27  import javax.faces.context.FacesContext;
28  import javax.faces.el.MethodBinding;
29  
30  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
31  import org.apache.myfaces.component.EventAware;
32  import org.apache.myfaces.component.StyleAware;
33  import org.apache.myfaces.component.UniversalProperties;
34  import org.apache.myfaces.component.UserRoleAware;
35  
36  /**
37   * A component which just renders as a single icon (with optional label) when "collapsed", hiding all child components. 
38   * 
39   * When open, the child components can be seen.
40   * 
41   * The title attribute defines the label shown for the collapsible panel.
42   * 
43   * @JSFComponent
44   *   name = "t:collapsiblePanel"
45   *   class = "org.apache.myfaces.custom.collapsiblepanel.HtmlCollapsiblePanel"  
46   *   tagClass = "org.apache.myfaces.custom.collapsiblepanel.HtmlCollapsiblePanelTag"
47   * 
48   * @JSFJspProperty name = "converter" tagExcluded = "true"
49   * @since 1.1.7 
50   * @author Kalle Korhonen (latest modification by $Author: lu4242 $)
51   * @version $Revision: 691856 $ $Date: 2008-09-03 21:40:30 -0500 (miƩ, 03 sep 2008) $
52   *
53   */
54  public abstract class AbstractHtmlCollapsiblePanel extends UIInput
55       implements StyleAware, UniversalProperties, EventAware,
56       UserRoleAware, ClientBehaviorHolder
57  {
58      public static final String COMPONENT_TYPE = "org.apache.myfaces.HtmlCollapsiblePanel";
59      public static final String COMPONENT_FAMILY = "javax.faces.Panel";
60      private static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.CollapsiblePanel";
61          
62      private static final String HEADER_FACET_NAME = "header";
63      
64      private static final String CLOSED_CONTENT_FACET_NAME = "closedContent";
65          
66      private boolean _currentlyCollapsed;
67      
68      public void setCurrentlyCollapsed(boolean collapsed)
69      {
70          _currentlyCollapsed = collapsed;
71      }
72  
73      public boolean isCurrentlyCollapsed()
74      {
75          return _currentlyCollapsed;
76      }
77      
78      public void setHeader(UIComponent header)
79      {
80          getFacets().put(HEADER_FACET_NAME, header);
81      }
82  
83      /**
84       * @JSFFacet
85       */
86      public UIComponent getHeader()
87      {
88          return (UIComponent) getFacets().get(HEADER_FACET_NAME);
89      }
90      
91      public void setClosedContent(UIComponent closedContent)
92      {
93          getFacets().put(CLOSED_CONTENT_FACET_NAME, closedContent);
94      }
95  
96      /**
97       * @JSFFacet
98       */
99      public UIComponent getClosedContent()
100     {
101         return (UIComponent) getFacets().get(CLOSED_CONTENT_FACET_NAME);
102     }
103     
104     //private static final Log log = LogFactory.getLog(HtmlCollapsiblePanel.class);
105 
106     public void processDecodes(FacesContext context)
107     {
108         if (context == null) throw new NullPointerException("context");
109 
110         initialiseVars(context);
111 
112         if (!isRendered()) return;
113 
114         try
115         {
116             decode(context);
117         }
118         catch (RuntimeException e)
119         {
120             context.renderResponse();
121             throw e;
122         }
123 
124         UIComponent headerComponent = getFacet("header");
125 
126         if(headerComponent != null)
127         {
128             for (Iterator it = headerComponent.getChildren().iterator(); it.hasNext(); )
129             {
130                 UIComponent child = (UIComponent)it.next();
131 
132                 child.processDecodes(context);
133             }
134         }
135 
136         if(isCurrentlyCollapsed())
137         {
138             UIComponent component = getFacet("closedContent");
139 
140             if(component != null)
141             {
142                 component.processDecodes(context);
143             }
144         }
145         else
146         {
147             for (Iterator it = getChildren().iterator(); it.hasNext(); )
148             {
149                 UIComponent child = (UIComponent)it.next();
150                 child.processDecodes(context);
151             }
152         }
153         
154         removeVars(context);
155     }
156 
157     public String getClientId(FacesContext context)
158     {
159         return super.getClientId(context);
160     }
161 
162     public void processUpdates(FacesContext context)
163     {
164         initialiseVars(context);
165 
166         super.processUpdates(context);
167 
168         removeVars(context);
169     }
170 
171     private void initialiseVars(FacesContext context)
172     {
173         if(getVar()!=null)
174         {
175             context.getExternalContext().getRequestMap().put(getVar(),
176                             Boolean.valueOf(isCollapsed()));
177         }
178 
179         if(getTitleVar()!=null)
180         {
181             context.getExternalContext().getRequestMap().put(getTitleVar(),
182                             getTitle());
183         }
184     }
185 
186     private void removeVars(FacesContext context)
187     {
188         if(getVar()!=null)
189         {
190             context.getExternalContext().getRequestMap().remove(getVar());
191         }
192 
193         if(getTitleVar()!=null)
194         {
195             context.getExternalContext().getRequestMap().remove(getTitleVar());
196         }
197     }
198 
199     public void processValidators(FacesContext context)
200     {
201         initialiseVars(context);
202 
203         super.processValidators(context);
204 
205         removeVars(context);
206     }
207 
208     public void encodeChildren(FacesContext context) throws IOException
209     {
210         initialiseVars(context);
211 
212         super.encodeChildren(context);
213 
214         removeVars(context);
215     }
216 
217     public void updateModel(FacesContext context)
218     {
219         super.updateModel(context);
220     }
221 
222     public boolean isCollapsed()
223     {
224         return isCollapsed(getValue());
225     }
226 
227     public static boolean isCollapsed(Object collapsedValue)
228     {
229         Object value = collapsedValue;
230 
231         if(value instanceof Boolean)
232         {
233             return ((Boolean) value).booleanValue();
234         }
235         else if (value instanceof String)
236         {
237             return Boolean.valueOf((String) value).booleanValue();
238         }
239 
240         return true;
241     }
242 
243     /**
244      * The variable which you can use to check for the collapsed 
245      * state of the enclosing component. This is especially useful 
246      * for custom headers you define in a facet with name 'header'.
247      * 
248      * @JSFProperty
249      */
250     public abstract String getVar();
251 
252     /**
253      * This variable is defined to hold the value of the title 
254      * component - you can use it for accessing this value in 
255      * custom headers you define in a facet with name 'header'.
256      * 
257      * @JSFProperty
258      */    
259     public abstract String getTitleVar();
260     
261     /**
262      * @JSFProperty tagExcluded = "true"
263      */
264     public MethodBinding getValidator(){
265         return super.getValidator();
266     }
267     
268     /**
269      * @JSFProperty tagExcluded = "true"
270      */
271     public MethodBinding getValueChangeListener()
272     {
273         return super.getValueChangeListener();
274     }
275     
276     /**
277      * @JSFProperty tagExcluded = "true"
278      */
279     public boolean isImmediate()
280     {
281         return super.isImmediate();
282     }
283     
284     /**
285      * @JSFProperty tagExcluded = "true"
286      */
287     public boolean isRequired()
288     {
289         return super.isRequired();
290     }
291     
292     /**
293      * The CSS class for this element.  Corresponds to the HTML 'class' attribute for the generated indicator span.
294      * This attribute is ignored if a custom "header" facet is provided
295      * for the collapsible panel 
296      * 
297      * @return
298      */
299     @JSFProperty
300     public abstract String getIndicatorStyleClass();
301     
302     /**
303      * HTML: CSS styling instructions for the generated indicator. 
304      * This attribute is ignored if a custom "header" facet is provided
305      * for the collapsible panel 
306      * 
307      * @return
308      */
309     @JSFProperty
310     public abstract String getIndicatorStyle(); 
311     
312     /**
313      * The CSS class for this element.  Corresponds to the HTML 'class' attribute for the generated title.
314      * This attribute is ignored if a custom "header" facet is provided
315      * for the collapsible panel 
316      * 
317      * @return
318      */
319     @JSFProperty
320     public abstract String getTitleStyleClass();
321     
322     /**
323      * HTML: CSS styling instructions for the generated title. 
324      * This attribute is ignored if a custom "header" facet is provided
325      * for the collapsible panel 
326      * 
327      * @return
328      */
329     @JSFProperty
330     public abstract String getTitleStyle(); 
331 }