Project

General

Profile

Feature #3725 » timeedit.patch

Benjamin Oldenburg, 01/12/2015 07:22 PM

View differences:

resources/themes/bootstrap/3/time-edit-button.png 1970-01-01 01:00:00.000000000 +0100 → resources/themes/bootstrap/3/time-edit-button.png 2014-12-30 09:51:22.000000000 +0000
1
?PNG
2

3

IHDR(f???qbKGD???????	pHYs
?
?B(?xtIME?	3???IDATx??]H?}??-7'󣌲XQl?:?Jʤ
4
R?e??9???:≨N:0t?h??ecA(??&?bs}@?u??vo??????>???x{wp_??{??????????1?????ٳH??@??dLV>RH?H?ʀr
&EEQ???b????(555????h??ɡ?????QA ?I^C??x?]?v???DQdvv?ݎ?nG?Ra2?????Ǐ?|>"?uuu??ձe?
5
E?8
6
???ƃ8t?


;v???4B?/_???????DQ???????U???x<?Ν;W?ñ?1N?<????ikk#???~?۷o??????g?]???ׯ??易? q5??ՅJ?????????2?H???>|?͛7???\?z?JEWW??ܱcǪ?,77??H__?ׯgdd?>099??른??+W?PQQ???gff&q5??th?Z?????룿?A(++??ŋdee????N?#JZG)??????dggc6????c~~???"6n??L?@?????6?3g????c)//?ĉ9r?p8Ljj*J?Q???q??YI?H>$UUUD"?v;^??BAjj*???h4?^/v??H$BUU??u??l??t:ݪ?,##???E?<y???$:??M?6?P(<??۷o3::J]]f??J??-V??TWW#?"????Z?????t????D"???S]]?Z???????[?n?T??(??z?????r?????c6??t????h4I??8`nn?<n???AP>$2??<$j?:y3?????[???(נ(ʀ?
7
(?"?P???q???dgg???illd||?P(??iI??x?m۶I??????p??ىJ???{qMM
V?um?UJ??a???<x???Z?=?F?!3<<Lkk+???ܸqC?a?????q???ٷo---?L???????a?~?:<{??$????Q?T???b2???bD?Qfgg????֭[l߾???T*??݉?A?^??`?ѣG?T*^?z?Ǐ??????q??i._???s?x??=??Ӊ???4?_?|??r???A????.?bX%σRbŰ
8
?@VV?????_k8^?a?f????>???(++?Ű?????!??????Hl?^1?????|>RRRP??dee????B???????7?RB?a?????aMII??ϟ????9?*%4
V??????jX?Z?qo??6??[1???ݿ֪???cX???(ʀ2?(?9?>?/??Y+?Y+֯_/o?׭[?t`???,,,?}P??ou?P???	???0???b0hjjbbb?????Z???9?N'N??R??h????~??(?????͛YZZ??=w听ɰ:?N:::(((?j?RTT7?###ttt???@SS?t?*%???f???????1??k+?uzz???f޼y???b??ݫΠ????E?Tb?Z1?q?:77GOOw??A??c??P*????Jo?R??vc4)**????ӧO?{????)N?:E,????ш????ݻ?!nX?~??ӧO@JJJ8???? D??U&??Z??kii)???߿SXXȆ
?)??jQ*???`YY.????aJJJ8~?8??Ű???1?͉mԕ??D?Q~????????p8?F???6??l??????????n޾}?N?#'''nX?w?cccX?VJKKQ*??z?EQ$??ͰZ,?N'????}??l6,??????5ꕻ??LMM??ۋ??F?Z-eeeTVV???7?????n?k?Vy`?e@P????Gc'/IEND?B`?
resources/themes/bootstrap/3/wt.css 2014-03-28 10:41:53.000000000 +0000 → resources/themes/bootstrap/3/wt.css 2014-12-30 09:42:15.000000000 +0000
320 320
}
321 321

  
322 322
/*
323
 * WTimeEdit
324
 */
325

  
326
.Wt-timeedit {
327
  padding-right: 40px;
328
  background-image: url('time-edit-button.png');
329
  background-position: right top;
330
  background-repeat: no-repeat;
331
}
332

  
333
.Wt-timeedit:hover {
334
  cursor: default;
335
  background-position: right -34px;
336
}
337

  
338
.Wt-timeedit:active {
339
  cursor: default;
340
  background-position: right -68px;
341
}
342

  
343
.Wt-timeedit::-ms-clear {
344
  display: none;
345
}
346

  
347
/*
323 348
 * WDatePicker
324 349
 */
325 350

  
resources/themes/bootstrap/3/wt.less 2014-03-28 10:41:53.000000000 +0000 → resources/themes/bootstrap/3/wt.less 2015-01-04 07:18:00.000000000 +0000
305 305
}
306 306

  
307 307
/*
308
 * WTimeEdit
309
 */
310
.Wt-timeedit {
311
    background-image: url('date-edit-button.png');
312
    background-repeat: no-repeat;
313
    background-position: right top;
314
    padding-right: 40px;
315

  
316
    &:hover {
317
        cursor: default;
318
        background-position: right -34px;
319
    }
320

  
321
    &:active {
322
        cursor: default;
323
        background-position: right -68px;
324
    }
325
}
326

  
327
.Wt-timeedit::-ms-clear {
328
    display:none
329
}
330

  
331
/*
308 332
 * WDatePicker
309 333
 */
310 334
.Wt-datepicker input {
src/CMakeLists.txt 2014-02-20 07:29:19.000000000 +0000 → src/CMakeLists.txt 2015-01-04 13:40:05.000000000 +0000
12 12

  
13 13
MACRO (FILE_TO_STRING infile outfile var)
14 14
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${outfile}
15
	           COMMAND ${CMAKE_COMMAND}
15
               COMMAND ${CMAKE_COMMAND}
16 16
                   ARGS -Dinfile:FILEPATH=${CMAKE_CURRENT_SOURCE_DIR}/${infile}
17 17
                        -Doutfile:FILEPATH=${CMAKE_CURRENT_BINARY_DIR}/${outfile}
18 18
                        -Dvar:STRING=${var}
19 19
                        -P ${CMAKE_CURRENT_SOURCE_DIR}/filetostring.cmake
20
		   MAIN_DEPENDENCY
21
		        ${CMAKE_CURRENT_SOURCE_DIR}/${infile}
20
           MAIN_DEPENDENCY
21
                ${CMAKE_CURRENT_SOURCE_DIR}/${infile}
22 22
)
23 23
ENDMACRO (FILE_TO_STRING)
24 24

  
......
43 43
FILE_TO_STRING(xml/wt.xml Wt_xml.C Wt_xml)
44 44
FILE_TO_STRING(xml/auth_strings.xml AuthStrings_xml.C AuthStrings_xml)
45 45
FILE_TO_STRING(xml/bootstrap_theme.xml
46
	BootstrapTheme_xml.C BootstrapTheme_xml)
46
    BootstrapTheme_xml.C BootstrapTheme_xml)
47 47
FILE_TO_STRING(xml/bootstrap3_theme.xml
48
	Bootstrap3Theme_xml.C Bootstrap3Theme_xml)
48
    Bootstrap3Theme_xml.C Bootstrap3Theme_xml)
49 49
FILE_TO_STRING(xml/auth_css_theme.xml
50
	AuthCssTheme_xml.C AuthCssTheme_xml)
50
    AuthCssTheme_xml.C AuthCssTheme_xml)
51 51

  
52 52
SET(libsources
53 53
Wt/PopupWindow.C
......
221 221
Wt/WTextEdit.C
222 222
Wt/WTheme.C
223 223
Wt/WTime.C
224
Wt/WTimeEdit.C
224 225
Wt/WTimer.C
225 226
Wt/WTimerWidget.C
227
Wt/WTimePicker.C
228
Wt/WTimeValidator.C
226 229
Wt/WToolBar.C
227 230
Wt/WTransform.C
228 231
Wt/WTree.C
src/js/WTimeEdit.js 1970-01-01 01:00:00.000000000 +0100 → src/js/WTimeEdit.js 2014-12-30 09:31:02.000000000 +0000
1
/*
2
 * Copyright (C) 2010 Emweb bvba, Kessel-Lo, Belgium.
3
 *
4
 * See the LICENSE file for terms of use.
5
 */
6

  
7
/* Note: this is at the same time valid JavaScript and C++. */
8

  
9
WT_DECLARE_WT_MEMBER
10
(1, JavaScriptConstructor, "WTimeEdit",
11
 function(APP, edit, popup) {
12
   /** @const */ var CLASS_HOVER = 'hover';
13
   /** @const */ var CLASS_ACTIVE = 'active';
14
   /** @const */ var CLASS_UNSELECTABLE = 'unselectable';
15

  
16
   jQuery.data(edit, 'dobj', this);
17

  
18
   var self = this, WT = APP.WT, $edit = $(edit);
19

  
20
   function isReadOnly() {
21
     return !!edit.getAttribute("readonly");
22
   }
23

  
24
   function isPopupVisible() {
25
     return popup.style.display === '';
26
   }
27

  
28
   function getPopup() {
29
     var p = $('#' + popup.id).get(0);
30
     return jQuery.data(p, 'popup');
31
   }
32

  
33
   function resetButton() {
34
     $edit.removeClass(CLASS_ACTIVE);
35
   }
36

  
37
   function showPopup() {
38
     var p = getPopup();
39
     p.bindHide(resetButton);
40
     p.show(edit, WT.Vertical);
41
   }
42

  
43
   this.mouseOut = function(o, event) {
44
     $edit.removeClass(CLASS_HOVER);
45
   };
46

  
47
   this.mouseMove = function(o, event) {
48
     if (isReadOnly())
49
       return;
50

  
51
     var xy = WT.widgetCoordinates(edit, event);
52

  
53
     if (xy.x > edit.offsetWidth - 40) {
54
       $edit.addClass(CLASS_HOVER);
55
     } else {
56
       if ($edit.hasClass(CLASS_HOVER))
57
     $edit.removeClass(CLASS_HOVER);
58
     }
59
   };
60

  
61
   this.mouseDown = function(o, event) {
62
     if (isReadOnly())
63
       return;
64

  
65
     var xy = WT.widgetCoordinates(edit, event);
66
     if (xy.x > edit.offsetWidth - 40) {
67
       $edit.addClass(CLASS_UNSELECTABLE).addClass(CLASS_ACTIVE);
68
     }
69
   };
70

  
71
   this.mouseUp = function(o, event) {
72
     $edit.removeClass(CLASS_UNSELECTABLE);
73

  
74
     var xy = WT.widgetCoordinates(edit, event);
75
     if (xy.x > edit.offsetWidth - 40)
76
       showPopup();
77
   };
78
 });
src/js/WTimeEdit.min.js 1970-01-01 01:00:00.000000000 +0100 → src/js/WTimeEdit.min.js 2014-12-30 09:31:07.000000000 +0000
1
WT_DECLARE_WT_MEMBER(1,JavaScriptConstructor,"WTimeEdit",function(g,a,h){function f(){return!!a.getAttribute("readonly")}function i(){var b=$("#"+h.id).get(0);return jQuery.data(b,"popup")}function j(){c.removeClass("active")}function k(){var b=i();b.bindHide(j);b.show(a,e.Vertical)}jQuery.data(a,"dobj",this);var e=g.WT,c=$(a);this.mouseOut=function(){c.removeClass("hover")};this.mouseMove=function(b,d){if(!f())if(e.widgetCoordinates(a,d).x>a.offsetWidth-40)c.addClass("hover");else c.hasClass("hover")&&
2
c.removeClass("hover")};this.mouseDown=function(b,d){f()||e.widgetCoordinates(a,d).x>a.offsetWidth-40&&c.addClass("unselectable").addClass("active")};this.mouseUp=function(b,d){c.removeClass("unselectable");e.widgetCoordinates(a,d).x>a.offsetWidth-40&&k()}});
src/js/WTimeValidator.js 1970-01-01 01:00:00.000000000 +0100 → src/js/WTimeValidator.js 2015-01-04 13:40:05.000000000 +0000
1
/*
2
 * Copyright (C) 2011 Emweb bvba, Kessel-Lo, Belgium.
3
 *
4
 * See the LICENSE file for terms of use.
5
 */
6

  
7
/* Note: this is at the same time valid JavaScript and C++. */
8

  
9
/*
10
 * We could merge this with WIntValidator ...
11
 */
12

  
13
WT_DECLARE_WT_MEMBER
14
(1, JavaScriptConstructor, "WTimeValidator",
15
   function(mandatory, formats, bottom, top, blankError,
16
        formatError) {
17

  
18
   this.validate = function(text) {
19
     if (text.length == 0)
20
       if (mandatory)
21
       return { valid: false, message: blankError };
22
     else
23
       return { valid: true };
24

  
25
     var results;
26

  
27
     var s = -1, m = -1, h = -1;
28

  
29
     for (var i = 0, il = formats.length; i < il; ++i) {
30
       var f = formats[i];
31
       var r = new RegExp("^" + f.regexp + "$");
32

  
33
       results = r.exec(text);
34
       if (results != null) {
35
     //s = f.getSecond(results);
36
     m = f.getMinute(results);
37
     h = f.getHour(results);
38

  
39
     break;
40
       }
41
     }
42

  
43
     if (results == null)
44
       return { valid: false, message: formatError };
45

  
46
     if( /*(m < 0) || (m > 59) ||*/ (m < 0) || (m > 59) || (h < 0) || (h > 23))
47
         return {valid: false, message: formatError };
48

  
49
     var dt = new Date(0, 0, 0, h, m, 0, 0);
50

  
51
     if(/*dt.getSeconds() != s ||*/ dt.getMinutes() != m || dt.getHours() != h)
52
     {
53
         return {valid: false, message: formatError };
54
     }
55

  
56
     /*
57
     if (bottom)
58
       if (dt.getTime() < bottom.getTime())
59
     return { valid: false, message: tooSmallError};
60

  
61
     if (top)
62
       if (dt.getTime() > top.getTime())
63
     return { valid:false, message: tooLargeError};
64

  
65
     */
66

  
67
     return { valid: true };
68
   };
69

  
70
   });
src/js/WTimeValidator.min.js 1970-01-01 01:00:00.000000000 +0100 → src/js/WTimeValidator.min.js 2015-01-04 13:40:05.000000000 +0000
1
WT_DECLARE_WT_MEMBER(1,JavaScriptConstructor,"WDateValidator",function(l,i,j,k,m,f,n,o){this.validate=function(a){if(a.length==0)return l?{valid:false,message:m}:{valid:true};for(var b,c=-1,d=-1,g=-1,h=0,p=i.length;h<p;++h){var e=i[h];b=(new RegExp("^"+e.regexp+"$")).exec(a);if(b!=null){c=e.getMonth(b);d=e.getDay(b);g=e.getYear(b);break}}if(b==null)return{valid:false,message:f};if(d<=0||d>31||c<=0||c>12)return{valid:false,message:f};a=new Date(g,c-1,d);if(a.getDate()!=d||a.getMonth()!=c-1||a.getFullYear()!=
2
g||a.getFullYear()<1400)return{valid:false,message:f};if(j)if(a.getTime()<j.getTime())return{valid:false,message:n};if(k)if(a.getTime()>k.getTime())return{valid:false,message:o};return{valid:true}}});
src/Wt/WBootstrapTheme.C 2014-04-29 21:55:27.000000000 +0100 → src/Wt/WBootstrapTheme.C 2015-01-04 07:17:19.000000000 +0000
13 13
#include "Wt/WComboBox"
14 14
#include "Wt/WDateEdit"
15 15
#include "Wt/WDatePicker"
16
#include "Wt/WTimeEdit"
16 17
#include "Wt/WDialog"
17 18
#include "Wt/WEnvironment"
18 19
#include "Wt/WGoogleMap"
......
151 152
    child->addStyleClass("Wt-datepicker");
152 153
    break;
153 154

  
155
  case TimePickerPopupRole:
156
    child->addStyleClass("Wt-timepicker");
157
    break;
158

  
154 159
  case PanelTitleBarRole:
155 160
    child->addStyleClass(classAccordionHeading());
156 161
    break;
......
381 386
        return;
382 387
      }
383 388

  
389
      WTimeEdit *timeEdit = dynamic_cast<WTimeEdit *>(widget);
390
      if (timeEdit) {
391
        element.addPropertyWord(PropertyClass, "Wt-timeedit");
392
        return;
393
      }
384 394

  
385 395
    }
386 396
    break;
src/Wt/WLocale 2014-02-25 22:12:04.000000000 +0000 → src/Wt/WLocale 2015-01-04 13:40:05.000000000 +0000
136 136
   */
137 137
  WT_USTRING dateFormat() const { return dateFormat_; }
138 138

  
139
  /*! \brief Sets the time format.
140
   *
141
   *  Sets the default format for time entry, eg. as used in
142
   *  WTimeValidator. See WTime::toString() for the supported syntax.
143
   *
144
   *  The default time format is "HH:mm:ss".
145
   */
146
  void setTimeFormat(const WT_USTRING &format);
147

  
148
  /*! \brief Returns the time format.
149
   *
150
   * Returns the time format.
151
   */
152
  WT_USTRING timeFormat() const { return timeFormat_; }
153

  
139 154
  /*! \brief Sets the date/time format.
140 155
   *
141 156
   * Sets the format for a localized time stamp (using
......
161 176

  
162 177
  /*! \brief Casts to the locale string (for pre-3.3.0 compatibility).
163 178
   *
164
   * \deprecated Use name() instead. 
179
   * \deprecated Use name() instead.
165 180
   */
166 181
  operator std::string() const { return name(); }
167 182

  
......
213 228
private:
214 229
  std::string name_;
215 230
  WT_UCHAR decimalPoint_, groupSeparator_;
216
  WT_USTRING dateFormat_, dateTimeFormat_;
231
  WT_USTRING dateFormat_, timeFormat_, dateTimeFormat_;
217 232

  
218 233
  boost::local_time::time_zone_ptr time_zone_;
219 234

  
src/Wt/WLocale.C 2014-03-07 11:21:38.000000000 +0000 → src/Wt/WLocale.C 2015-01-04 13:40:05.000000000 +0000
16 16
  : decimalPoint_("."),
17 17
    groupSeparator_(""),
18 18
    dateFormat_("yyyy-MM-dd"),
19
    timeFormat_("HH:mm:ss"),
19 20
    dateTimeFormat_("yyyy-MM-dd HH:mm:ss")
20 21
{ }
21 22

  
......
24 25
    decimalPoint_(other.decimalPoint()),
25 26
    groupSeparator_(other.groupSeparator()),
26 27
    dateFormat_(other.dateFormat()),
28
    timeFormat_(other.timeFormat()),
27 29
    dateTimeFormat_(other.dateTimeFormat()),
28 30
    time_zone_(other.time_zone_)
29 31
{ }
......
33 35
    decimalPoint_(systemLocale.decimalPoint()),
34 36
    groupSeparator_(systemLocale.groupSeparator()),
35 37
    dateFormat_(systemLocale.dateFormat()),
38
    timeFormat_(systemLocale.timeFormat()),
36 39
    dateTimeFormat_(systemLocale.dateTimeFormat()),
37 40
    time_zone_(systemLocale.time_zone_)
38 41
{ }
......
42 45
    decimalPoint_(systemLocale.decimalPoint()),
43 46
    groupSeparator_(systemLocale.groupSeparator()),
44 47
    dateFormat_(systemLocale.dateFormat()),
48
    timeFormat_(systemLocale.timeFormat()),
45 49
    dateTimeFormat_(systemLocale.dateTimeFormat()),
46 50
    time_zone_(systemLocale.time_zone_)
47 51
{ }
......
61 65
  dateFormat_ = format;
62 66
}
63 67

  
68
void WLocale::setTimeFormat(const WT_USTRING &format)
69
{
70
  timeFormat_ = format;
71
}
72

  
64 73
void WLocale::setTimeZone(const std::string& posixTimeZone)
65 74
{
66 75
  time_zone_.reset(new boost::local_time::posix_time_zone(posixTimeZone));
src/Wt/WTheme 2014-04-29 21:55:27.000000000 +0100 → src/Wt/WTheme 2015-01-04 07:17:19.000000000 +0000
35 35
  TableViewRowContainerRole = 300,
36 36

  
37 37
  DatePickerPopupRole = 400,
38
  TimePickerPopupRole = 410,
38 39

  
39 40
  PanelTitleBarRole = 500,
40 41
  PanelCollapseButtonRole = 501,
......
179 180
  /*! \brief Applies a style that indicates the result of validation.
180 181
   */
181 182
  virtual void applyValidationStyle(WWidget *widget,
182
				    const Wt::WValidator::Result& validation,
183
				    WFlags<ValidationStyleFlag> flags) const
183
                    const Wt::WValidator::Result& validation,
184
                    WFlags<ValidationStyleFlag> flags) const
184 185
    = 0;
185 186

  
186 187
  virtual bool canBorderBoxElement(const DomElement& element) const = 0;
src/Wt/WTime.C 2014-04-29 21:55:27.000000000 +0100 → src/Wt/WTime.C 2015-01-04 13:40:05.000000000 +0000
474 474
    time_(t)
475 475
{ }
476 476

  
477
WTime::RegExpInfo WTime::formatToRegExp(const WT_USTRING &format)
478
{
479
    RegExpInfo result;
480
    return result;
481
}
482

  
477 483
}
src/Wt/WTimeEdit 1970-01-01 01:00:00.000000000 +0100 → src/Wt/WTimeEdit 2015-01-04 13:50:33.000000000 +0000
1

  
2
#ifndef WTIME_EDIT_H_
3
#define WTIME_EDIT_H_
4

  
5
#include <Wt/WLineEdit>
6
#include <Wt/WTime>
7
#include <Wt/WTimeValidator>
8
#include <Wt/WTimePicker>
9

  
10
namespace Wt {
11

  
12
class WT_API WTimeEdit : public WLineEdit
13
{
14
public:
15
    /*! \brief Creates a new time edit.
16
     */
17
    WTimeEdit(WContainerWidget *parent = 0);
18

  
19
    /*! \brief Sets the time
20
     *
21
     *  Does nothing if the current time is \p Null.
22
     *
23
     * \sa time()
24
     */
25
    void setTime(const WTime& time);
26

  
27
    /*! \brief Returns the time.
28
     *
29
     * Returns an invalid time (for which WTime::isValid() returns
30
     * \c false) if the time coult not be parsed using the current format(). <br>
31
     *
32
     * \sa setTime(), WTime::fromString(), WLineEdit::text()
33
     */
34
    WTime time() const;
35

  
36
    virtual WTimeValidator *validator() const;
37

  
38
    void setFormat(const WT_USTRING& format);
39

  
40
    WT_USTRING format() const;
41

  
42
    virtual void setHidden(bool hidden, const WAnimation& animation = WAnimation());
43

  
44
    int minuteStep() const { return timePicker_->minuteStep(); }
45
    void setMinuteStep(int step) { timePicker_->setMinuteStep(step); }
46

  
47
protected:
48

  
49
    virtual void render(WFlags<RenderFlag> flags);
50
    virtual void propagateSetEnabled(bool enabled);
51

  
52
    /*! \brief Sets the value from the time scroller to the line edit.
53
     */
54
    virtual void setFromTimePicker();
55

  
56
    /*! \brief Sets the value from the line edit to the time scroller.
57
     */
58
    virtual void setFromLineEdit();
59

  
60
    virtual void setText(const WString &text) { WLineEdit::setText(text); }
61

  
62

  
63
private:
64

  
65
    WPopupWidget *popup_;
66
    WTimePicker *timePicker_;
67

  
68
    void defineJavaScript();
69
    void connectJavaScript(Wt::EventSignalBase& s, const std::string& methodName);
70

  
71
};
72

  
73
}
74

  
75
#endif // WTIME_EDIT_H_
src/Wt/WTimeEdit.C 1970-01-01 01:00:00.000000000 +0100 → src/Wt/WTimeEdit.C 2015-01-04 13:50:33.000000000 +0000
1

  
2
#include "Wt/WTimeEdit"
3

  
4
#include "Wt/WApplication"
5
#include "Wt/WContainerWidget"
6
#include "Wt/WLineEdit"
7
#include "Wt/WLogger"
8
#include "Wt/WPopupWidget"
9
#include "Wt/WPushButton"
10
#include "Wt/WTemplate"
11
#include "Wt/WTheme"
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

  
23
WTimeEdit::WTimeEdit(WContainerWidget *parent)
24
    : WLineEdit(parent)
25
{
26
    changed().connect(this, &WTimeEdit::setFromLineEdit);
27

  
28
    const char *TEMPLATE = "${timePicker}";
29

  
30
    WTemplate *t = new WTemplate(WString::fromUTF8(TEMPLATE));
31
    popup_ = new WPopupWidget(t, this);
32
    popup_->setAnchorWidget(this);
33
    popup_->setTransient(true, 2);
34

  
35
    timePicker_ = new WTimePicker();
36
    timePicker_->selectionChanged().connect(this, &WTimeEdit::setFromTimePicker);
37

  
38
    t->bindWidget("timePicker", timePicker_);
39

  
40
    WApplication::instance()->theme()->apply(this, popup_, TimePickerPopupRole);
41

  
42
    escapePressed().connect(popup_, &WPopupWidget::hide);
43
    escapePressed().connect(this, &WTimeEdit::setFocus);
44

  
45
    setValidator(new WTimeValidator("HH:mm", this));
46

  
47
}
48

  
49
void WTimeEdit::setTime(const WTime& time)
50
{
51
    setText(time.toString(format()));
52

  
53
    timePicker_->setTime(time);
54
}
55

  
56
WTime WTimeEdit::time() const
57
{
58
    return WTime::fromString(text(), format());
59
}
60

  
61
WTimeValidator *WTimeEdit::validator() const
62
{
63
    return dynamic_cast<WTimeValidator *>(WLineEdit::validator());
64
}
65

  
66
void WTimeEdit::setFormat(const WT_USTRING& format)
67
{
68
    WTimeValidator *tv = validator();
69

  
70
    if(tv)
71
    {
72
        WTime t = this->time();
73
        tv->setFormat(format);
74
        setTime(t);
75
    }
76
    else
77
    {
78
        LOG_WARN("setFormaT() ignored since validator is not WTimeValidator");
79
    }
80
}
81

  
82
WT_USTRING WTimeEdit::format() const
83
{
84
    WTimeValidator *tv = validator();
85

  
86
    if(tv)
87
    {
88
        return tv->format();
89
    }
90
    else
91
    {
92
        LOG_WARN("format() is bogus since validator is not WTimeValidator.");
93
        return WT_USTRING();
94
    }
95
}
96

  
97
void WTimeEdit::setHidden(bool hidden, const WAnimation& animation)
98
{
99
    WLineEdit::setHidden(hidden, animation);
100

  
101
    popup_->setHidden(hidden, animation);
102
}
103

  
104
void WTimeEdit::render(WFlags<RenderFlag> flags)
105
{
106
    if(flags & RenderFull) {
107
        defineJavaScript();
108
    }
109

  
110
    WLineEdit::render(flags);
111
}
112

  
113
void WTimeEdit::propagateSetEnabled(bool enabled)
114
{
115
    WLineEdit::propagateSetEnabled(enabled);
116
}
117

  
118
void WTimeEdit::setFromTimePicker()
119
{
120
    setTime(timePicker_->time());
121
}
122

  
123
void WTimeEdit::setFromLineEdit()
124
{
125
    WTime t = WTime::fromString(text(), format());
126

  
127
    if(t.isValid())
128
    {
129
        timePicker_->setTime(t);
130
    }
131
}
132

  
133
void WTimeEdit::defineJavaScript()
134
{
135
    WApplication *app = WApplication::instance();
136

  
137
    LOAD_JAVASCRIPT(app, "js/WTimeEdit.js", "WTimeEdit", wtjs1);
138

  
139
    std::string jsObj = "new " WT_CLASS ".WTimeEdit("
140
            + app->javaScriptClass() + "," + jsRef() + ","
141
            + popup_->jsRef() + ");";
142

  
143
    setJavaScriptMember(" WTimeEdit", jsObj);
144

  
145
#ifdef WT_CNOR
146
    EventSignalBase& b = mouseMoved();
147
    EventSignalBase& c = keyWentDown();
148
#endif
149

  
150
    connectJavaScript(mouseMoved(), "mouseMove");
151
    connectJavaScript(mouseWentUp(), "mouseUp");
152
    connectJavaScript(mouseWentDown(), "mouseDown");
153
    connectJavaScript(mouseWentOut(), "mouseOut");
154

  
155
}
156

  
157
void WTimeEdit::connectJavaScript(Wt::EventSignalBase& s, const std::string& methodName)
158
{
159
    std::string jsFunction =
160
            "function(dobj, event) {"
161
            """var o = jQuery.data(" + jsRef() + ", 'dobj');"
162
            """if(o) o." + methodName + "(dobj, event);"
163
            "}";
164

  
165
    s.connect(jsFunction);
166
}
167

  
168
}
src/Wt/WTimePicker 1970-01-01 01:00:00.000000000 +0100 → src/Wt/WTimePicker 2014-12-31 10:08:39.000000000 +0000
1

  
2
#ifndef WTIME_PICKER_H_
3
#define WTIME_PICKER_H_
4

  
5
#include "WCompositeWidget"
6
#include "WContainerWidget"
7
#include "WTime"
8

  
9
namespace Wt {
10

  
11
class WT_API WTimePicker : public WCompositeWidget
12
{
13
public:
14
    WTimePicker(WContainerWidget *parent = 0);
15
    WTimePicker(const WTime &time, WContainerWidget *parent = 0);
16

  
17
    WTime time();
18
    void setTime(const WTime& time);
19

  
20
    int minuteStep() const { return minuteStep_; }
21
    void setMinuteStep(int step) { minuteStep_ = step; }
22

  
23
    Signal<>& selectionChanged() { return selectionChanged_; }
24

  
25
private:
26

  
27
    int minuteStep_;
28

  
29
    void init(const WTime &time = WTime());
30

  
31
    WText *hourText_;
32
    WText *minuteText_;
33

  
34
    void incrementMinutes();
35
    void decrementMinutes();
36
    void incrementHours();
37
    void decrementHours();
38

  
39
    Signal<> selectionChanged_;
40

  
41
};
42

  
43

  
44
} // end namespace Wt
45

  
46
#endif // WTIME_PICKER_H_
src/Wt/WTimePicker.C 1970-01-01 01:00:00.000000000 +0100 → src/Wt/WTimePicker.C 2015-01-04 13:40:05.000000000 +0000
1

  
2
#include <boost/format.hpp>
3

  
4
#include "WTimePicker"
5

  
6
#include "WStringStream"
7
#include "WTemplate"
8
#include "WPushButton"
9
#include "WText"
10

  
11
namespace Wt {
12

  
13
WTimePicker::WTimePicker(WContainerWidget *parent)
14
    : WCompositeWidget(parent), minuteStep_(1),
15
      selectionChanged_(this)
16
{
17
    init();
18
}
19

  
20
WTimePicker::WTimePicker(const WTime &time, WContainerWidget *parent)
21
    : WCompositeWidget(parent), minuteStep_(1)
22
{
23
    init(time);
24
}
25

  
26
void WTimePicker::init(const WTime &time)
27
{
28
    Wt::WStringStream text;
29
    text << "<table>"
30
            """<tr>"
31
            ""  "<th>${incrementHour}</th>"
32
            ""  "<th></th>"
33
            ""  "<th>${incrementMinute}</th>"
34
            """</tr>"
35
            """<tr style=\"height: 20px;\">"
36
            ""  "<td valign=\"middle\" align=\"center\">${hourText}</td>"
37
            ""  "<td valign=\"middle\" align=\"center\">:</td>"
38
            ""  "<td valign=\"middle\" align=\"center\">${minuteText}</td>"
39
            """</tr>"
40
            """<tr>"
41
            ""  "<th>${decrementHour}</th>"
42
            ""  "<th></th>"
43
            ""  "<th>${decrementMinute}</th>"
44
            """</tr>"
45
            "</table>";
46

  
47
    WTemplate *impl = new WTemplate();
48
    setImplementation(impl);
49
    impl->setTemplateText(WString::fromUTF8(text.str(), XHTMLUnsafeText));
50

  
51
    WPushButton *incHourButton = new WPushButton();
52
    incHourButton->setIcon("resources/themes/bootstrap/3/glyphicons_up.png");
53

  
54
    WPushButton *decHourButton = new WPushButton();
55
    decHourButton->setIcon("resources/themes/bootstrap/3/glyphicons_down.png");
56

  
57
    WPushButton *incMinuteButton = new WPushButton();
58
    incMinuteButton->setIcon("resources/themes/bootstrap/3/glyphicons_up.png");
59

  
60
    WPushButton *decMinuteButton = new WPushButton();
61
    decMinuteButton->setIcon("resources/themes/bootstrap/3/glyphicons_down.png");
62

  
63
    hourText_ = new WText("0");
64
    hourText_->setInline(false);
65
    hourText_->setTextAlignment(AlignCenter);
66

  
67
    minuteText_ = new WText("00");
68
    minuteText_->setInline(false);
69
    minuteText_->setTextAlignment(AlignCenter);
70

  
71
    impl->bindWidget("incrementHour", incHourButton);
72
    impl->bindWidget("decrementHour", decHourButton);
73

  
74
    impl->bindWidget("hourText", hourText_);
75
    impl->bindWidget("minuteText", minuteText_);
76

  
77
    impl->bindWidget("incrementMinute", incMinuteButton);
78
    impl->bindWidget("decrementMinute", decMinuteButton);
79

  
80
    incHourButton->clicked().connect(this, &WTimePicker::incrementHours);
81
    decHourButton->clicked().connect(this, &WTimePicker::decrementHours);
82

  
83
    incMinuteButton->clicked().connect(this, &WTimePicker::incrementMinutes);
84
    decMinuteButton->clicked().connect(this, &WTimePicker::decrementMinutes);
85

  
86
}
87

  
88
WTime WTimePicker::time()
89
{
90
    int hours = 0, minutes = 0;
91

  
92
    try
93
    {
94
        hours = boost::lexical_cast<int>(hourText_->text().toUTF8());
95
        minutes = boost::lexical_cast<int>(minuteText_->text().toUTF8());
96
    }
97
    catch(const boost::bad_lexical_cast& ex)
98
    {
99
        Wt::log("Error") << "boost::bad_lexical_cast caught in " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << "): " << ex.what();
100
    }
101

  
102
    return WTime(hours, minutes);
103
}
104

  
105
void WTimePicker::setTime(const WTime& time)
106
{
107

  
108
    if(!time.isValid())
109
    {
110
        Wt::log("error") << "Time is invalid!";
111
        return;
112
    }
113

  
114
    std::string hoursStr("0"), minutesStr("00");
115

  
116
    try
117
    {
118
        hoursStr = time.toString("hh").toUTF8();
119

  
120
        minutesStr = time.toString("mm").toUTF8();
121
    }
122
    catch(const boost::bad_lexical_cast& ex)
123
    {
124
        Wt::log("Error") << "boost::bad_lexical_cast caught in " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << "): " << ex.what();
125
    }
126

  
127
    hourText_->setText(hoursStr);
128
    minuteText_->setText(minutesStr);
129
}
130

  
131
void WTimePicker::incrementMinutes()
132
{
133
    std::string str = minuteText_->text().toUTF8();
134
    int curVal = 0;
135
    if(!str.empty())
136
    {
137
        try
138
        {
139
            curVal = boost::lexical_cast<int>(str);
140
        }
141
        catch(const boost::bad_lexical_cast& ex)
142
        {
143
            Wt::log("Error") << "boost::bad_lexical_cast caught in " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << "): " << ex.what();
144
        }
145
    }
146

  
147
    if((curVal += minuteStep_) >= 60)
148
    {
149
        curVal -= 60;
150
    }
151

  
152
    try
153
    {
154
        std::stringstream ss;
155
        ss << std::setw(2) << std::setfill('0') <<  curVal;
156
        str = ss.str();
157
    }
158
    catch(const boost::bad_lexical_cast& ex)
159
    {
160
        Wt::log("Error") << "boost::bad_lexical_cast caught in " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << "): " << ex.what();
161
    }
162

  
163
    minuteText_->setText(str);
164

  
165
    selectionChanged_.emit();
166
}
167

  
168
void WTimePicker::decrementMinutes()
169
{
170
    std::string str = minuteText_->text().toUTF8();
171
    int curVal = 0;
172
    if(!str.empty())
173
    {
174
        try
175
        {
176
            curVal = boost::lexical_cast<int>(str);
177
        }
178
        catch(const boost::bad_lexical_cast& ex)
179
        {
180
            Wt::log("Error") << "boost::bad_lexical_cast caught in " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << "): " << ex.what();
181
        }
182
    }
183

  
184
    if((curVal -= minuteStep_) < 0)
185
    {
186
        curVal += 60;
187
    }
188

  
189
    try
190
    {
191
        std::stringstream ss;
192
        ss << std::setw(2) << std::setfill('0') <<  curVal;
193
        str = ss.str();
194
    }
195
    catch(const boost::bad_lexical_cast& ex)
196
    {
197
        Wt::log("Error") << "boost::bad_lexical_cast caught in " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << "): " << ex.what();
198
    }
199

  
200
    minuteText_->setText(str);
201

  
202
    selectionChanged_.emit();
203
}
204

  
205
void WTimePicker::incrementHours()
206
{
207
    std::string str = hourText_->text().toUTF8();
208
    int curVal = 0;
209
    if(!str.empty())
210
    {
211
        try
212
        {
213
            curVal = boost::lexical_cast<int>(str);
214
        }
215
        catch(const boost::bad_lexical_cast& ex)
216
        {
217
            Wt::log("Error") << "boost::bad_lexical_cast caught in " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << "): " << ex.what();
218
        }
219
    }
220

  
221
    if((curVal + 1) < 24)
222
    {
223
        curVal++;
224
    }
225
    else
226
    {
227
        curVal -= 23;
228
    }
229

  
230
    try
231
    {
232
        std::stringstream ss;
233
        ss << std::setw(2) << std::setfill('0') <<  curVal;
234
        str = ss.str();
235
    }
236
    catch(const boost::bad_lexical_cast& ex)
237
    {
238
        Wt::log("Error") << "boost::bad_lexical_cast caught in " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << "): " << ex.what();
239
    }
240

  
241

  
242
    hourText_->setText(str);
243

  
244
    selectionChanged_.emit();
245
}
246

  
247
void WTimePicker::decrementHours()
248
{
249
    std::string str = hourText_->text().toUTF8();
250
    int curVal = 0;
251
    if(!str.empty())
252
    {
253
        try
254
        {
255
            curVal = boost::lexical_cast<int>(str);
256
        }
257
        catch(const boost::bad_lexical_cast& ex)
258
        {
259
            Wt::log("Error") << "boost::bad_lexical_cast caught in " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << "): " << ex.what();
260
        }
261
    }
262

  
263
    if((curVal - 1) >= 0)
264
    {
265
        curVal--;
266
    }
267
    else
268
    {
269
        curVal += 23;
270
    }
271

  
272
    try
273
    {
274
        std::stringstream ss;
275
        ss << std::setw(2) << std::setfill('0') <<  curVal;
276
        str = ss.str();
277
    }
278
    catch(const boost::bad_lexical_cast& ex)
279
    {
280
        Wt::log("Error") << "boost::bad_lexical_cast caught in " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << "): " << ex.what();
281
    }
282

  
283
    hourText_->setText(str);
284

  
285
    selectionChanged_.emit();
286
}
287

  
288
} // end namespace Wt
src/Wt/WTimeValidator 1970-01-01 01:00:00.000000000 +0100 → src/Wt/WTimeValidator 2015-01-04 13:40:05.000000000 +0000
1

  
2
#ifndef WTIME_VALIDATOR_H_
3
#define WTIME_VALIDATOR_H_
4

  
5
#include "Wt/WValidator"
6

  
7
namespace Wt {
8

  
9
class WT_API WTimeValidator : public WValidator
10
{
11
public:
12
    WTimeValidator(WObject *parent = 0);
13

  
14
    WTimeValidator(const WT_USTRING &format, WObject *parent = 0);
15

  
16
    void setFormat(const WT_USTRING &format);
17

  
18
    virtual WT_USTRING format() const { return formats_[0]; }
19

  
20
    /*! \brief Sets the time formats used to parse time strings.
21
     */
22
    void setFormats(const std::vector<WT_USTRING>& formats);
23

  
24
    /*! \brief Returns the time formats used to parse time strings.
25
     */
26
    const std::vector<WT_USTRING>& formats() const { return formats_; }
27

  
28
    virtual Result validate(const WT_USTRING &input) const;
29

  
30
    void setInvalidNotATimeText(const WString &text);
31

  
32
    WString invalidNotATimeText() const;
33

  
34
    virtual std::string javaScriptValidate() const;
35

  
36

  
37
private:
38

  
39
    std::vector<WT_USTRING> formats_;
40

  
41
    WString notATimeText_;
42

  
43
    static void loadJavascript(WApplication *app);
44

  
45
};
46

  
47
}
48

  
49
#endif // WTIME_VALIDATOR_H_
src/Wt/WTimeValidator.C 1970-01-01 01:00:00.000000000 +0100 → src/Wt/WTimeValidator.C 2015-01-04 13:40:05.000000000 +0000
1

  
2
#include "Wt/WApplication"
3

  
4
#include "Wt/WTime"
5
#include "Wt/WTimeValidator"
6
#include "Wt/WLocale"
7
#include "Wt/WLogger"
8
#include "Wt/WStringStream"
9

  
10
#ifndef WT_DEBUG_JS
11
#include "js/WTimeValidator.min.js"
12
#endif
13

  
14
namespace Wt {
15

  
16
LOGGER("WTimeValidator");
17

  
18
WTimeValidator::WTimeValidator(WObject *parent)
19
    : WValidator(parent)
20
{
21
    setFormat(WLocale::currentLocale().timeFormat());
22
}
23

  
24
WTimeValidator::WTimeValidator(const WString &format, WObject *parent)
25
    : WValidator(parent)
26
{
27
    setFormat(format);
28
}
29

  
30
void WTimeValidator::setFormat(const WT_USTRING &format)
31
{
32
    if(formats_.empty() || formats_[0] != format) {
33
        formats_.clear();
34
        formats_.push_back(format);
35
        repaint();
36
    }
37
}
38

  
39
void WTimeValidator::setFormats(const std::vector<WT_USTRING>& formats)
40
{
41
    formats_ = formats;
42
    repaint();
43
}
44

  
45
WValidator::Result WTimeValidator::validate(const WT_USTRING &input) const
46
{
47
    if(input.empty())
48
    {
49
        return WValidator::validate(input);
50
    }
51

  
52
    for(unsigned i = 0; i < formats_.size(); ++i)
53
    {
54
        try
55
        {
56
            WTime t = WTime::fromString(input, formats_[i]);
57

  
58
            if(t.isValid())
59
            {
60
                return Result(Valid);
61
            }
62
        }
63
        catch(std::exception &e)
64
        {
65
            LOG_WARN("validate(): " << e.what());
66
        }
67
    }
68

  
69
    return Result(Invalid, invalidNotATimeText());
70
}
71

  
72
void WTimeValidator::setInvalidNotATimeText(const WString &text)
73
{
74
    notATimeText_ = text;
75
}
76

  
77
WString WTimeValidator::invalidNotATimeText() const
78
{
79
    if(!notATimeText_.empty())
80
    {
81
        WString s = notATimeText_;
82
        s.arg(formats_[0]);
83
        return s;
84
    }
85
    else
86
    {
87
        return WString::tr("Wt.WTimeValidator.WrongFormat").arg(formats_[0]);
88
    }
89
}
90

  
91
std::string WTimeValidator::javaScriptValidate() const
92
{
93
    loadJavascript(WApplication::instance());
94

  
95
    WStringStream js;
96

  
97
    js << "new " WT_CLASS ".WTimeValidator("
98
       << isMandatory()
99
       << ", [";
100

  
101
    for(unsigned i = 0; i < formats_.size(); ++i)
102
    {
103
        WTime::RegExpInfo r = WTime::formatToRegExp(formats_[i]);
104

  
105
        if(i != 0)
106
        {
107
            js << ',';
108
        }
109

  
110
        js << "{"
111
           << "regexp:" << WWebWidget::jsStringLiteral(r.regexp) << ','
112
           << "getSecond:function(results){" << r.secGetJS << ";},"
113
           << "getMinute:function(results){" << r.minuteGetJS << ";},"
114
           << "getHour:function(results){" << r.hourGetJS << ";}"
115
           << "}";
116
    }
117

  
118
    js << "],";
119

  
120
    js << "null, ";
121

  
122
    js << "null, ";
123

  
124
    js << "," << invalidBlankText().jsStringLiteral()
125
       << "," << invalidNotATimeText().jsStringLiteral()
126
       << ");";
127

  
128
    //return js.str();
129
    return std::string();
130
}
131

  
132
void WTimeValidator::loadJavascript(WApplication *app)
133
{
134
    LOAD_JAVASCRIPT(app, "js/WTimeValidator.js", "WTimeValidator", wtjs1);
135

  
136

  
137

  
138

  
139
}
140

  
141
}
    (1-1/1)