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