1 /////////////////////////////////////////////////////////////////////////////
2 // Name: generic/datectlg.cpp
3 // Purpose: generic wxDatePickerCtrl 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"
27 #include "wx/bmpbuttn.h"
28 #include "wx/dialog.h"
29 #include "wx/dcmemory.h"
31 #include "wx/textctrl.h"
32 #include "wx/valtext.h"
35 #define _WX_DEFINE_DATE_EVENTS_
36 #include "wx/dateevt.h"
38 #include "wx/datectrl.h"
39 #include "wx/calctrl.h"
41 // ----------------------------------------------------------------------------
43 // ----------------------------------------------------------------------------
53 #ifndef DEFAULT_ITEM_WIDTH
54 #define DEFAULT_ITEM_WIDTH 100
57 // ============================================================================
58 // wxDatePickerCtrl implementation
59 // ============================================================================
61 BEGIN_EVENT_TABLE(wxDatePickerCtrl
, wxDatePickerCtrlBase
)
62 EVT_BUTTON(CTRLID_BTN
, wxDatePickerCtrl::OnClick
)
63 EVT_TEXT(CTRLID_TXT
, wxDatePickerCtrl::OnText
)
64 EVT_CHILD_FOCUS(wxDatePickerCtrl::OnChildSetFocus
)
67 IMPLEMENT_DYNAMIC_CLASS(wxDatePickerCtrl
, wxDatePickerCtrlBase
)
69 // ----------------------------------------------------------------------------
71 // ----------------------------------------------------------------------------
73 wxDatePickerCtrl::wxDatePickerCtrl(wxWindow
*parent
,
75 const wxDateTime
& date
,
82 Create(parent
, id
, date
, pos
, size
, style
, name
);
86 bool wxDatePickerCtrl::Create(wxWindow
*parent
,
88 const wxDateTime
& date
,
94 wxASSERT_MSG( !(style
& wxDP_SPIN
),
95 _T("wxDP_SPIN style not supported, use wxDP_DEFAULT") );
97 if ( !wxControl::Create(parent
, id
, pos
, size
,
98 style
| wxCLIP_CHILDREN
| wxWANTS_CHARS
,
99 wxDefaultValidator
, name
) )
105 SetWindowStyle(style
| wxWANTS_CHARS
);
112 dc
.SelectObject(bmp
);
113 dc
.SetBrush(wxBrush(GetBackgroundColour()));
114 dc
.SetPen(wxPen(GetBackgroundColour()));
115 dc
.DrawRectangle(0,0, 8,4);
117 dc
.SetBrush(wxBrush(GetForegroundColour()));
118 dc
.SetPen(wxPen(GetForegroundColour()));
119 wxPoint pt
[3] = { wxPoint(0,0), wxPoint(6,0), wxPoint(3,3) };
120 dc
.DrawPolygon(3, pt
);
121 dc
.SelectObject(wxNullBitmap
);
124 m_txt
=new wxTextCtrl(this, CTRLID_TXT
);
125 m_txt
->Connect(wxID_ANY
, wxID_ANY
, wxEVT_KEY_DOWN
,
126 (wxObjectEventFunction
)&wxDatePickerCtrl::OnEditKey
,
128 m_txt
->Connect(wxID_ANY
, wxID_ANY
, wxEVT_KILL_FOCUS
,
129 (wxObjectEventFunction
)&wxDatePickerCtrl::OnKillFocus
,
132 m_btn
= new wxBitmapButton(this, CTRLID_BTN
, bmp
);
134 m_popup
= new wxPopupWindow(this);
135 m_popup
->SetFont(GetFont());
137 wxPanel
*panel
=new wxPanel(m_popup
, CTRLID_PAN
,
138 wxPoint(0, 0), wxDefaultSize
,
140 m_cal
= new wxCalendarCtrl(panel
, CTRLID_CAL
, wxDefaultDateTime
,
141 wxPoint(0,0), wxDefaultSize
,
142 wxCAL_SHOW_HOLIDAYS
| wxSUNKEN_BORDER
);
143 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_SEL_CHANGED
,
144 (wxObjectEventFunction
)&wxDatePickerCtrl::OnSelChange
,
146 m_cal
->Connect(wxID_ANY
, wxID_ANY
, wxEVT_KEY_DOWN
,
147 (wxObjectEventFunction
)&wxDatePickerCtrl::OnCalKey
,
149 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_DOUBLECLICKED
,
150 (wxObjectEventFunction
)&wxDatePickerCtrl::OnSelChange
,
152 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_DAY_CHANGED
,
153 (wxObjectEventFunction
)&wxDatePickerCtrl::OnSelChange
,
155 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_MONTH_CHANGED
,
156 (wxObjectEventFunction
)&wxDatePickerCtrl::OnSelChange
,
158 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_YEAR_CHANGED
,
159 (wxObjectEventFunction
)&wxDatePickerCtrl::OnSelChange
,
162 wxWindow
*yearControl
= m_cal
->GetYearControl();
164 Connect(wxID_ANY
, wxID_ANY
, wxEVT_SET_FOCUS
,
165 (wxObjectEventFunction
)&wxDatePickerCtrl::OnSetFocus
);
167 wxClientDC
dc(yearControl
);
169 wxCoord width
, dummy
;
170 dc
.GetTextExtent(wxT("2000"), &width
, &dummy
);
171 width
+= ConvertDialogToPixels(wxSize(20,0)).x
;
173 wxSize calSize
= m_cal
->GetBestSize();
174 wxSize yearSize
= yearControl
->GetSize();
177 wxPoint yearPosition
= yearControl
->GetPosition();
179 SetFormat(wxT("%x"));
182 m_txt
->SetValue(date
.Format(m_format
));
191 width
= yearPosition
.x
+ yearSize
.x
+2+CALBORDER
/2;
192 if (width
< calSize
.x
-4)
195 int calPos
= (width
-calSize
.x
)/2;
201 m_cal
->SetSize(calPos
, 0, calSize
.x
, calSize
.y
);
202 yearControl
->SetSize(width
-yearSize
.x
-CALBORDER
/2, yearPosition
.y
,
203 yearSize
.x
, yearSize
.y
);
204 m_cal
->GetMonthControl()->Move(0, 0);
208 panel
->SetClientSize(width
+CALBORDER
/2, calSize
.y
-2+CALBORDER
);
209 m_popup
->SetClientSize(panel
->GetSize());
216 void wxDatePickerCtrl::Init()
224 m_ignoreDrop
= false;
228 bool wxDatePickerCtrl::Destroy()
244 return wxControl::Destroy();
247 // ----------------------------------------------------------------------------
248 // overridden base class methods
249 // ----------------------------------------------------------------------------
251 void wxDatePickerCtrl::DoMoveWindow(int x
, int y
, int w
, int h
)
253 wxControl::DoMoveWindow(x
, y
, w
, h
);
254 wxSize bs
=m_btn
->GetBestSize();
255 int eh
=m_txt
->GetBestSize().y
;
257 m_txt
->SetSize(0, 0, w
-bs
.x
-1, h
> eh
? eh
: h
);
258 m_btn
->SetSize(w
- bs
.x
, 0, bs
.x
, h
> bs
.y
? bs
.y
: h
);
264 wxSize
wxDatePickerCtrl::DoGetBestSize() const
266 int bh
=m_btn
->GetBestSize().y
;
267 int eh
=m_txt
->GetBestSize().y
;
268 return wxSize(DEFAULT_ITEM_WIDTH
, bh
> eh
? bh
: eh
);
272 bool wxDatePickerCtrl::Show(bool show
)
274 if ( !wxControl::Show(show
) )
292 bool wxDatePickerCtrl::Enable(bool enable
)
294 if ( !wxControl::Enable(enable
) )
305 m_btn
->Enable(enable
);
309 // ----------------------------------------------------------------------------
310 // wxDatePickerCtrl API
311 // ----------------------------------------------------------------------------
314 wxDatePickerCtrl::SetDateRange(const wxDateTime
& lowerdate
,
315 const wxDateTime
& upperdate
)
317 return m_cal
->SetDateRange(lowerdate
, upperdate
);
320 bool wxDatePickerCtrl::SetFormat(const wxChar
*fmt
)
322 wxString currentText
;
323 wxDateTime currentDate
;
326 currentText
= m_txt
->GetValue();
327 if (!currentText
.IsEmpty())
328 currentDate
.ParseFormat(currentText
, m_format
);
331 dt
.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
332 wxString str
=dt
.Format(fmt
);
333 wxChar
*p
=(wxChar
*)str
.c_str();
335 m_format
=wxEmptyString
;
340 if (n
== dt
.GetDay())
342 m_format
.Append(wxT("%d"));
345 else if (n
== (int)dt
.GetMonth()+1)
347 m_format
.Append(wxT("%m"));
350 else if (n
== dt
.GetYear())
352 m_format
.Append(wxT("%Y"));
355 else if (n
== (dt
.GetYear() % 100))
357 m_format
.Append(wxT("%y"));
361 m_format
.Append(*p
++);
366 wxStringList valList
;
368 for (c
='0'; c
<= '9'; c
++)
369 valList
.Add(wxString(c
, 1));
370 wxChar
*p
=(wxChar
*)m_format
.c_str();
376 valList
.Add(wxString(*p
++, 1));
378 wxTextValidator
tv(wxFILTER_INCLUDE_CHAR_LIST
);
379 tv
.SetIncludeList(valList
);
381 m_txt
->SetValidator(tv
);
383 if (!currentText
.IsEmpty())
384 m_txt
->SetValue(currentDate
.Format(m_format
));
390 wxDateTime
wxDatePickerCtrl::GetValue() const
393 wxString txt
=m_txt
->GetValue();
396 dt
.ParseFormat(txt
, m_format
);
402 void wxDatePickerCtrl::SetValue(const wxDateTime
& date
)
407 m_txt
->SetValue(date
.Format(m_format
));
409 m_txt
->SetValue(wxEmptyString
);
414 bool wxDatePickerCtrl::GetRange(wxDateTime
*dt1
, wxDateTime
*dt2
) const
417 *dt1
= m_cal
->GetLowerDateLimit();
419 *dt2
= m_cal
->GetUpperDateLimit();
424 void wxDatePickerCtrl::SetRange(const wxDateTime
&dt1
, const wxDateTime
&dt2
)
426 m_cal
->SetDateRange(dt1
, dt2
);
429 // ----------------------------------------------------------------------------
431 // ----------------------------------------------------------------------------
433 void wxDatePickerCtrl::DropDown(bool down
)
440 if (!m_txt
->GetValue().IsEmpty())
441 dt
.ParseFormat(m_txt
->GetValue(), m_format
);
446 m_cal
->SetDate(wxDateTime::Today());
448 wxPoint pos
=GetParent()->ClientToScreen(GetPosition());
449 m_popup
->Move(pos
.x
, pos
.y
+ GetSize().y
);
463 void wxDatePickerCtrl::OnChildSetFocus(wxChildFocusEvent
&ev
)
466 m_ignoreDrop
= false;
468 wxWindow
*w
=(wxWindow
*)ev
.GetEventObject();
479 if (ev
.GetEventObject() == m_btn
)
485 void wxDatePickerCtrl::OnClick(wxCommandEvent
& event
)
489 m_ignoreDrop
= false;
500 void wxDatePickerCtrl::OnSetFocus(wxFocusEvent
&ev
)
505 m_txt
->SetSelection(0, 100);
510 void wxDatePickerCtrl::OnKillFocus(wxFocusEvent
&ev
)
515 dt
.ParseFormat(m_txt
->GetValue(), m_format
);
517 m_txt
->SetValue(wxEmptyString
);
519 m_txt
->SetValue(dt
.Format(m_format
));
523 void wxDatePickerCtrl::OnSelChange(wxCalendarEvent
&ev
)
527 m_txt
->SetValue(m_cal
->GetDate().Format(m_format
));
528 if (ev
.GetEventType() == wxEVT_CALENDAR_DOUBLECLICKED
)
534 ev
.SetEventObject(this);
536 GetParent()->ProcessEvent(ev
);
540 void wxDatePickerCtrl::OnText(wxCommandEvent
&ev
)
542 ev
.SetEventObject(this);
544 GetParent()->ProcessEvent(ev
);
546 // We'll create an additional event if the date is valid.
547 // If the date isn't valid, the user's probable in the middle of typing
548 wxString txt
=m_txt
->GetValue();
552 dt
.ParseFormat(txt
, m_format
);
557 wxCalendarEvent
cev(m_cal
, wxEVT_CALENDAR_SEL_CHANGED
);
558 cev
.SetEventObject(this);
562 GetParent()->ProcessEvent(cev
);
566 void wxDatePickerCtrl::OnEditKey(wxKeyEvent
& ev
)
568 if (ev
.GetKeyCode() == WXK_DOWN
&& !ev
.HasModifiers())
575 void wxDatePickerCtrl::OnCalKey(wxKeyEvent
& ev
)
577 if (ev
.GetKeyCode() == WXK_ESCAPE
&& !ev
.HasModifiers())