View Javadoc

1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.uif.container;
17  
18  import org.kuali.rice.core.api.util.KeyValue;
19  import org.kuali.rice.krad.datadictionary.parse.BeanTag;
20  import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
21  import org.kuali.rice.krad.datadictionary.parse.BeanTags;
22  import org.kuali.rice.krad.uif.component.Component;
23  import org.kuali.rice.krad.uif.control.MultiValueControl;
24  import org.kuali.rice.krad.uif.element.Message;
25  import org.kuali.rice.krad.uif.field.InputField;
26  import org.kuali.rice.krad.uif.field.MessageField;
27  import org.kuali.rice.krad.uif.view.View;
28  
29  import java.util.ArrayList;
30  import java.util.Collections;
31  import java.util.List;
32  
33  /**
34   * Special type of <code>Group</code> that presents a the content for a modal dialog
35   *
36   * <p>
37   * This type of group will be hidden when the main view is displayed. It will be used as
38   * content inside the LightBox widget when the modal dialog is displayed.
39   * For convenience, this group contains a standard set of components for commonly used modal dialogs
40   * <ul>
41   * <li>a prompt to display in the lightbox</li>
42   * <li>an optional explanation <code>InputField</code> for holding the user's textual response</li>
43   * <li>a set of response options for the user to choose from</li>
44   * </ul>
45   *
46   * <p>
47   * The DialogGroup may also serve as a base class for more complex dialogs.
48   * The default settings for this DialogGroup is to display a prompt message
49   * with two buttons labeled OK and Cancel.
50   * The optional explanation <code>TextAreaControl</code> is hidden by default.
51   * </p>
52   *
53   * <p>
54   * The prompt text, number of user options and their corresponding label are configurable.
55   * The <code>InputField</code> for the explanation is <code>TextAreaControl</code> by default.
56   * It may be configured to other types of InputFields.
57   * The Component for ResponseInputField is a <code>HorizontalCheckboxGroup</code> by default.
58   * JQuery styling is then used to style the checkboxes as buttons. The ResponseInputField may
59   * be configured to other <code>InputField</code> types.
60   * </p>
61   *
62   * @author Kuali Rice Team (rice.collab@kuali.org)
63   */
64  @BeanTags({@BeanTag(name = "dialogGroup-bean", parent = "Uif-DialogGroup"),
65          @BeanTag(name = "sensitiveData-dialogGroup-bean", parent = "Uif-SensitiveData-DialogGroup"),
66          @BeanTag(name = "ok-cancel-dialogGroup-bean", parent = "Uif-OK-Cancel-DialogGroup"),
67          @BeanTag(name = "yes-no-dialogGroup-bean", parent = "Uif-Yes-No-DialogGroup"),
68          @BeanTag(name = "true-false-dialogGroup-bean", parent = "Uif-True-False-DialogGroup"),
69          @BeanTag(name = "checkbox-dialogGroup-bean", parent = "Uif-Checkbox-DialogGroup"),
70          @BeanTag(name = "radioButton-dialogGroup-bean", parent = "Uif-RadioButton-DialogGroup")})
71  public class DialogGroup extends Group {
72      private static final long serialVersionUID = 1L;
73  
74      private String promptText;
75      private List<KeyValue> availableResponses;
76  
77      private MessageField prompt;
78      private InputField explanation;
79      private InputField responseInputField;
80  
81      private boolean reverseButtonOrder = false;
82      private boolean displayExplanation = false;
83      private boolean useAjaxCallForContent = false;
84  
85      public DialogGroup() {
86          super();
87      }
88  
89      /**
90       * Process rich message content that may be in the options, by creating and initializing the richOptions
91       *
92       * @see org.kuali.rice.krad.uif.component.ComponentBase#performApplyModel(org.kuali.rice.krad.uif.view.View,
93       *      java.lang.Object, org.kuali.rice.krad.uif.component.Component)
94       */
95      @Override
96      public void performApplyModel(View view, Object model, Component parent) {
97          super.performApplyModel(view, model, parent);
98  
99          // set the messageTest to the promptText
100         prompt.setMessageText(promptText);
101 
102         // hide or show explanation
103         explanation.setRender(displayExplanation);
104 
105         // add options to checkbox
106         if (responseInputField.getControl() != null && responseInputField.getControl() instanceof MultiValueControl) {
107             MultiValueControl multiValueControl = (MultiValueControl) responseInputField.getControl();
108 
109             if (reverseButtonOrder) {
110                 // reverse the button order (without changing original list)
111                 List<KeyValue> buttonList = new ArrayList<KeyValue>(availableResponses);
112                 Collections.reverse(buttonList);
113                 multiValueControl.setOptions(buttonList);
114             } else {
115                 multiValueControl.setOptions(availableResponses);
116             }
117         }
118     }
119 
120     /**
121      * @see org.kuali.rice.krad.uif.component.ComponentBase#getComponentsForLifecycle()
122      */
123     @Override
124     public List<Component> getComponentsForLifecycle() {
125         List<Component> components = super.getComponentsForLifecycle();
126 
127         components.add(prompt);
128         components.add(explanation);
129         components.add(responseInputField);
130 
131         return components;
132     }
133 
134     /**
135      * The following actions are performed:
136      *
137      * <ul>
138      * <li>Move custom dialogGroup properties prompt, explanation, and responseInputField into items collection if they
139      * are not already present</li>
140      * </ul>
141      *
142      * @see org.kuali.rice.krad.uif.component.ComponentBase#performInitialization(org.kuali.rice.krad.uif.view.View,
143      *      java.lang.Object)
144      */
145     @Override
146     public void performInitialization(View view, Object model) {
147         super.performInitialization(view, model);
148 
149         // move dialogGroup custom properties into the items property.
150         // where they will be rendered by group.jsp
151         List<Component> newItems = new ArrayList<Component>();
152         List<? extends Component> items = getItems();
153 
154         // do not add the custom properties if they are already present
155         if (!(items.contains(prompt))) {
156             newItems.add(prompt);
157         }
158 
159         if (!(items.contains(explanation))) {
160             newItems.add(explanation);
161         }
162 
163         newItems.addAll(getItems());
164 
165         if (!(items.contains(responseInputField))) {
166             newItems.add(responseInputField);
167         }
168 
169         this.setItems(newItems);
170     }
171 
172     /**
173      * Performs the final phase of the component lifecycle.
174      *
175      * <p>For this DialogGroup component, perform the following:
176      * <ul>
177      * <li>set the promptText in the message</li>
178      * <li>sets whether to render explanation field</li>
179      * <li>set the options for the checkbox control to the availableResponses KeyValue property of
180      * this dialogGroup</li>
181      * <li>orders response buttons</li>
182      * </ul>
183      * </p>
184      *
185      * @param view - view instance that should be finalized for rendering
186      * @param model - top level object containing the data
187      * @param parent - parent component
188      */
189     @Override
190     public void performFinalize(View view, Object model, Component parent) {
191         super.performFinalize(view, model, parent);
192 
193         // if ajax, just render a placeholder
194         if (useAjaxCallForContent) {
195             setProgressiveRenderViaAJAX(useAjaxCallForContent);
196             setProgressiveRender("");
197             setRender(false);
198         }
199     }
200 
201     // Getters and Setters
202 
203     /**
204      * Returns the text to be displayed as the prompt or main message in this simple dialog
205      *
206      * @return String containing the prompt text
207      */
208 
209     @BeanTagAttribute(name = "promptText")
210     public String getPromptText() {
211         return promptText;
212     }
213 
214     /**
215      * Sets the text String to display as the main message in this dialog
216      *
217      * @param promptText - the String to be displayed as the main message
218      */
219     public void setPromptText(String promptText) {
220         this.promptText = promptText;
221     }
222 
223     /**
224      * Retrieves the Message element for this dialog
225      *
226      * @return Message - the text element containing the message string
227      */
228     @BeanTagAttribute(name = "prompt", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
229     public MessageField getPrompt() {
230         return prompt;
231     }
232 
233     /**
234      * Sets the prompt Message for this dialog
235      *
236      * @param prompt - The Message element for this dialog
237      */
238     public void setPrompt(MessageField prompt) {
239         this.prompt = prompt;
240     }
241 
242     /**
243      * Retrieves the explanation InputField used to gather user input text from the dialog
244      *
245      * <p>
246      * By default, the control for this input is configured as a TextAreaControl. It may be configured for
247      * other types of input fields.
248      * </p>
249      *
250      * @return InputField component
251      */
252     @BeanTagAttribute(name = "explanation", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
253     public InputField getExplanation() {
254         return explanation;
255     }
256 
257     /**
258      * Sets the InputField for gathering user text input
259      *
260      * @param explanation - InputField
261      */
262     public void setExplanation(InputField explanation) {
263         this.explanation = explanation;
264     }
265 
266     /**
267      * determines if the explanation InputField is to be displayed in this dialog
268      *
269      * <p>
270      * False by default.
271      * </p>
272      *
273      * @return boolean - true if this user input is to be rendered, false if not.
274      */
275     @BeanTagAttribute(name = "displayExplanation")
276     public boolean isDisplayExplanation() {
277         return displayExplanation;
278     }
279 
280     /**
281      * Sets whether to display the Explanation InputField on this dialog
282      *
283      * @param displayExplanation - true if explanation control is to be displayed, false if not
284      */
285     public void setDisplayExplanation(boolean displayExplanation) {
286         this.displayExplanation = displayExplanation;
287     }
288 
289     /**
290      * Gets the choices provided for user response.
291      *
292      * <p>
293      * A List of KeyValue pairs for each of the choices provided on this dialog.
294      * </p>
295      *
296      * @return the List of response actions to provide the user.
297      */
298     @BeanTagAttribute(name = "availableResponses", type = BeanTagAttribute.AttributeType.LISTBEAN)
299     public List<KeyValue> getAvailableResponses() {
300         return availableResponses;
301     }
302 
303     /**
304      * Sets the list of user responses to provide on this dialog
305      *
306      * @param availableResponses - a List of KeyValue pairs representing the user response choices
307      */
308     public void setAvailableResponses(List<KeyValue> availableResponses) {
309         this.availableResponses = availableResponses;
310     }
311 
312     /**
313      * Retrieves the InputField containing the choices displayed in this dialog
314      *
315      * <p>
316      * By default, this InputField is configured to be a HorizontalCheckboxControl.
317      * Styling is then used to make the checkboxes appear to be buttons.
318      * The values of the availableResponses List are used as labels for the "buttons".
319      * </p>
320      *
321      * @return InputField component within this dialog
322      */
323     @BeanTagAttribute(name = "responseInputField", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
324     public InputField getResponseInputField() {
325         return responseInputField;
326     }
327 
328     /**
329      * Sets the type of InputField used to display the user choices in this dialog
330      *
331      * @param responseInputField - A component used to display the response choices
332      */
333     public void setResponseInputField(InputField responseInputField) {
334         this.responseInputField = responseInputField;
335     }
336 
337     /**
338      * Determines the positioning order of the choices displayed on this dialog
339      *
340      * <p>
341      * Some page designers like the positive choice on the left and the negative choice on the right.
342      * Others, prefer just the opposite. This allows the order to easily be switched.
343      * </p>
344      *
345      * @return - true if choices left to right
346      *         false if choices right to left
347      */
348     @BeanTagAttribute(name = "reverseButtonOrder")
349     public boolean isReverseButtonOrder() {
350         return reverseButtonOrder;
351     }
352 
353     /**
354      * Sets the display order of the choices displayed on this dialog
355      *
356      * <p>
357      * By default, the choices are displayed left to right
358      * </p>
359      *
360      * @param reverseButtonOrder - true if buttons displayed left to right, false if right to left
361      */
362     public void setReverseButtonOrder(boolean reverseButtonOrder) {
363         this.reverseButtonOrder = reverseButtonOrder;
364     }
365 
366     /**
367      * Indicates which approach is used to fill the lightbox content for this dialog.
368      *
369      * <p>
370      * Two techniques are used for filling the content of the lightbox when displaying this dialog.
371      * <ul>
372      * <li>a hidden group on the page is used as content</li>
373      * <li>an ajax call is made to the server to get the content</li>
374      * </ul>
375      * The default approach is to use a hidden form.
376      * </p>
377      *
378      * @return boolean
379      */
380     @BeanTagAttribute(name = "useAjaxCallForContent")
381     public boolean isUseAjaxCallForContent() {
382         return useAjaxCallForContent;
383     }
384 
385     /**
386      * Sets whether the content for the dialog will be filled via ajax call or hidden group
387      *
388      * @param useAjaxCallForContent - boolean set to true if ajax call is used to get content,
389      * false if hidden group is used for content.
390      */
391     public void setUseAjaxCallForContent(boolean useAjaxCallForContent) {
392         this.useAjaxCallForContent = useAjaxCallForContent;
393     }
394 
395 }