001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.acacia.client.widgets; 029 030import org.opencms.acacia.client.css.I_CmsWidgetsLayoutBundle; 031import org.opencms.ade.contenteditor.client.Messages; 032import org.opencms.gwt.client.ui.CmsScrollPanel; 033import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle; 034import org.opencms.gwt.client.ui.input.CmsCheckBox; 035import org.opencms.gwt.client.util.CmsClientStringUtil; 036import org.opencms.gwt.client.util.CmsDomUtil; 037 038import java.util.Iterator; 039import java.util.LinkedList; 040import java.util.List; 041import java.util.Map; 042 043import com.google.gwt.core.client.GWT; 044import com.google.gwt.dom.client.Element; 045import com.google.gwt.dom.client.Style.Unit; 046import com.google.gwt.event.dom.client.FocusEvent; 047import com.google.gwt.event.dom.client.FocusHandler; 048import com.google.gwt.event.logical.shared.ValueChangeEvent; 049import com.google.gwt.event.logical.shared.ValueChangeHandler; 050import com.google.gwt.event.shared.HandlerRegistration; 051import com.google.gwt.user.client.ui.Composite; 052import com.google.gwt.user.client.ui.FlowPanel; 053import com.google.gwt.user.client.ui.SimplePanel; 054 055/** 056 * Provides a widget for a standard HTML form for a group of radio buttons.<p> 057 * 058 * Regarding widget configuration, see <code>{@link org.opencms.acacia.client.widgets.CmsSelectConfigurationParser}</code>.<p> 059 * 060 * */ 061public class CmsMultiSelectWidget extends Composite implements I_CmsEditWidget { 062 063 /** Configuration parameter to indicate the multi-select needs to be activated by a check box. */ 064 public static final String CONFIGURATION_REQUIRES_ACTIVATION = "|requiresactivation"; 065 066 /** Default value of rows to be shown. */ 067 private static final int DEFAULT_ROWS_SHOWN = 10; 068 069 /** The main panel of this widget. */ 070 FlowPanel m_panel = new FlowPanel(); 071 072 /** The scroll panel around the multi-selections. */ 073 CmsScrollPanel m_scrollPanel; 074 075 /** Activation button.*/ 076 private CmsCheckBox m_activation; 077 078 /** Value of the activation. */ 079 private boolean m_active = true; 080 081 /** List of all check boxes button. */ 082 private List<CmsCheckBox> m_checkboxes; 083 084 /** The default check boxes set in xsd. */ 085 private List<CmsCheckBox> m_defaultCheckBox; 086 087 /** Value of the requiresactivation. */ 088 private boolean m_requiresactivation; 089 090 /** The parameter set from configuration.*/ 091 private int m_rowsToShow = DEFAULT_ROWS_SHOWN; 092 093 /** 094 * Constructs an OptionalTextBox with the given caption on the check.<p> 095 * @param config the configuration string. 096 */ 097 public CmsMultiSelectWidget(String config) { 098 099 FlowPanel main = new FlowPanel(); 100 m_scrollPanel = GWT.create(CmsScrollPanel.class); 101 // add separate style to the panel. 102 m_scrollPanel.addStyleName(I_CmsWidgetsLayoutBundle.INSTANCE.widgetCss().radioButtonPanel()); 103 104 if (config.contains(CONFIGURATION_REQUIRES_ACTIVATION)) { 105 config = config.replace(CONFIGURATION_REQUIRES_ACTIVATION, ""); 106 m_requiresactivation = true; 107 } 108 CmsSelectConfigurationParser parser = new CmsSelectConfigurationParser(config); 109 // generate a list of all radio button. 110 m_defaultCheckBox = new LinkedList<CmsCheckBox>(); 111 m_checkboxes = new LinkedList<CmsCheckBox>(); 112 if (m_requiresactivation) { 113 114 buildActivationButton(); 115 SimplePanel activation = new SimplePanel(m_activation); 116 activation.addStyleName(I_CmsWidgetsLayoutBundle.INSTANCE.widgetCss().radioButtonPanel()); 117 activation.getElement().getStyle().setMarginBottom(5, Unit.PX); 118 main.add(activation); 119 } 120 FocusHandler focusHandler = new FocusHandler() { 121 122 public void onFocus(FocusEvent event) { 123 124 CmsDomUtil.fireFocusEvent(CmsMultiSelectWidget.this); 125 } 126 }; 127 128 for (Map.Entry<String, String> entry : parser.getOptions().entrySet()) { 129 CmsCheckBox checkbox = new CmsCheckBox(entry.getValue()); 130 checkbox.setInternalValue(entry.getKey()); 131 if (parser.getDefaultValues().contains(entry.getKey())) { 132 m_defaultCheckBox.add(checkbox); 133 } 134 checkbox.addValueChangeHandler(new ValueChangeHandler<Boolean>() { 135 136 public void onValueChange(ValueChangeEvent<Boolean> event) { 137 138 fireChangeEvent(); 139 140 } 141 142 }); 143 // add a separate style each checkbox . 144 checkbox.addStyleName(I_CmsWidgetsLayoutBundle.INSTANCE.widgetCss().checkboxlabel()); 145 checkbox.getButton().addFocusHandler(focusHandler); 146 m_checkboxes.add(checkbox); 147 // add the checkbox to the panel. 148 m_panel.add(checkbox); 149 150 } 151 // All composites must call initWidget() in their constructors. 152 m_scrollPanel.add(m_panel); 153 m_scrollPanel.setResizable(false); 154 155 int inputHeight = CmsClientStringUtil.parseInt(I_CmsLayoutBundle.INSTANCE.constants().css().inputHeight()); 156 157 int height = (m_rowsToShow * inputHeight) + 6; 158 if (m_checkboxes.size() < m_rowsToShow) { 159 height = (m_checkboxes.size() * inputHeight) + 6; 160 } 161 m_scrollPanel.setDefaultHeight(height); 162 m_scrollPanel.setHeight(height + "px"); 163 main.add(m_scrollPanel); 164 initWidget(main); 165 if (m_requiresactivation) { 166 setAllCheckboxEnabled(false); 167 } 168 169 } 170 171 /** 172 * @see com.google.gwt.event.dom.client.HasFocusHandlers#addFocusHandler(com.google.gwt.event.dom.client.FocusHandler) 173 */ 174 public HandlerRegistration addFocusHandler(FocusHandler handler) { 175 176 return addDomHandler(handler, FocusEvent.getType()); 177 } 178 179 /** 180 * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler) 181 */ 182 public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) { 183 184 return addHandler(handler, ValueChangeEvent.getType()); 185 } 186 187 /** 188 * Represents a value change event.<p> 189 * 190 */ 191 public void fireChangeEvent() { 192 193 ValueChangeEvent.fire(this, generateValue()); 194 } 195 196 /** 197 * @see com.google.gwt.user.client.ui.HasValue#getValue() 198 */ 199 public String getValue() { 200 201 return generateValue(); 202 } 203 204 /** 205 * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#isActive() 206 */ 207 public boolean isActive() { 208 209 return m_active; 210 } 211 212 /** 213 * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#onAttachWidget() 214 */ 215 public void onAttachWidget() { 216 217 super.onAttach(); 218 } 219 220 /** 221 * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#owns(com.google.gwt.dom.client.Element) 222 */ 223 public boolean owns(Element element) { 224 225 // TODO implement this in case we want the delete behavior for optional fields 226 return false; 227 228 } 229 230 /** 231 * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#setActive(boolean) 232 */ 233 public void setActive(boolean active) { 234 235 // check if the value has changed. If there is no change do nothing. 236 if (m_active == active) { 237 return; 238 } 239 // set the new value. 240 m_active = active; 241 // Iterate over all checkboxes. 242 for (CmsCheckBox checkbox : m_checkboxes) { 243 // set the checkbox active / inactive. 244 checkbox.setEnabled(active); 245 // if this widget is set inactive. 246 if (active) { 247 // select the default value if set. 248 if (m_defaultCheckBox != null) { 249 Iterator<CmsCheckBox> it = m_defaultCheckBox.iterator(); 250 while (it.hasNext()) { 251 it.next().setChecked(active); 252 } 253 } 254 } 255 } 256 // fire value change event. 257 if (active) { 258 fireChangeEvent(); 259 } 260 261 } 262 263 /** 264 * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#setName(java.lang.String) 265 */ 266 public void setName(String name) { 267 268 // no input field so nothing to do 269 270 } 271 272 /** 273 * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object) 274 */ 275 public void setValue(String value) { 276 277 setValue(value, false); 278 279 } 280 281 /** 282 * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object, boolean) 283 */ 284 public void setValue(String value, boolean fireEvents) { 285 286 String[] values; 287 if ((value != null) && (value != "")) { 288 if (value.contains(",")) { 289 values = value.split(","); 290 } else { 291 values = new String[] {value}; 292 } 293 for (CmsCheckBox checkbox : m_checkboxes) { 294 checkbox.setChecked(false); 295 for (int j = 0; j < values.length; j++) { 296 if (checkbox.getInternalValue().equals(values[j])) { 297 checkbox.setChecked(true); 298 } 299 } 300 } 301 302 } 303 304 // fire change event. 305 if (fireEvents) { 306 fireChangeEvent(); 307 } 308 309 } 310 311 /** 312 * Sets the checkboxes enabled or disabled.<p> 313 * 314 * @param value if it should be enabled or disabled 315 */ 316 protected void setAllCheckboxEnabled(boolean value) { 317 318 for (CmsCheckBox checkbox : m_checkboxes) { 319 // set the checkbox active / inactive. 320 checkbox.setEnabled(value); 321 } 322 } 323 324 /** 325 * Adds a button to activate or deactivate the selection.<p> 326 */ 327 private void buildActivationButton() { 328 329 m_activation = new CmsCheckBox(Messages.get().key(Messages.GUI_MULTISELECT_ACTIVATE_0)); 330 331 m_activation.addStyleName(I_CmsWidgetsLayoutBundle.INSTANCE.widgetCss().checkboxlabel()); 332 m_activation.addValueChangeHandler(new ValueChangeHandler<Boolean>() { 333 334 public void onValueChange(ValueChangeEvent<Boolean> event) { 335 336 setAllCheckboxEnabled(event.getValue().booleanValue()); 337 338 } 339 }); 340 } 341 342 /** 343 * Generate a string with all selected checkboxes separated with ','. 344 * 345 * @return a string with all selected checkboxes 346 * */ 347 private String generateValue() { 348 349 String result = ""; 350 for (CmsCheckBox checkbox : m_checkboxes) { 351 if (checkbox.isChecked()) { 352 result += checkbox.getInternalValue() + ","; 353 } 354 } 355 if (result.contains(",")) { 356 result = result.substring(0, result.lastIndexOf(",")); 357 } 358 return result; 359 } 360}