View Javadoc
1   /**
2    * This file Copyright (c) 2003-2014 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.cms.gui.dialog;
35  
36  import info.magnolia.cms.core.Content;
37  import info.magnolia.cms.gui.control.Button;
38  import info.magnolia.cms.gui.control.ButtonSet;
39  import info.magnolia.cms.gui.control.ControlImpl;
40  import info.magnolia.cms.gui.control.Hidden;
41  import info.magnolia.cms.gui.misc.CssConstants;
42  import info.magnolia.cms.security.AccessDeniedException;
43  import info.magnolia.cms.util.ContentUtil;
44  import info.magnolia.cms.util.NodeDataUtil;
45  import info.magnolia.repository.RepositoryConstants;
46  
47  import java.io.IOException;
48  import java.io.Writer;
49  import java.util.ArrayList;
50  import java.util.Collection;
51  import java.util.Iterator;
52  import java.util.List;
53  
54  import javax.jcr.PathNotFoundException;
55  import javax.jcr.PropertyType;
56  import javax.jcr.RepositoryException;
57  import javax.servlet.http.HttpServletRequest;
58  import javax.servlet.http.HttpServletResponse;
59  
60  import org.apache.commons.lang.StringUtils;
61  import org.slf4j.Logger;
62  import org.slf4j.LoggerFactory;
63  
64  
65  /**
66   * @author Vinzenz Wyser
67   * @version 2.0
68   */
69  public class DialogButtonSet extends DialogBox {
70  
71      /**
72       * Logger.
73       */
74      private static Logger log = LoggerFactory.getLogger(DialogButtonSet.class);
75  
76      private int buttonType = ControlImpl.BUTTONTYPE_RADIO;
77  
78      public void setOptions(Content configNode, boolean setDefaultSelected) {
79          // setDefaultSelected: does not work properly (no difference between never stored and removed...)
80          // therefore do only use for radio, not for checkbox
81          List options = new ArrayList();
82          try {
83              Iterator it = getOptionNodes(configNode).iterator();
84              while (it.hasNext()) {
85                  Content n = ((Content) it.next());
86                  String valueNodeData = this.getConfigValue("valueNodeData", "value");
87                  String labelNodeData = this.getConfigValue("labelNodeData", "label");
88  
89                  String value = NodeDataUtil.getString(n, valueNodeData);//$NON-NLS-1$
90                  String label = NodeDataUtil.getString(n, labelNodeData);//$NON-NLS-1$
91  
92                  //label = this.getMessage(label);
93                  Button button = new Button(this.getName(), value);
94                  // if (n.getNodeData("label").isExist()) button.setLabel(n.getNodeData("label").getString());
95                  button.setLabel(label);
96  
97                  String iconSrc = n.getNodeData("iconSrc").getString(); //$NON-NLS-1$
98                  if (StringUtils.isNotEmpty(iconSrc)) {
99                      button.setIconSrc(iconSrc);
100                 }
101 
102                 if (setDefaultSelected && n.getNodeData("selected").getBoolean()) { //$NON-NLS-1$
103                     button.setState(ControlImpl.BUTTONSTATE_PUSHED);
104                 }
105                 options.add(button);
106             }
107         }
108         catch (RepositoryException e) {
109             if (log.isDebugEnabled()) {
110                 log.debug("Exception caught: " + e.getMessage(), e); //$NON-NLS-1$
111             }
112         }
113         this.setOptions(options);
114     }
115 
116     protected Collection getOptionNodes(Content configNode) throws PathNotFoundException, RepositoryException, AccessDeniedException {
117         Content optionsNode = null;
118 
119         if(configNode.hasContent("options")){
120             optionsNode = configNode.getContent("options"); //$NON-NLS-1$
121         }
122         else{
123             String repository = this.getConfigValue("repository", RepositoryConstants.WEBSITE);
124             String path = this.getConfigValue("path");
125             if(StringUtils.isNotEmpty(path)){
126                 optionsNode = ContentUtil.getContent(repository, path);
127             }
128         }
129 
130         if(optionsNode != null){
131             return ContentUtil.getAllChildren(optionsNode);
132         }
133         return new ArrayList();
134     }
135 
136     public void setOption(Content configNode) {
137         // checkboxSwitch -> only one option, value always true/false
138         List options = new ArrayList();
139         Button button = new Button(this.getName() + "_dummy", StringUtils.EMPTY);
140         String label = configNode.getNodeData("buttonLabel").getString();
141         //label = this.getMessage(label);
142         button.setLabel(label);
143 
144         if (configNode.getNodeData("selected").getBoolean()) { //$NON-NLS-1$
145             button.setState(ControlImpl.BUTTONSTATE_PUSHED);
146         }
147 
148         button.setValue("true"); //$NON-NLS-1$
149         button.setOnclick("mgnlDialogShiftCheckboxSwitch('" + this.getName() + "');"); //$NON-NLS-1$ //$NON-NLS-2$
150         options.add(button);
151         this.setOptions(options);
152     }
153 
154     /**
155      * @see info.magnolia.cms.gui.dialog.DialogControl#init(HttpServletRequest, HttpServletResponse, Content, Content)
156      */
157     @Override
158     public void init(HttpServletRequest request, HttpServletResponse response, Content websiteNode, Content configNode)
159         throws RepositoryException {
160         super.init(request, response, websiteNode, configNode);
161 
162         // confignode can be null if instantiated directly
163         if (configNode != null) {
164             String controlType = this.getConfigValue("selectType",this.getConfigValue("controlType")); //$NON-NLS-1$
165 
166             if (log.isDebugEnabled()) {
167                 log.debug("Init DialogButtonSet with type=" + controlType); //$NON-NLS-1$
168             }
169 
170             // custom settings
171             if (controlType.equals("radio")) { //$NON-NLS-1$
172                 setButtonType(ControlImpl.BUTTONTYPE_RADIO);
173                 setOptions(configNode, true);
174             }
175             else if (controlType.equals("checkbox")) { //$NON-NLS-1$
176                 setButtonType(ControlImpl.BUTTONTYPE_CHECKBOX);
177                 setOptions(configNode, false);
178                 setConfig("valueType", "multiple"); //$NON-NLS-1$ //$NON-NLS-2$
179             }
180             else if (controlType.equals("checkboxSwitch")) { //$NON-NLS-1$
181                 setButtonType(ControlImpl.BUTTONTYPE_CHECKBOX);
182                 setOption(configNode);
183             }
184         }
185     }
186 
187     @Override
188     public void drawHtmlPreSubs(Writer out) throws IOException {
189         this.drawHtmlPre(out);
190     }
191 
192     @Override
193     public void drawHtmlPostSubs(Writer out) throws IOException {
194         this.drawHtmlPost(out);
195     }
196 
197     public void setButtonType(int i) {
198         this.buttonType = i;
199     }
200 
201     public int getButtonType() {
202         return this.buttonType;
203     }
204 
205     /**
206      * @see info.magnolia.cms.gui.dialog.DialogControl#drawHtml(Writer)
207      */
208     @Override
209     public void drawHtml(Writer out) throws IOException {
210         this.drawHtmlPre(out);
211 
212         for (int i = 0; i < this.getOptions().size(); i++) {
213             Button b = (Button) this.getOptions().get(i);
214          // translate
215             b.setLabel(this.getMessage(b.getLabel()));
216             if(b.getName().endsWith("_dummy")){
217                 b.setName(this.getName() + "_dummy");
218                 b.setOnclick("mgnlDialogShiftCheckboxSwitch('" + this.getName() + "');");
219             }else if(this.getName().startsWith(b.getName() + "_")){
220                 b.setName(this.getName());
221             }
222         }
223 
224         ButtonSet control;
225         if (this.getConfigValue("valueType").equals("multiple")) { //$NON-NLS-1$ //$NON-NLS-2$
226             // checkbox
227             control = new ButtonSet(this.getName(), this.getValues());
228             control.setValueType(ControlImpl.VALUETYPE_MULTIPLE);
229         }
230         else if (this.getButtonType() == ControlImpl.BUTTONTYPE_CHECKBOX) {
231             // checkboxSwitch
232             control = new ButtonSet(this.getName() + "_SWITCH", this.getValue()); //$NON-NLS-1$
233         }
234         else {
235             // radio
236             control = new ButtonSet(this.getName(), this.getValue());
237         }
238         control.setButtonType(this.getButtonType());
239 
240         // maem: extension to allow for fine grained layout control. E.g. radio buttons with picture
241         control.setCssClass(this.getConfigValue("cssClass", CssConstants.CSSCLASS_BUTTONSETBUTTON)); //$NON-NLS-1$
242 
243         if (this.getConfigValue("saveInfo").equals("false")) { //$NON-NLS-1$ //$NON-NLS-2$
244             control.setSaveInfo(false);
245         }
246         final String type = this.getConfigValue("type", PropertyType.TYPENAME_STRING);
247         control.setType(type); //$NON-NLS-1$
248         String width = this.getConfigValue("width", null); //$NON-NLS-1$
249         control.setButtonHtmlPre("<tr><td class=\"" + CssConstants.CSSCLASS_BUTTONSETBUTTON + "\">"); //$NON-NLS-1$ //$NON-NLS-2$
250         control.setButtonHtmlInter("</td><td class=\"" + CssConstants.CSSCLASS_BUTTONSETLABEL + "\">"); //$NON-NLS-1$ //$NON-NLS-2$
251         control.setButtonHtmlPost("</td></tr>"); //$NON-NLS-1$
252         int cols = Integer.valueOf(this.getConfigValue("cols", "1")).intValue(); //$NON-NLS-1$ //$NON-NLS-2$
253         if (cols > 1) {
254             width = "100%"; // outer table squeezes inner table if outer's width is not defined... //$NON-NLS-1$
255             control.setHtmlPre(control.getHtmlPre() + "<tr>"); //$NON-NLS-1$
256             control.setHtmlPost("</tr>" + control.getHtmlPost()); //$NON-NLS-1$
257             int item = 1;
258             int itemsPerCol = (int) Math.ceil(this.getOptions().size() / ((double) cols));
259             for (int i = 0; i < this.getOptions().size(); i++) {
260                 Button b = (Button) this.getOptions().get(i);
261                 if (item == 1) {
262                     b.setHtmlPre("<td><table cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" //$NON-NLS-1$
263                         + control.getButtonHtmlPre());
264                 }
265                 if (item == itemsPerCol) {
266                     b.setHtmlPost(control.getButtonHtmlPost() + "</table></td><td class=\"" //$NON-NLS-1$
267                         + CssConstants.CSSCLASS_BUTTONSETINTERCOL
268                         + "\"></td>"); //$NON-NLS-1$
269                     item = 1;
270                 }
271                 else {
272                     item++;
273                 }
274             }
275             // very last button: close table
276             int lastIndex = this.getOptions().size() - 1;
277             // avoid ArrayIndexOutOfBoundsException, but should not happen
278             if (lastIndex > -1) {
279                 ((Button) this.getOptions().get(lastIndex)).setHtmlPost(control.getButtonHtmlPost() + "</table>"); //$NON-NLS-1$
280             }
281         }
282         if (width != null) {
283             control.setHtmlPre("<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"" + width + "\">"); //$NON-NLS-1$ //$NON-NLS-2$
284         }
285         control.setButtons(this.getOptions());
286         out.write(control.getHtml());
287         if (control.getButtonType() == ControlImpl.BUTTONTYPE_CHECKBOX
288             && control.getValueType() != ControlImpl.VALUETYPE_MULTIPLE) {
289             // checkboxSwitch: value is stored in a hidden field (allows default selecting)
290             String value = this.getValue();
291             if (StringUtils.isEmpty(value)) {
292                 if (this.getConfigValue("selected").equals("true")) { //$NON-NLS-1$ //$NON-NLS-2$
293                     value = "true"; //$NON-NLS-1$
294                 }
295                 else {
296                     value = "false"; //$NON-NLS-1$
297                 }
298             }
299             Hidden hiddenValueField = new Hidden(this.getName(), value);
300             hiddenValueField.setType(type);
301             hiddenValueField.setSaveInfo(control.getSaveInfo());
302             out.write(hiddenValueField.getHtml());
303         }
304         this.drawHtmlPost(out);
305     }
306 }