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.upload; 029 030import org.opencms.gwt.client.Messages; 031import org.opencms.gwt.client.ui.CmsFlowPanel; 032import org.opencms.gwt.client.ui.I_CmsButton; 033import org.opencms.gwt.client.ui.I_CmsButton.ButtonColor; 034import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle; 035import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle; 036import org.opencms.gwt.client.util.CmsDomUtil; 037import org.opencms.util.CmsStringUtil; 038 039import com.google.gwt.core.client.GWT; 040import com.google.gwt.dom.client.Style.Display; 041import com.google.gwt.event.dom.client.ChangeEvent; 042import com.google.gwt.event.dom.client.ChangeHandler; 043import com.google.gwt.event.dom.client.ClickEvent; 044import com.google.gwt.event.dom.client.ClickHandler; 045import com.google.gwt.event.dom.client.MouseOutEvent; 046import com.google.gwt.event.dom.client.MouseOverEvent; 047import com.google.gwt.i18n.client.NumberFormat; 048import com.google.gwt.uibinder.client.UiBinder; 049import com.google.gwt.uibinder.client.UiField; 050import com.google.gwt.uibinder.client.UiHandler; 051import com.google.gwt.user.client.ui.Composite; 052import com.google.gwt.user.client.ui.HTML; 053import com.google.gwt.user.client.ui.HasHorizontalAlignment; 054 055/** 056 * Provides a upload button.<p> 057 * 058 * @since 8.0.0 059 */ 060public class CmsUploadButton extends Composite implements HasHorizontalAlignment, I_CmsUploadButton { 061 062 /** The ui-binder interface. */ 063 protected interface I_CmsUploadButtonUiBinder extends UiBinder<CmsFlowPanel, CmsUploadButton> { 064 // GWT interface, nothing to do 065 } 066 067 /** The size for kilobytes in bytes. */ 068 private static final float KILOBYTE = 1024L; 069 070 /** The ui-binder for this widget. */ 071 private static I_CmsUploadButtonUiBinder m_uiBinder = GWT.create(I_CmsUploadButtonUiBinder.class); 072 073 /** The button face. */ 074 @UiField 075 protected HTML m_buttonFace; 076 077 /** The main panel. */ 078 @UiField 079 protected CmsFlowPanel m_main; 080 081 /** The handler for the upload button. */ 082 I_CmsUploadButtonHandler m_buttonHandler; 083 084 /** The file input field. */ 085 CmsFileInput m_fileInput; 086 087 /** The horizontal alignment. */ 088 private HorizontalAlignmentConstant m_align; 089 090 /** Stores the button style. */ 091 private ButtonStyle m_buttonStyle; 092 093 /** Stores the button color. */ 094 private I_CmsButton.ButtonColor m_color; 095 096 /** Flag if button is enabled. */ 097 private boolean m_enabled; 098 099 /** The icon image css class. */ 100 private String m_imageClass; 101 102 /** The button size. */ 103 private I_CmsButton.Size m_size; 104 105 /** The current style dependent name. */ 106 private String m_styleDependent; 107 108 /** The button text. */ 109 private String m_text; 110 111 /** The button title. */ 112 private String m_title; 113 114 /** Flag if a button minimum width should be used. */ 115 private boolean m_useMinWidth; 116 117 /** 118 * The default constructor.<p> 119 * 120 * Creates a new upload button. This upload button opens a new OS file selector on click.<p> 121 * 122 * On change the button handler passed into the constructor is notified.<p> 123 * 124 * @param buttonHandler the buttonHandler 125 */ 126 public CmsUploadButton(I_CmsUploadButtonHandler buttonHandler) { 127 128 org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.INSTANCE.uploadButton().ensureInjected(); 129 initWidget(m_uiBinder.createAndBindUi(this)); 130 m_buttonHandler = buttonHandler; 131 m_buttonHandler.setButton(this); 132 m_align = HasHorizontalAlignment.ALIGN_RIGHT; 133 updateState("up"); 134 m_enabled = true; 135 // set the button properties 136 setSize(I_CmsButton.Size.medium); 137 setText(Messages.get().key(Messages.GUI_UPLOAD_BUTTON_TITLE_0)); 138 setTitle(Messages.get().key(Messages.GUI_UPLOAD_BUTTON_TITLE_0)); 139 setButtonStyle(ButtonStyle.TEXT, ButtonColor.BLUE); 140 createFileInput(); 141 // prevent click event from bubbling up to the surrounding widget 142 addDomHandler(new ClickHandler() { 143 144 public void onClick(ClickEvent event) { 145 146 event.stopPropagation(); 147 } 148 }, ClickEvent.getType()); 149 } 150 151 /** 152 * Formats a given bytes value (file size).<p> 153 * 154 * @param filesize the file size to format 155 * 156 * @return the formated file size in KB 157 */ 158 public static String formatBytes(long filesize) { 159 160 double kByte = Math.ceil(filesize / KILOBYTE); 161 String formated = NumberFormat.getDecimalFormat().format(Double.valueOf(kByte)); 162 return formated + " KB"; 163 } 164 165 /** 166 * Creates and adds a file input.<p> 167 * 168 * @return returns the previous file input widget 169 */ 170 public CmsFileInput createFileInput() { 171 172 // remove the current file input field and add a new one 173 CmsFileInput previous = m_fileInput; 174 if (m_fileInput != null) { 175 m_fileInput.getElement().getStyle().setDisplay(Display.NONE); 176 } 177 m_fileInput = new CmsFileInput(); 178 m_fileInput.addChangeHandler(new ChangeHandler() { 179 180 public void onChange(ChangeEvent event) { 181 182 CmsDomUtil.ensureMouseOut(m_main.getElement()); 183 m_buttonHandler.onChange(m_fileInput); 184 } 185 }); 186 m_buttonHandler.initializeFileInput(m_fileInput); 187 m_main.add(m_fileInput); 188 return previous; 189 } 190 191 /** 192 * Disables the button and changes the button title attribute to the disabled reason.<p> 193 * 194 * @param disabledReason the disabled reason 195 */ 196 public void disable(String disabledReason) { 197 198 m_enabled = false; 199 // hide the current file input field 200 if (m_fileInput != null) { 201 m_fileInput.getElement().getStyle().setDisplay(Display.NONE); 202 } 203 204 updateState("up-disabled"); 205 super.setTitle(disabledReason); 206 } 207 208 /** 209 * Enables the button, switching the button title attribute from the disabled reason to the original title.<p> 210 */ 211 public void enable() { 212 213 updateState("up"); 214 m_enabled = true; 215 // show the current file input field 216 if (m_fileInput != null) { 217 m_fileInput.getElement().getStyle().clearDisplay(); 218 } 219 super.setTitle(m_title); 220 } 221 222 /** 223 * Gets the upload button handler instance for this button.<p> 224 * 225 * @return the upload button handler 226 */ 227 public I_CmsUploadButtonHandler getButtonHandler() { 228 229 return m_buttonHandler; 230 } 231 232 /** 233 * This is the alignment of the text in reference to the image, possible values are left or right.<p> 234 * 235 * @see com.google.gwt.user.client.ui.HasHorizontalAlignment#getHorizontalAlignment() 236 */ 237 public HorizontalAlignmentConstant getHorizontalAlignment() { 238 239 return m_align; 240 } 241 242 /** 243 * Returns the master image class.<p> 244 * 245 * @return the master image class 246 */ 247 public String getImageClass() { 248 249 return m_imageClass; 250 } 251 252 /** 253 * Returns the size.<p> 254 * 255 * @return the size 256 */ 257 public I_CmsButton.Size getSize() { 258 259 return m_size; 260 } 261 262 /** 263 * Returns the text.<p> 264 * 265 * @return the text 266 */ 267 public String getText() { 268 269 return m_text; 270 } 271 272 /** 273 * Returns the title.<p> 274 * 275 * @return the title 276 */ 277 @Override 278 public String getTitle() { 279 280 return m_title; 281 } 282 283 /** 284 * Returns if the upload button is enabled.<p> 285 * 286 * @return <code>true</code> if the upload button is enabled 287 */ 288 public boolean isEnabled() { 289 290 return m_enabled; 291 } 292 293 /** 294 * Checks if the button is constraint to a minimal width.<p> 295 * 296 * @return <code>true</code> if the button is constraint to a minimal width 297 */ 298 public boolean isUseMinWidth() { 299 300 return m_useMinWidth; 301 } 302 303 /** 304 * Reinitializes the button with a new button handler.<p> 305 * 306 * @param buttonHandler the button handler 307 */ 308 public void reinitButton(I_CmsUploadButtonHandler buttonHandler) { 309 310 m_buttonHandler = buttonHandler; 311 m_buttonHandler.setButton(this); 312 updateState("up"); 313 m_enabled = true; 314 createFileInput(); 315 } 316 317 /** 318 * Sets the button style.<p> 319 * 320 * @param style the style to set 321 * @param color the color to set 322 */ 323 public void setButtonStyle(I_CmsButton.ButtonStyle style, I_CmsButton.ButtonColor color) { 324 325 if (m_buttonStyle != null) { 326 for (String styleName : m_buttonStyle.getAdditionalClasses()) { 327 removeStyleName(styleName); 328 } 329 } 330 if (style == ButtonStyle.TRANSPARENT) { 331 setSize(null); 332 } 333 addStyleName(style.getCssClassName()); 334 m_buttonStyle = style; 335 336 if (m_color != null) { 337 removeStyleName(m_color.getClassName()); 338 } 339 if (color != null) { 340 addStyleName(color.getClassName()); 341 } 342 m_color = color; 343 } 344 345 public void setEnabled(boolean enabled, String disabledMessage) { 346 347 if (enabled) { 348 enable(); 349 } else { 350 disable(disabledMessage); 351 } 352 353 // TODO Auto-generated method stub 354 355 } 356 357 /** 358 * This is the alignment of the text in reference to the image, possible values are left or right.<p> 359 * 360 * @see com.google.gwt.user.client.ui.HasHorizontalAlignment#setHorizontalAlignment(com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant) 361 */ 362 public void setHorizontalAlignment(HorizontalAlignmentConstant align) { 363 364 if (align.equals(HasHorizontalAlignment.ALIGN_CENTER)) { 365 // ignore center alignment 366 return; 367 } 368 m_align = align; 369 } 370 371 /** 372 * Sets the master image class.<p> 373 * 374 * @param imageClass the master image class to set 375 */ 376 public void setImageClass(String imageClass) { 377 378 setUpFace(m_text, imageClass); 379 } 380 381 /** 382 * Sets the size.<p> 383 * 384 * @param size the size to set 385 */ 386 public void setSize(I_CmsButton.Size size) { 387 388 if (m_size != null) { 389 removeStyleName(m_size.getCssClassName()); 390 } 391 if (size != null) { 392 addStyleName(size.getCssClassName()); 393 } 394 m_size = size; 395 } 396 397 /** 398 * Sets the text.<p> 399 * 400 * @param text the text to set 401 */ 402 public void setText(String text) { 403 404 setUpFace(text, m_imageClass); 405 setTitle(text); 406 } 407 408 /** 409 * @see com.google.gwt.user.client.ui.UIObject#setTitle(java.lang.String) 410 */ 411 @Override 412 public void setTitle(String title) { 413 414 m_main.setTitle(title); 415 m_title = title; 416 } 417 418 /** 419 * Sets the up face text and image.<p> 420 * 421 * @param text the up face text to set, set to <code>null</code> to not show any 422 * @param imageClass the up face image class to use, set to <code>null</code> to not show any 423 */ 424 public void setUpFace(String text, String imageClass) { 425 426 m_text = text; 427 m_imageClass = imageClass; 428 m_buttonFace.setHTML(getFaceHtml(text, imageClass)); 429 } 430 431 /** 432 * Tells the button to use a minimal width.<p> 433 * 434 * @param useMinWidth <code>true</code> to use a minimal width 435 */ 436 public void setUseMinWidth(boolean useMinWidth) { 437 438 if (useMinWidth != m_useMinWidth) { 439 if (useMinWidth) { 440 addStyleName(I_CmsLayoutBundle.INSTANCE.buttonCss().cmsMinWidth()); 441 } else { 442 removeStyleName(I_CmsLayoutBundle.INSTANCE.buttonCss().cmsMinWidth()); 443 } 444 m_useMinWidth = useMinWidth; 445 } 446 } 447 448 public void updateFileInput() { 449 450 m_buttonHandler.initializeFileInput(m_fileInput); 451 } 452 453 /** 454 * Convenience method to assemble the HTML to use for a button face.<p> 455 * 456 * @param text text the up face text to set, set to <code>null</code> to not show any 457 * @param imageClass the up face image class to use, set to <code>null</code> to not show any 458 * 459 * @return the HTML 460 */ 461 protected String getFaceHtml(String text, String imageClass) { 462 463 return CmsDomUtil.createFaceHtml(text, imageClass, m_align); 464 } 465 466 /** 467 * Handles the mouse over event on the main panel.<p> 468 * 469 * @param event the event 470 * 471 * @see com.google.gwt.event.dom.client.MouseOutHandler#onMouseOut(com.google.gwt.event.dom.client.MouseOutEvent) 472 */ 473 @UiHandler("m_main") 474 protected void handleMouseOut(MouseOutEvent event) { 475 476 if (isEnabled()) { 477 updateState("up"); 478 } 479 } 480 481 /** 482 * Handles the mouse over event on the main panel.<p> 483 * 484 * @param event the event 485 * 486 * @see com.google.gwt.event.dom.client.MouseOverHandler#onMouseOver(com.google.gwt.event.dom.client.MouseOverEvent) 487 */ 488 @UiHandler("m_main") 489 protected void handleMouseOver(MouseOverEvent event) { 490 491 if (isEnabled()) { 492 updateState("up-hovering"); 493 } 494 } 495 496 /** 497 * Updates the CSS classes according to the button state.<p> 498 * 499 * @param styleDependent the dependent style name 500 */ 501 private void updateState(String styleDependent) { 502 503 if (CmsStringUtil.isEmptyOrWhitespaceOnly(styleDependent)) { 504 // reseting to cmsState-up 505 styleDependent = "up"; 506 } 507 if (!styleDependent.equals(m_styleDependent)) { 508 m_main.removeStyleDependentName(m_styleDependent); 509 m_main.setStyleDependentName(styleDependent, true); 510 m_styleDependent = styleDependent; 511 } 512 } 513}