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