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