1 /////////////////////////////////////////////////////////////////////////////
2 // Name: generic/datectlg.cpp
3 // Purpose: generic wxDatePickerCtrlGeneric implementation
4 // Author: Andreas Pflug
8 // Copyright: (c) 2005 Andreas Pflug <pgadmin@pse-consulting.de>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
26 #if wxUSE_DATEPICKCTRL
28 #include "wx/datectrl.h"
30 // use this version if we're explicitly requested to do it or if it's the only
32 #if wxUSE_DATEPICKCTRL_GENERIC || !defined(wxHAS_NATIVE_DATEPICKCTRL)
35 #include "wx/bmpbuttn.h"
36 #include "wx/dialog.h"
37 #include "wx/dcmemory.h"
39 #include "wx/textctrl.h"
40 #include "wx/valtext.h"
43 // otherwise it's defined in the native version implementation
44 #ifndef wxHAS_NATIVE_DATEPICKCTRL
45 #define _WX_DEFINE_DATE_EVENTS_
48 #include "wx/dateevt.h"
49 #include "wx/generic/datectrl.h"
51 #include "wx/arrstr.h"
52 #include "wx/calctrl.h"
53 #include "wx/popupwin.h"
54 #include "wx/renderer.h"
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
68 #ifndef DEFAULT_ITEM_WIDTH
69 #define DEFAULT_ITEM_WIDTH 100
72 // ============================================================================
73 // wxDatePickerCtrlGeneric implementation
74 // ============================================================================
76 BEGIN_EVENT_TABLE(wxDatePickerCtrlGeneric
, wxDatePickerCtrlBase
)
77 EVT_BUTTON(CTRLID_BTN
, wxDatePickerCtrlGeneric::OnClick
)
78 EVT_TEXT(CTRLID_TXT
, wxDatePickerCtrlGeneric::OnText
)
79 EVT_CHILD_FOCUS(wxDatePickerCtrlGeneric::OnChildSetFocus
)
82 #ifndef wxHAS_NATIVE_DATEPICKCTRL
83 IMPLEMENT_DYNAMIC_CLASS(wxDatePickerCtrl
, wxDatePickerCtrlBase
)
86 // ----------------------------------------------------------------------------
88 // ----------------------------------------------------------------------------
90 bool wxDatePickerCtrlGeneric::Create(wxWindow
*parent
,
92 const wxDateTime
& date
,
96 const wxValidator
& validator
,
99 wxASSERT_MSG( !(style
& wxDP_SPIN
),
100 _T("wxDP_SPIN style not supported, use wxDP_DEFAULT") );
102 if ( !wxControl::Create(parent
, id
, pos
, size
,
103 style
| wxCLIP_CHILDREN
| wxWANTS_CHARS
,
112 m_txt
= new wxTextCtrl(this, CTRLID_TXT
);
113 m_txt
->Connect(wxID_ANY
, wxID_ANY
, wxEVT_KEY_DOWN
,
114 (wxObjectEventFunction
)
116 (wxCharEventFunction
)
117 &wxDatePickerCtrlGeneric::OnEditKey
,
119 m_txt
->Connect(wxID_ANY
, wxID_ANY
, wxEVT_KILL_FOCUS
,
120 (wxObjectEventFunction
)
122 (wxFocusEventFunction
)
123 &wxDatePickerCtrlGeneric::OnKillFocus
,
126 const int height
= m_txt
->GetBestSize().y
- 4; // FIXME: fudge
127 wxBitmap
bmp(height
, height
);
130 dc
.SelectObject(bmp
);
131 wxRendererNative::Get().DrawComboBoxDropButton
135 wxRect(0, 0, height
, height
)
139 wxBitmapButton
*btn
= new wxBitmapButton(this, CTRLID_BTN
, bmp
);
140 btn
->SetMargins(0, 0);
143 m_popup
= new wxPopupWindow(this);
144 m_popup
->SetFont(GetFont());
146 wxPanel
*panel
=new wxPanel(m_popup
, CTRLID_PAN
,
147 wxPoint(), wxDefaultSize
,
149 m_cal
= new wxCalendarCtrl(panel
, CTRLID_CAL
, wxDefaultDateTime
,
150 wxPoint(), wxDefaultSize
,
151 wxCAL_SHOW_HOLIDAYS
| wxSUNKEN_BORDER
);
152 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_SEL_CHANGED
,
153 (wxObjectEventFunction
)
155 (wxCalendarEventFunction
)
156 &wxDatePickerCtrlGeneric::OnSelChange
,
158 m_cal
->Connect(wxID_ANY
, wxID_ANY
, wxEVT_KEY_DOWN
,
159 (wxObjectEventFunction
)
161 (wxCharEventFunction
)
162 &wxDatePickerCtrlGeneric::OnCalKey
,
164 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_DOUBLECLICKED
,
165 (wxObjectEventFunction
)
167 (wxCalendarEventFunction
)
168 &wxDatePickerCtrlGeneric::OnSelChange
,
170 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_DAY_CHANGED
,
171 (wxObjectEventFunction
)
173 (wxCalendarEventFunction
)
174 &wxDatePickerCtrlGeneric::OnSelChange
,
176 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_MONTH_CHANGED
,
177 (wxObjectEventFunction
)
179 (wxCalendarEventFunction
)
180 &wxDatePickerCtrlGeneric::OnSelChange
,
182 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_YEAR_CHANGED
,
183 (wxObjectEventFunction
)
185 (wxCalendarEventFunction
)
186 &wxDatePickerCtrlGeneric::OnSelChange
,
189 wxWindow
*yearControl
= m_cal
->GetYearControl();
191 Connect(wxID_ANY
, wxID_ANY
, wxEVT_SET_FOCUS
,
192 (wxObjectEventFunction
)
194 (wxFocusEventFunction
)
195 &wxDatePickerCtrlGeneric::OnSetFocus
);
197 wxClientDC
dc(yearControl
);
199 wxCoord width
, dummy
;
200 dc
.GetTextExtent(wxT("2000"), &width
, &dummy
);
201 width
+= ConvertDialogToPixels(wxSize(20,0)).x
;
203 wxSize calSize
= m_cal
->GetBestSize();
204 wxSize yearSize
= yearControl
->GetSize();
207 wxPoint yearPosition
= yearControl
->GetPosition();
209 SetFormat(wxT("%x"));
212 m_txt
->SetValue(date
.Format(m_format
));
221 width
= yearPosition
.x
+ yearSize
.x
+2+CALBORDER
/2;
222 if (width
< calSize
.x
-4)
225 int calPos
= (width
-calSize
.x
)/2;
231 m_cal
->SetSize(calPos
, 0, calSize
.x
, calSize
.y
);
232 yearControl
->SetSize(width
-yearSize
.x
-CALBORDER
/2, yearPosition
.y
,
233 yearSize
.x
, yearSize
.y
);
234 m_cal
->GetMonthControl()->Move(0, 0);
238 panel
->SetClientSize(width
+CALBORDER
/2, calSize
.y
-2+CALBORDER
);
239 m_popup
->SetClientSize(panel
->GetSize());
246 void wxDatePickerCtrlGeneric::Init()
254 m_ignoreDrop
= false;
258 bool wxDatePickerCtrlGeneric::Destroy()
274 return wxControl::Destroy();
277 // ----------------------------------------------------------------------------
278 // overridden base class methods
279 // ----------------------------------------------------------------------------
281 void wxDatePickerCtrlGeneric::DoMoveWindow(int x
, int y
, int w
, int h
)
283 wxControl::DoMoveWindow(x
, y
, w
, h
);
284 wxSize bs
=m_btn
->GetBestSize();
285 int eh
=m_txt
->GetBestSize().y
;
287 m_txt
->SetSize(0, 0, w
-bs
.x
-1, h
> eh
? eh
: h
);
288 m_btn
->SetSize(w
- bs
.x
, 0, bs
.x
, h
> bs
.y
? bs
.y
: h
);
294 wxSize
wxDatePickerCtrlGeneric::DoGetBestSize() const
296 int bh
=m_btn
->GetBestSize().y
;
297 int eh
=m_txt
->GetBestSize().y
;
298 return wxSize(DEFAULT_ITEM_WIDTH
, bh
> eh
? bh
: eh
);
302 bool wxDatePickerCtrlGeneric::Show(bool show
)
304 if ( !wxControl::Show(show
) )
322 bool wxDatePickerCtrlGeneric::Enable(bool enable
)
324 if ( !wxControl::Enable(enable
) )
335 m_btn
->Enable(enable
);
339 // ----------------------------------------------------------------------------
340 // wxDatePickerCtrlGeneric API
341 // ----------------------------------------------------------------------------
344 wxDatePickerCtrlGeneric::SetDateRange(const wxDateTime
& lowerdate
,
345 const wxDateTime
& upperdate
)
347 return m_cal
->SetDateRange(lowerdate
, upperdate
);
350 bool wxDatePickerCtrlGeneric::SetFormat(const wxChar
*fmt
)
352 wxString currentText
;
353 wxDateTime currentDate
;
356 currentText
= m_txt
->GetValue();
357 if (!currentText
.empty())
358 currentDate
.ParseFormat(currentText
, m_format
);
361 dt
.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
362 wxString str
=dt
.Format(fmt
);
363 wxChar
*p
=(wxChar
*)str
.c_str();
365 m_format
=wxEmptyString
;
370 if (n
== dt
.GetDay())
372 m_format
.Append(wxT("%d"));
375 else if (n
== (int)dt
.GetMonth()+1)
377 m_format
.Append(wxT("%m"));
380 else if (n
== dt
.GetYear())
382 m_format
.Append(wxT("%Y"));
385 else if (n
== (dt
.GetYear() % 100))
387 m_format
.Append(wxT("%y"));
391 m_format
.Append(*p
++);
396 wxArrayString valList
;
398 for (c
='0'; c
<= '9'; c
++)
399 valList
.Add(wxString(c
, 1));
400 wxChar
*p
=(wxChar
*)m_format
.c_str();
406 valList
.Add(wxString(*p
++, 1));
408 wxTextValidator
tv(wxFILTER_INCLUDE_CHAR_LIST
);
409 tv
.SetIncludes(valList
);
411 m_txt
->SetValidator(tv
);
413 if (!currentText
.empty())
414 m_txt
->SetValue(currentDate
.Format(m_format
));
420 wxDateTime
wxDatePickerCtrlGeneric::GetValue() const
423 wxString txt
=m_txt
->GetValue();
426 dt
.ParseFormat(txt
, m_format
);
432 void wxDatePickerCtrlGeneric::SetValue(const wxDateTime
& date
)
437 m_txt
->SetValue(date
.Format(m_format
));
439 m_txt
->SetValue(wxEmptyString
);
444 bool wxDatePickerCtrlGeneric::GetRange(wxDateTime
*dt1
, wxDateTime
*dt2
) const
447 *dt1
= m_cal
->GetLowerDateLimit();
449 *dt2
= m_cal
->GetUpperDateLimit();
455 wxDatePickerCtrlGeneric::SetRange(const wxDateTime
&dt1
, const wxDateTime
&dt2
)
457 m_cal
->SetDateRange(dt1
, dt2
);
460 // ----------------------------------------------------------------------------
462 // ----------------------------------------------------------------------------
464 void wxDatePickerCtrlGeneric::DropDown(bool down
)
471 if (!m_txt
->GetValue().empty())
472 dt
.ParseFormat(m_txt
->GetValue(), m_format
);
477 m_cal
->SetDate(wxDateTime::Today());
479 wxPoint pos
=GetParent()->ClientToScreen(GetPosition());
480 m_popup
->Move(pos
.x
, pos
.y
+ GetSize().y
);
494 void wxDatePickerCtrlGeneric::OnChildSetFocus(wxChildFocusEvent
&ev
)
497 m_ignoreDrop
= false;
499 wxWindow
*w
=(wxWindow
*)ev
.GetEventObject();
510 if (ev
.GetEventObject() == m_btn
)
516 void wxDatePickerCtrlGeneric::OnClick(wxCommandEvent
& WXUNUSED(event
))
520 m_ignoreDrop
= false;
531 void wxDatePickerCtrlGeneric::OnSetFocus(wxFocusEvent
& WXUNUSED(ev
))
536 m_txt
->SetSelection(0, 100);
541 void wxDatePickerCtrlGeneric::OnKillFocus(wxFocusEvent
&ev
)
546 dt
.ParseFormat(m_txt
->GetValue(), m_format
);
548 m_txt
->SetValue(wxEmptyString
);
550 m_txt
->SetValue(dt
.Format(m_format
));
554 void wxDatePickerCtrlGeneric::OnSelChange(wxCalendarEvent
&ev
)
558 m_txt
->SetValue(m_cal
->GetDate().Format(m_format
));
559 if (ev
.GetEventType() == wxEVT_CALENDAR_DOUBLECLICKED
)
565 ev
.SetEventObject(this);
567 GetParent()->ProcessEvent(ev
);
571 void wxDatePickerCtrlGeneric::OnText(wxCommandEvent
&ev
)
573 ev
.SetEventObject(this);
575 GetParent()->ProcessEvent(ev
);
577 // We'll create an additional event if the date is valid.
578 // If the date isn't valid, the user's probable in the middle of typing
579 wxString txt
=m_txt
->GetValue();
583 dt
.ParseFormat(txt
, m_format
);
588 wxCalendarEvent
cev(m_cal
, wxEVT_CALENDAR_SEL_CHANGED
);
589 cev
.SetEventObject(this);
593 GetParent()->ProcessEvent(cev
);
597 void wxDatePickerCtrlGeneric::OnEditKey(wxKeyEvent
& ev
)
599 if (ev
.GetKeyCode() == WXK_DOWN
&& !ev
.HasModifiers())
606 void wxDatePickerCtrlGeneric::OnCalKey(wxKeyEvent
& ev
)
608 if (ev
.GetKeyCode() == WXK_ESCAPE
&& !ev
.HasModifiers())
614 #endif // wxUSE_DATEPICKCTRL_GENERIC
616 #endif // wxUSE_DATEPICKCTRL