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.CmsCoreProvider; 031import org.opencms.gwt.client.I_CmsHasInit; 032import org.opencms.gwt.client.Messages; 033import org.opencms.gwt.client.ui.CmsPopup; 034import org.opencms.gwt.client.ui.CmsPushButton; 035import org.opencms.gwt.client.ui.I_CmsAutoHider; 036import org.opencms.gwt.client.ui.css.I_CmsInputLayoutBundle; 037import org.opencms.gwt.client.ui.input.form.CmsWidgetFactoryRegistry; 038import org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory; 039import org.opencms.gwt.client.util.CmsDomUtil; 040import org.opencms.util.CmsStringUtil; 041 042import java.util.Map; 043 044import com.google.common.base.Optional; 045import com.google.gwt.core.client.Scheduler; 046import com.google.gwt.core.client.Scheduler.ScheduledCommand; 047import com.google.gwt.dom.client.Document; 048import com.google.gwt.event.dom.client.BlurEvent; 049import com.google.gwt.event.dom.client.BlurHandler; 050import com.google.gwt.event.dom.client.ClickEvent; 051import com.google.gwt.event.dom.client.ClickHandler; 052import com.google.gwt.event.logical.shared.ValueChangeHandler; 053import com.google.gwt.user.client.ui.Composite; 054import com.google.gwt.user.client.ui.FlowPanel; 055import com.google.gwt.user.client.ui.Label; 056import com.google.gwt.user.client.ui.Panel; 057import com.google.gwt.user.client.ui.SimplePanel; 058import com.google.gwt.user.client.ui.TextBox; 059 060/** 061 * Basic text area widget for forms.<p> 062 * 063 * @since 8.0.0 064 * 065 */ 066public class CmsColorPicker extends Composite implements I_CmsFormWidget, I_CmsHasInit { 067 068 /** The widget type identifier for this widget. */ 069 private static final String WIDGET_TYPE = "colorPicker"; 070 071 /** The color picker JS library path. */ 072 private static final String COLOR_PICKER_JS = "components/widgets/vanilla-picker.min.js"; 073 074 /** The field to display the color. */ 075 protected SimplePanel m_colorField = new SimplePanel(); 076 077 /** The color value.*/ 078 protected String m_colorValue = "transparent"; 079 080 /** The popup to choose the color. */ 081 protected CmsPopup m_popup = new CmsPopup(); 082 083 /** The parent to the native color picker. */ 084 private Label m_nativePickerParent; 085 086 /** The field to display the value. */ 087 protected SimplePanel m_textboxpanel = new SimplePanel(); 088 089 /** The x-coords of the popup. */ 090 protected int m_xcoordspopup; 091 092 /** The y-coords of the popup. */ 093 protected int m_ycoordspopup; 094 095 /** The error display for this widget. */ 096 private CmsErrorWidget m_error = new CmsErrorWidget(); 097 098 /** The root panel containing the other components of this widget. */ 099 private Panel m_panel = new FlowPanel(); 100 101 /** The internal textbox used by this widget to display the color value. */ 102 protected TextBox m_textboxColorValue = new TextBox(); 103 104 /** THe counter to not set the buttons more then one time. */ 105 int m_count; 106 107 /** The current native picker color value. */ 108 private String m_nativePickerValue; 109 110 /** 111 * Text area widgets for ADE forms.<p> 112 */ 113 public CmsColorPicker() { 114 115 super(); 116 String jsUri = CmsStringUtil.joinPaths(CmsCoreProvider.get().getWorkplaceResourcesPrefix(), COLOR_PICKER_JS); 117 CmsDomUtil.ensureJavaScriptIncluded(jsUri); 118 initWidget(m_panel); 119 m_panel.add(m_colorField); 120 m_panel.add(m_textboxpanel); 121 m_panel.add(m_error); 122 m_textboxpanel.add(m_textboxColorValue); 123 124 m_panel.addStyleName(I_CmsInputLayoutBundle.INSTANCE.inputCss().colorPicker()); 125 m_textboxColorValue.addBlurHandler(new BlurHandler() { 126 127 public void onBlur(BlurEvent event) { 128 129 checkvalue(m_textboxColorValue.getValue()); 130 131 } 132 }); 133 134 m_colorField.addDomHandler(new ClickHandler() { 135 136 public void onClick(ClickEvent event) { 137 138 if (m_popup.isShowing()) { 139 closePopup(); 140 } else { 141 openPopup(); 142 } 143 144 } 145 146 }, ClickEvent.getType()); 147 148 } 149 150 /** 151 * Initializes this class.<p> 152 */ 153 public static void initClass() { 154 155 // registers a factory for creating new instances of this widget 156 CmsWidgetFactoryRegistry.instance().registerFactory(WIDGET_TYPE, new I_CmsFormWidgetFactory() { 157 158 /** 159 * @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory#createWidget(java.util.Map, com.google.common.base.Optional) 160 */ 161 public I_CmsFormWidget createWidget(Map<String, String> widgetParams, Optional<String> defaultValue) { 162 163 return new CmsColorPicker(); 164 } 165 }); 166 } 167 168 /** 169 * Adds a value change handler to the textbox.<p> 170 * 171 * @param handler the value change handler to add 172 */ 173 public void addValueChangeHandler(ValueChangeHandler<String> handler) { 174 175 m_textboxColorValue.addValueChangeHandler(handler); 176 } 177 178 /** 179 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getApparentValue() 180 */ 181 public String getApparentValue() { 182 183 return getFormValueAsString(); 184 } 185 186 /** 187 * Returns the colorfield.<p> 188 * 189 * @return the colorfield 190 */ 191 public SimplePanel getColorfield() { 192 193 return m_colorField; 194 } 195 196 /** 197 * Returns the color value textbox.<p> 198 * 199 * @return the color value textbox 200 * */ 201 public TextBox getColorValueBox() { 202 203 return m_textboxColorValue; 204 } 205 206 /** 207 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFieldType() 208 */ 209 public FieldType getFieldType() { 210 211 return I_CmsFormWidget.FieldType.STRING; 212 } 213 214 /** 215 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFormValue() 216 */ 217 public Object getFormValue() { 218 219 if ((m_textboxColorValue.getText() == null) || !validateColorValue(m_textboxColorValue.getText())) { 220 m_textboxColorValue.setText(""); 221 } 222 return m_textboxColorValue.getText(); 223 } 224 225 /** 226 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFormValueAsString() 227 */ 228 public String getFormValueAsString() { 229 230 return (String)getFormValue(); 231 } 232 233 /** 234 * Returns the text contained in the text area.<p> 235 * 236 * @return the text in the text area 237 */ 238 public String getText() { 239 240 return m_textboxColorValue.getText(); 241 } 242 243 /** 244 * Returns the color value textboxpanel.<p> 245 * 246 * @return the color value textboxpanel 247 */ 248 public SimplePanel getTextboxPanel() { 249 250 return m_textboxpanel; 251 } 252 253 /** 254 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#isEnabled() 255 */ 256 public boolean isEnabled() { 257 258 return m_textboxColorValue.isEnabled(); 259 } 260 261 /** 262 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#reset() 263 */ 264 public void reset() { 265 266 m_textboxColorValue.setText(""); 267 } 268 269 /** 270 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setAutoHideParent(org.opencms.gwt.client.ui.I_CmsAutoHider) 271 */ 272 public void setAutoHideParent(I_CmsAutoHider autoHideParent) { 273 274 // nothing to do 275 } 276 277 /** 278 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setEnabled(boolean) 279 */ 280 public void setEnabled(boolean enabled) { 281 282 // TODO: Auto-generated method stub 283 284 } 285 286 /** 287 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setErrorMessage(java.lang.String) 288 */ 289 public void setErrorMessage(String errorMessage) { 290 291 m_error.setText(errorMessage); 292 } 293 294 /** 295 * Sets the value of the widget.<p> 296 * 297 * @param value the new value 298 */ 299 public void setFormValue(Object value) { 300 301 if (value == null) { 302 value = ""; 303 } 304 if (value instanceof String) { 305 String strValue = (String)value; 306 if (strValue.length() > 0) { 307 checkvalue(strValue); 308 } 309 } 310 311 } 312 313 /** 314 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setFormValueAsString(java.lang.String) 315 */ 316 public void setFormValueAsString(String newValue) { 317 318 setFormValue(newValue); 319 } 320 321 /** 322 * Sets the name of the input field.<p> 323 * 324 * @param name of the input field 325 * */ 326 public void setName(String name) { 327 328 m_textboxColorValue.setName(name); 329 330 } 331 332 /** 333 * Sets the text in the text area.<p> 334 * 335 * @param text the new text 336 */ 337 public void setText(String text) { 338 339 m_textboxColorValue.setText(text); 340 } 341 342 /** 343 * Validates the inputed color value. 344 * @param colorvalue the value of the color 345 * @return true if the inputed color value is valid 346 */ 347 protected boolean checkvalue(String colorvalue) { 348 349 boolean valid = validateColorValue(colorvalue); 350 if (valid) { 351 if (colorvalue.length() == 4) { 352 char[] chr = colorvalue.toCharArray(); 353 for (int i = 1; i < 4; i++) { 354 String foo = String.valueOf(chr[i]); 355 colorvalue = colorvalue.replaceFirst(foo, foo + foo); 356 } 357 } 358 m_textboxColorValue.setValue(colorvalue, true); 359 m_colorField.getElement().getStyle().setBackgroundColor(colorvalue); 360 m_colorValue = colorvalue; 361 } 362 return valid; 363 } 364 365 /** 366 * Close the popup and store the color value in the colorvalue field.<p> 367 * 368 */ 369 protected void closePopup() { 370 371 if (checkvalue(m_nativePickerValue)) { 372 m_popup.hide(); 373 } 374 } 375 376 /** 377 * Close the popup and store the old color value in the colorvalue field.<p> 378 * 379 */ 380 protected void closePopupDefault() { 381 382 if (checkvalue(m_textboxColorValue.getText())) { 383 m_popup.hide(); 384 } 385 386 } 387 388 /** 389 * Converts the integer value to an hex value.<p> 390 * @param i the integer value 391 * @return the hex string 392 */ 393 protected String convertToHex(int i) { 394 395 String hexString = Integer.toHexString(i); 396 while (hexString.length() < 2) { 397 hexString = "0" + hexString; 398 } 399 return hexString; 400 } 401 402 /** 403 * @see com.google.gwt.user.client.ui.Composite#onAttach() 404 */ 405 @Override 406 protected void onAttach() { 407 408 super.onAttach(); 409 Scheduler.get().scheduleDeferred(new ScheduledCommand() { 410 411 public void execute() { 412 413 m_colorField.getElement().getStyle().setBackgroundColor(m_colorValue); 414 } 415 }); 416 } 417 418 /** 419 * Helper function to open the popup.<p> 420 */ 421 protected void openPopup() { 422 423 m_popup.setWidth(262); 424 m_popup.setAutoHideEnabled(false); 425 m_popup.showRelativeTo(m_colorField); 426 m_popup.setModal(true); 427 if (m_popup.getWidgetCount() != 0) { 428 m_popup.remove(m_popup.getWidget(0)); 429 } 430 m_nativePickerParent = new Label(); 431 String id = Document.get().createUniqueId(); 432 m_nativePickerParent.getElement().setId(id); 433 434 m_popup.add(m_nativePickerParent); 435 initNativePicker(getFormValueAsString(), "#" + id); 436 if (m_count == 0) { 437 CmsPushButton close = new CmsPushButton(); 438 CmsPushButton cancel = new CmsPushButton(); 439 cancel.setText(Messages.get().key(Messages.GUI_CANCEL_0)); 440 cancel.setTitle(Messages.get().key(Messages.GUI_CANCEL_0)); 441 close.setText(Messages.get().key(Messages.GUI_OK_0)); 442 close.setTitle(Messages.get().key(Messages.GUI_OK_0)); 443 close.addClickHandler(new ClickHandler() { 444 445 public void onClick(ClickEvent event) { 446 447 closePopup(); 448 449 } 450 }); 451 cancel.addClickHandler(new ClickHandler() { 452 453 public void onClick(ClickEvent event) { 454 455 closePopupDefault(); 456 457 } 458 }); 459 m_popup.addButton(cancel); 460 m_popup.addButton(close); 461 m_count = 1; 462 } 463 464 m_xcoordspopup = m_popup.getPopupLeft(); 465 m_ycoordspopup = m_popup.getPopupTop(); 466 // reposition to take used height into account 467 Scheduler.get().scheduleDeferred(new ScheduledCommand() { 468 469 public void execute() { 470 471 m_popup.showRelativeTo(m_colorField); 472 } 473 }); 474 475 } 476 477 /** 478 * Initializes the native color picker.<p> 479 * 480 * @param value the current value 481 * @param selector the parent element selector 482 */ 483 private native void initNativePicker(String value, String selector) /*-{ 484 var self = this; 485 self.@org.opencms.gwt.client.ui.input.CmsColorPicker::m_nativePickerValue = value; 486 var parentEl = $doc.querySelector(selector); 487 var picker = new $wnd.Picker( 488 { 489 parent : parentEl, 490 color : value, 491 popup : false, 492 alpha : false, 493 editorFormat : 'hex', 494 editor : true, 495 onChange : function(color) { 496 // cut off the last two digits to remove the alpha value 497 var hexVal = color.hex; 498 hexVal = hexVal.substring(0, 7) 499 self.@org.opencms.gwt.client.ui.input.CmsColorPicker::m_nativePickerValue = hexVal; 500 }, 501 }); 502 }-*/; 503 504 /** 505 * Checks if the given string is a valid colorvalue.<p> 506 * 507 * @param colorvalue to check 508 * @return true if the value is valid otherwise false 509 */ 510 private boolean validateColorValue(String colorvalue) { 511 512 boolean valid = colorvalue.matches("^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"); 513 return valid; 514 } 515}