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