001package com.github.gwtbootstrap.timepicker.client.ui.base;
002
003import com.github.gwtbootstrap.client.ui.TextBox;
004import com.github.gwtbootstrap.client.ui.base.HasAlternateSize;
005import com.github.gwtbootstrap.client.ui.base.HasId;
006import com.github.gwtbootstrap.client.ui.base.HasPlaceholder;
007import com.github.gwtbootstrap.client.ui.base.HasSize;
008import com.github.gwtbootstrap.client.ui.base.HasStyle;
009import com.github.gwtbootstrap.client.ui.base.HasVisibility;
010import com.github.gwtbootstrap.client.ui.base.IsResponsive;
011import com.github.gwtbootstrap.client.ui.base.IsSearchQuery;
012import com.github.gwtbootstrap.client.ui.base.PlaceholderHelper;
013import com.github.gwtbootstrap.client.ui.base.ResponsiveHelper;
014import com.github.gwtbootstrap.client.ui.base.SearchQueryStyleHelper;
015import com.github.gwtbootstrap.client.ui.base.SizeHelper;
016import com.github.gwtbootstrap.client.ui.base.Style;
017import com.github.gwtbootstrap.client.ui.base.StyleHelper;
018import com.github.gwtbootstrap.client.ui.constants.AlternateSize;
019import com.github.gwtbootstrap.client.ui.constants.Device;
020import com.github.gwtbootstrap.client.ui.event.HasVisibleHandlers;
021import com.github.gwtbootstrap.client.ui.event.HiddenEvent;
022import com.github.gwtbootstrap.client.ui.event.HiddenHandler;
023import com.github.gwtbootstrap.client.ui.event.HideEvent;
024import com.github.gwtbootstrap.client.ui.event.HideHandler;
025import com.github.gwtbootstrap.client.ui.event.ShowEvent;
026import com.github.gwtbootstrap.client.ui.event.ShowHandler;
027import com.github.gwtbootstrap.client.ui.event.ShownEvent;
028import com.github.gwtbootstrap.client.ui.event.ShownHandler;
029import com.google.gwt.core.client.GWT;
030import com.google.gwt.dom.client.Element;
031import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
032import com.google.gwt.event.logical.shared.ValueChangeEvent;
033import com.google.gwt.event.logical.shared.ValueChangeHandler;
034import com.google.gwt.event.shared.HandlerRegistration;
035import com.google.gwt.i18n.client.DateTimeFormat;
036import com.google.gwt.user.client.ui.HasEnabled;
037import com.google.gwt.user.client.ui.HasValue;
038import com.google.gwt.user.client.ui.Widget;
039
040import java.util.Date;
041
042/**
043 * Base TimePicker component.
044 *
045 * @author Carlos Alexandro Becker
046 * @author Joshua Godi
047 * @since 2.3.2.0
048 */
049public class TimeBoxBase extends Widget implements HasVisibleHandlers, HasPlaceholder, HasTemplate, HasShowInputs, HasSecondStep,
050        HasModalBackdrop, HasMinuteStep, HasDisableFocus, HasDefaultTime, HasShowSeconds, HasMeridian, HasAlternateSize,
051        IsSearchQuery, HasSize, HasId, IsResponsive, HasStyle, HasValue<Date>, HasEnabled, HasValueChangeHandlers<Date>, HasVisibility, HasTimeFormat {
052
053    private final TextBox box;
054    private String format;
055    private DateTimeFormat dtf;
056
057    // Defaults
058    private Template template = Template.DROPDOWN;
059    private int minuteStep = 15;
060    private boolean showSeconds = false;
061    private int secondStep = 15;
062    private DefaultTime defaultTime = DefaultTime.CURRENT;
063    private boolean showMeridian = false;
064    private boolean showInputs = true;
065    private boolean disableFocus = false;
066    private boolean modalBackdrop = false;
067
068    /**
069     * placeholderHelper
070     */
071    private PlaceholderHelper placeholderHelper = GWT.create(PlaceholderHelper.class);
072
073    public TimeBoxBase() {
074        box = new TextBox();
075        box.setStyleName("input-mini");
076        setElement(box.getElement());
077        setFormat("HH:mm:ss a");
078        setValue(new Date());
079    }
080
081    /**
082     * @see com.google.gwt.user.client.ui.ValueBoxBase#isReadOnly()
083     */
084    public boolean isReadOnly() {
085        return box.isReadOnly();
086    }
087
088    /**
089     * @see com.google.gwt.user.client.ui.ValueBoxBase#setReadOnly(boolean)
090     */
091    public void setReadOnly(boolean readonly) {
092        box.setReadOnly(readonly);
093    }
094
095    /**
096     * Returns the internal instance of textbox element. Use only if know what you are doing.
097     *
098     * @return internal textbox intance.
099     */
100    protected TextBox getBox() {
101        return box;
102    }
103
104    /**
105     * Get un-transformed text
106     *
107     * @return text box value
108     */
109    public String getOriginalValue() {
110        return box.getValue();
111    }
112
113    /**
114     * {@inheritDoc}
115     */
116    @Override
117    public Date getValue() {
118        try {
119            return dtf != null && box.getValue() != null ? dtf.parse(box.getValue()) : null;
120        } catch (Exception e) {
121            return null;
122        }
123    }
124
125    /**
126     * {@inheritDoc}
127     */
128    @Override
129    public void setValue(Date value) {
130        setValue(value, false);
131    }
132
133    /**
134     * {@inheritDoc}
135     */
136    protected native void updateValue(Element e)/*-{
137        if ($wnd.jQuery(e).data('changeTime.timepicker')) {
138            $wnd.jQuery(e).data('changeTime.timepicker').update();
139        }
140    }-*/;
141
142    /**
143     * {@inheritDoc}
144     */
145    @Override
146    public void setValue(Date value, boolean fireEvents) {
147        box.setValue(value != null ? dtf.format(value) : null);
148
149        updateValue(box.getElement());
150
151        if (fireEvents) {
152            ValueChangeEvent.fire(this, value);
153        }
154    }
155
156    /**
157     * configure this timepicker
158     */
159    protected void configure() {
160        configure(this);
161    }
162
163    /**
164     * Configure the elements for a specific widget.
165     * Use only if you know what you are doing.
166     *
167     * @param w: the widget to configure.
168     */
169    protected void configure(Widget w) {
170        w.getElement().setAttribute("data-date-format", format);
171        configure(w.getElement(), template.name().toLowerCase(), defaultTime.name().toLowerCase(), minuteStep, showSeconds, secondStep, showMeridian,
172                showInputs, disableFocus, modalBackdrop);
173    }
174
175    /**
176     * call jquery timepicker plugin in a element.
177     *
178     * @param e: Element that will be transformed in a timepicker.
179     */
180    protected native void configure(Element e, String template, String defaultTime, int minuteStep, boolean showSeconds, int secondStep,
181                                    boolean showMeridian, boolean showInputs, boolean disableFocus, boolean modalBackdrop) /*-{
182        $wnd.jQuery(e).timepicker(
183            {
184                template: template,
185                defaultTime: defaultTime,
186                minuteStep: minuteStep,
187                showSeconds: showSeconds,
188                secondStep: secondStep,
189                showMeridian: showMeridian,
190                showInputs: showInputs,
191                disableFocus: disableFocus,
192                modalBackdrop: modalBackdrop
193            }
194        );
195    }-*/;
196
197    private native void execute(Element e, String cmd) /*-{
198        $wnd.jQuery(e).timepicker(cmd);
199    }-*/;
200
201    private void execute(String cmd) {
202        execute(getElement(), cmd);
203    }
204
205    /**
206     * {@inheritDoc}
207     */
208    @Override
209    public void show() {
210        execute("show");
211    }
212
213    /**
214     * {@inheritDoc}
215     */
216    @Override
217    public void hide() {
218        execute("hide");
219    }
220
221    @Override
222    public void toggle() {
223        execute("toggle");
224    }
225
226    /**
227     * Safely removes data
228     *
229     * @param e: Element that will be cleared
230     */
231    protected native void removeDataIfExists(Element e) /*-{
232        var $that = $wnd.jQuery(e);
233        data = $that.data('timepicker');
234        if (data) {
235            picker = data.picker;
236            $that.removeData('timepicker');
237            picker.remove();
238            $that.off();
239        }
240    }-*/;
241
242    /**
243     * Removes any data in the time picker and reconfigures it
244     */
245    public void reconfigure() {
246        removeDataIfExists(getElement());
247        configure(getElement(), template.name().toLowerCase(), defaultTime.name().toLowerCase(), minuteStep, showSeconds, secondStep, showMeridian,
248                showInputs, disableFocus, modalBackdrop);
249    }
250
251    /**
252     * {@inheritDoc}
253     */
254    @Override
255    protected void onLoad() {
256        super.onLoad();
257        configure(getElement(), template.name().toLowerCase(), defaultTime.name().toLowerCase(), minuteStep, showSeconds, secondStep, showMeridian,
258                showInputs, disableFocus, modalBackdrop);
259    }
260
261    /**
262     * This method is called immediately before a widget will be detached from the browser's document.
263     */
264    @Override
265    protected void onUnload() {
266        super.onUnload();
267        execute("remove");
268        removeDataIfExists(getElement());
269    }
270
271    /**
272     * {@inheritDoc}
273     */
274    @Override
275    public void setPlaceholder(String placeholder) {
276        placeholderHelper.setPlaceholer(getElement(), placeholder);
277    }
278
279    /**
280     * {@inheritDoc}
281     */
282    @Override
283    public String getPlaceholder() {
284        return placeholderHelper.getPlaceholder(getElement());
285    }
286
287    /**
288     * {@inheritDoc}
289     */
290    @Override
291    public void setTemplate(Template template) {
292        this.template = template;
293    }
294
295    /**
296     * {@inheritDoc}
297     */
298    @Override
299    public void setTemplate(String template) {
300        this.template = Template.valueOf(template);
301    }
302
303    /**
304     * {@inheritDoc}
305     */
306    @Override
307    public void setMeridian(boolean meridian) {
308        this.showMeridian = meridian;
309    }
310
311    /**
312     * {@inheritDoc}
313     */
314    @Override
315    public void setAlternateSize(AlternateSize size) {
316        StyleHelper.changeStyle(this, size, AlternateSize.class);
317    }
318
319    /**
320     * {@inheritDoc}
321     */
322    @Override
323    public String getId() {
324        return getElement().getId();
325    }
326
327    /**
328     * {@inheritDoc}
329     */
330    @Override
331    public void setId(String id) {
332        getElement().setId(id);
333    }
334
335    /**
336     * {@inheritDoc}
337     */
338    @Override
339    public void setSize(int size) {
340        SizeHelper.setSize(this, size);
341    }
342
343    /**
344     * {@inheritDoc}
345     */
346    @Override
347    public void setStyle(Style style) {
348        StyleHelper.setStyle(this, style);
349    }
350
351    /**
352     * {@inheritDoc}
353     */
354    @Override
355    public void addStyle(Style style) {
356        StyleHelper.addStyle(this, style);
357    }
358
359    /**
360     * {@inheritDoc}
361     */
362    @Override
363    public void removeStyle(Style style) {
364        StyleHelper.removeStyle(this, style);
365    }
366
367    /**
368     * {@inheritDoc}
369     */
370    @Override
371    public void setShowOn(Device device) {
372        ResponsiveHelper.setHideOn(this, device);
373    }
374
375    /**
376     * {@inheritDoc}
377     */
378    @Override
379    public void setHideOn(Device device) {
380        ResponsiveHelper.setHideOn(this, device);
381    }
382
383    /**
384     * {@inheritDoc}
385     */
386    @Override
387    public void setSearchQuery(boolean searchQuery) {
388        SearchQueryStyleHelper.setSearchQuery(this, searchQuery);
389    }
390
391    /**
392     * {@inheritDoc}
393     */
394    @Override
395    public boolean isSearchQuery() {
396        return SearchQueryStyleHelper.isSearchQuery(this);
397    }
398
399    /**
400     * {@inheritDoc}
401     */
402    @Override
403    public boolean isEnabled() {
404        return box.isEnabled();
405    }
406
407    /**
408     * {@inheritDoc}
409     */
410    @Override
411    public void setEnabled(boolean enabled) {
412        box.setEnabled(enabled);
413    }
414
415    /**
416     * {@inheritDoc}
417     */
418    @Override
419    public void setShowSeconds(boolean showSeconds) {
420        this.showSeconds = showSeconds;
421    }
422
423    /**
424     * {@inheritDoc}
425     */
426    @Override
427    public void setDisableFocus(boolean disableFocus) {
428        this.disableFocus = disableFocus;
429    }
430
431    /**
432     * {@inheritDoc}
433     */
434    @Override
435    public void setModalBackdrop(boolean modalBackdrop) {
436        this.modalBackdrop = modalBackdrop;
437    }
438
439    /**
440     * {@inheritDoc}
441     */
442    @Override
443    public void setShowInputs(boolean showInputs) {
444        this.showInputs = showInputs;
445    }
446
447    /**
448     * {@inheritDoc}
449     */
450    @Override
451    public void setMinuteStep(int minuteStep) {
452        this.minuteStep = minuteStep;
453    }
454
455    /**
456     * {@inheritDoc}
457     */
458    @Override
459    public void setSecondStep(int secondStep) {
460        this.secondStep = secondStep;
461    }
462
463    /**
464     * {@inheritDoc}
465     */
466    @Override
467    public void setDefaultTime(DefaultTime defaultTime) {
468        this.defaultTime = defaultTime;
469    }
470
471    /**
472     * {@inheritDoc}
473     */
474    @Override
475    public void setDefaultTime(String defaultTime) {
476        this.defaultTime = DefaultTime.valueOf(defaultTime);
477    }
478
479    /**
480     * {@inheritDoc}
481     */
482    @Override
483    public HandlerRegistration addHideHandler(HideHandler handler) {
484        return addHandler(handler, HideEvent.getType());
485
486    }
487
488    /**
489     * {@inheritDoc}
490     */
491    @Override
492    public HandlerRegistration addHiddenHandler(HiddenHandler handler) {
493        return addHandler(handler, HiddenEvent.getType());
494
495    }
496
497    /**
498     * {@inheritDoc}
499     */
500    @Override
501    public HandlerRegistration addShowHandler(ShowHandler handler) {
502        return addHandler(handler, ShowEvent.getType());
503    }
504
505    /**
506     * {@inheritDoc}
507     */
508    @Override
509    public HandlerRegistration addShownHandler(ShownHandler handler) {
510        return addHandler(handler, ShownEvent.getType());
511    }
512
513    /**
514     * {@inheritDoc}
515     */
516    @Override
517    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Date> handler) {
518        return addHandler(handler, ValueChangeEvent.getType());
519    }
520
521    @Override
522    public void setFormat(String format) {
523        this.format = format;
524        Date oldValue = getValue();
525        this.dtf = DateTimeFormat.getFormat(format);
526        if (oldValue != null) {
527            setValue(oldValue);
528        }
529    }
530}