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.gwt.client.ui.input; 029 030import org.opencms.gwt.client.I_CmsHasInit; 031import org.opencms.gwt.client.property.CmsPropertySelectBox; 032import org.opencms.gwt.client.ui.CmsPushButton; 033import org.opencms.gwt.client.ui.I_CmsAutoHider; 034import org.opencms.gwt.client.ui.I_CmsButton; 035import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle; 036import org.opencms.gwt.client.ui.css.I_CmsInputLayoutBundle; 037import org.opencms.gwt.client.ui.history.CmsPropertyComboBox; 038import org.opencms.gwt.client.ui.input.form.CmsWidgetFactoryRegistry; 039import org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory; 040 041import java.util.HashMap; 042import java.util.Map; 043 044import com.google.common.base.Optional; 045import com.google.gwt.event.dom.client.ClickEvent; 046import com.google.gwt.event.dom.client.ClickHandler; 047import com.google.gwt.event.logical.shared.HasValueChangeHandlers; 048import com.google.gwt.event.logical.shared.ValueChangeHandler; 049import com.google.gwt.event.shared.HandlerRegistration; 050import com.google.gwt.user.client.ui.Composite; 051import com.google.gwt.user.client.ui.FlowPanel; 052 053/** 054 * Hybrid select / combo box widget.<p> 055 * 056 * This widget behaves like a select box, until a button on it is pressed, after which the select box is transformed into a combo box. 057 * The reason for this is that the combo box always displays the currently selected value itself, rather than the label from the widget configuration, 058 * which may be confusing to nontechnical users in some cases. 059 */ 060public class CmsSelectComboBox extends Composite 061implements I_CmsFormWidget, I_CmsHasInit, HasValueChangeHandlers<String>, I_CmsHasGhostValue { 062 063 /** Widget type identifier for the configuration. */ 064 public static final String WIDGET_TYPE = "selectcombo"; 065 066 /** Widget type identifier for the widget to use in the property dialog. */ 067 private static final String WIDGET_TYPE_PROP = "selectcombo_prop"; 068 069 /** The panel containing the actual widgets. */ 070 private FlowPanel m_panel = new FlowPanel(); 071 072 /** The select box initially displayed by this widget. */ 073 private CmsSelectBox m_selectBox; 074 075 /** The options for the widget. */ 076 private Map<String, String> m_options; 077 078 /** The combo box (initially null). */ 079 private CmsComboBox m_comboBox; 080 081 /** True if the widget was switched from select box mode to combo box mode. */ 082 private boolean m_comboMode; 083 084 /** An error which has been set before. */ 085 private String m_error; 086 087 /** 088 * Creates a new widget instance.<p> 089 * 090 * @param options the widget options 091 * @param forProperties if true, use the special widget versions for the property dialog 092 * @param nullOption true if null option should be added 093 */ 094 public CmsSelectComboBox(Map<String, String> options, boolean forProperties, boolean nullOption) { 095 096 m_options = options; 097 m_selectBox = forProperties 098 ? new CmsPropertySelectBox(new HashMap<>(options)) 099 : new CmsSelectBox(new HashMap<>(options), nullOption); 100 m_comboBox = forProperties 101 ? new CmsPropertyComboBox(new HashMap<>(m_options)) 102 : new CmsComboBox(new HashMap<>(m_options), nullOption); 103 m_panel.add(m_selectBox); 104 CmsPushButton comboButton = new CmsPushButton(); 105 comboButton.setButtonStyle(ButtonStyle.FONT_ICON, null); 106 comboButton.setImageClass(I_CmsButton.PEN_SMALL); 107 comboButton.addStyleName(I_CmsInputLayoutBundle.INSTANCE.inputCss().selectComboIcon()); 108 m_selectBox.addWidget(comboButton); 109 comboButton.addClickHandler(new ClickHandler() { 110 111 public void onClick(ClickEvent event) { 112 113 enableComboMode(); 114 } 115 }); 116 117 initWidget(m_panel); 118 } 119 120 /** 121 * Initializes this class.<p> 122 */ 123 public static void initClass() { 124 125 CmsWidgetFactoryRegistry.instance().registerFactory(WIDGET_TYPE, new I_CmsFormWidgetFactory() { 126 127 /** 128 * @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory#createWidget(java.util.Map, com.google.common.base.Optional) 129 */ 130 public I_CmsFormWidget createWidget(Map<String, String> widgetParams, Optional<String> defaultValue) { 131 132 return new CmsSelectComboBox(widgetParams, false, true); 133 } 134 }); 135 CmsWidgetFactoryRegistry.instance().registerFactory( 136 WIDGET_TYPE + CmsSelectBox.NOTNULL_SUFFIX, 137 new I_CmsFormWidgetFactory() { 138 139 /** 140 * @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory#createWidget(java.util.Map, com.google.common.base.Optional) 141 */ 142 public I_CmsFormWidget createWidget(Map<String, String> widgetParams, Optional<String> defaultValue) { 143 144 return new CmsSelectComboBox(widgetParams, false, false); 145 } 146 }); 147 CmsWidgetFactoryRegistry.instance().registerFactory(WIDGET_TYPE_PROP, new I_CmsFormWidgetFactory() { 148 149 /** 150 * @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory#createWidget(java.util.Map, com.google.common.base.Optional) 151 */ 152 public I_CmsFormWidget createWidget(Map<String, String> widgetParams, Optional<String> defaultValue) { 153 154 return new CmsSelectComboBox(widgetParams, true, false); 155 } 156 }); 157 158 } 159 160 /** 161 * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler) 162 */ 163 public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) { 164 165 final HandlerRegistration r1 = m_selectBox.addValueChangeHandler(handler); 166 final HandlerRegistration r2 = m_comboBox.addValueChangeHandler(handler); 167 return new HandlerRegistration() { 168 169 public void removeHandler() { 170 171 r1.removeHandler(); 172 r2.removeHandler(); 173 } 174 }; 175 } 176 177 /** 178 * Returns whether the select options are being displayed below or above the widget.<p> 179 * 180 * @return <code>true</code> in case the select options are displayed above the widget 181 */ 182 public boolean displayingAbove() { 183 184 return getActiveWidget().displayingAbove(); 185 } 186 187 /** 188 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getApparentValue() 189 */ 190 public String getApparentValue() { 191 192 return getActiveWidget().getApparentValue(); 193 } 194 195 /** 196 * Gets the combo box instance.<p> 197 * 198 * @return the combo box 199 */ 200 public CmsComboBox getComboBox() { 201 202 return m_comboBox; 203 } 204 205 /** 206 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFieldType() 207 */ 208 public FieldType getFieldType() { 209 210 return getActiveWidget().getFieldType(); 211 } 212 213 /** 214 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFormValue() 215 */ 216 public Object getFormValue() { 217 218 return getActiveWidget().getFormValue(); 219 } 220 221 /** 222 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFormValueAsString() 223 */ 224 public String getFormValueAsString() { 225 226 return getActiveWidget().getFormValueAsString(); 227 } 228 229 /** 230 * Gets the select box instance.<p> 231 * 232 * @return the select box instance 233 */ 234 public CmsSelectBox getSelectBox() { 235 236 return m_selectBox; 237 } 238 239 /** 240 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#isEnabled() 241 */ 242 public boolean isEnabled() { 243 244 return getActiveWidget().isEnabled(); 245 } 246 247 /** 248 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#reset() 249 */ 250 public void reset() { 251 252 getActiveWidget().reset(); 253 } 254 255 /** 256 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setAutoHideParent(org.opencms.gwt.client.ui.I_CmsAutoHider) 257 */ 258 public void setAutoHideParent(I_CmsAutoHider autoHideParent) { 259 260 // do nothing 261 } 262 263 /** 264 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setEnabled(boolean) 265 */ 266 public void setEnabled(boolean enabled) { 267 268 getActiveWidget().setEnabled(enabled); 269 } 270 271 /** 272 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setErrorMessage(java.lang.String) 273 */ 274 public void setErrorMessage(String errorMessage) { 275 276 m_error = errorMessage; 277 278 getActiveWidget().setErrorMessage(errorMessage); 279 } 280 281 /** 282 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setFormValueAsString(java.lang.String) 283 */ 284 public void setFormValueAsString(String value) { 285 286 getActiveWidget().setFormValueAsString(value); 287 } 288 289 /** 290 * @see org.opencms.gwt.client.ui.input.I_CmsHasGhostValue#setGhostMode(boolean) 291 */ 292 public void setGhostMode(boolean enable) { 293 294 m_selectBox.setGhostMode(enable); 295 m_comboBox.setGhostMode(enable); 296 } 297 298 /** 299 * @see org.opencms.gwt.client.ui.input.I_CmsHasGhostValue#setGhostValue(java.lang.String, boolean) 300 */ 301 public void setGhostValue(String value, boolean isGhostMode) { 302 303 m_selectBox.setGhostValue(value, isGhostMode); 304 m_comboBox.setGhostValue(value, isGhostMode); 305 } 306 307 /** 308 * Switches to combo box mode.<p> 309 */ 310 protected void enableComboMode() { 311 312 String value = m_selectBox.getFormValueAsString(); 313 m_selectBox.removeFromParent(); 314 m_comboMode = true; 315 m_panel.add(m_comboBox); 316 m_comboBox.setFormValueAsString(value); 317 m_comboBox.setErrorMessage(m_error); 318 m_comboBox.setEnabled(m_selectBox.isEnabled()); 319 } 320 321 /** 322 * Gets the active widget (select or combo box).<p> 323 * 324 * @return the active widget 325 */ 326 private A_CmsSelectBox<?> getActiveWidget() { 327 328 if (m_comboMode) { 329 return m_comboBox; 330 } else { 331 return m_selectBox; 332 } 333 } 334 335}