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.util.Iterator;
22  import java.util.List;
23  
24  import javax.faces.component.UIComponent;
25  import javax.faces.context.FacesContext;
26  import javax.faces.event.AbortProcessingException;
27  import javax.faces.event.ActionEvent;
28  import javax.faces.event.FacesEvent;
29  import javax.faces.event.PhaseId;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.myfaces.component.html.ext.HtmlCommandLink;
34  
35  /**
36   * Command, that represents a navigation item.
37   *
38   * Must be nested inside a panel_navigation action and renders a 
39   * clickable navigation item. This action is derived from the 
40   * standard command_link action and has equal attributes. 
41   * (Replaces former "navigation_item" tag.) 
42   * 
43   * Unless otherwise specified, all attributes accept static values 
44   * or EL expressions.
45   *
46   * @JSFComponent
47   *   name = "t:commandNavigation"
48   *   class = "org.apache.myfaces.custom.navigation.HtmlCommandNavigation"
49   *   tagClass = "org.apache.myfaces.custom.navigation.HtmlCommandNavigationTag"
50   * @since 1.1.7
51   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
52   * @version $Revision: 1001029 $ $Date: 2010-09-24 13:57:00 -0500 (Fri, 24 Sep 2010) $
53   */
54  public abstract class AbstractHtmlCommandNavigation
55          extends HtmlCommandLink
56  {
57      private static final Log log = LogFactory.getLog(AbstractHtmlCommandNavigation.class);
58  
59      public static final String COMPONENT_TYPE = "org.apache.myfaces.HtmlCommandNavigation";
60      public static final String COMPONENT_FAMILY = "javax.faces.Command";
61      private static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.Navigation";
62      
63      public boolean isImmediate()
64      {
65          //always immediate
66          return true;
67      }
68  
69      public void setImmediate(boolean immediate)
70      {
71          if (log.isWarnEnabled()) log.warn("Immediate property of HtmlCommandNavigation cannot be set --> ignored.");
72      }
73  
74      public Boolean getOpenDirectly()
75      {
76          return Boolean.valueOf(isOpen());            
77      }
78      
79      public Boolean getActiveDirectly()
80      {
81          return Boolean.valueOf(isActive());            
82      }
83      
84      /**
85       * @return false, if this item is child of another HtmlCommandNavigation, which is closed
86       */
87      public boolean isRendered()
88      {
89          if (! super.isRendered()) {
90              return false;
91          }
92          UIComponent parent = getParent();
93          while (parent != null)
94          {
95              if (parent instanceof HtmlCommandNavigation)
96              {
97                  if (!((HtmlCommandNavigation)parent).isOpen())
98                  {
99                      return false;
100                 }
101             }
102 
103             if (parent instanceof HtmlPanelNavigation)
104             {
105                 break;
106             }
107             else
108             {
109                 parent = parent.getParent();
110             }
111         }
112 
113         return true;
114     }
115 
116     /**
117      * @JSFProperty
118      *   tagExcluded="true"
119      */
120     public abstract boolean isOpen();
121     
122     public abstract void setOpen(boolean open);
123 
124     /**
125      * @JSFProperty
126      *   tagExcluded="true"
127      */
128     public abstract boolean isActive();
129     
130     public abstract void setActive(boolean active);
131         
132     public void toggleOpen()
133     {
134         if (isOpen())
135         {
136             if (getChildCount() > 0)
137             {
138                 //item is a menu group --> close item
139                 setOpen(false);
140             }
141         }
142         else
143         {
144             UIComponent parent = getParent();
145 
146             //close all siblings
147             closeAllChildren(parent.getChildren().iterator());
148 
149             //open all parents (to be sure) and search HtmlPanelNavigation
150             UIComponent p = parent;
151             while (p != null && !(p instanceof HtmlPanelNavigation))
152             {
153                 if (p instanceof HtmlCommandNavigation)
154                 {
155                     ((HtmlCommandNavigation)p).setOpen(true);
156                 }
157                 p = p.getParent();
158             }
159             // p is now the HtmlPanelNavigation
160 
161             if (!hasCommandNavigationChildren())
162             {
163                 //item is an end node --> deactivate all other nodes, and then...
164                 if (!(p instanceof HtmlPanelNavigation))
165                 {
166                     log.error("HtmlCommandNavigation without parent HtmlPanelNavigation ?!");
167                 }
168                 else
169                 {
170                     //deactivate all other items
171                     deactivateAllChildren(p.getChildren().iterator());
172                 }
173                 //...activate this item
174                 setActive(true);
175             }
176             else
177             {
178                 //open item
179                 setOpen(true);
180             }
181         }
182     }
183 
184     private boolean hasCommandNavigationChildren()
185     {
186         if (getChildCount() == 0)
187         {
188             return false;
189         }
190         List list = getChildren();
191         for (int i = 0, sizei = list.size(); i < sizei; i++)
192         {
193             if (list.get(i) instanceof HtmlCommandNavigation)
194             {
195                 return true;
196             }
197         }
198         return false;
199     }
200 
201 
202     private static void deactivateAllChildren(Iterator children)
203     {
204         while (children.hasNext())
205         {
206             UIComponent ni = (UIComponent)children.next();
207             if (ni instanceof HtmlCommandNavigation)
208             {
209                 ((HtmlCommandNavigation)ni).setActive(false);
210                 if (ni.getChildCount() > 0)
211                 {
212                     deactivateAllChildren(ni.getChildren().iterator());
213                 }
214             }
215         }
216     }
217 
218     private static void closeAllChildren(Iterator children)
219     {
220         while (children.hasNext())
221         {
222             UIComponent ni = (UIComponent)children.next();
223             if (ni instanceof HtmlCommandNavigation)
224             {
225                 ((HtmlCommandNavigation)ni).setOpen(false);
226                 if (ni.getChildCount() > 0)
227                 {
228                     closeAllChildren(ni.getChildren().iterator());
229                 }
230             }
231         }
232     }
233 
234 
235     public void broadcast(FacesEvent event) throws AbortProcessingException
236     {
237         if (event instanceof ActionEvent)
238         {
239             ActionEvent actionEvent = (ActionEvent)event;
240             if (actionEvent.getPhaseId() == PhaseId.APPLY_REQUEST_VALUES)
241             {
242                 HtmlCommandNavigation navItem = (HtmlCommandNavigation)actionEvent.getComponent();
243                 navItem.toggleOpen();
244                 FacesContext.getCurrentInstance().renderResponse();
245             }
246         }
247         super.broadcast(event);
248     }
249     
250 }