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