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