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 }