View Javadoc

1   /*
2    * $Id: TabbedPanel.java 651946 2008-04-27 13:41:38Z apetrelli $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  package org.apache.struts2.dojo.components;
23  
24  import java.util.Random;
25  
26  import javax.servlet.http.HttpServletRequest;
27  import javax.servlet.http.HttpServletResponse;
28  
29  import org.apache.struts2.components.ClosingUIBean;
30  import org.apache.struts2.views.annotations.StrutsTag;
31  import org.apache.struts2.views.annotations.StrutsTagAttribute;
32  import org.apache.struts2.views.annotations.StrutsTagSkipInheritance;
33  
34  import com.opensymphony.xwork2.util.ValueStack;
35  
36  /***
37   * <!-- START SNIPPET: javadoc -->
38   * The tabbedpanel widget is primarily an AJAX component, where each tab can either be local content or remote
39   * content (refreshed each time the user selects that tab).</p>
40   * If the useSelectedTabCookie attribute is set to true, the id of the selected tab is saved in a cookie on activation.
41   * When coming back to this view, the cookie is read and the tab will be activated again, unless an actual value for the
42   * selectedTab attribute is specified.</p>
43   * If you want to use the cookie feature, please be sure that you provide a unique id for your tabbedpanel component,
44   * since this will also be the identifying name component of the stored cookie.</p>
45   * <!-- END SNIPPET: javadoc -->
46   *
47   * <p/> <b>Examples</b>
48   * <p/>
49   * 
50   * <!-- START SNIPPET: example1 -->
51   * &lt;s:tabbedpanel id="test" &gt;
52   *    &lt;s:div id="one" label="one" theme="ajax" labelposition="top" &gt;
53   *        This is the first pane&lt;br/&gt;
54   *        &lt;s:form&gt;
55   *            &lt;s:textfield name="tt" label="Test Text"/&gt;  &lt;br/&gt;
56   *            &lt;s:textfield name="tt2" label="Test Text2"/&gt;
57   *        &lt;/s:form&gt;
58   *    &lt;/s:div&gt;
59   *    &lt;s:div id="three" label="remote" theme="ajax" href="/AjaxTest.action" &gt;
60   *        This is the remote tab
61   *    &lt;/s:div&gt;
62   * &lt;/s:tabbedpanel&gt;
63   * <!-- END SNIPPET: example1 -->
64   * 
65   * <!-- START SNIPPET: example2 -->
66   * &lt;script type="text/javascript"&gt;
67   * dojo.event.topic.subscribe("/beforeSelect", function(event, tab, tabContainer){
68   *     event.cancel = true;
69   * });
70   * &lt;/script&gt;
71   * 
72   * &lt;s:tabbedpanel id="test" beforeSelectTabNotifyTopics="/beforeSelect"&gt;
73   *    &lt;s:div id="three" label="remote" theme="ajax" href="/AjaxTest.action" &gt;
74   *        One Tab
75   *    &lt;/s:div&gt;
76   *    &lt;s:div id="three" label="remote" theme="ajax" href="/AjaxTest.action" &gt;
77   *        Another tab
78   *    &lt;/s:div&gt;
79   * &lt;/s:tabbedpanel&gt;
80   * <!-- END SNIPPET: example2 -->
81   */
82  @StrutsTag(name="tabbedpanel", tldTagClass="org.apache.struts2.dojo.views.jsp.ui.TabbedPanelTag", description="Render a tabbedPanel widget.")
83  public class TabbedPanel extends ClosingUIBean {
84      public static final String TEMPLATE = "tabbedpanel";
85      public static final String TEMPLATE_CLOSE = "tabbedpanel-close";
86      final private static String COMPONENT_NAME = TabbedPanel.class.getName();
87      private final static transient Random RANDOM = new Random();    
88  
89      protected String selectedTab;
90      protected String closeButton;
91      protected String doLayout ;
92      protected String templateCssPath;
93      protected String beforeSelectTabNotifyTopics;
94      protected String afterSelectTabNotifyTopics;
95      protected String disabledTabCssClass; 
96      protected String useSelectedTabCookie;
97  
98      public TabbedPanel(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
99          super(stack, request, response);
100     }
101 
102 
103     protected void evaluateExtraParams() {
104         super.evaluateExtraParams();
105 
106         if (selectedTab != null)
107             addParameter("selectedTab", findString(selectedTab));
108         if (closeButton != null)
109             addParameter("closeButton", findString(closeButton));
110         addParameter("doLayout", doLayout != null ? findValue(doLayout, Boolean.class) : Boolean.FALSE);
111         if (labelPosition != null) {
112             //dojo has some weird name for label positions
113             if(labelPosition.equalsIgnoreCase("left"))
114                labelPosition = "left-h";
115             if(labelPosition.equalsIgnoreCase("right"))
116                 labelPosition = "right-h";
117             addParameter("labelPosition", null);
118             addParameter("labelPosition", labelPosition);
119         }
120         if (templateCssPath != null)
121             addParameter("templateCssPath", findString(templateCssPath));
122         if (beforeSelectTabNotifyTopics!= null)
123             addParameter("beforeSelectTabNotifyTopics", findString(beforeSelectTabNotifyTopics));
124         if (afterSelectTabNotifyTopics!= null)
125             addParameter("afterSelectTabNotifyTopics", findString(afterSelectTabNotifyTopics));
126         if (disabledTabCssClass!= null)
127             addParameter("disabledTabCssClass", findString(disabledTabCssClass));
128         if(useSelectedTabCookie != null) {
129             addParameter("useSelectedTabCookie", findString(useSelectedTabCookie));
130         }
131 
132         // generate a random ID if not explicitly set and not parsing the content
133         Boolean parseContent = (Boolean)stack.getContext().get(Head.PARSE_CONTENT);
134         boolean generateId = (parseContent != null ? !parseContent : true);
135         
136         addParameter("pushId", generateId);
137         if ((this.id == null || this.id.length() == 0) && generateId) {
138             // resolves Math.abs(Integer.MIN_VALUE) issue reported by FindBugs 
139             // http://findbugs.sourceforge.net/bugDescriptions.html#RV_ABSOLUTE_VALUE_OF_RANDOM_INT
140             int nextInt = RANDOM.nextInt();
141             nextInt = nextInt == Integer.MIN_VALUE ? Integer.MAX_VALUE : Math.abs(nextInt);  
142             this.id = "widget_" + String.valueOf(nextInt);
143             addParameter("id", this.id);
144         }
145     }
146 
147     @Override
148     @StrutsTagSkipInheritance
149     public void setTheme(String theme) {
150         super.setTheme(theme);
151     }
152     
153     @Override
154     public String getTheme() {
155         return "ajax";
156     }
157     
158     public String getDefaultOpenTemplate() {
159         return TEMPLATE;
160     }
161 
162     protected String getDefaultTemplate() {
163         return TEMPLATE_CLOSE;
164     }
165 
166     public String getComponentName() {
167         return COMPONENT_NAME;
168     }
169 
170     @StrutsTagAttribute(description="The id to assign to the component.", required=true)
171     public void setId(String id) {
172         // This is required to override tld generation attributes to required=true
173         super.setId(id);
174     }
175 
176 
177     @StrutsTagAttribute(description=" The id of the tab that will be selected by default")
178     public void setSelectedTab(String selectedTab) {
179       this.selectedTab = selectedTab;
180     }
181 
182     @StrutsTagAttribute(description="Deprecated. Use 'closable' on each div(tab)")
183     public void setCloseButton(String closeButton) {
184         this.closeButton = closeButton;
185     }
186 
187     @StrutsTagAttribute(description="If doLayout is false, the tab container's height equals the height of the currently selected tab", type="Boolean", defaultValue="false")
188     public void setDoLayout(String doLayout) {
189         this.doLayout = doLayout;
190     }
191 
192     @StrutsTagAttribute(description="Template css path")
193     public void setTemplateCssPath(String templateCssPath) {
194         this.templateCssPath = templateCssPath;
195     }
196 
197 
198     @StrutsTagAttribute(description="Comma separated list of topics to be published when a tab is clicked on (before it is selected)" +
199     		"The tab container widget will be passed as the first argument to the topic. The second parameter is the tab widget." +
200     		"The event can be cancelled setting to 'true' the 'cancel' property " +
201     		"of the third parameter passed to the topics.")
202     public void setBeforeSelectTabNotifyTopics(String selectedTabNotifyTopics) {
203         this.beforeSelectTabNotifyTopics = selectedTabNotifyTopics;
204     }
205 
206     @StrutsTagAttribute(description="Comma separated list of topics to be published when a tab is clicked on (after it is selected)." +
207         "The tab container widget will be passed as the first argument to the topic. The second parameter is the tab widget.")
208     public void setAfterSelectTabNotifyTopics(String afterSelectTabNotifyTopics) {
209         this.afterSelectTabNotifyTopics = afterSelectTabNotifyTopics;
210     }
211 
212     @StrutsTagAttribute(description="Css class to be applied to the tab button of disabled tabs", defaultValue="strutsDisabledTab")
213     public void setDisabledTabCssClass(String disabledTabCssClass) {
214         this.disabledTabCssClass = disabledTabCssClass;
215     }
216 
217     @StrutsTagAttribute(required = false, defaultValue = "false", description = "If set to true, the id of the last selected " +
218             "tab will be stored in cookie. If the view is rendered, it will be tried to read this cookie and activate " +
219             "the corresponding tab on success, unless overridden by the selectedTab attribute. The cookie name is \"Struts2TabbedPanel_selectedTab_\"+id.")
220     public void setUseSelectedTabCookie( String useSelectedTabCookie ) {
221         this.useSelectedTabCookie = useSelectedTabCookie;
222     }
223 }