]>
Commit | Line | Data |
---|---|---|
39df3acd | 1 | ///////////////////////////////////////////////////////////////////////////// |
d5ae99f5 | 2 | // Name: generic/datectlg.cpp |
7ae712f5 | 3 | // Purpose: generic wxDatePickerCtrlGeneric implementation |
39df3acd VZ |
4 | // Author: Andreas Pflug |
5 | // Modified by: | |
6 | // Created: 2005-01-19 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) 2005 Andreas Pflug <pgadmin@pse-consulting.de> | |
9 | // Licence: wxWindows licence | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | // ============================================================================ | |
13 | // declarations | |
14 | // ============================================================================ | |
15 | ||
16 | // ---------------------------------------------------------------------------- | |
17 | // headers | |
18 | // ---------------------------------------------------------------------------- | |
19 | ||
20 | #include "wx/wxprec.h" | |
21 | ||
22 | #ifdef __BORLANDC__ | |
23 | #pragma hdrstop | |
24 | #endif | |
25 | ||
7ae712f5 VZ |
26 | #if wxUSE_DATEPICKCTRL |
27 | ||
15c86b39 | 28 | #include "wx/datectrl.h" |
7ae712f5 VZ |
29 | |
30 | // use this version if we're explicitly requested to do it or if it's the only | |
31 | // one we have | |
15c86b39 | 32 | #if wxUSE_DATEPICKCTRL_GENERIC || !defined(wxHAS_NATIVE_DATEPICKCTRL) |
7ae712f5 | 33 | |
a962d4e0 KH |
34 | #ifndef WX_PRECOMP |
35 | #include "wx/bmpbuttn.h" | |
36 | #include "wx/dialog.h" | |
37 | #include "wx/dcmemory.h" | |
38 | #include "wx/panel.h" | |
39 | #include "wx/textctrl.h" | |
40 | #include "wx/valtext.h" | |
41 | #endif | |
42 | ||
1721a8c0 VZ |
43 | #ifdef wxHAS_NATIVE_DATEPICKCTRL |
44 | // this header is not included from wx/datectrl.h if we have a native | |
45 | // version, but we do need it here | |
46 | #include "wx/generic/datectrl.h" | |
47 | #endif | |
48 | ||
49 | // we need to define _WX_DEFINE_DATE_EVENTS_ before including wx/dateevt.h to | |
50 | // define the event types we use if we're the only date picker control version | |
51 | // being compiled -- otherwise it's defined in the native version implementation | |
15c86b39 | 52 | #ifndef wxHAS_NATIVE_DATEPICKCTRL |
7ae712f5 VZ |
53 | #define _WX_DEFINE_DATE_EVENTS_ |
54 | #endif | |
55 | ||
91edf16c VZ |
56 | #include "wx/dateevt.h" |
57 | ||
4b134bb2 | 58 | #include "wx/calctrl.h" |
4221a0e5 | 59 | #include "wx/renderer.h" |
39df3acd VZ |
60 | |
61 | // ---------------------------------------------------------------------------- | |
62 | // constants | |
63 | // ---------------------------------------------------------------------------- | |
64 | ||
65 | enum | |
66 | { | |
67 | CTRLID_TXT = 101, | |
4b134bb2 VZ |
68 | CTRLID_CAL, |
69 | CTRLID_BTN, | |
39df3acd VZ |
70 | CTRLID_PAN |
71 | }; | |
72 | ||
73 | #ifndef DEFAULT_ITEM_WIDTH | |
74 | #define DEFAULT_ITEM_WIDTH 100 | |
75 | #endif | |
76 | ||
1721a8c0 VZ |
77 | // ---------------------------------------------------------------------------- |
78 | // local classes | |
79 | // ---------------------------------------------------------------------------- | |
80 | ||
38511687 VZ |
81 | |
82 | class wxDropdownButton : public wxBitmapButton | |
83 | { | |
84 | public: | |
85 | wxDropdownButton() { Init(); } | |
86 | wxDropdownButton(wxWindow *parent, | |
87 | wxWindowID id, | |
88 | const wxPoint& pos = wxDefaultPosition, | |
89 | const wxSize& size = wxDefaultSize, | |
90 | long style=0, | |
91 | const wxValidator& validator = wxDefaultValidator); | |
92 | ||
93 | void Init() | |
94 | { | |
95 | m_borderX = -1; | |
96 | m_borderY = -1; | |
97 | } | |
94ab4d92 | 98 | bool Create(wxWindow *parent, |
38511687 VZ |
99 | wxWindowID id, |
100 | const wxPoint& pos = wxDefaultPosition, | |
101 | const wxSize& size = wxDefaultSize, | |
102 | long style = 0, | |
103 | const wxValidator& validator = wxDefaultValidator); | |
104 | ||
105 | void DoMoveWindow(int x, int y, int w, int h); | |
106 | ||
107 | protected: | |
108 | int m_borderX, m_borderY; | |
109 | }; | |
110 | ||
111 | ||
112 | wxDropdownButton::wxDropdownButton(wxWindow *parent, | |
113 | wxWindowID id, | |
114 | const wxPoint& pos, | |
115 | const wxSize& size, | |
116 | long style, | |
117 | const wxValidator& validator) | |
118 | { | |
119 | Init(); | |
120 | Create(parent, id, pos, size, style, validator); | |
121 | } | |
122 | ||
123 | ||
94ab4d92 | 124 | bool wxDropdownButton::Create(wxWindow *parent, |
38511687 VZ |
125 | wxWindowID id, |
126 | const wxPoint& pos, | |
127 | const wxSize& size, | |
94ab4d92 | 128 | long WXUNUSED(style), |
38511687 VZ |
129 | const wxValidator& validator) |
130 | { | |
131 | wxBitmap chkBmp(15,15); // arbitrary | |
94ab4d92 VZ |
132 | if ( !wxBitmapButton::Create(parent, id, chkBmp, |
133 | pos, wxDefaultSize, wxBU_AUTODRAW, validator) ) | |
134 | return false; | |
38511687 | 135 | |
94ab4d92 VZ |
136 | const wxSize sz = GetSize(); |
137 | int w = chkBmp.GetWidth(), | |
138 | h = chkBmp.GetHeight(); | |
139 | m_borderX = sz.x - m_marginX - w; | |
140 | m_borderY = sz.y - m_marginY - h; | |
38511687 | 141 | |
94ab4d92 VZ |
142 | w = size.x > 0 ? size.x : sz.x; |
143 | h = size.y > 0 ? size.y : sz.y; | |
38511687 VZ |
144 | |
145 | DoMoveWindow(pos.x, pos.y, w, h); | |
94ab4d92 VZ |
146 | |
147 | return true; | |
38511687 VZ |
148 | } |
149 | ||
150 | ||
151 | void wxDropdownButton::DoMoveWindow(int x, int y, int w, int h) | |
152 | { | |
153 | if (m_borderX >= 0 && m_borderY >= 0 && (w >= 0 || h >= 0)) | |
154 | { | |
155 | wxMemoryDC dc; | |
156 | if (w < 0) | |
157 | w = GetSize().x; | |
158 | #ifdef __WXGTK__ | |
159 | else | |
160 | w = m_marginX + m_borderX + 15; // GTK magic size | |
161 | #endif | |
162 | if (h < 0) | |
163 | h = GetSize().y; | |
164 | ||
165 | int bw = w - m_marginX - m_borderX; | |
166 | int bh = h - m_marginY - m_borderY; | |
167 | if (bh < 11) bh=11; | |
168 | if (bw < 9) bw=9; | |
169 | ||
170 | wxBitmap bmp(bw, bh); | |
171 | dc.SelectObject(bmp); | |
172 | ||
173 | wxRendererNative::Get().DrawComboBoxDropButton(this, dc, wxRect(0,0,bw, bh)); | |
174 | ||
175 | SetBitmapLabel(bmp); | |
176 | } | |
177 | ||
178 | wxBitmapButton::DoMoveWindow(x, y, w, h); | |
179 | } | |
180 | ||
181 | ||
1721a8c0 VZ |
182 | #if wxUSE_POPUPWIN |
183 | ||
184 | #include "wx/popupwin.h" | |
185 | ||
186 | class wxDatePopupInternal : public wxPopupTransientWindow | |
187 | { | |
188 | public: | |
189 | wxDatePopupInternal(wxWindow *parent) : wxPopupTransientWindow(parent) { } | |
190 | ||
191 | void ShowAt(int x, int y) | |
192 | { | |
193 | Position(wxPoint(x, y), wxSize(0, 0)); | |
194 | Popup(); | |
195 | } | |
196 | ||
197 | void Hide() | |
198 | { | |
199 | Dismiss(); | |
200 | } | |
201 | }; | |
202 | ||
203 | #else // !wxUSE_POPUPWIN | |
204 | ||
205 | class wxDatePopupInternal : public wxDialog | |
206 | { | |
207 | public: | |
208 | wxDatePopupInternal(wxWindow *parent) | |
209 | : wxDialog(parent, | |
210 | wxID_ANY, | |
211 | wxEmptyString, | |
212 | wxDefaultPosition, | |
213 | wxDefaultSize, | |
214 | wxSIMPLE_BORDER) | |
215 | { | |
216 | } | |
217 | ||
218 | void ShowAt(int x, int y) | |
219 | { | |
220 | Show(); | |
221 | Move(x, y); | |
222 | } | |
223 | ||
224 | void Hide() | |
225 | { | |
226 | wxDialog::Hide(); | |
227 | } | |
228 | }; | |
229 | ||
230 | #endif // wxUSE_POPUPWIN/!wxUSE_POPUPWIN | |
231 | ||
39df3acd | 232 | // ============================================================================ |
7ae712f5 | 233 | // wxDatePickerCtrlGeneric implementation |
39df3acd VZ |
234 | // ============================================================================ |
235 | ||
7ae712f5 VZ |
236 | BEGIN_EVENT_TABLE(wxDatePickerCtrlGeneric, wxDatePickerCtrlBase) |
237 | EVT_BUTTON(CTRLID_BTN, wxDatePickerCtrlGeneric::OnClick) | |
238 | EVT_TEXT(CTRLID_TXT, wxDatePickerCtrlGeneric::OnText) | |
239 | EVT_CHILD_FOCUS(wxDatePickerCtrlGeneric::OnChildSetFocus) | |
39df3acd VZ |
240 | END_EVENT_TABLE() |
241 | ||
b6292ff0 | 242 | #ifndef wxHAS_NATIVE_DATEPICKCTRL |
94ab4d92 | 243 | IMPLEMENT_DYNAMIC_CLASS(wxDatePickerCtrl, wxControl) |
b6292ff0 | 244 | #endif |
39df3acd VZ |
245 | |
246 | // ---------------------------------------------------------------------------- | |
247 | // creation | |
248 | // ---------------------------------------------------------------------------- | |
249 | ||
7ae712f5 VZ |
250 | bool wxDatePickerCtrlGeneric::Create(wxWindow *parent, |
251 | wxWindowID id, | |
252 | const wxDateTime& date, | |
253 | const wxPoint& pos, | |
254 | const wxSize& size, | |
255 | long style, | |
807f5038 | 256 | const wxValidator& validator, |
7ae712f5 | 257 | const wxString& name) |
39df3acd | 258 | { |
29c86948 VZ |
259 | wxASSERT_MSG( !(style & wxDP_SPIN), |
260 | _T("wxDP_SPIN style not supported, use wxDP_DEFAULT") ); | |
261 | ||
39df3acd VZ |
262 | if ( !wxControl::Create(parent, id, pos, size, |
263 | style | wxCLIP_CHILDREN | wxWANTS_CHARS, | |
807f5038 | 264 | validator, name) ) |
39df3acd VZ |
265 | |
266 | { | |
267 | return false; | |
268 | } | |
269 | ||
39df3acd VZ |
270 | InheritAttributes(); |
271 | ||
4221a0e5 | 272 | m_txt = new wxTextCtrl(this, CTRLID_TXT); |
38511687 | 273 | |
b6261304 VZ |
274 | m_txt->Connect(wxEVT_KEY_DOWN, |
275 | wxKeyEventHandler(wxDatePickerCtrlGeneric::OnEditKey), | |
276 | NULL, this); | |
277 | m_txt->Connect(wxEVT_KILL_FOCUS, | |
278 | wxFocusEventHandler(wxDatePickerCtrlGeneric::OnKillFocus), | |
279 | NULL, this); | |
39df3acd | 280 | |
38511687 | 281 | const int height = m_txt->GetBestSize().y; |
39df3acd | 282 | |
38511687 VZ |
283 | m_btn = new wxDropdownButton(this, CTRLID_BTN, wxDefaultPosition, wxSize(height, height)); |
284 | ||
1721a8c0 | 285 | m_popup = new wxDatePopupInternal(this); |
d5ae99f5 | 286 | m_popup->SetFont(GetFont()); |
39df3acd | 287 | |
d5ae99f5 | 288 | wxPanel *panel=new wxPanel(m_popup, CTRLID_PAN, |
1721a8c0 | 289 | wxPoint(0, 0), wxDefaultSize, |
4b134bb2 VZ |
290 | wxSUNKEN_BORDER); |
291 | m_cal = new wxCalendarCtrl(panel, CTRLID_CAL, wxDefaultDateTime, | |
1721a8c0 | 292 | wxPoint(0, 0), wxDefaultSize, |
4b134bb2 | 293 | wxCAL_SHOW_HOLIDAYS | wxSUNKEN_BORDER); |
b6261304 VZ |
294 | m_cal->Connect(wxEVT_CALENDAR_SEL_CHANGED, |
295 | wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange), | |
296 | NULL, this); | |
297 | m_cal->Connect(wxEVT_KEY_DOWN, | |
298 | wxKeyEventHandler(wxDatePickerCtrlGeneric::OnCalKey), | |
299 | NULL, this); | |
300 | m_cal->Connect(wxEVT_CALENDAR_DOUBLECLICKED, | |
301 | wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange), | |
302 | NULL, this); | |
303 | m_cal->Connect(wxEVT_CALENDAR_DAY_CHANGED, | |
304 | wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange), | |
305 | NULL, this); | |
306 | m_cal->Connect(wxEVT_CALENDAR_MONTH_CHANGED, | |
307 | wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange), | |
308 | NULL, this); | |
309 | m_cal->Connect(wxEVT_CALENDAR_YEAR_CHANGED, | |
310 | wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange), | |
311 | NULL, this); | |
39df3acd VZ |
312 | |
313 | wxWindow *yearControl = m_cal->GetYearControl(); | |
314 | ||
b6261304 VZ |
315 | Connect(wxEVT_SET_FOCUS, |
316 | wxFocusEventHandler(wxDatePickerCtrlGeneric::OnSetFocus)); | |
39df3acd VZ |
317 | |
318 | wxClientDC dc(yearControl); | |
319 | dc.SetFont(m_font); | |
320 | wxCoord width, dummy; | |
321 | dc.GetTextExtent(wxT("2000"), &width, &dummy); | |
1721a8c0 | 322 | width += ConvertDialogToPixels(wxSize(20, 0)).x; |
39df3acd VZ |
323 | |
324 | wxSize calSize = m_cal->GetBestSize(); | |
325 | wxSize yearSize = yearControl->GetSize(); | |
326 | yearSize.x = width; | |
327 | ||
328 | wxPoint yearPosition = yearControl->GetPosition(); | |
329 | ||
d5ae99f5 VZ |
330 | SetFormat(wxT("%x")); |
331 | ||
d5ae99f5 | 332 | |
39df3acd | 333 | #ifdef __WXMSW__ |
1721a8c0 VZ |
334 | #define CALBORDER 0 |
335 | #define RIGHTBUTTONBORDER 2 | |
336 | #define TOPBUTTONBORDER 1 | |
39df3acd | 337 | #else |
1721a8c0 VZ |
338 | #define CALBORDER 4 |
339 | #define RIGHTBUTTONBORDER 0 | |
340 | #define TOPBUTTONBORDER 0 | |
39df3acd VZ |
341 | #endif |
342 | ||
343 | width = yearPosition.x + yearSize.x+2+CALBORDER/2; | |
344 | if (width < calSize.x-4) | |
345 | width = calSize.x-4; | |
346 | ||
347 | int calPos = (width-calSize.x)/2; | |
348 | if (calPos == -1) | |
349 | { | |
350 | calPos = 0; | |
351 | width += 2; | |
352 | } | |
353 | m_cal->SetSize(calPos, 0, calSize.x, calSize.y); | |
4b134bb2 VZ |
354 | yearControl->SetSize(width-yearSize.x-CALBORDER/2, yearPosition.y, |
355 | yearSize.x, yearSize.y); | |
39df3acd VZ |
356 | m_cal->GetMonthControl()->Move(0, 0); |
357 | ||
358 | ||
359 | ||
360 | panel->SetClientSize(width+CALBORDER/2, calSize.y-2+CALBORDER); | |
d5ae99f5 VZ |
361 | m_popup->SetClientSize(panel->GetSize()); |
362 | m_popup->Hide(); | |
39df3acd | 363 | |
1721a8c0 | 364 | if (!date.IsValid()) |
d8b49350 RD |
365 | SetValue(wxDateTime::Today()); |
366 | else | |
367 | SetValue(date); | |
1721a8c0 | 368 | |
d8b49350 RD |
369 | SetBestFittingSize(size); |
370 | ||
3a0c6181 | 371 | return true; |
39df3acd VZ |
372 | } |
373 | ||
374 | ||
7ae712f5 | 375 | void wxDatePickerCtrlGeneric::Init() |
39df3acd | 376 | { |
d5ae99f5 | 377 | m_popup = NULL; |
39df3acd VZ |
378 | m_txt = NULL; |
379 | m_cal = NULL; | |
380 | m_btn = NULL; | |
381 | ||
382 | m_dropped = false; | |
383 | m_ignoreDrop = false; | |
384 | } | |
385 | ||
386 | ||
7ae712f5 | 387 | bool wxDatePickerCtrlGeneric::Destroy() |
39df3acd VZ |
388 | { |
389 | if (m_cal) | |
390 | m_cal->Destroy(); | |
d5ae99f5 VZ |
391 | if (m_popup) |
392 | m_popup->Destroy(); | |
39df3acd VZ |
393 | if (m_txt) |
394 | m_txt->Destroy(); | |
395 | if (m_btn) | |
396 | m_btn->Destroy(); | |
397 | ||
d5ae99f5 | 398 | m_popup = NULL; |
39df3acd VZ |
399 | m_txt = NULL; |
400 | m_cal = NULL; | |
401 | m_btn = NULL; | |
402 | ||
403 | return wxControl::Destroy(); | |
404 | } | |
405 | ||
406 | // ---------------------------------------------------------------------------- | |
407 | // overridden base class methods | |
408 | // ---------------------------------------------------------------------------- | |
409 | ||
7ae712f5 | 410 | void wxDatePickerCtrlGeneric::DoMoveWindow(int x, int y, int w, int h) |
39df3acd VZ |
411 | { |
412 | wxControl::DoMoveWindow(x, y, w, h); | |
413 | wxSize bs=m_btn->GetBestSize(); | |
414 | int eh=m_txt->GetBestSize().y; | |
415 | ||
416 | m_txt->SetSize(0, 0, w-bs.x-1, h > eh ? eh : h); | |
1721a8c0 | 417 | m_btn->SetSize(w - bs.x-RIGHTBUTTONBORDER, TOPBUTTONBORDER, bs.x, h > bs.y ? bs.y : h); |
39df3acd VZ |
418 | |
419 | if (m_dropped) | |
1721a8c0 | 420 | DropDown(true); |
39df3acd VZ |
421 | } |
422 | ||
7ae712f5 | 423 | wxSize wxDatePickerCtrlGeneric::DoGetBestSize() const |
39df3acd VZ |
424 | { |
425 | int bh=m_btn->GetBestSize().y; | |
426 | int eh=m_txt->GetBestSize().y; | |
427 | return wxSize(DEFAULT_ITEM_WIDTH, bh > eh ? bh : eh); | |
428 | } | |
429 | ||
430 | ||
7ae712f5 | 431 | bool wxDatePickerCtrlGeneric::Show(bool show) |
39df3acd VZ |
432 | { |
433 | if ( !wxControl::Show(show) ) | |
434 | { | |
3a0c6181 | 435 | return false; |
39df3acd VZ |
436 | } |
437 | ||
1721a8c0 | 438 | if ( !show ) |
39df3acd | 439 | { |
1721a8c0 | 440 | if ( m_popup ) |
39df3acd | 441 | { |
d5ae99f5 | 442 | m_popup->Hide(); |
39df3acd VZ |
443 | m_dropped = false; |
444 | } | |
445 | } | |
446 | ||
3a0c6181 | 447 | return true; |
39df3acd VZ |
448 | } |
449 | ||
450 | ||
7ae712f5 | 451 | bool wxDatePickerCtrlGeneric::Enable(bool enable) |
39df3acd VZ |
452 | { |
453 | if ( !wxControl::Enable(enable) ) | |
454 | { | |
3a0c6181 | 455 | return false; |
39df3acd VZ |
456 | } |
457 | ||
1721a8c0 | 458 | if ( !enable ) |
39df3acd | 459 | { |
1721a8c0 | 460 | if ( m_cal ) |
39df3acd VZ |
461 | m_cal->Hide(); |
462 | } | |
1721a8c0 VZ |
463 | |
464 | if ( m_btn ) | |
39df3acd | 465 | m_btn->Enable(enable); |
1721a8c0 | 466 | |
3a0c6181 | 467 | return true; |
39df3acd VZ |
468 | } |
469 | ||
470 | // ---------------------------------------------------------------------------- | |
7ae712f5 | 471 | // wxDatePickerCtrlGeneric API |
39df3acd VZ |
472 | // ---------------------------------------------------------------------------- |
473 | ||
4b134bb2 | 474 | bool |
7ae712f5 VZ |
475 | wxDatePickerCtrlGeneric::SetDateRange(const wxDateTime& lowerdate, |
476 | const wxDateTime& upperdate) | |
4b134bb2 VZ |
477 | { |
478 | return m_cal->SetDateRange(lowerdate, upperdate); | |
479 | } | |
480 | ||
7ae712f5 | 481 | bool wxDatePickerCtrlGeneric::SetFormat(const wxChar *fmt) |
39df3acd VZ |
482 | { |
483 | wxDateTime dt; | |
484 | dt.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d")); | |
485 | wxString str=dt.Format(fmt); | |
486 | wxChar *p=(wxChar*)str.c_str(); | |
487 | ||
488 | m_format=wxEmptyString; | |
489 | ||
490 | while (*p) | |
491 | { | |
492 | int n=wxAtoi(p); | |
493 | if (n == dt.GetDay()) | |
494 | { | |
495 | m_format.Append(wxT("%d")); | |
496 | p += 2; | |
497 | } | |
498 | else if (n == (int)dt.GetMonth()+1) | |
499 | { | |
500 | m_format.Append(wxT("%m")); | |
501 | p += 2; | |
502 | } | |
503 | else if (n == dt.GetYear()) | |
504 | { | |
505 | m_format.Append(wxT("%Y")); | |
506 | p += 4; | |
507 | } | |
d5ae99f5 VZ |
508 | else if (n == (dt.GetYear() % 100)) |
509 | { | |
1721a8c0 VZ |
510 | if (GetWindowStyle() & wxDP_SHOWCENTURY) |
511 | m_format.Append(wxT("%Y")); | |
512 | else | |
513 | m_format.Append(wxT("%y")); | |
d5ae99f5 VZ |
514 | p += 2; |
515 | } | |
39df3acd VZ |
516 | else |
517 | m_format.Append(*p++); | |
518 | } | |
519 | ||
520 | if (m_txt) | |
521 | { | |
1721a8c0 VZ |
522 | wxArrayString allowedChars; |
523 | for ( wxChar c = _T('0'); c <= _T('9'); c++ ) | |
524 | allowedChars.Add(wxString(c, 1)); | |
525 | ||
526 | const wxChar *p = m_format.c_str(); | |
39df3acd VZ |
527 | while (*p) |
528 | { | |
529 | if (*p == '%') | |
530 | p += 2; | |
531 | else | |
1721a8c0 | 532 | allowedChars.Add(wxString(*p++, 1)); |
39df3acd | 533 | } |
1721a8c0 | 534 | |
39df3acd | 535 | wxTextValidator tv(wxFILTER_INCLUDE_CHAR_LIST); |
1721a8c0 | 536 | tv.SetIncludes(allowedChars); |
39df3acd VZ |
537 | |
538 | m_txt->SetValidator(tv); | |
d5ae99f5 | 539 | |
1721a8c0 VZ |
540 | if (m_currentDate.IsValid()) |
541 | m_txt->SetValue(m_currentDate.Format(m_format)); | |
39df3acd | 542 | } |
1721a8c0 | 543 | |
39df3acd VZ |
544 | return true; |
545 | } | |
546 | ||
547 | ||
7ae712f5 | 548 | wxDateTime wxDatePickerCtrlGeneric::GetValue() const |
39df3acd | 549 | { |
1721a8c0 | 550 | return m_currentDate; |
39df3acd VZ |
551 | } |
552 | ||
553 | ||
7ae712f5 | 554 | void wxDatePickerCtrlGeneric::SetValue(const wxDateTime& date) |
39df3acd VZ |
555 | { |
556 | if (m_cal) | |
557 | { | |
558 | if (date.IsValid()) | |
d5ae99f5 | 559 | m_txt->SetValue(date.Format(m_format)); |
39df3acd | 560 | else |
1721a8c0 VZ |
561 | { |
562 | wxASSERT_MSG( HasFlag(wxDP_ALLOWNONE), | |
563 | _T("this control must have a valid date") ); | |
564 | ||
39df3acd | 565 | m_txt->SetValue(wxEmptyString); |
1721a8c0 VZ |
566 | } |
567 | ||
568 | m_currentDate = date; | |
39df3acd VZ |
569 | } |
570 | } | |
571 | ||
572 | ||
7ae712f5 | 573 | bool wxDatePickerCtrlGeneric::GetRange(wxDateTime *dt1, wxDateTime *dt2) const |
39df3acd VZ |
574 | { |
575 | if (dt1) | |
4b134bb2 | 576 | *dt1 = m_cal->GetLowerDateLimit(); |
39df3acd | 577 | if (dt1) |
4b134bb2 | 578 | *dt2 = m_cal->GetUpperDateLimit(); |
39df3acd VZ |
579 | return true; |
580 | } | |
581 | ||
582 | ||
7ae712f5 VZ |
583 | void |
584 | wxDatePickerCtrlGeneric::SetRange(const wxDateTime &dt1, const wxDateTime &dt2) | |
39df3acd | 585 | { |
4b134bb2 | 586 | m_cal->SetDateRange(dt1, dt2); |
39df3acd VZ |
587 | } |
588 | ||
589 | // ---------------------------------------------------------------------------- | |
590 | // event handlers | |
591 | // ---------------------------------------------------------------------------- | |
592 | ||
7ae712f5 | 593 | void wxDatePickerCtrlGeneric::DropDown(bool down) |
39df3acd | 594 | { |
d5ae99f5 | 595 | if (m_popup) |
39df3acd VZ |
596 | { |
597 | if (down) | |
598 | { | |
d5ae99f5 | 599 | wxDateTime dt; |
a7c58211 | 600 | if (!m_txt->GetValue().empty()) |
39df3acd | 601 | dt.ParseFormat(m_txt->GetValue(), m_format); |
d5ae99f5 VZ |
602 | |
603 | if (dt.IsValid()) | |
39df3acd | 604 | m_cal->SetDate(dt); |
d5ae99f5 VZ |
605 | else |
606 | m_cal->SetDate(wxDateTime::Today()); | |
39df3acd | 607 | |
d5ae99f5 | 608 | wxPoint pos=GetParent()->ClientToScreen(GetPosition()); |
1721a8c0 | 609 | m_popup->ShowAt(pos.x, pos.y + GetSize().y); |
39df3acd | 610 | m_dropped = true; |
1721a8c0 | 611 | m_cal->SetFocus(); |
39df3acd VZ |
612 | } |
613 | else | |
614 | { | |
615 | if (m_dropped) | |
d5ae99f5 | 616 | m_popup->Hide(); |
39df3acd VZ |
617 | m_dropped = false; |
618 | } | |
619 | } | |
620 | } | |
621 | ||
622 | ||
7ae712f5 | 623 | void wxDatePickerCtrlGeneric::OnChildSetFocus(wxChildFocusEvent &ev) |
39df3acd VZ |
624 | { |
625 | ev.Skip(); | |
626 | m_ignoreDrop = false; | |
627 | ||
628 | wxWindow *w=(wxWindow*)ev.GetEventObject(); | |
629 | while (w) | |
630 | { | |
d5ae99f5 | 631 | if (w == m_popup) |
39df3acd VZ |
632 | return; |
633 | w = w->GetParent(); | |
634 | } | |
635 | ||
636 | if (m_dropped) | |
637 | { | |
638 | DropDown(false); | |
639 | if (ev.GetEventObject() == m_btn) | |
640 | m_ignoreDrop = true; | |
641 | } | |
642 | } | |
643 | ||
644 | ||
b6292ff0 | 645 | void wxDatePickerCtrlGeneric::OnClick(wxCommandEvent& WXUNUSED(event)) |
39df3acd VZ |
646 | { |
647 | if (m_ignoreDrop) | |
648 | { | |
649 | m_ignoreDrop = false; | |
650 | m_txt->SetFocus(); | |
651 | } | |
652 | else | |
653 | { | |
654 | DropDown(); | |
655 | m_cal->SetFocus(); | |
656 | } | |
657 | } | |
658 | ||
659 | ||
b6292ff0 | 660 | void wxDatePickerCtrlGeneric::OnSetFocus(wxFocusEvent& WXUNUSED(ev)) |
39df3acd VZ |
661 | { |
662 | if (m_txt) | |
663 | { | |
664 | m_txt->SetFocus(); | |
1721a8c0 | 665 | m_txt->SetSelection(-1, -1); // select everything |
39df3acd VZ |
666 | } |
667 | } | |
668 | ||
669 | ||
7ae712f5 | 670 | void wxDatePickerCtrlGeneric::OnKillFocus(wxFocusEvent &ev) |
39df3acd VZ |
671 | { |
672 | ev.Skip(); | |
673 | ||
674 | wxDateTime dt; | |
675 | dt.ParseFormat(m_txt->GetValue(), m_format); | |
2436cac7 | 676 | if ( !dt.IsValid() ) |
1721a8c0 VZ |
677 | { |
678 | if ( !HasFlag(wxDP_ALLOWNONE) ) | |
679 | dt = m_currentDate; | |
680 | } | |
681 | ||
a7c58211 WS |
682 | if(dt.IsValid()) |
683 | m_txt->SetValue(dt.Format(m_format)); | |
684 | else | |
685 | m_txt->SetValue(wxEmptyString); | |
1721a8c0 VZ |
686 | |
687 | // notify that we had to change the date after validation | |
2436cac7 VZ |
688 | if ( (dt.IsValid() && m_currentDate != dt) || |
689 | (!dt.IsValid() && m_currentDate.IsValid()) ) | |
1721a8c0 VZ |
690 | { |
691 | m_currentDate = dt; | |
692 | wxDateEvent event(this, dt, wxEVT_DATE_CHANGED); | |
693 | GetEventHandler()->ProcessEvent(event); | |
694 | } | |
39df3acd VZ |
695 | } |
696 | ||
697 | ||
7ae712f5 | 698 | void wxDatePickerCtrlGeneric::OnSelChange(wxCalendarEvent &ev) |
39df3acd VZ |
699 | { |
700 | if (m_cal) | |
701 | { | |
1721a8c0 VZ |
702 | m_currentDate = m_cal->GetDate(); |
703 | m_txt->SetValue(m_currentDate.Format(m_format)); | |
39df3acd VZ |
704 | if (ev.GetEventType() == wxEVT_CALENDAR_DOUBLECLICKED) |
705 | { | |
706 | DropDown(false); | |
707 | m_txt->SetFocus(); | |
708 | } | |
709 | } | |
710 | ev.SetEventObject(this); | |
711 | ev.SetId(GetId()); | |
712 | GetParent()->ProcessEvent(ev); | |
1721a8c0 VZ |
713 | |
714 | wxDateEvent dev(this, ev.GetDate(), wxEVT_DATE_CHANGED); | |
715 | GetParent()->ProcessEvent(dev); | |
39df3acd VZ |
716 | } |
717 | ||
718 | ||
7ae712f5 | 719 | void wxDatePickerCtrlGeneric::OnText(wxCommandEvent &ev) |
39df3acd VZ |
720 | { |
721 | ev.SetEventObject(this); | |
722 | ev.SetId(GetId()); | |
723 | GetParent()->ProcessEvent(ev); | |
724 | ||
725 | // We'll create an additional event if the date is valid. | |
1721a8c0 | 726 | // If the date isn't valid, the user's probably in the middle of typing |
a7c58211 | 727 | wxString txt = m_txt->GetValue(); |
39df3acd | 728 | wxDateTime dt; |
a7c58211 | 729 | if (!txt.empty()) |
39df3acd VZ |
730 | { |
731 | dt.ParseFormat(txt, m_format); | |
732 | if (!dt.IsValid()) | |
733 | return; | |
734 | } | |
735 | ||
736 | wxCalendarEvent cev(m_cal, wxEVT_CALENDAR_SEL_CHANGED); | |
737 | cev.SetEventObject(this); | |
738 | cev.SetId(GetId()); | |
739 | cev.SetDate(dt); | |
740 | ||
741 | GetParent()->ProcessEvent(cev); | |
1721a8c0 VZ |
742 | |
743 | wxDateEvent dev(this, dt, wxEVT_DATE_CHANGED); | |
744 | GetParent()->ProcessEvent(dev); | |
39df3acd VZ |
745 | } |
746 | ||
747 | ||
7ae712f5 | 748 | void wxDatePickerCtrlGeneric::OnEditKey(wxKeyEvent & ev) |
39df3acd VZ |
749 | { |
750 | if (ev.GetKeyCode() == WXK_DOWN && !ev.HasModifiers()) | |
1721a8c0 | 751 | DropDown(true); |
39df3acd VZ |
752 | else |
753 | ev.Skip(); | |
754 | } | |
755 | ||
756 | ||
7ae712f5 | 757 | void wxDatePickerCtrlGeneric::OnCalKey(wxKeyEvent & ev) |
39df3acd VZ |
758 | { |
759 | if (ev.GetKeyCode() == WXK_ESCAPE && !ev.HasModifiers()) | |
760 | DropDown(false); | |
761 | else | |
762 | ev.Skip(); | |
763 | } | |
764 | ||
7ae712f5 VZ |
765 | #endif // wxUSE_DATEPICKCTRL_GENERIC |
766 | ||
767 | #endif // wxUSE_DATEPICKCTRL | |
768 |