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.navmenu.htmlnavmenu;
20  
21  import java.io.IOException;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import javax.faces.component.NamingContainer;
26  import javax.faces.component.UIComponent;
27  import javax.faces.component.UIViewRoot;
28  import javax.faces.context.FacesContext;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.myfaces.component.AlignProperty;
33  import org.apache.myfaces.component.DataProperties;
34  import org.apache.myfaces.component.EventAware;
35  import org.apache.myfaces.component.PanelProperties;
36  import org.apache.myfaces.component.UniversalProperties;
37  import org.apache.myfaces.component.html.ext.HtmlPanelGroup;
38  
39  /**
40   * Renders a vertical menu structure with support for nested menu items. 
41   * 
42   * The menu is rendered as unordered List. The menu-tree can be 
43   * dynamically build using NavigationMenuItem(s). 
44   * 
45   * Unless otherwise specified, all attributes accept static values or EL expressions.
46   * 
47   * Many thanks to the guys from Swiss Federal Institute of Intellectual Property and Marc Bouquet
48   * for helping to develop this component.
49   * 
50   * @JSFComponent
51   *   name = "t:panelNavigation2"
52   *   class = "org.apache.myfaces.custom.navmenu.htmlnavmenu.HtmlPanelNavigationMenu"
53   *   tagClass = "org.apache.myfaces.custom.navmenu.htmlnavmenu.HtmlPanelNavigationMenuTag"
54   * @since 1.1.7
55   * @author Manfred Geiler
56   * @author Thomas Spiegl
57   */
58  public abstract class AbstractHtmlPanelNavigationMenu extends HtmlPanelGroup 
59      implements NamingContainer, UniversalProperties, EventAware, 
60      PanelProperties, AlignProperty, DataProperties
61  {
62      private static final Log log = LogFactory.getLog(AbstractHtmlPanelNavigationMenu.class);
63  
64      public static final String COMPONENT_TYPE = "org.apache.myfaces.HtmlPanelNavigationMenu";
65      public static final String COMPONENT_FAMILY = "javax.faces.Panel";
66      private static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.NavigationMenu";
67      
68      static final String PREVIOUS_VIEW_ROOT = AbstractHtmlPanelNavigationMenu.class.getName() + ".PREVIOUS_VIEW_ROOT";
69      private static final int DEFAULT_BORDER = Integer.MIN_VALUE;
70  
71      private boolean _itemOpenActiveStatesRestored = false;
72  
73      public void decode(FacesContext context)
74      {
75          super.decode(context);    //To change body of overridden methods use File | Settings | File Templates.
76  
77          //Save the current view root for later reference...
78          context.getExternalContext().getRequestMap().put(PREVIOUS_VIEW_ROOT, context.getViewRoot());
79          //...and remember that this instance needs NO special treatment on rendering:
80          _itemOpenActiveStatesRestored = true;
81      }
82  
83      public void encodeBegin(FacesContext context) throws IOException
84      {
85          if (!_itemOpenActiveStatesRestored && getChildCount() > 0)
86          {
87              UIViewRoot previousRoot = (UIViewRoot)context.getExternalContext().getRequestMap().get(PREVIOUS_VIEW_ROOT);
88              if (previousRoot != null)
89              {
90                  if(previousRoot.findComponent(getClientId(context)) instanceof AbstractHtmlPanelNavigationMenu)
91                  {
92                      restoreOpenActiveStates(context, previousRoot, getChildren());
93                  }
94              }
95              else
96              {
97                  //no previous root, means no decode was done
98                  //--> a new request
99              }
100         }
101 
102         super.encodeBegin(context);    //To change body of overridden methods use File | Settings | File Templates.
103     }
104 
105     public void restoreOpenActiveStates(FacesContext facesContext,
106                                         UIViewRoot previousRoot,
107                                         List children)
108     {
109         for (Iterator it = children.iterator(); it.hasNext(); )
110         {
111             UIComponent child = (UIComponent)it.next();
112             UIComponent prevItem = (UIComponent)previousRoot.findComponent(child.getClientId(facesContext));
113             
114             if (prevItem instanceof HtmlCommandNavigationItem &&
115                     child instanceof HtmlCommandNavigationItem)
116             {
117                 HtmlCommandNavigationItem previousItem = (HtmlCommandNavigationItem)prevItem;
118                 if (previousItem != null)
119                 {
120                     ((HtmlCommandNavigationItem)child).setOpen(previousItem.isOpen());
121                     ((HtmlCommandNavigationItem)child).setActive(previousItem.isActive());
122                 }
123                 else
124                 {
125                     log.debug("Navigation item " + child.getClientId(facesContext) + " not found in previous view.");
126                 }
127                 if (child.getChildCount() > 0)
128                 {
129                     restoreOpenActiveStates(facesContext, previousRoot, child.getChildren());
130                 }
131             }
132         }
133     }
134     
135     /**
136      * The CSS class of closed navigation items.
137      * 
138      * @JSFProperty
139      */
140     public abstract String getItemClass();
141 
142     /**
143      * The CSS class of open navigation items.
144      * 
145      * @JSFProperty
146      */
147     public abstract String getOpenItemClass();
148 
149     /**
150      * The CSS class of open navigation items.
151      * 
152      * @JSFProperty
153      */
154     public abstract String getActiveItemClass();
155 
156     /**
157      * The CSS class for the td element of a separator.
158      * 
159      * @JSFProperty
160      */
161     public abstract String getSeparatorClass();
162 
163     /**
164      * The CSS Style of closed navigation items.
165      * 
166      * @JSFProperty
167      */
168     public abstract String getItemStyle();
169 
170     /**
171      * The CSS Style of open navigation items.
172      * 
173      * @JSFProperty
174      */
175     public abstract String getOpenItemStyle();
176 
177     /**
178      * The CSS Style of the active navigation item.
179      * 
180      * @JSFProperty
181      */
182     public abstract String getActiveItemStyle();
183 
184     /**
185      * The CSS Style for the td element of a separator.
186      * 
187      * @JSFProperty
188      */
189     public abstract String getSeparatorStyle();
190     
191     /**
192      * 'table' or 'list' Layout (default is 'table')
193      * 
194      * @JSFProperty
195      */
196     public abstract String getLayout();
197 
198     /**
199      * @JSFProperty
200      *   tagExcluded="true"
201      *   literalOnly = "true"
202      *   defaultValue = "false"
203      */
204     public abstract Boolean getPreprocessed();
205 
206     /**
207      * If set to true all Items are expanded from the beginning and never closed.
208      * 
209      * @JSFProperty
210      *   defaultValue="false"
211      */
212     public abstract boolean isExpandAll();
213     
214     /**
215      *  If set to true all Items are rendered and other methods, like 
216      *  CSS should be used to hide them as necessary
217      * 
218      * @JSFProperty
219      *   defaultValue="false"
220      */
221     public abstract boolean isRenderAll();
222 
223     /**
224      * When set instead of a Hyperlink a span tag is rendered in the corresponding Component
225      * 
226      * @JSFProperty
227      *   defaultValue="false"
228      */
229     public abstract boolean isDisabled();
230 
231     /**
232      * CSS-Style Attribute to render when disabled is true
233      * 
234      * @JSFProperty
235      */
236     public abstract String getDisabledStyle();
237 
238     /**
239      * CSS-Style Class to use when disabled is true
240      * 
241      * @JSFProperty
242      */
243     public abstract String getDisabledStyleClass();
244 
245 }