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.autoscroll;
20  
21  import java.io.IOException;
22  import java.util.List;
23  
24  import javax.faces.component.StateHolder;
25  import javax.faces.component.UICommand;
26  import javax.faces.component.UIComponent;
27  import javax.faces.component.UIViewRoot;
28  import javax.faces.component.behavior.ClientBehavior;
29  import javax.faces.component.behavior.ClientBehaviorHolder;
30  import javax.faces.context.FacesContext;
31  import javax.faces.event.ComponentSystemEvent;
32  import javax.faces.event.ComponentSystemEventListener;
33  import javax.faces.event.PostAddToViewEvent;
34  import javax.faces.event.PostRestoreStateEvent;
35  import javax.faces.event.SystemEvent;
36  import javax.faces.event.SystemEventListener;
37  import javax.faces.view.facelets.FaceletContext;
38  import javax.faces.view.facelets.TagAttribute;
39  import javax.faces.view.facelets.TagConfig;
40  import javax.faces.view.facelets.TagHandler;
41  
42  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
43  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
44  
45  /**
46   * Adds to UICommand components that implements ClientBehaviorHolder interface an
47   * AutoscrollBehavior.
48   * <p>
49   * Use it in this way to ensure proper operation:
50   * </p>
51   * <code>
52   * &lt;f:metadata&gt;
53   *   &lt;t:autoScrollPage/&gt;
54   * &lt;/f:metadata&gt;
55   * </code>
56   * <p>
57   * Or in this way:
58   * </p>
59   * <code>
60   * &lt;h:body&gt;
61   *   &lt;t:autoScrollPage/&gt;
62   * </code>
63   * <p>
64   * It is possible to use it at start of the page too, but note this tag attach a listener to
65   * PostAddToViewEvent, so previous components added to the view before apply this TagHandler
66   * will not be taken into account.
67   * </p>
68   * 
69   * @since 1.1.10
70   * @author Leonardo Uribe (latest modification by $Author: lu4242 $)
71   * @version $Revision: 691856 $ $Date: 2008-09-03 21:40:30 -0500 (miƩ, 03 sep 2008) $
72   */
73  @JSFFaceletTag(name="t:autoScrollPage")
74  public class AutoscrollPageTagHandler extends TagHandler
75  {
76  
77      /**
78       * 
79       */
80      @JSFFaceletAttribute(name="event",
81              className="javax.el.ValueExpression",
82              deferredValueType="java.lang.String")
83      private TagAttribute _event;
84      
85      public AutoscrollPageTagHandler(TagConfig config)
86      {
87          super(config);
88          _event = this.getAttribute("event");
89      }
90  
91      public void apply(FaceletContext ctx, UIComponent parent)
92              throws IOException
93      {
94          UIViewRoot root = getViewRoot(ctx, parent);
95          
96          if (!root.getAttributes().containsKey(AutoscrollBehaviorTagHandler.AUTOSCROLL_TAG_ON_PAGE))
97          {
98              root.getAttributes().put(AutoscrollBehaviorTagHandler.AUTOSCROLL_TAG_ON_PAGE, Boolean.TRUE);
99          }
100         
101         String eventName = (_event == null) ? null : _event.getValue(ctx);
102         
103         root.subscribeToViewEvent(PostAddToViewEvent.class, 
104                 new RegisterAutoscrollBehaviorOnCommandListener(eventName));
105         root.subscribeToEvent(PostRestoreStateEvent.class, new RegisterAutoscrollListener(eventName));
106     }
107     
108     private UIViewRoot getViewRoot(FaceletContext ctx, UIComponent parent)
109     {
110         UIComponent c = parent;
111         do
112         {
113             if (c instanceof UIViewRoot)
114             {
115                 return (UIViewRoot) c;
116             }
117             else
118             {
119                 c = c.getParent();
120             }
121         } while (c != null);
122 
123         return ctx.getFacesContext().getViewRoot();
124     }
125 
126     public static class RegisterAutoscrollListener implements ComponentSystemEventListener, StateHolder
127     {
128         private String eventName;
129         
130         public RegisterAutoscrollListener()
131         {
132             super();
133         }
134 
135         public RegisterAutoscrollListener(String event)
136         {
137             super();
138             eventName = event;
139         }
140 
141         public void processEvent(ComponentSystemEvent event)
142         {
143             FacesContext.getCurrentInstance().getViewRoot().subscribeToViewEvent(PostAddToViewEvent.class, 
144                     new RegisterAutoscrollBehaviorOnCommandListener(eventName));
145         }
146 
147         public boolean isTransient()
148         {
149             return false;
150         }
151         
152         public void setTransient(boolean newTransientValue)
153         {
154         }
155 
156         public void restoreState(FacesContext context, Object state)
157         {
158             eventName = (String)state;
159         }
160 
161         public Object saveState(FacesContext context)
162         {
163             return eventName;
164         }
165     }
166     
167     public static class RegisterAutoscrollBehaviorOnCommandListener implements SystemEventListener
168     {
169         private String _eventName;
170 
171         public RegisterAutoscrollBehaviorOnCommandListener(String eventName)
172         {
173             super();
174             _eventName = eventName;
175         }
176 
177         public boolean isListenerForSource(Object source)
178         {
179             return (source instanceof UICommand && source instanceof ClientBehaviorHolder);
180         }        
181         
182         public void processEvent(SystemEvent event)
183         {
184             ClientBehaviorHolder component = (ClientBehaviorHolder) event.getSource();
185             
186             String eventName = (_eventName == null) ? component.getDefaultEventName() : _eventName;
187             
188             boolean found = false;
189             List<ClientBehavior> list = component.getClientBehaviors().get(eventName);
190             if (list != null)
191             {
192                 for (ClientBehavior cb : list)
193                 {
194                     if (cb instanceof AutoscrollBehavior)
195                     {
196                         found = true;
197                         break;
198                     }
199                 }
200             }
201             
202             if (!found)
203             {
204                 ClientBehavior behavior = (ClientBehavior) FacesContext.getCurrentInstance().getApplication().createBehavior(AutoscrollBehavior.BEHAVIOR_ID);
205                 component.addClientBehavior(eventName, behavior);
206             }
207         }
208     }
209 }