]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/generic/datectlg.cpp
fixing file paths after renaming
[wxWidgets.git] / src / generic / datectlg.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/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#ifndef WX_PRECOMP
29 #include "wx/dialog.h"
30 #include "wx/dcmemory.h"
31 #include "wx/panel.h"
32 #include "wx/textctrl.h"
33 #include "wx/valtext.h"
34#endif
35
36#include "wx/datectrl.h"
37#include "wx/generic/datectrl.h"
38
39
40// ----------------------------------------------------------------------------
41// constants
42// ----------------------------------------------------------------------------
43
44
45// ----------------------------------------------------------------------------
46// global variables
47// ----------------------------------------------------------------------------
48
49
50// ----------------------------------------------------------------------------
51// local classes
52// ----------------------------------------------------------------------------
53
54class wxCalendarComboPopup : public wxCalendarCtrl,
55 public wxComboPopup
56{
57public:
58
59 wxCalendarComboPopup() : wxCalendarCtrl(),
60 wxComboPopup()
61 {
62 }
63
64 virtual void Init()
65 {
66 }
67
68 // NB: Don't create lazily since it didn't work that way before
69 // wxComboCtrl was used, and changing behaviour would almost
70 // certainly introduce new bugs.
71 virtual bool Create(wxWindow* parent)
72 {
73 if ( !wxCalendarCtrl::Create(parent, wxID_ANY, wxDefaultDateTime,
74 wxPoint(0, 0), wxDefaultSize,
75 wxCAL_SEQUENTIAL_MONTH_SELECTION
76 | wxCAL_SHOW_HOLIDAYS | wxBORDER_SUNKEN) )
77 return false;
78
79 SetFormat("%x");
80
81 m_useSize = wxCalendarCtrl::GetBestSize();
82
83 wxWindow* tx = m_combo->GetTextCtrl();
84 if ( !tx )
85 tx = m_combo;
86
87 tx->Connect(wxEVT_KILL_FOCUS,
88 wxFocusEventHandler(wxCalendarComboPopup::OnKillTextFocus),
89 NULL, this);
90
91 return true;
92 }
93
94 virtual wxSize GetAdjustedSize(int WXUNUSED(minWidth),
95 int WXUNUSED(prefHeight),
96 int WXUNUSED(maxHeight))
97 {
98 return m_useSize;
99 }
100
101 virtual wxWindow *GetControl() { return this; }
102
103 void SetDateValue(const wxDateTime& date)
104 {
105 if ( date.IsValid() )
106 {
107 m_combo->SetText(date.Format(m_format));
108 SetDate(date);
109 }
110 else // invalid date
111 {
112 wxASSERT_MSG( HasDPFlag(wxDP_ALLOWNONE),
113 _T("this control must have a valid date") );
114
115 m_combo->SetText(wxEmptyString);
116 }
117 }
118
119 bool ParseDateTime(const wxString& s, wxDateTime* pDt)
120 {
121 wxASSERT(pDt);
122
123 if ( !s.empty() )
124 {
125 pDt->ParseFormat(s.c_str(), m_format);
126 if ( !pDt->IsValid() )
127 return false;
128 }
129
130 return true;
131 }
132
133 void SendDateEvent(const wxDateTime& dt)
134 {
135 // Sends both wxCalendarEvent and wxDateEvent
136 wxWindow* datePicker = m_combo->GetParent();
137
138 wxCalendarEvent cev(datePicker, dt, wxEVT_CALENDAR_SEL_CHANGED);
139 datePicker->GetEventHandler()->ProcessEvent(cev);
140
141 wxDateEvent event(datePicker, dt, wxEVT_DATE_CHANGED);
142 datePicker->GetEventHandler()->ProcessEvent(event);
143 }
144
145private:
146
147 void OnCalKey(wxKeyEvent & ev)
148 {
149 if (ev.GetKeyCode() == WXK_ESCAPE && !ev.HasModifiers())
150 Dismiss();
151 else
152 ev.Skip();
153 }
154
155 void OnSelChange(wxCalendarEvent &ev)
156 {
157 m_combo->SetText(GetDate().Format(m_format));
158
159 if ( ev.GetEventType() == wxEVT_CALENDAR_DOUBLECLICKED )
160 {
161 Dismiss();
162 }
163
164 SendDateEvent(GetDate());
165 }
166
167 void OnKillTextFocus(wxFocusEvent &ev)
168 {
169 ev.Skip();
170
171 const wxDateTime& dtOld = GetDate();
172
173 wxDateTime dt;
174 wxString value = m_combo->GetValue();
175 if ( !ParseDateTime(value, &dt) )
176 {
177 if ( !HasDPFlag(wxDP_ALLOWNONE) )
178 dt = dtOld;
179 }
180
181 m_combo->SetText(GetStringValueFor(dt));
182
183 if ( !dt.IsValid() && HasDPFlag(wxDP_ALLOWNONE) )
184 return;
185
186 // notify that we had to change the date after validation
187 if ( (dt.IsValid() && (!dtOld.IsValid() || dt != dtOld)) ||
188 (!dt.IsValid() && dtOld.IsValid()) )
189 {
190 SetDate(dt);
191 SendDateEvent(dt);
192 }
193 }
194
195 bool HasDPFlag(int flag)
196 {
197 return m_combo->GetParent()->HasFlag(flag);
198 }
199
200 bool SetFormat(const wxString& fmt)
201 {
202 m_format.clear();
203
204 wxDateTime dt;
205 dt.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
206 wxString str(dt.Format(fmt));
207
208 const wxChar *p = str.c_str();
209 while ( *p )
210 {
211 int n=wxAtoi(p);
212 if (n == dt.GetDay())
213 {
214 m_format.Append(wxT("%d"));
215 p += 2;
216 }
217 else if (n == (int)dt.GetMonth()+1)
218 {
219 m_format.Append(wxT("%m"));
220 p += 2;
221 }
222 else if (n == dt.GetYear())
223 {
224 m_format.Append(wxT("%Y"));
225 p += 4;
226 }
227 else if (n == (dt.GetYear() % 100))
228 {
229 if ( HasDPFlag(wxDP_SHOWCENTURY) )
230 m_format.Append(wxT("%Y"));
231 else
232 m_format.Append(wxT("%y"));
233 p += 2;
234 }
235 else
236 m_format.Append(*p++);
237 }
238
239 if ( m_combo )
240 {
241 wxArrayString allowedChars;
242 for ( wxChar c = _T('0'); c <= _T('9'); c++ )
243 allowedChars.Add(wxString(c, 1));
244
245 const wxChar *p2 = m_format.c_str();
246 while ( *p2 )
247 {
248 if ( *p2 == '%')
249 p2 += 2;
250 else
251 allowedChars.Add(wxString(*p2++, 1));
252 }
253
254 #if wxUSE_VALIDATORS
255 wxTextValidator tv(wxFILTER_INCLUDE_CHAR_LIST);
256 tv.SetIncludes(allowedChars);
257 m_combo->SetValidator(tv);
258 #endif
259
260 if ( GetDate().IsValid() )
261 m_combo->SetText(GetDate().Format(m_format));
262 }
263
264 return true;
265 }
266
267 virtual void SetStringValue(const wxString& s)
268 {
269 wxDateTime dt;
270 if ( !s.empty() && ParseDateTime(s, &dt) )
271 SetDate(dt);
272 //else: keep the old value
273 }
274
275 virtual wxString GetStringValue() const
276 {
277 return GetStringValueFor(GetDate());
278 }
279
280private:
281 // returns either the given date representation using the current format or
282 // an empty string if it's invalid
283 wxString GetStringValueFor(const wxDateTime& dt) const
284 {
285 wxString val;
286 if ( dt.IsValid() )
287 val = dt.Format(m_format);
288
289 return val;
290 }
291
292 wxSize m_useSize;
293 wxString m_format;
294
295 DECLARE_EVENT_TABLE()
296};
297
298
299BEGIN_EVENT_TABLE(wxCalendarComboPopup, wxCalendarCtrl)
300 EVT_KEY_DOWN(wxCalendarComboPopup::OnCalKey)
301 EVT_CALENDAR_SEL_CHANGED(wxID_ANY, wxCalendarComboPopup::OnSelChange)
302 EVT_CALENDAR_PAGE_CHANGED(wxID_ANY, wxCalendarComboPopup::OnSelChange)
303 EVT_CALENDAR(wxID_ANY, wxCalendarComboPopup::OnSelChange)
304END_EVENT_TABLE()
305
306
307// ============================================================================
308// wxDatePickerCtrlGeneric implementation
309// ============================================================================
310
311BEGIN_EVENT_TABLE(wxDatePickerCtrlGeneric, wxDatePickerCtrlBase)
312 EVT_TEXT(wxID_ANY, wxDatePickerCtrlGeneric::OnText)
313 EVT_SIZE(wxDatePickerCtrlGeneric::OnSize)
314 EVT_SET_FOCUS(wxDatePickerCtrlGeneric::OnFocus)
315END_EVENT_TABLE()
316
317#ifndef wxHAS_NATIVE_DATEPICKCTRL
318 IMPLEMENT_DYNAMIC_CLASS(wxDatePickerCtrl, wxControl)
319#endif
320
321// ----------------------------------------------------------------------------
322// creation
323// ----------------------------------------------------------------------------
324
325bool wxDatePickerCtrlGeneric::Create(wxWindow *parent,
326 wxWindowID id,
327 const wxDateTime& date,
328 const wxPoint& pos,
329 const wxSize& size,
330 long style,
331 const wxValidator& validator,
332 const wxString& name)
333{
334 wxASSERT_MSG( !(style & wxDP_SPIN),
335 _T("wxDP_SPIN style not supported, use wxDP_DEFAULT") );
336
337 if ( !wxControl::Create(parent, id, pos, size,
338 style | wxCLIP_CHILDREN | wxWANTS_CHARS | wxBORDER_NONE,
339 validator, name) )
340 {
341 return false;
342 }
343
344 InheritAttributes();
345
346 m_combo = new wxComboCtrl(this, -1, wxEmptyString,
347 wxDefaultPosition, wxDefaultSize);
348
349 m_combo->SetCtrlMainWnd(this);
350
351 m_popup = new wxCalendarComboPopup();
352
353#if defined(__WXMSW__)
354 // without this keyboard navigation in month control doesn't work
355 m_combo->UseAltPopupWindow();
356#endif
357 m_combo->SetPopupControl(m_popup);
358
359 m_popup->SetDateValue(date.IsValid() ? date : wxDateTime::Today());
360
361 SetInitialSize(size);
362
363 return true;
364}
365
366
367void wxDatePickerCtrlGeneric::Init()
368{
369 m_combo = NULL;
370 m_popup = NULL;
371}
372
373wxDatePickerCtrlGeneric::~wxDatePickerCtrlGeneric()
374{
375}
376
377bool wxDatePickerCtrlGeneric::Destroy()
378{
379 if ( m_combo )
380 m_combo->Destroy();
381
382 m_combo = NULL;
383 m_popup = NULL;
384
385 return wxControl::Destroy();
386}
387
388// ----------------------------------------------------------------------------
389// overridden base class methods
390// ----------------------------------------------------------------------------
391
392wxSize wxDatePickerCtrlGeneric::DoGetBestSize() const
393{
394 return m_combo->GetBestSize();
395}
396
397// ----------------------------------------------------------------------------
398// wxDatePickerCtrlGeneric API
399// ----------------------------------------------------------------------------
400
401bool
402wxDatePickerCtrlGeneric::SetDateRange(const wxDateTime& lowerdate,
403 const wxDateTime& upperdate)
404{
405 return m_popup->SetDateRange(lowerdate, upperdate);
406}
407
408
409wxDateTime wxDatePickerCtrlGeneric::GetValue() const
410{
411 return m_popup->GetDate();
412}
413
414
415void wxDatePickerCtrlGeneric::SetValue(const wxDateTime& date)
416{
417 m_popup->SetDateValue(date);
418}
419
420
421bool wxDatePickerCtrlGeneric::GetRange(wxDateTime *dt1, wxDateTime *dt2) const
422{
423 return m_popup->GetDateRange(dt1, dt2);
424}
425
426
427void
428wxDatePickerCtrlGeneric::SetRange(const wxDateTime &dt1, const wxDateTime &dt2)
429{
430 m_popup->SetDateRange(dt1, dt2);
431}
432
433wxCalendarCtrl *wxDatePickerCtrlGeneric::GetCalendar() const
434{
435 return m_popup;
436}
437
438// ----------------------------------------------------------------------------
439// event handlers
440// ----------------------------------------------------------------------------
441
442
443void wxDatePickerCtrlGeneric::OnSize(wxSizeEvent& event)
444{
445 if ( m_combo )
446 m_combo->SetSize(GetClientSize());
447
448 event.Skip();
449}
450
451
452void wxDatePickerCtrlGeneric::OnText(wxCommandEvent &ev)
453{
454 ev.SetEventObject(this);
455 ev.SetId(GetId());
456 GetParent()->GetEventHandler()->ProcessEvent(ev);
457
458 // We'll create an additional event if the date is valid.
459 // If the date isn't valid, the user's probably in the middle of typing
460 wxDateTime dt;
461 if ( !m_popup || !m_popup->ParseDateTime(m_combo->GetValue(), &dt) )
462 return;
463
464 m_popup->SendDateEvent(dt);
465}
466
467
468void wxDatePickerCtrlGeneric::OnFocus(wxFocusEvent& WXUNUSED(event))
469{
470 m_combo->SetFocus();
471}
472
473
474#endif // wxUSE_DATEPICKCTRL
475