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.datepicker.client.ui.base;
017
018import com.github.gwtbootstrap.client.ui.TextBox;
019import com.github.gwtbootstrap.client.ui.base.HasAlternateSize;
020import com.github.gwtbootstrap.client.ui.base.HasId;
021import com.github.gwtbootstrap.client.ui.base.HasPlaceholder;
022import com.github.gwtbootstrap.client.ui.base.HasSize;
023import com.github.gwtbootstrap.client.ui.base.HasStyle;
024import com.github.gwtbootstrap.client.ui.base.HasVisibility;
025import com.github.gwtbootstrap.client.ui.base.IsResponsive;
026import com.github.gwtbootstrap.client.ui.base.IsSearchQuery;
027import com.github.gwtbootstrap.client.ui.base.PlaceholderHelper;
028import com.github.gwtbootstrap.client.ui.base.ResponsiveHelper;
029import com.github.gwtbootstrap.client.ui.base.SearchQueryStyleHelper;
030import com.github.gwtbootstrap.client.ui.base.SizeHelper;
031import com.github.gwtbootstrap.client.ui.base.Style;
032import com.github.gwtbootstrap.client.ui.base.StyleHelper;
033import com.github.gwtbootstrap.client.ui.constants.AlternateSize;
034import com.github.gwtbootstrap.client.ui.constants.Device;
035import com.github.gwtbootstrap.client.ui.event.HasVisibleHandlers;
036import com.github.gwtbootstrap.client.ui.event.HiddenHandler;
037import com.github.gwtbootstrap.client.ui.event.HideEvent;
038import com.github.gwtbootstrap.client.ui.event.HideHandler;
039import com.github.gwtbootstrap.client.ui.event.ShowEvent;
040import com.github.gwtbootstrap.client.ui.event.ShowHandler;
041import com.github.gwtbootstrap.client.ui.event.ShownHandler;
042import com.github.gwtbootstrap.datepicker.client.ui.util.LocaleUtil;
043import com.google.gwt.core.client.GWT;
044import com.google.gwt.dom.client.Element;
045import com.google.gwt.editor.client.IsEditor;
046import com.google.gwt.editor.client.adapters.TakesValueEditor;
047import com.google.gwt.event.dom.client.ChangeEvent;
048import com.google.gwt.event.dom.client.ChangeHandler;
049import com.google.gwt.event.dom.client.HasChangeHandlers;
050import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
051import com.google.gwt.event.logical.shared.ValueChangeEvent;
052import com.google.gwt.event.logical.shared.ValueChangeHandler;
053import com.google.gwt.event.shared.HandlerRegistration;
054import com.google.gwt.i18n.client.DateTimeFormat;
055import com.google.gwt.i18n.client.LocaleInfo;
056import com.google.gwt.user.client.Event;
057import com.google.gwt.user.client.ui.HasEnabled;
058import com.google.gwt.user.client.ui.HasName;
059import com.google.gwt.user.client.ui.HasValue;
060import com.google.gwt.user.client.ui.ValueBoxBase.TextAlignment;
061import com.google.gwt.user.client.ui.Widget;
062
063import java.util.Date;
064
065/**
066 * Base DatePicker component.
067 *
068 * @author Carlos Alexandro Becker
069 * @author ohashi keisuke
070 * @since 2.0.4.0
071 */
072public class DateBoxBase extends Widget implements HasValue<Date>,HasEnabled, HasValueChangeHandlers<Date>, HasVisibility,
073        HasChangeHandlers, HasVisibleHandlers, HasAllDatePickerHandlers, IsEditor<TakesValueEditor<Date>>, HasPlaceholder, HasAlternateSize, IsSearchQuery, HasSize, HasId, IsResponsive , HasStyle, HasName {
074
075    private final TextBox box;
076    private String format;
077    private String language;
078    private DateTimeFormat dtf;
079    private TakesValueEditor<Date> editor;
080
081    /** placeholderHelper */
082    private PlaceholderHelper placeholderHelper = GWT.create(PlaceholderHelper.class);
083    private boolean autoclose = false;
084
085    public DateBoxBase() {
086        this.box = new TextBox();
087        this.language = LocaleUtil.getLanguage();
088        setElement(box.getElement());
089        setFormat(DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_SHORT).getPattern().toLowerCase());
090        setWeekStart(LocaleInfo.getCurrentLocale().getDateTimeFormatInfo().firstDayOfTheWeek());
091        setValue(new Date());
092    }
093
094    public void setAlignment(TextAlignment align) {
095        box.setAlignment(align);
096    }
097
098    /**
099     * @see com.google.gwt.user.client.ui.ValueBoxBase#isReadOnly()
100     */
101    public boolean isReadOnly() {
102        return box.isReadOnly();
103    }
104
105    /**
106     * @see com.google.gwt.user.client.ui.ValueBoxBase#setReadOnly(boolean)
107     */
108    public void setReadOnly(boolean readonly) {
109        box.setReadOnly(readonly);
110    }
111
112    /**
113     * {@inheritDoc}
114     */
115    @Override
116    public void setFormat(String format) {
117        this.format = format;
118        Date oldValue = getValue();
119        this.dtf = DateTimeFormat.getFormat(format.replaceAll("mm", "MM"));
120        if (oldValue != null) {
121            setValue(oldValue);
122        }
123    }
124
125    public void setLanguage(String language) {
126        this.language = language;
127        LocaleUtil.forceLocale(language);
128    }
129
130    /**
131     * Returns the internal instance of textbox element. Use only if know what you are doing.
132     *
133     * @return internal textbox intance.
134     */
135    protected TextBox getBox() {
136        return box;
137    }
138
139    /**
140     * {@inheritDoc}
141     */
142    @Override
143    public Date getValue() {
144        try {
145            return dtf != null && box.getValue() != null ? dtf.parse(box.getValue()) : null;
146        } catch(Exception e) {
147            return null;
148        }
149    }
150
151    /**
152     * Get un-tranceform text
153     * @return text box value
154     */
155    public String getOriginalValue() {
156        return box.getValue();
157    }
158
159    /**
160     * {@inheritDoc}
161     */
162    @Override
163    public void setValue(Date value) {
164        setValue(value, false);
165    }
166
167    /**
168     * {@inheritDoc}
169     */
170    @Override
171    public void setValue(Date value, boolean fireEvents) {
172        box.setValue(value != null ? dtf.format(value) : null);
173
174        updateValue(box.getElement());
175
176        if (fireEvents) {
177            ValueChangeEvent.fire(this, value);
178        }
179    }
180
181    protected native void updateValue(Element e)/*-{
182        if($wnd.jQuery(e).data('datepicker')) {
183            $wnd.jQuery(e).data('datepicker').update();
184        }
185    }-*/;
186
187    /**
188     * {@inheritDoc}
189     */
190    @Override
191    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Date> dateValueChangeHandler) {
192        return addHandler(dateValueChangeHandler, ValueChangeEvent.getType());
193    }
194
195    /**
196     * {@inheritDoc}
197     */
198    @Override
199    protected void onLoad() {
200        super.onLoad();
201        configure();
202    }
203
204    @Override
205    protected void onUnload() {
206        super.onUnload();
207        execute("remove");
208        removeDataIfExists(getElement());
209    }
210
211    /**
212     * Configure the elements for a specific widget.
213     * Use only if you know what you are doing.
214     *
215     * @param w: the widget to configure.
216     */
217    protected void configure(Widget w) {
218        w.getElement().setAttribute("data-date-format", format);
219        w.getElement().setAttribute("data-date-language", language);
220        configure(w.getElement(), autoclose);
221    }
222
223    /**
224     * dateChange event handler.
225     */
226    public void onChange() {
227        ValueChangeEvent.fire(this, getValue());
228    }
229
230    public void onShow(Event e) {
231        fireEvent(new ShowEvent(e));
232    }
233
234    public void onHide(Event e) {
235        fireEvent(new HideEvent(e));
236    }
237
238    public void reconfigure() {
239        removeDataIfExists(getElement());
240        configure();
241    }
242
243    /**
244     * configure this datepicker.
245     */
246    protected void configure() {
247        configure(this);
248    }
249
250    protected native void removeDataIfExists(Element e) /*-{
251        var $that = $wnd.jQuery(e);
252        dpData = $that.data('datepicker');
253        if(dpData) {
254            picker = dpData.picker;
255            $that.removeData('dateFormat');
256            $that.removeData('dateLanguage');
257            $that.removeData('dateWeekstart');
258            $that.removeData('dateStartdate');
259            $that.removeData('dateEnddate');
260            $that.removeData('dateStartView');
261            $that.removeData('datepicker');
262            picker.remove(); // Explicitly remove the picker element
263            $that.off();
264        }
265    }-*/;
266
267    /**
268     * call jquery datepicker plugin in a element.
269     *
270     * @param e: Element that will be transformed in a datepicker.
271     * @param autoclose  is autoclose?
272     */
273    protected native void configure(Element e, boolean autoclose) /*-{
274        var that = this;
275        $wnd.jQuery(e).datepicker({autoclose : autoclose})
276        .on('change' , function() {
277            that.@com.github.gwtbootstrap.datepicker.client.ui.base.DateBoxBase::onChange()();
278        })
279        .on("show", function (e) {
280            that.@com.github.gwtbootstrap.datepicker.client.ui.base.DateBoxBase::onShow(Lcom/google/gwt/user/client/Event;)(e);
281        })
282        .on("hide", function (e) {
283            that.@com.github.gwtbootstrap.datepicker.client.ui.base.DateBoxBase::onHide(Lcom/google/gwt/user/client/Event;)(e);
284        });
285    }-*/;
286
287    private native void execute(Element e, String cmd) /*-{
288        $wnd.jQuery(e).datepicker(cmd);
289    }-*/;
290
291    private void execute(String cmd) {
292        execute(getElement(), cmd);
293    }
294
295    /**
296     * {@inheritDoc}
297     */
298    @Override
299    public void show() {
300        execute("show");
301    }
302
303    /**
304     * {@inheritDoc}
305     */
306    @Override
307    public void hide() {
308        execute("hide");
309    }
310
311    /**
312     * {@inheritDoc}
313     */
314    @Override
315    public void toggle() {
316        //TODO 2012/06/21 ohashi keisuke shoud be support
317        throw new UnsupportedOperationException("not support toggle");
318    }
319
320    /**
321     * {@inheritDoc}
322     */
323    @Override
324    public HandlerRegistration addHideHandler(HideHandler handler) {
325        return addHandler(handler, HideEvent.getType());
326    }
327
328    /**
329     * {@inheritDoc}
330     */
331    @Override
332    public HandlerRegistration addHiddenHandler(HiddenHandler handler) {
333        //TODO 2012/06/21 ohashi keisuke shoud be support
334        throw new UnsupportedOperationException("not support hidden event");
335    }
336
337    /**
338     * {@inheritDoc}
339     */
340    @Override
341    public HandlerRegistration addShowHandler(ShowHandler handler) {
342        return addHandler(handler, ShowEvent.getType());
343    }
344
345    /**
346     * {@inheritDoc}
347     */
348    @Override
349    public HandlerRegistration addShownHandler(ShownHandler handler) {
350        //TODO 2012/06/21 ohashi keisuke shoud be support
351        throw new UnsupportedOperationException("not support shown event");
352    }
353
354    /**
355     * {@inheritDoc}
356     */
357    @Override
358    public void setWeekStart(int start) {
359        getElement().setAttribute("data-date-weekstart", start + "");
360    }
361
362    /**
363     * {@inheritDoc}
364     */
365    @Override
366    public void setStartDate(String startDate) {
367        getElement().setAttribute("data-date-startdate", startDate);
368    }
369
370    /**
371     * {@inheritDoc}
372     */
373    @Override
374    public void setStartDate_(Date startDate) {
375        setStartDate(dtf.format(startDate));
376    }
377
378
379    /**
380     * {@inheritDoc}
381     */
382    @Override
383    public void setEndDate(String endDate) {
384        getElement().setAttribute("data-date-enddate", endDate);
385    }
386
387    /**
388     * {@inheritDoc}
389     */
390    @Override
391    public void setEndDate_(Date endDate) {
392        setEndDate(dtf.format(endDate));
393    }
394
395    /**
396     * {@inheritDoc}
397     */
398    @Override
399    public void setAutoClose(boolean autoclose) {
400        this.autoclose = autoclose;
401    }
402
403    /**
404     * {@inheritDoc}
405     */
406    @Override
407    public void setStartView(ViewMode mode) {
408        setStartView(mode.name());
409    }
410
411    /**
412     * {@inheritDoc}
413     */
414    @Override
415    public void setStartView(String mode) {
416        getElement().setAttribute("data-date-start-view", mode.toLowerCase());
417    }
418
419        /**
420         * Retuen Editor
421         * @return editor
422         */
423        @Override
424        public TakesValueEditor<Date> asEditor() {
425                if(editor == null){
426                        editor = TakesValueEditor.of(this);
427                }
428                return editor;
429        }
430
431    @Override
432    public HandlerRegistration addChangeHandler(ChangeHandler handler) {
433        return addHandler(handler, ChangeEvent.getType());
434    }
435
436    /**
437     * {@inheritDoc}
438     */
439    @Override
440    public void setPlaceholder(String placeholder) {
441        placeholderHelper.setPlaceholer(getElement(), placeholder);
442    }
443
444    /**
445     * {@inheritDoc}
446     */
447    @Override
448    public String getPlaceholder() {
449        return placeholderHelper.getPlaceholder(getElement());
450    }
451
452    /**
453     * {@inheritDoc}
454     */
455    @Override
456    public void setSearchQuery(boolean searchQuery) {
457        SearchQueryStyleHelper.setSearchQuery(this, searchQuery);
458    }
459
460    /**
461     * {@inheritDoc}
462     */
463    @Override
464    public boolean isSearchQuery() {
465        return SearchQueryStyleHelper.isSearchQuery(this);
466    }
467
468    /**
469     * {@inheritDoc}
470     */
471    @Override
472    public void setAlternateSize(AlternateSize size) {
473        StyleHelper.changeStyle(this, size, AlternateSize.class);
474    }
475
476    /**
477     * {@inheritDoc}
478     */
479    @Override
480    public void setSize(int size) {
481        SizeHelper.setSize(this, size);
482    }
483
484    /**
485     * {@inheritDoc}
486     */
487    @Override
488    public String getId() {
489        return getElement().getId();
490    }
491
492    /**
493     * {@inheritDoc}
494     */
495    @Override
496    public void setId(String id) {
497        getElement().setId(id);
498    }
499
500    /**
501     * {@inheritDoc}
502     */
503    @Override
504    public void setShowOn(Device device) {
505        ResponsiveHelper.setShowOn(this, device);
506    }
507
508    /**
509     * {@inheritDoc}
510     */
511    @Override
512    public void setHideOn(Device device) {
513        ResponsiveHelper.setHideOn(this, device);
514
515    }
516
517    /**
518     * {@inheritDoc}
519     */
520    @Override
521    public void setStyle(Style style) {
522        StyleHelper.setStyle(this, style);
523    }
524
525    /**
526     * {@inheritDoc}
527     */
528    @Override
529    public void addStyle(Style style) {
530        StyleHelper.addStyle(this, style);
531    }
532
533    /**
534     * {@inheritDoc}
535     */
536    @Override
537    public void removeStyle(Style style) {
538        StyleHelper.removeStyle(this, style);
539
540    }
541
542    /**
543     * {@inheritDoc}
544     */
545    @Override
546    public boolean isEnabled() {
547        return false;
548    }
549
550    /**
551     * {@inheritDoc}
552     */
553    @Override
554    public void setEnabled(boolean enabled) {
555        box.setEnabled(enabled);
556    }
557
558    /**
559     * {@inheritDoc}
560     */
561        @Override
562        public void setName(String name) {
563                box.setName(name);
564        }
565
566         /**
567     * {@inheritDoc} 
568     */
569        @Override
570        public String getName() {
571                return box.getName();
572        }
573}