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