1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.custom.navmenu.htmlnavmenu;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.myfaces.custom.navmenu.NavigationMenuUtils;
24 import org.apache.myfaces.custom.navmenu.UINavigationMenuItem;
25 import org.apache.myfaces.shared_tomahawk.el.SimpleActionMethodBinding;
26 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
27 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
28 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
29
30 import javax.faces.component.UIComponent;
31 import javax.faces.component.UIOutput;
32 import javax.faces.component.UIViewRoot;
33 import javax.faces.context.FacesContext;
34 import javax.faces.context.ResponseWriter;
35 import javax.faces.el.MethodBinding;
36 import javax.faces.el.ValueBinding;
37 import javax.faces.event.ActionEvent;
38 import java.io.IOException;
39 import java.util.Iterator;
40 import java.util.List;
41
42
43
44
45
46 class HtmlNavigationMenuRendererUtils {
47 private static final Log log = LogFactory.getLog(HtmlNavigationMenuRendererUtils.class);
48
49 private static final Class[] ACTION_LISTENER_ARGS = {ActionEvent.class};
50
51 private HtmlNavigationMenuRendererUtils() {
52 }
53
54 public static void renderChildrenListLayout(FacesContext facesContext,
55 ResponseWriter writer,
56 HtmlPanelNavigationMenu panelNav,
57 List children,
58 int level) throws IOException {
59 for (Iterator it = children.iterator(); it.hasNext();) {
60 UIComponent child = (UIComponent) it.next();
61 if (!child.isRendered()) continue;
62
63 if (child instanceof UINavigationMenuItem) {
64 renderChildrenListLayout(facesContext, writer, panelNav, child.getChildren(), level);
65 }
66 if (child instanceof HtmlCommandNavigationItem) {
67
68 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
69
70 HtmlCommandNavigationItem navItem = (HtmlCommandNavigationItem) child;
71
72 String externalLink = navItem.getExternalLink();
73
74 String style = HtmlNavigationMenuRendererUtils.getNavigationItemStyle(panelNav, navItem);
75 String styleClass = HtmlNavigationMenuRendererUtils.getNavigationItemClass(panelNav, navItem);
76
77 writer.startElement(HTML.LI_ELEM, panelNav);
78 HtmlNavigationMenuRendererUtils.writeStyleAttributes(writer, style, styleClass);
79
80 Object value = navItem.getValue();
81 boolean renderAsOutputLink = externalLink != null && value != null;
82
83 if (!renderAsOutputLink) {
84
85
86 if (externalLink == null) {
87 navItem.setValue(null);
88 navItem.encodeBegin(facesContext);
89 }
90 HtmlNavigationMenuRendererUtils.renderChildren(facesContext, navItem, panelNav);
91 if (externalLink == null) {
92 navItem.encodeEnd(facesContext);
93 navItem.setValue(value);
94 }
95 }
96 else {
97
98 renderChildren(facesContext, navItem, panelNav);
99 }
100
101 if (hasCommandNavigationItemChildren(navItem)) {
102 writer.startElement(HTML.UL_ELEM, panelNav);
103
104 if (panelNav.isRenderAll())
105 HtmlNavigationMenuRendererUtils.writeStyleAttributes(writer, navItem.getStyle(), navItem.getStyleClass());
106
107 HtmlRendererUtils.renderHTMLAttributes(writer, panelNav, HTML.UL_PASSTHROUGH_ATTRIBUTES);
108 renderChildrenListLayout(facesContext, writer, panelNav, child.getChildren(), level + 1);
109 writer.endElement(HTML.UL_ELEM);
110 }
111
112 writer.endElement(HTML.LI_ELEM);
113 }
114 }
115 }
116
117 private static boolean hasCommandNavigationItemChildren(HtmlCommandNavigationItem item) {
118 List children = item.getChildren();
119 for (int i = 0, sizei = children.size(); i < sizei; i++) {
120 if (children.get(i) instanceof HtmlCommandNavigationItem) {
121 return true;
122 }
123 }
124 return false;
125 }
126
127 public static void renderChildrenTableLayout(FacesContext facesContext,
128 ResponseWriter writer,
129 HtmlPanelNavigationMenu panelNav,
130 List children,
131 int level) throws IOException {
132 for (Iterator it = children.iterator(); it.hasNext();) {
133 UIComponent child = (UIComponent) it.next();
134 if (!child.isRendered()) continue;
135 if (child instanceof HtmlCommandNavigationItem) {
136
137 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
138
139 String style = getNavigationItemStyle(panelNav, (HtmlCommandNavigationItem) child);
140 String styleClass = getNavigationItemClass(panelNav, (HtmlCommandNavigationItem) child);
141
142 writer.startElement(HTML.TR_ELEM, panelNav);
143 writer.startElement(HTML.TD_ELEM, panelNav);
144 writeStyleAttributes(writer, style, styleClass);
145
146 if (style != null || styleClass != null) {
147 writer.startElement(HTML.SPAN_ELEM, panelNav);
148 writeStyleAttributes(writer, style, styleClass);
149 }
150 indent(writer, level);
151 child.encodeBegin(facesContext);
152
153 child.encodeEnd(facesContext);
154 if (style != null || styleClass != null) {
155 writer.endElement(HTML.SPAN_ELEM);
156 }
157
158 writer.endElement(HTML.TD_ELEM);
159 writer.endElement(HTML.TR_ELEM);
160
161 if (child.getChildCount() > 0) {
162 renderChildrenTableLayout(facesContext, writer, panelNav, child.getChildren(), level + 1);
163 }
164 }
165 else {
166
167 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
168
169 String style = panelNav.getSeparatorStyle();
170 String styleClass = panelNav.getSeparatorClass();
171
172 writer.startElement(HTML.TR_ELEM, panelNav);
173 writer.startElement(HTML.TD_ELEM, panelNav);
174 writeStyleAttributes(writer, style, styleClass);
175
176 if (style != null || styleClass != null) {
177 writer.startElement(HTML.SPAN_ELEM, panelNav);
178 writeStyleAttributes(writer, style, styleClass);
179 }
180 indent(writer, level);
181 RendererUtils.renderChild(facesContext, child);
182 if (style != null || styleClass != null) {
183 writer.endElement(HTML.SPAN_ELEM);
184 }
185
186 writer.endElement(HTML.TD_ELEM);
187 writer.endElement(HTML.TR_ELEM);
188 }
189 }
190 }
191
192 public static void indent(ResponseWriter writer, int level) throws IOException {
193 StringBuffer buf = new StringBuffer();
194 for (int i = 0; i < level; i++) {
195 buf.append("    ");
196 }
197 writer.write(buf.toString());
198 }
199
200 public static String getNavigationItemStyle(HtmlPanelNavigationMenu navPanel, HtmlCommandNavigationItem navItem) {
201 if (navItem.isActive()) {
202 return navPanel.getActiveItemStyle();
203 }
204 else if (navItem.isOpen()) {
205 return navPanel.getOpenItemStyle();
206 }
207 else {
208 return navPanel.getItemStyle();
209 }
210 }
211
212 public static String getNavigationItemClass(HtmlPanelNavigationMenu navPanel,
213 HtmlCommandNavigationItem navItem) {
214
215
216 if (navItem.getStyleClass() != null) {
217 return navItem.getStyleClass();
218 }
219 if (navItem.isActive()) {
220 return navPanel.getActiveItemClass();
221 }
222 else if (navItem.isOpen()) {
223 return navPanel.getOpenItemClass();
224 }
225 else {
226 return navPanel.getItemClass();
227 }
228 }
229
230 public static void writeStyleAttributes(ResponseWriter writer,
231 String style,
232 String styleClass) throws IOException {
233 HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_ATTR, HTML.STYLE_ATTR, style);
234 HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_CLASS_ATTR, HTML.STYLE_CLASS_ATTR, styleClass);
235 }
236
237 public static UIComponent getPanel(UIComponent link) {
238 UIComponent navPanel = link.getParent();
239 while (navPanel != null && !(navPanel instanceof HtmlPanelNavigationMenu)) {
240 navPanel = navPanel.getParent();
241 }
242 if (navPanel == null) {
243 throw new IllegalStateException("HtmlCommandNavigationItem not nested in HtmlPanelNavigation!?");
244 }
245 return navPanel;
246 }
247
248 public static boolean isListLayout(HtmlPanelNavigationMenu panelNav) {
249 return !"Table".equalsIgnoreCase(panelNav.getLayout());
250 }
251
252 public static void renderChildren(FacesContext facesContext, HtmlCommandNavigationItem component, HtmlPanelNavigationMenu parentPanelNav) throws IOException {
253 if (component.getChildCount() > 0) {
254
255 if (component.getExternalLink() != null) {
256 ResponseWriter writer = facesContext.getResponseWriter();
257
258 writer.startElement(HTML.ANCHOR_ELEM, null);
259 writer.writeAttribute(HTML.HREF_ATTR, component.getExternalLink(), null);
260 if (component.getTarget() != null)
261 writer.writeAttribute(HTML.TARGET_ATTR, component.getTarget(), null);
262
263
264
265 String style = HtmlNavigationMenuRendererUtils.getNavigationItemStyle(parentPanelNav, component);
266 String styleClass = HtmlNavigationMenuRendererUtils.getNavigationItemClass(parentPanelNav, component);
267 HtmlNavigationMenuRendererUtils.writeStyleAttributes(writer, style, styleClass);
268 }
269
270 for (Iterator it = component.getChildren().iterator(); it.hasNext();) {
271 UIComponent child = (UIComponent) it.next();
272 if (!(child instanceof HtmlCommandNavigationItem)) {
273 RendererUtils.renderChild(facesContext, child);
274 }
275 }
276
277
278 if (component.getExternalLink() != null) {
279 ResponseWriter writer = facesContext.getResponseWriter();
280 writer.endElement(HTML.ANCHOR_ELEM);
281 }
282 }
283 }
284
285 public static void debugTree(Log log, FacesContext facesContext, List children, int level) {
286 for (Iterator it = children.iterator(); it.hasNext();) {
287 UIComponent child = (UIComponent) it.next();
288 if (child instanceof UINavigationMenuItem) {
289 UINavigationMenuItem item = (UINavigationMenuItem) child;
290 StringBuffer buf = new StringBuffer();
291 for (int i = 0; i < level * 4; i++) buf.append(' ');
292 log.debug(buf.toString() + "--> " + item.getItemLabel() + " id:" + item.getClientId(facesContext));
293 debugTree(log, facesContext, child.getChildren(), level + 1);
294 }
295 else if (child instanceof HtmlCommandNavigationItem) {
296 HtmlCommandNavigationItem item = (HtmlCommandNavigationItem) child;
297 StringBuffer buf = new StringBuffer();
298 for (int i = 0; i < level * 4; i++) buf.append(' ');
299 String value;
300 if (item.getChildren().size() > 0 && item.getChildren().get(0) instanceof UIOutput) {
301 UIOutput uiOutput = (UIOutput) item.getChildren().get(0);
302 value = uiOutput.getValue() != null ? uiOutput.getValue().toString() : "?";
303 }
304 else {
305 value = item.getValue() != null ? item.getValue().toString() : "";
306 }
307 log.debug(buf.toString() + value + " id:" + item.getClientId(facesContext));
308 debugTree(log, facesContext, child.getChildren(), level + 1);
309 }
310 }
311 }
312
313 public static HtmlCommandNavigationItem findPreviousItem(UIViewRoot previousViewRoot, String clientId) {
314 HtmlCommandNavigationItem previousItem = null;
315 if (previousViewRoot != null) {
316 UIComponent previousComp = previousViewRoot.findComponent(clientId);
317 if (previousComp instanceof HtmlCommandNavigationItem) {
318 previousItem = (HtmlCommandNavigationItem) previousComp;
319 }
320 }
321 return previousItem;
322 }
323
324 public static MethodBinding getMethodBinding(FacesContext facesContext, String value, boolean actionListener) {
325 MethodBinding mb;
326 if (NavigationMenuUtils.isValueReference(value)) {
327 mb = facesContext.getApplication().createMethodBinding(value, actionListener ? ACTION_LISTENER_ARGS : null);
328 }
329 else {
330 if (actionListener) {
331 log.error("Invalid actionListener value " + value + " (has to be ValueReference!)");
332 mb = null;
333 }
334 else {
335 mb = new SimpleActionMethodBinding(value);
336 }
337 }
338 return mb;
339 }
340
341 public static void setAttributeValue(FacesContext facesContext, UIComponent comp, String attribute, String value) {
342 if (value == null)
343 return;
344 if (NavigationMenuUtils.isValueReference(value)) {
345 ValueBinding vb = facesContext.getApplication().createValueBinding(value);
346 comp.setValueBinding(attribute, vb);
347 }
348 else {
349 comp.getAttributes().put(attribute, value);
350 }
351 }
352
353 }