001/* 002 * Copyright 2012 GWT-Bootstrap 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.github.gwtbootstrap.client.ui; 017 018import com.github.gwtbootstrap.client.ui.base.*; 019import com.github.gwtbootstrap.client.ui.constants.ButtonType; 020import com.github.gwtbootstrap.client.ui.constants.Constants; 021import com.github.gwtbootstrap.client.ui.constants.DismissType; 022import com.github.gwtbootstrap.client.ui.constants.IconType; 023import com.github.gwtbootstrap.client.ui.resources.ButtonSize; 024import com.google.gwt.dom.client.Document; 025import com.google.gwt.dom.client.Element; 026import com.google.gwt.dom.client.NativeEvent; 027import com.google.gwt.event.dom.client.*; 028import com.google.gwt.event.shared.HandlerRegistration; 029import com.google.gwt.user.client.ui.HasEnabled; 030 031//@formatter:off 032/** 033 * Button with optional icon. 034 * 035 * <p> 036 * <h3>UiBinder Usage:</h3> 037 * 038 * <pre> 039 * {@code <b:Button icon="TRASH" type="ERROR" toggle="true" loadingText="I'm loading..." completeText="Oh hoh, I completed the action!">Delete</b:Button>} 040 * </pre> 041 * 042 * All arguments are optional. 043 * </p> 044 * 045 * @since 2.0.4.0 046 * 047 * @author Carlos Alexandro Becker 048 * @author Dominik Mayer 049 * @author Sven Jacobs 050 * 051 * @see <a 052 * href="http://twitter.github.com/bootstrap/base-css.html#buttons">Bootstrap 053 * documentation</a> 054 * @see ButtonGroup 055 * @see ButtonToolbar 056 * @see DropdownButton 057 * @see SplitDropdownButton 058 * @see NavbarButton 059 */ 060// @formatter:on 061public class Button extends IconAnchor implements HasClickHandlers, 062 HasDoubleClickHandlers, HasEnabled, HasType<ButtonType>, 063 HasAllDragAndDropHandlers, HasAllFocusHandlers, HasAllGestureHandlers, 064 HasAllKeyHandlers, HasAllMouseHandlers, HasAllTouchHandlers { 065 066 private final LoadingStateBehavior state = new LoadingStateBehavior(); 067 private ButtonType type; 068 private ButtonSize size; 069 070 /** 071 * Creates an empty Button. 072 */ 073 public Button() { 074 super(); 075 addStyleName(Constants.BTN); 076 } 077 078 /** 079 * Creates an Button with ClickHandler 080 * @param handler Butotn ClickHandler 081 */ 082 public Button(ClickHandler handler) { 083 this(); 084 addClickHandler(handler); 085 086 } 087 088 /** 089 * Creates a Button with the given caption. 090 * 091 * @param caption 092 * the caption of the Button 093 */ 094 public Button(String caption) { 095 this(); 096 setText(caption); 097 } 098 099 /** 100 * Create Button with click handler. 101 * @param caption the caption of the Button 102 * @param handler Button Click Handler 103 */ 104 public Button(String caption, ClickHandler handler) { 105 this(caption); 106 addClickHandler(handler); 107 } 108 109 /** 110 * Creates a Button with the given caption and icon. 111 * 112 * @param caption 113 * the caption of the Button 114 * @param icon 115 * the Icon on the caption's left 116 */ 117 public Button(String caption, IconType icon) { 118 this(caption); 119 setIcon(icon); 120 } 121 122 /** 123 * Creates a Button with the given caption and icon and ClickHandler. 124 * 125 * @param caption 126 * the caption of the Button 127 * @param icon 128 * the Icon on the caption's left 129 * @param handler 130 * the ClickHandler of the Button. 131 */ 132 public Button(String caption, IconType icon, ClickHandler handler) { 133 this(caption, icon); 134 addClickHandler(handler); 135 } 136 137 /** 138 * Sets the type of the Button. 139 * <p> 140 * Different types give the button a different look. 141 * 142 * @param type 143 * the type of the Button. 144 */ 145 public void setType(ButtonType type) { 146 this.type = type; 147 StyleHelper.changeStyle(this, type, ButtonType.class); 148 } 149 150 /** 151 * Sets the size of the Button. 152 * 153 * @param size 154 * the size of the Button. 155 */ 156 public void setSize(ButtonSize size) { 157 this.size = size; 158 StyleHelper.changeStyle(this, size, ButtonSize.class); 159 } 160 161 /** 162 * Whether the Button is enabled or disabled. 163 * <p> 164 * A disabled widget cannot be used. 165 * 166 * @return <code>false</code> if the Button is disabled. 167 */ 168 public boolean isEnabled() { 169 return !getStyleName().contains(Constants.DISABLED); 170 } 171 172 /** 173 * Sets whether the Button is enabled or disabled. 174 * <p> 175 * A disabled widget cannot be used. 176 * 177 * @param enabled 178 * <code>false</code> if the Button should be disabled. Default: 179 * <code>true</code> 180 */ 181 public void setEnabled(boolean enabled) { 182 if (enabled) 183 removeStyleName(Constants.DISABLED); 184 else 185 addStyleName(Constants.DISABLED); 186 } 187 188 /** 189 * Enable ou disable the data-toggle behavior. 190 * 191 * @param toggle 192 * <code>true</code> will enable this behavior. 193 * <code>false</code> will disable it or do nothing if it never 194 * was enabled. 195 */ 196 public void setToggle(boolean toggle) { 197 if (toggle) 198 getElement().setAttribute(Constants.DATA_TOGGLE, "button"); 199 else 200 getElement().removeAttribute(Constants.DATA_TOGGLE); 201 } 202 203 /** 204 * Verify if the property "toggle" is set. 205 * 206 * @return true: if the data-toggle is equal 'button' 207 * false: otherwise 208 */ 209 public boolean isToggle() { 210 return getElement().getAttribute(Constants.DATA_TOGGLE).equals("button"); 211 } 212 213 /** 214 * Verify if the button is toggled. 215 * @return true: if yes (it will contain the "active" styleclass 216 * false: otherwise. 217 */ 218 public boolean isToggled() { 219 return getStyleName().toLowerCase().contains("active"); 220 } 221 222 /** 223 * Set a Loading Text to show when some action are in work with this button. 224 * 225 * @see LoadingStateBehavior 226 * @param text 227 */ 228 public void setLoadingText(String text) { 229 if (text == null || text.trim().isEmpty()) { 230 getElement().removeAttribute(Constants.DATA_LOADING_TEXT); 231 return; 232 } 233 234 getElement().setAttribute(Constants.DATA_LOADING_TEXT, text); 235 } 236 237 /** 238 * Set a Loading Text to show when some action are completed with this 239 * button. 240 * 241 * @see LoadingStateBehavior 242 * @param text 243 */ 244 public void setCompleteText(String text) { 245 if (text == null || text.trim().isEmpty()) { 246 getElement().removeAttribute(Constants.DATA_COMPLETE_TEXT); 247 return; 248 } 249 250 getElement().setAttribute(Constants.DATA_COMPLETE_TEXT, text); 251 } 252 253 /** 254 * A simple DSL to change the button state to loading, complete, or reset 255 * it. 256 * 257 * @return 258 */ 259 public LoadingStateBehavior state() { 260 return state; 261 } 262 263 /** 264 * A simple class to encapsulate the button state managing from the user. 265 * 266 * @author Carlos Alexandro Becker 267 */ 268 public class LoadingStateBehavior { 269 270 /** 271 * put the button in the loading state. 272 */ 273 public void loading() { 274 setLoadingBehavior("loading"); 275 } 276 277 /** 278 * reset the button state. 279 */ 280 public void reset() { 281 setLoadingBehavior("reset"); 282 } 283 284 /** 285 * put the button in the completed state. 286 */ 287 public void complete() { 288 setLoadingBehavior("complete"); 289 } 290 291 private void setLoadingBehavior(String behavior) { 292 // Remove icon because it will be removed by Bootstrap's "$(element).button(behavior)" anyway 293 icon.removeFromParent(); 294 295 setLoadingBehavior(getElement(), behavior); 296 297 // Recreate icon and add it to inner content with setText() 298 icon = new Icon(icon.getIconType()); 299 setText(getText()); 300 } 301 302 private native void setLoadingBehavior(Element e, String behavior) /*-{ 303 $wnd.jQuery(e).button(behavior); 304 }-*/; 305 } 306 307 /** 308 * {@inheritDoc} 309 */ 310 public HandlerRegistration addClickHandler(ClickHandler handler) { 311 return addDomHandler(handler, ClickEvent.getType()); 312 } 313 314 /** 315 * {@inheritDoc} 316 */ 317 public HandlerRegistration addDoubleClickHandler(DoubleClickHandler handler) { 318 return addDomHandler(handler, DoubleClickEvent.getType()); 319 } 320 321 /** 322 * {@inheritDoc} 323 */ 324 public HandlerRegistration addDragEndHandler(DragEndHandler handler) { 325 return addDomHandler(handler, DragEndEvent.getType()); 326 } 327 328 /** 329 * {@inheritDoc} 330 */ 331 public HandlerRegistration addDragEnterHandler(DragEnterHandler handler) { 332 return addDomHandler(handler, DragEnterEvent.getType()); 333 } 334 335 /** 336 * {@inheritDoc} 337 */ 338 public HandlerRegistration addDragLeaveHandler(DragLeaveHandler handler) { 339 return addDomHandler(handler, DragLeaveEvent.getType()); 340 } 341 342 /** 343 * {@inheritDoc} 344 */ 345 public HandlerRegistration addDragHandler(DragHandler handler) { 346 return addDomHandler(handler, DragEvent.getType()); 347 } 348 349 /** 350 * {@inheritDoc} 351 */ 352 public HandlerRegistration addDragOverHandler(DragOverHandler handler) { 353 return addDomHandler(handler, DragOverEvent.getType()); 354 } 355 356 /** 357 * {@inheritDoc} 358 */ 359 public HandlerRegistration addDragStartHandler(DragStartHandler handler) { 360 return addDomHandler(handler, DragStartEvent.getType()); 361 } 362 363 /** 364 * {@inheritDoc} 365 */ 366 public HandlerRegistration addDropHandler(DropHandler handler) { 367 return addDomHandler(handler, DropEvent.getType()); 368 } 369 370 /** 371 * {@inheritDoc} 372 */ 373 public HandlerRegistration addFocusHandler(FocusHandler handler) { 374 return addDomHandler(handler, FocusEvent.getType()); 375 } 376 377 /** 378 * {@inheritDoc} 379 */ 380 public HandlerRegistration addBlurHandler(BlurHandler handler) { 381 return addDomHandler(handler, BlurEvent.getType()); 382 } 383 384 /** 385 * {@inheritDoc} 386 */ 387 public HandlerRegistration addGestureStartHandler( 388 GestureStartHandler handler) { 389 return addDomHandler(handler, GestureStartEvent.getType()); 390 } 391 392 /** 393 * {@inheritDoc} 394 */ 395 public HandlerRegistration addGestureChangeHandler( 396 GestureChangeHandler handler) { 397 return addDomHandler(handler, GestureChangeEvent.getType()); 398 } 399 400 /** 401 * {@inheritDoc} 402 */ 403 public HandlerRegistration addGestureEndHandler(GestureEndHandler handler) { 404 return addDomHandler(handler, GestureEndEvent.getType()); 405 } 406 407 /** 408 * {@inheritDoc} 409 */ 410 public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) { 411 return addDomHandler(handler, KeyUpEvent.getType()); 412 } 413 414 /** 415 * {@inheritDoc} 416 */ 417 public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { 418 return addDomHandler(handler, KeyDownEvent.getType()); 419 } 420 421 /** 422 * {@inheritDoc} 423 */ 424 public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) { 425 return addDomHandler(handler, KeyPressEvent.getType()); 426 } 427 428 /** 429 * {@inheritDoc} 430 */ 431 public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) { 432 return addDomHandler(handler, MouseDownEvent.getType()); 433 } 434 435 /** 436 * {@inheritDoc} 437 */ 438 public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) { 439 return addDomHandler(handler, MouseUpEvent.getType()); 440 } 441 442 /** 443 * {@inheritDoc} 444 */ 445 public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) { 446 return addDomHandler(handler, MouseOutEvent.getType()); 447 } 448 449 /** 450 * {@inheritDoc} 451 */ 452 public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) { 453 return addDomHandler(handler, MouseOverEvent.getType()); 454 } 455 456 /** 457 * {@inheritDoc} 458 */ 459 public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) { 460 return addDomHandler(handler, MouseMoveEvent.getType()); 461 } 462 463 /** 464 * {@inheritDoc} 465 */ 466 public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler) { 467 return addDomHandler(handler, MouseWheelEvent.getType()); 468 } 469 470 /** 471 * {@inheritDoc} 472 */ 473 public HandlerRegistration addTouchStartHandler(TouchStartHandler handler) { 474 return addDomHandler(handler, TouchStartEvent.getType()); 475 } 476 477 /** 478 * {@inheritDoc} 479 */ 480 public HandlerRegistration addTouchMoveHandler(TouchMoveHandler handler) { 481 return addDomHandler(handler, TouchMoveEvent.getType()); 482 } 483 484 /** 485 * {@inheritDoc} 486 */ 487 public HandlerRegistration addTouchEndHandler(TouchEndHandler handler) { 488 return addDomHandler(handler, TouchEndEvent.getType()); 489 } 490 491 /** 492 * {@inheritDoc} 493 */ 494 public HandlerRegistration addTouchCancelHandler(TouchCancelHandler handler) { 495 return addDomHandler(handler, TouchCancelEvent.getType()); 496 } 497 498 /** 499 * Get Button Type 500 * @return Current Button Type 501 */ 502 public ButtonType getType() { 503 return type; 504 } 505 506 /** 507 * Get Button Size 508 * @return Current Button Size 509 */ 510 public ButtonSize getSize() { 511 return size; 512 } 513 514 /** 515 * Set element as a Block Level Button 516 * @param block true:Block Level false:Default 517 */ 518 public void setBlock(boolean block) { 519 setStyleName(Constants.BTN_BLOCK, block); 520 } 521 522 /** 523 * Programmatic equivalent of the user clicking the button. 524 */ 525 public void click() { 526 NativeEvent event = Document.get().createClickEvent(0, 0, 0, 0, 0, false, false, false, false); 527 DomEvent.fireNativeEvent(event, this); 528 } 529 530 /** 531 * Buttons can act as a dismiss button when inside a {@link Modal} or {@link Alert}. 532 * <p/> 533 * UiBinder example: 534 * <code><pre> 535 * <b:Modal> 536 * <b:ModalFooter> 537 * <b:Button text="Close" dismiss="MODAL"/> 538 * </b:ModalFooter> 539 * </b:Modal> 540 * </pre></code> 541 * <p/> 542 * See <a href="http://twitter.github.io/bootstrap/javascript.html#modals">Bootstrap</a> documentation. 543 * 544 * @param type Type of dismiss ("modal" or "alert") 545 * @since 2.3.2.0 546 */ 547 public void setDismiss(final DismissType type) { 548 getElement().setAttribute(Constants.DATA_DISMISS, type.get()); 549 } 550}