1 
2 #include "Wt/WTimeEdit.h"
3 
4 #include "Wt/WApplication.h"
5 #include "Wt/WContainerWidget.h"
6 #include "Wt/WLineEdit.h"
7 #include "Wt/WLogger.h"
8 #include "Wt/WPopupWidget.h"
9 #include "Wt/WPushButton.h"
10 #include "Wt/WTemplate.h"
11 #include "Wt/WTheme.h"
12 
13 #include "WebUtils.h"
14 
15 #ifndef WT_DEBUG_JS
16 #include "js/WTimeEdit.min.js"
17 #endif
18 
19 namespace Wt {
20 
21 LOGGER("WTimeEdit");
22 
WTimeEdit()23 WTimeEdit::WTimeEdit()
24   : WLineEdit()
25 {
26   setValidator(std::shared_ptr<WTimeValidator>(new WTimeValidator()));
27   changed().connect(this, &WTimeEdit::setFromLineEdit);
28 
29   timePicker_ = new WTimePicker(this);
30   timePicker_->selectionChanged().connect(this, &WTimeEdit::setFromTimePicker);
31   timePicker_->setWrapAroundEnabled(true);
32 }
33 
~WTimeEdit()34 WTimeEdit::~WTimeEdit()
35 {
36   if (!popup_) {
37     // timePicker_ is not owned by popup_, because it doesn't exist
38     delete timePicker_;
39   }
40 }
41 
load()42 void WTimeEdit::load()
43 {
44   bool wasLoaded = loaded();
45 
46   WLineEdit::load();
47   // Loading of popup_ is deferred (see issue #4897)
48 
49   if (wasLoaded)
50     return;
51 
52   const char *TEMPLATE = "${timePicker}";
53 
54   std::unique_ptr<WTemplate> t(new WTemplate(WString::fromUTF8(TEMPLATE)));
55   t->bindWidget("timePicker", std::unique_ptr<WTimePicker>(timePicker_));
56   popup_.reset(new WPopupWidget(std::move(t)));
57   if (isHidden()) {
58     popup_->setHidden(true);
59   }
60   popup_->setAnchorWidget(this);
61   popup_->setTransient(true);
62 
63   WApplication::instance()
64     ->theme()->apply(this, popup_.get(), TimePickerPopup);
65 
66   escapePressed().connect(popup_.get(), &WPopupWidget::hide);
67   escapePressed().connect(this, &WWidget::setFocus);
68 }
69 
setTime(const WTime & time)70 void WTimeEdit::setTime(const WTime& time)
71 {
72   if (!time.isNull()) {
73     setText(time.toString(format()));
74     timePicker_->setTime(time);
75   }
76 }
77 
time()78 WTime WTimeEdit::time() const
79 {
80   return WTime::fromString(text(), format());
81 }
82 
timeValidator()83 std::shared_ptr<WTimeValidator> WTimeEdit::timeValidator() const
84 {
85   return std::dynamic_pointer_cast<WTimeValidator>(WLineEdit::validator());
86 }
87 
setFormat(const WT_USTRING & format)88 void WTimeEdit::setFormat(const WT_USTRING& format)
89 {
90   auto tv = timeValidator();
91 
92   if (tv) {
93     WTime t = this->time();
94     tv->setFormat(format);
95     timePicker_->configure();
96     setTime(t);
97   } else
98     LOG_WARN("setFormat() ignored since validator is not WTimeValidator");
99 }
100 
format()101 WT_USTRING WTimeEdit::format() const
102 {
103   auto tv = timeValidator();
104 
105   if (tv)
106     return tv->format();
107   else {
108     LOG_WARN("format() is bogus since validator is not WTimeValidator.");
109     return WT_USTRING();
110   }
111 }
112 
setBottom(const WTime & bottom)113 void WTimeEdit::setBottom(const WTime &bottom)
114 {
115     auto tv = timeValidator();
116     if(tv)
117         tv->setBottom(bottom);
118 }
119 
bottom()120 WTime WTimeEdit::bottom() const
121 {
122     auto tv = timeValidator();
123     if(tv)
124         return tv->bottom();
125     return WTime();
126 }
127 
setTop(const WTime & top)128 void WTimeEdit::setTop(const WTime &top)
129 {
130     auto tv = timeValidator();
131     if(tv)
132         tv->setTop(top);
133 }
134 
top()135 WTime WTimeEdit::top() const
136 {
137     auto tv = timeValidator();
138     if(tv)
139         return tv->top();
140     return WTime();
141 }
142 
setHidden(bool hidden,const WAnimation & animation)143 void WTimeEdit::setHidden(bool hidden, const WAnimation& animation)
144 {
145   WLineEdit::setHidden(hidden, animation);
146   if (popup_) {
147     popup_->setHidden(hidden, animation);
148   }
149 }
150 
render(WFlags<RenderFlag> flags)151 void WTimeEdit::render(WFlags<RenderFlag> flags)
152 {
153   if (flags.test(RenderFlag::Full))
154     defineJavaScript();
155 
156   WLineEdit::render(flags);
157 }
158 
propagateSetEnabled(bool enabled)159 void WTimeEdit::propagateSetEnabled(bool enabled)
160 {
161   WLineEdit::propagateSetEnabled(enabled);
162 }
163 
setFromTimePicker()164 void WTimeEdit::setFromTimePicker()
165 {
166   setTime(timePicker_->time());
167   textInput().emit();
168   changed().emit();
169 }
170 
setFromLineEdit()171 void WTimeEdit::setFromLineEdit()
172 {
173   WTime t = WTime::fromString(text(), format());
174   if (t.isValid())
175     timePicker_->setTime(t);
176 }
177 
defineJavaScript()178 void WTimeEdit::defineJavaScript()
179 {
180   WApplication *app = WApplication::instance();
181   LOAD_JAVASCRIPT(app, "js/WTimeEdit.js", "WTimeEdit", wtjs1);
182   std::string jsObj = "new " WT_CLASS ".WTimeEdit("
183                       + app->javaScriptClass() + "," + jsRef() + ","
184 		      + jsStringLiteral(popup_->id()) + ");";
185   setJavaScriptMember(" WTimeEdit", jsObj);
186 #ifdef WT_CNOR
187   EventSignalBase& b = mouseMoved();
188   EventSignalBase& c = keyWentDown();
189 #endif
190   connectJavaScript(mouseMoved(), "mouseMove");
191   connectJavaScript(mouseWentUp(), "mouseUp");
192   connectJavaScript(mouseWentDown(), "mouseDown");
193   connectJavaScript(mouseWentOut(), "mouseOut");
194 }
195 
connectJavaScript(Wt::EventSignalBase & s,const std::string & methodName)196 void WTimeEdit::connectJavaScript(Wt::EventSignalBase& s,
197                                   const std::string& methodName)
198 {
199   std::string jsFunction =
200     "function(dobj, event) {"
201     """var o = " + jsRef() + ";"
202     """if(o && o.wtDObj) o.wtDObj." + methodName + "(dobj, event);"
203     "}";
204   s.connect(jsFunction);
205 }
206 
setHourStep(int step)207 void WTimeEdit::setHourStep(int step)
208 {
209   timePicker_->setHourStep(step);
210 }
211 
hourStep()212 int WTimeEdit::hourStep() const
213 {
214   return timePicker_->hourStep();
215 }
216 
setMinuteStep(int step)217 void WTimeEdit::setMinuteStep(int step)
218 {
219   timePicker_->setMinuteStep(step);
220 }
221 
minuteStep()222 int WTimeEdit::minuteStep() const
223 {
224   return timePicker_->minuteStep();
225 }
226 
setSecondStep(int step)227 void WTimeEdit::setSecondStep(int step)
228 {
229   timePicker_->setSecondStep(step);
230 }
231 
secondStep()232 int WTimeEdit::secondStep() const
233 {
234   return timePicker_->secondStep();
235 }
236 
setMillisecondStep(int step)237 void WTimeEdit::setMillisecondStep(int step)
238 {
239   timePicker_->setMillisecondStep(step);
240 }
241 
millisecondStep()242 int WTimeEdit::millisecondStep() const
243 {
244   return timePicker_->millisecondStep();
245 }
246 
setWrapAroundEnabled(bool enabled)247 void WTimeEdit::setWrapAroundEnabled(bool enabled)
248 {
249   timePicker_->setWrapAroundEnabled(enabled);
250 }
251 
wrapAroundEnabled()252 bool WTimeEdit::wrapAroundEnabled() const
253 {
254   return timePicker_->wrapAroundEnabled();
255 }
256 
257 
258 }
259