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    }