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.navigation;
20  
21  import java.io.IOException;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Map;
25  
26  import javax.faces.component.UIComponent;
27  import javax.faces.component.behavior.ClientBehavior;
28  import javax.faces.context.FacesContext;
29  import javax.faces.context.ResponseWriter;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.myfaces.renderkit.html.ext.HtmlLinkRenderer;
34  import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
35  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
36  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
37  import org.apache.myfaces.shared_tomahawk.renderkit.html.util.ResourceUtils;
38  
39  /**
40   * @JSFRenderer
41   *   renderKitId = "HTML_BASIC" 
42   *   family = "javax.faces.Panel"
43   *   type = "org.apache.myfaces.Navigation"
44   *   
45   * @JSFRenderer
46   *   renderKitId = "HTML_BASIC" 
47   *   family = "javax.faces.Command"
48   *   type = "org.apache.myfaces.Navigation"
49   * 
50   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
51   * @version $Revision: 659874 $ $Date: 2008-05-24 15:59:15 -0500 (sáb, 24 may 2008) $
52   */
53  public class HtmlNavigationRenderer
54          extends HtmlLinkRenderer
55  {
56      private static final Log log = LogFactory.getLog(HtmlNavigationRenderer.class);
57  
58      private static final Integer ZERO_INTEGER = new Integer(0);
59  
60      public boolean getRendersChildren()
61      {
62          return true;
63      }
64  
65      public void decode(FacesContext facesContext, UIComponent component)
66      {
67          if (component instanceof HtmlCommandNavigation)
68          {
69              //HtmlCommandNavigation
70              super.decode(facesContext, component);
71          }
72      }
73  
74      public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException
75      {
76          if (component instanceof HtmlCommandNavigation)
77          {
78              //HtmlCommandNavigation
79              super.encodeBegin(facesContext, component);
80          }
81      }
82  
83      public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException
84      {
85          if (component instanceof HtmlCommandNavigation)
86          {
87              //HtmlCommandNavigation
88              super.encodeChildren(facesContext, component);
89          }
90      }
91  
92      public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException
93      {
94          if (component instanceof HtmlCommandNavigation)
95          {
96              //HtmlCommandNavigation
97              super.encodeEnd(facesContext, component);
98              return;
99          }
100 
101         RendererUtils.checkParamValidity(facesContext, component, HtmlPanelNavigation.class);
102         ResponseWriter writer = facesContext.getResponseWriter();
103         HtmlPanelNavigation panelNav = (HtmlPanelNavigation)component;
104         
105         Map<String, List<ClientBehavior>> behaviors = panelNav.getClientBehaviors();
106         if (!behaviors.isEmpty())
107         {
108             ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, writer);
109         }
110 
111         if (panelNav.getChildCount() > 0)
112         {
113             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
114             writer.startElement(HTML.TABLE_ELEM, component);
115             
116             if (behaviors != null && !behaviors.isEmpty())
117             {
118                 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext),null);
119                 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, panelNav, behaviors);
120                 HtmlRendererUtils.renderHTMLAttributes(writer, panelNav, HTML.TABLE_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS); 
121             }
122             else
123             {
124                 HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
125                 HtmlRendererUtils.renderHTMLAttributes(writer, panelNav, HTML.TABLE_PASSTHROUGH_ATTRIBUTES);            
126             }            
127             
128             boolean isBorderAlreadyDefined = component.getAttributes().containsKey(HTML.BORDER_ATTR);
129             
130             if (panelNav.getStyle() == null && panelNav.getStyleClass() == null && !isBorderAlreadyDefined)
131             {
132                 writer.writeAttribute(HTML.BORDER_ATTR, ZERO_INTEGER, null);
133             }
134 
135             renderChildren(facesContext, writer, panelNav, panelNav.getChildren(), 0);
136 
137             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
138             writer.endElement(HTML.TABLE_ELEM);
139         }
140         else
141         {
142             if (log.isWarnEnabled()) log.warn("Navigation panel without children.");
143         }
144     }
145 
146 
147     protected void renderChildren(FacesContext facesContext,
148                                   ResponseWriter writer,
149                                   HtmlPanelNavigation panelNav,
150                                   List children,
151                                   int level)
152             throws IOException
153     {
154         for (Iterator it = children.iterator(); it.hasNext(); )
155         {
156             UIComponent child = (UIComponent)it.next();
157             if (!child.isRendered()) continue;
158             if (child instanceof HtmlCommandNavigation)
159             {
160                 //navigation item
161                 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
162 
163                 String style = getNavigationItemStyle(panelNav, (HtmlCommandNavigation)child);
164                 String styleClass = getNavigationItemClass(panelNav, (HtmlCommandNavigation)child);
165 
166                 writer.startElement(HTML.TR_ELEM, panelNav);
167                 writer.startElement(HTML.TD_ELEM, panelNav);
168                 writeStyleAttributes(writer, style, styleClass);
169 
170                 if (style != null || styleClass != null)
171                 {
172                     writer.startElement(HTML.SPAN_ELEM, panelNav);
173                     writeStyleAttributes(writer, style, styleClass);
174                 }
175                 indent(writer, level);
176                 child.encodeBegin(facesContext);
177                 child.encodeEnd(facesContext);
178                 if (style != null || styleClass != null)
179                 {
180                     writer.endElement(HTML.SPAN_ELEM);
181                 }
182 
183                 writer.endElement(HTML.TD_ELEM);
184                 writer.endElement(HTML.TR_ELEM);
185 
186                 if (child.getChildCount() > 0)
187                 {
188                     renderChildren(facesContext, writer, panelNav, child.getChildren(), level + 1);
189                 }
190             }
191             else
192             {
193                 //separator
194                 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
195 
196                 String style = panelNav.getSeparatorStyle();
197                 String styleClass = panelNav.getSeparatorClass();
198 
199                 writer.startElement(HTML.TR_ELEM, panelNav);
200                 writer.startElement(HTML.TD_ELEM, panelNav);
201                 writeStyleAttributes(writer, style, styleClass);
202 
203                 if (style != null || styleClass != null)
204                 {
205                     writer.startElement(HTML.SPAN_ELEM, panelNav);
206                     writeStyleAttributes(writer, style, styleClass);
207                 }
208                 indent(writer, level);
209                 RendererUtils.renderChild(facesContext, child);
210                 if (style != null || styleClass != null)
211                 {
212                     writer.endElement(HTML.SPAN_ELEM);
213                 }
214 
215                 writer.endElement(HTML.TD_ELEM);
216                 writer.endElement(HTML.TR_ELEM);
217             }
218 
219         }
220     }
221 
222 
223     protected void indent(ResponseWriter writer, int level)
224         throws IOException
225     {
226         StringBuffer buf = new StringBuffer();
227         for (int i = 0; i < level; i++)
228         {
229             buf.append("&#160;&#160;&#160;&#160;");
230         }
231         writer.write(buf.toString());
232     }
233 
234 
235 
236     protected String getNavigationItemStyle(HtmlPanelNavigation navPanel,
237                                             HtmlCommandNavigation navItem)
238     {
239         if (navItem.isActive())
240         {
241             return navPanel.getActiveItemStyle();
242         }
243         else if (navItem.isOpen())
244         {
245             return navPanel.getOpenItemStyle();
246         }
247         else
248         {
249             return navPanel.getItemStyle();
250         }
251     }
252 
253     protected String getNavigationItemClass(HtmlPanelNavigation navPanel,
254                                             HtmlCommandNavigation navItem)
255     {
256         // MYFACES-117, if a styleClass is supplied for a HtmlCommandNavigation,
257         // panelNavigation active/open/normal styles for items will be overriden
258         if (navItem.getStyleClass() != null) 
259         {
260             return navItem.getStyleClass();
261         }
262         
263         if (navItem.isActive())
264         {
265             return navPanel.getActiveItemClass();
266         }
267         else if (navItem.isOpen())
268         {
269             return navPanel.getOpenItemClass();
270         }
271         else
272         {
273             return navPanel.getItemClass();
274         }
275     }
276 
277 
278 
279     protected void writeStyleAttributes(ResponseWriter writer,
280                                         String style,
281                                         String styleClass)
282             throws IOException
283     {
284         HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_ATTR, HTML.STYLE_ATTR, style);
285         HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_CLASS_ATTR, HTML.STYLE_CLASS_ATTR, styleClass);
286     }
287 
288 
289     protected String getStyle(FacesContext facesContext, UIComponent link)
290     {
291         if (!(link instanceof HtmlCommandNavigation))
292         {
293             throw new IllegalArgumentException();
294         }
295 
296         UIComponent navPanel = link.getParent();
297         while (navPanel != null && !(navPanel instanceof HtmlPanelNavigation))
298         {
299             navPanel = navPanel.getParent();
300         }
301         if (navPanel == null)
302         {
303             throw new IllegalStateException("HtmlCommandNavigation not nested in HtmlPanelNavigation!?");
304         }
305 
306         HtmlCommandNavigation navItem = (HtmlCommandNavigation)link;
307         if (navItem.isActive())
308         {
309             return ((HtmlPanelNavigation)navPanel).getActiveItemStyle();
310         }
311         else if (navItem.isOpen())
312         {
313             return ((HtmlPanelNavigation)navPanel).getOpenItemStyle();
314         }
315         else
316         {
317             return ((HtmlPanelNavigation)navPanel).getItemStyle();
318         }
319     }
320 
321 
322     protected String getStyleClass(FacesContext facesContext, UIComponent link)
323     {
324         if (!(link instanceof HtmlCommandNavigation))
325         {
326             throw new IllegalArgumentException();
327         }
328 
329         UIComponent navPanel = link.getParent();
330         while (navPanel != null && !(navPanel instanceof HtmlPanelNavigation))
331         {
332             navPanel = navPanel.getParent();
333         }
334         if (navPanel == null)
335         {
336             throw new IllegalStateException("HtmlCommandNavigation not nested in HtmlPanelNavigation!?");
337         }
338 
339         HtmlCommandNavigation navItem = (HtmlCommandNavigation)link;
340         if (navItem.isActive())
341         {
342             return ((HtmlPanelNavigation)navPanel).getActiveItemClass();
343         }
344         else if (navItem.isOpen())
345         {
346             return ((HtmlPanelNavigation)navPanel).getOpenItemClass();
347         }
348         else
349         {
350             return ((HtmlPanelNavigation)navPanel).getItemClass();
351         }
352     }
353 
354 
355 
356 }