View Javadoc

1   // WARNING: This file was automatically generated. Do not edit it directly,
2   //          or you will lose your changes.
3   
4   /*
5    * Licensed to the Apache Software Foundation (ASF) under one
6    * or more contributor license agreements.  See the NOTICE file
7    * distributed with this work for additional information
8    * regarding copyright ownership.  The ASF licenses this file
9    * to you under the Apache License, Version 2.0 (the
10   * "License"); you may not use this file except in compliance
11   * with the License.  You may obtain a copy of the License at
12   *
13   *   http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing,
16   * software distributed under the License is distributed on an
17   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   * KIND, either express or implied.  See the License for the
19   * specific language governing permissions and limitations
20   * under the License.
21  */
22  package org.apache.myfaces.trinidad.component;
23  
24  import java.io.IOException;
25  import javax.faces.component.UIComponent;
26  import javax.faces.component.visit.VisitCallback;
27  import javax.faces.component.visit.VisitContext;
28  import javax.faces.component.visit.VisitContextWrapper;
29  import javax.faces.component.visit.VisitHint;
30  import javax.faces.component.visit.VisitResult;
31  import javax.faces.context.FacesContext;
32  import javax.faces.event.FacesEvent;
33  import javax.faces.event.PhaseId;
34  import org.apache.myfaces.trinidad.bean.FacesBean;
35  import org.apache.myfaces.trinidad.event.DisclosureEvent;
36  
37  /**
38   *
39   * showOne is the base abstraction for components that contains
40   * a group of showDetails, but displays one of them.
41   *
42   * <h4>Events:</h4>
43   * <table border="1" width="100%" cellpadding="3" summary="">
44   * <tr bgcolor="#CCCCFF" class="TableHeadingColor">
45   * <th align="left">Type</th>
46   * <th align="left">Phases</th>
47   * <th align="left">Description</th>
48   * </tr>
49   * <tr class="TableRowColor">
50   * <td valign="top"><code>org.apache.myfaces.trinidad.event.AttributeChangeEvent</code></td>
51   * <td valign="top" nowrap>Invoke<br>Application<br>Apply<br>Request<br>Values</td>
52   * <td valign="top">Event delivered to describe an attribute change.  Attribute change events are not delivered for any programmatic change to a property.  They are only delivered when a renderer changes a property without the application's specific request.  An example of an attribute change event might include the width of a column that supported client-side resizing.</td>
53   * </tr>
54   * </table>
55   */
56  public class UIXShowOne extends UIXComponentBase
57  {
58    static public final FacesBean.Type TYPE = new FacesBean.Type(
59      UIXComponentBase.TYPE);
60  
61    static public final String COMPONENT_FAMILY =
62      "org.apache.myfaces.trinidad.ShowOne";
63    static public final String COMPONENT_TYPE =
64      "org.apache.myfaces.trinidad.ShowOne";
65  
66    /**
67     * Construct an instance of the UIXShowOne.
68     */
69    public UIXShowOne()
70    {
71      super("org.apache.myfaces.trinidad.Tab");
72    }
73    
74    @Override
75    @SuppressWarnings("unchecked")
76    public void queueEvent(FacesEvent e)
77    {
78      // Care only if it is a DisclosureEvent, and only if its source is one of
79      // its immediate children, for... one could bubble up from one of its grand
80      // children that could be a ShowDetail.
81      FacesEvent unwrappedEvent = e;
82      while (unwrappedEvent instanceof WrapperEvent) // e.g. DisclosureEvent in a tr:iterator
83      {
84        unwrappedEvent = ((WrapperEvent)unwrappedEvent).getEvent();
85      }
86  
87      if (unwrappedEvent instanceof DisclosureEvent)
88      {
89        UIComponent parent = unwrappedEvent.getComponent().getParent();
90        while (parent != null && parent instanceof FlattenedComponent)
91        {
92          parent = parent.getParent();
93        }
94  
95        if (this == parent)
96        {
97          // Care only if the incoming event was from the to-be-disclosed showDetailItem.
98          DisclosureEvent disclosureEvent = (DisclosureEvent)unwrappedEvent;
99          if (disclosureEvent.isExpanded())
100         {
101           FacesContext context = FacesContext.getCurrentInstance();
102           String disclosedClientId = disclosureEvent.getComponent().getClientId(context);
103 
104           // Visit all of the flattened children:
105           try
106           {
107             UIXComponent.processFlattenedChildren(
108               context,
109               _undisclosureCallback,
110               getChildren(),
111               new UndisclosureCallbackState(e, disclosedClientId));
112           }
113           catch (IOException ioe)
114           {
115             // This exception is not expected since no IO is used in this visitor's implementation.
116             ioe.printStackTrace();
117           }
118         }
119       }
120     }
121     super.queueEvent(e);
122   }
123 
124   @Override
125   public boolean visitTree(
126     VisitContext  visitContext,
127     VisitCallback callback)
128   {
129     if (visitContext.getHints().contains(VisitHint.SKIP_UNRENDERED))
130     {
131       // Filter which children to be visited so that only one show detail
132       // is visited for this show one component
133       visitContext = new PartialVisitContext(visitContext);
134     }
135     return super.visitTree(visitContext, callback);
136   }
137 
138   protected boolean isChildSelected(
139     UIXShowDetail component)
140   {
141     return component.isDisclosed();
142   }
143 
144   /**
145    * State passed to the UndisclosureCallback.
146    */
147   private static class UndisclosureCallbackState
148   {
149     public UndisclosureCallbackState(
150       FacesEvent facesEvent,
151       String     clientIdBeingDisclosed)
152     {
153       this.facesEvent = facesEvent;
154       this.clientIdBeingDisclosed = clientIdBeingDisclosed;
155     }
156 
157     protected final FacesEvent facesEvent;
158     protected final String clientIdBeingDisclosed;
159   }
160 
161   /**
162    * Visitor for each flattened child, using the information in the UndisclosureCallbackState.
163    */
164   private class UndisclosureCallback implements ComponentProcessor<UndisclosureCallbackState>
165   {
166     public void processComponent(
167       FacesContext               facesContext,
168       ComponentProcessingContext processContext,
169       UIComponent                child,
170       UndisclosureCallbackState  callbackState)
171       throws IOException
172     {
173       String clientIdBeingDisclosed = callbackState.clientIdBeingDisclosed;
174 
175       // Search for the other item(s) to undisclose (make sure to skip the clientIdBeingDisclosed):
176       String childClientId = child.getClientId(facesContext);
177       if (!clientIdBeingDisclosed.equals(childClientId))
178       {
179         UIXShowDetail toBeUnDisclosedChild = (UIXShowDetail)child;
180         if (toBeUnDisclosedChild.isDisclosed())
181         {
182           // Override the phaseId that would be already set on this event
183           // (coming off of the to-be-disclosed showDetailItem), because the
184           // phase-id should actually be determined by the 'immediate' attribute
185           // on the to-be-undisclosed showDetailItem
186           if (toBeUnDisclosedChild.isImmediate())
187           {
188             callbackState.facesEvent.setPhaseId(PhaseId.ANY_PHASE);
189           }
190           else
191           {
192             callbackState.facesEvent.setPhaseId(PhaseId.INVOKE_APPLICATION);
193           }
194 
195           // Now queue the event for the to-be-undisclosed showDetailItem
196           // Note that this is always delivered earlier than the one that is
197           // already queued for to-be-disclosed showDetailItem.
198           (new DisclosureEvent(toBeUnDisclosedChild, false)).queue();
199         }
200       }
201     }
202   }
203 
204   private class PartialVisitContext
205     extends VisitContextWrapper
206   {
207     PartialVisitContext(VisitContext wrapped)
208     {
209       _wrapped = wrapped;
210     }
211 
212     public VisitContext getWrapped()
213     {
214       return _wrapped;
215     }
216 
217     @Override
218     public VisitResult invokeVisitCallback(
219       UIComponent   component,
220       VisitCallback visitCallback)
221     {
222       if (component instanceof UIXShowDetail)
223       {
224         UIXShowDetail showDetail = (UIXShowDetail)component;
225         if (_isShowDetailForCurrentComponent(showDetail))
226         {
227           if (_foundItemToRender || !isChildSelected(showDetail))
228           {
229             // We already visited the one to be shown
230             return VisitResult.REJECT;
231           }
232           else
233           {
234             _foundItemToRender = true;
235           }
236         }
237       }
238 
239       return super.invokeVisitCallback(component, visitCallback);
240     }
241 
242     private boolean _isShowDetailForCurrentComponent(
243       UIXShowDetail showDetail)
244     {
245       for (UIComponent parent = showDetail.getParent(); parent != null; parent = parent.getParent())
246       {
247         if (parent == UIXShowOne.this)
248         {
249           return true;
250         }
251 
252         if (parent instanceof FlattenedComponent &&
253           ((FlattenedComponent)parent).isFlatteningChildren(getFacesContext()))
254         {
255           continue;
256         }
257 
258         // The first-non flattened component is not the show one, do not filter it
259         return false;
260       }
261 
262       return false;
263     }
264 
265     private boolean      _foundItemToRender;
266     private VisitContext _wrapped;
267   }
268 
269   private final UndisclosureCallback _undisclosureCallback = new UndisclosureCallback();
270 
271   @Override
272   public String getFamily()
273   {
274     return COMPONENT_FAMILY;
275   }
276 
277   @Override
278   protected FacesBean.Type getBeanType()
279   {
280     return TYPE;
281   }
282 
283   /**
284    * Construct an instance of the UIXShowOne.
285    */
286   protected UIXShowOne(
287     String rendererType
288     )
289   {
290     super(rendererType);
291   }
292 
293   static
294   {
295     TYPE.lockAndRegister("org.apache.myfaces.trinidad.ShowOne","org.apache.myfaces.trinidad.Tab");
296   }
297 }