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.Messages; 032import org.opencms.gwt.client.ui.I_CmsAutoHider; 033import org.opencms.gwt.client.ui.input.form.CmsWidgetFactoryRegistry; 034import org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory; 035import org.opencms.gwt.client.util.CmsMessages; 036import org.opencms.util.CmsStringUtil; 037 038import java.util.HashMap; 039import java.util.Map; 040 041import com.google.common.base.Optional; 042import com.google.gwt.user.client.ui.FocusPanel; 043 044/** 045 * Widget for selecting one of multiple items from a drop-down list which opens 046 * after the user clicks on the widget.<p> 047 * 048 * @since 8.0.0 049 * 050 */ 051public class CmsSelectBox extends A_CmsSelectBox<CmsLabelSelectCell> implements I_CmsHasInit, I_CmsHasGhostValue { 052 053 /** The key for the text which should be displayed in the opener if no option is available. */ 054 public static final String NO_SELECTION_OPENER_TEXT = "%NO_SELECTION_OPENER_TEXT%"; 055 056 /** The key for the text which should be displayed if no option is available. */ 057 public static final String NO_SELECTION_TEXT = "%NO_SELECTION_TEXT%"; 058 059 /** Text metrics key. */ 060 private static final String TM_OPENER_LABEL = "OpenerLabel"; 061 062 /** The widget type identifier. */ 063 public static final String WIDGET_TYPE = "select"; 064 065 /** Suffix for select/selectcombo widget names to prevent creation of 'no selection' value. */ 066 public static final String NOTNULL_SUFFIX = "_notnull"; 067 068 /** Widget type identifier (no null value). */ 069 public static final String WIDGET_TYPE_NOTNULL = WIDGET_TYPE + NOTNULL_SUFFIX; 070 071 /** Widget parameter to control the resize behavior, defaults to 'true'. */ 072 public static final String OPTION_RESIZABLE = "CmsSelectBox_resizable"; 073 074 /** The ghost value. */ 075 protected String m_ghostValue; 076 077 /** The widget displayed in the opener. */ 078 protected CmsLabel m_openerWidget; 079 080 /** A map from select options to their label texts. */ 081 private Map<String, String> m_items; 082 083 /** The text which should be displayed in the opener if there is no selection. */ 084 private String m_noSelectionOpenerText; 085 086 /** The text which should be displayed if there is no selection. */ 087 private String m_noSelectionText; 088 089 /** A map of titles for the select options which should be displayed on mouseover. */ 090 private Map<String, String> m_titles = new HashMap<String, String>(); 091 092 /** 093 * Default constructor.<p> 094 */ 095 public CmsSelectBox() { 096 097 super(); 098 099 } 100 101 /** 102 * Constructs a new select box from a map.<p> 103 * 104 * The keys of the map are the values of the select options, and the values of the map are the labels to be displayed 105 * for each option. 106 * 107 * @param items the map of select options 108 */ 109 public CmsSelectBox(Map<String, String> items) { 110 111 this(); 112 setItems(items); 113 } 114 115 /** 116 * Creates a new select box, with the option of adding a "not selected" choice.<p> 117 * 118 * @param items the map of select options 119 * @param addNullOption if true, a "not selected" option will be added to the select box 120 */ 121 public CmsSelectBox(Map<String, String> items, boolean addNullOption) { 122 123 this(); 124 String resizable = items.remove(OPTION_RESIZABLE); 125 if ((resizable != null) && Boolean.FALSE.toString().equals(resizable)) { 126 setPopupResize(false); 127 } 128 if (items.containsKey(NO_SELECTION_TEXT)) { 129 m_noSelectionText = items.get(NO_SELECTION_TEXT); 130 m_noSelectionOpenerText = items.get(NO_SELECTION_OPENER_TEXT); 131 if (m_noSelectionOpenerText == null) { 132 m_noSelectionOpenerText = m_noSelectionText; 133 } 134 items.remove(NO_SELECTION_TEXT); 135 items.remove(NO_SELECTION_OPENER_TEXT); 136 } 137 if (addNullOption) { 138 String text = Messages.get().key(Messages.GUI_SELECTBOX_EMPTY_SELECTION_0); 139 items.put("", text); 140 } 141 setItems(items); 142 if (addNullOption) { 143 selectValue(""); 144 } 145 } 146 147 /** 148 * Initializes this class.<p> 149 */ 150 public static void initClass() { 151 152 // registers a factory for creating new instances of this widget 153 CmsWidgetFactoryRegistry.instance().registerFactory(WIDGET_TYPE, new I_CmsFormWidgetFactory() { 154 155 /** 156 * @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory#createWidget(java.util.Map, com.google.common.base.Optional) 157 */ 158 public I_CmsFormWidget createWidget(Map<String, String> widgetParams, Optional<String> defaultValue) { 159 160 return new CmsSelectBox(widgetParams, true); 161 } 162 }); 163 164 CmsWidgetFactoryRegistry.instance().registerFactory(WIDGET_TYPE_NOTNULL, new I_CmsFormWidgetFactory() { 165 166 /** 167 * @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory#createWidget(java.util.Map, com.google.common.base.Optional) 168 */ 169 public I_CmsFormWidget createWidget(Map<String, String> widgetParams, Optional<String> defaultValue) { 170 171 return new CmsSelectBox(widgetParams, false); 172 } 173 }); 174 175 } 176 177 /** 178 * Adds a new selection cell.<p> 179 * 180 * @param value the value of the select option 181 * @param text the text to be displayed for the select option 182 */ 183 public void addOption(String value, String text) { 184 185 String title = getTitle(value, text); 186 CmsLabelSelectCell cell = new CmsLabelSelectCell(value, text, title); 187 addOption(cell); 188 } 189 190 /** 191 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getApparentValue() 192 */ 193 public String getApparentValue() { 194 195 String val = getFormValueAsString(); 196 if (val == null) { 197 val = m_ghostValue; 198 } 199 return val; 200 201 } 202 203 /** 204 * Returns the items as a map for option values to label text.<p> 205 * 206 * @return the items as a map for option values to label text 207 */ 208 public Map<String, String> getItems() { 209 210 return m_items; 211 } 212 213 /** 214 * Returns the opener of this widget.<p> 215 * 216 * @return the opener of this widget 217 */ 218 public FocusPanel getOpener() { 219 220 return m_opener; 221 } 222 223 /** 224 * @see org.opencms.gwt.client.ui.input.A_CmsSelectBox#selectValue(java.lang.String) 225 */ 226 @Override 227 public void selectValue(String value) { 228 229 super.selectValue(value); 230 updateStyle(); 231 } 232 233 /** 234 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setAutoHideParent(org.opencms.gwt.client.ui.I_CmsAutoHider) 235 */ 236 public void setAutoHideParent(I_CmsAutoHider autoHideParent) { 237 238 // nothing to do 239 240 } 241 242 /** 243 * @see org.opencms.gwt.client.ui.input.I_CmsHasGhostValue#setGhostMode(boolean) 244 */ 245 public void setGhostMode(boolean ghostMode) { 246 247 // do nothing for now 248 249 } 250 251 /** 252 * @see org.opencms.gwt.client.ui.input.I_CmsHasGhostValue#setGhostValue(java.lang.String, boolean) 253 */ 254 public void setGhostValue(String value, boolean ghostMode) { 255 256 if (value == null) { 257 value = ""; 258 } 259 String otherOptionText = m_items.get(value); 260 String message = m_noSelectionText != null 261 ? m_noSelectionText 262 : Messages.get().key(Messages.GUI_SELECTBOX_EMPTY_SELECTION_1); 263 message = CmsMessages.formatMessage(message, otherOptionText); 264 //setTextForNullSelection(message); 265 m_ghostValue = value; 266 updateCells(); 267 if (ghostMode) { 268 selectValue(""); 269 } 270 } 271 272 /** 273 * Sets the items using a map from option values to label texts.<p> 274 * 275 * @param items the map containing the select options 276 */ 277 public void setItems(Map<String, String> items) { 278 279 clearItems(); 280 m_items = items; 281 for (Map.Entry<String, String> entry : items.entrySet()) { 282 addOption(entry.getKey(), entry.getValue()); 283 } 284 } 285 286 /** 287 * Sets the text that is used for the "not selected" option.<p> 288 * 289 * @param text the text which should be used for the "not selected" option 290 */ 291 public void setTextForNullSelection(String text) { 292 293 // do nothing if there's no null option 294 CmsLabelSelectCell cell = m_selectCells.get(""); 295 if (cell == null) { 296 return; 297 } 298 cell.setText(text); 299 // if the null option is selected, we still need to update the opener 300 if (CmsStringUtil.isEmptyOrWhitespaceOnly(m_selectedValue)) { 301 selectValue(""); 302 } 303 } 304 305 /** 306 * Sets the title for a select option.<p> 307 * 308 * Note: This will only affect select options added *after* calling this method! 309 * 310 * @param option the select option value 311 * @param title the new title for the option 312 */ 313 public void setTitle(String option, String title) { 314 315 m_titles.put(option, title); 316 } 317 318 /** 319 * @see org.opencms.gwt.client.ui.input.A_CmsSelectBox#truncateOpener(java.lang.String, int) 320 */ 321 @Override 322 public void truncateOpener(String prefix, int width) { 323 324 m_openerWidget.truncate(prefix + '_' + TM_OPENER_LABEL, width); 325 } 326 327 /** 328 * Updates a single select cell.<p> 329 * 330 * @param cell the select cell to update 331 */ 332 public void updateCell(CmsLabelSelectCell cell) { 333 334 // do nothing 335 } 336 337 /** 338 * Updates the select cells.<p> 339 */ 340 public void updateCells() { 341 342 for (CmsLabelSelectCell cell : m_selectCells.values()) { 343 updateCell(cell); 344 } 345 } 346 347 /** 348 * @see org.opencms.gwt.client.ui.input.A_CmsSelectBox#createUnknownOption(java.lang.String) 349 */ 350 @Override 351 protected CmsLabelSelectCell createUnknownOption(String value) { 352 353 CmsLabelSelectCell cell = new CmsLabelSelectCell(value, value); 354 return cell; 355 356 } 357 358 /** 359 * Helper method to get the title for a given select option.<p> 360 * 361 * @param option the select option value 362 * @param defaultValue the value to return when no title for the value was found 363 * 364 * @return the title for the select option 365 */ 366 protected String getTitle(String option, String defaultValue) { 367 368 String result; 369 if ((option != null) && m_titles.containsKey(option)) { 370 result = m_titles.get(option); 371 } else { 372 result = defaultValue; 373 } 374 if (result != null) { 375 result = result.trim(); 376 } 377 return result; 378 } 379 380 /** 381 * @see org.opencms.gwt.client.ui.input.A_CmsSelectBox#initOpener() 382 */ 383 @Override 384 protected void initOpener() { 385 386 m_openerWidget = new CmsLabel(); 387 m_openerWidget.addStyleName(CSS.selectBoxOpener()); 388 m_opener.add(m_openerWidget); 389 } 390 391 /** 392 * @see com.google.gwt.user.client.ui.Widget#onLoad() 393 */ 394 @Override 395 protected void onLoad() { 396 397 super.onLoad(); 398 updateStyle(); 399 } 400 401 /** 402 * @see org.opencms.gwt.client.ui.input.A_CmsSelectBox#updateOpener(java.lang.String) 403 */ 404 @Override 405 protected void updateOpener(String newValue) { 406 407 CmsLabel label = m_openerWidget; 408 CmsLabelSelectCell cell = m_selectCells.get(newValue); 409 String openerText = cell.getOpenerText(); 410 label.setText(openerText); 411 label.setTitle(getTitle(cell.getValue(), openerText)); 412 } 413 414 /** 415 * This method should be used to make changes to the CSS style of the select box when the value changes.<p> 416 */ 417 protected void updateStyle() { 418 419 // do nothing 420 } 421}