1 /////////////////////////////////////////////////////////////////////////////
2 // Name: generic/datectrl.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"
26 #include "wx/datectrl.h"
28 // ----------------------------------------------------------------------------
30 // ----------------------------------------------------------------------------
40 #ifndef DEFAULT_ITEM_WIDTH
41 #define DEFAULT_ITEM_WIDTH 100
44 // ============================================================================
45 // wxDatePickerCtrl implementation
46 // ============================================================================
48 BEGIN_EVENT_TABLE(wxDatePickerCtrl
, wxDatePickerCtrlBase
)
49 EVT_BUTTON(CTRLID_BTN
, wxDatePickerCtrl::OnClick
)
50 EVT_TEXT(CTRLID_TXT
, wxDatePickerCtrl::OnText
)
51 EVT_CHILD_FOCUS(wxDatePickerCtrl::OnChildSetFocus
)
54 IMPLEMENT_DYNAMIC_CLASS(wxDatePickerCtrl
, wxDatePickerCtrlBase
)
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 wxDatePickerCtrl::wxDatePickerCtrl(wxWindow
*parent
,
62 const wxDateTime
& date
,
69 Create(parent
, id
, date
, pos
, size
, style
, name
);
73 bool wxDatePickerCtrl::Create(wxWindow
*parent
,
75 const wxDateTime
& date
,
83 txt
= date
.FormatDate();
85 if ( !wxControl::Create(parent
, id
, pos
, size
,
86 style
| wxCLIP_CHILDREN
| wxWANTS_CHARS
,
87 wxDefaultValidator
, name
) )
93 SetWindowStyle(style
| wxWANTS_CHARS
);
100 dc
.SelectObject(bmp
);
101 dc
.SetBrush(wxBrush(GetBackgroundColour()));
102 dc
.SetPen(wxPen(GetBackgroundColour()));
103 dc
.DrawRectangle(0,0, 8,4);
105 dc
.SetBrush(wxBrush(GetForegroundColour()));
106 dc
.SetPen(wxPen(GetForegroundColour()));
107 wxPoint pt
[3] = { wxPoint(0,0), wxPoint(6,0), wxPoint(3,3) };
108 dc
.DrawPolygon(3, pt
);
109 dc
.SelectObject(wxNullBitmap
);
112 m_txt
=new wxTextCtrl(this, CTRLID_TXT
, txt
);
113 m_txt
->Connect(wxID_ANY
, wxID_ANY
, wxEVT_KEY_DOWN
, (wxObjectEventFunction
)&wxDatePickerCtrl::OnEditKey
, 0, this);
114 m_txt
->Connect(wxID_ANY
, wxID_ANY
, wxEVT_KILL_FOCUS
, (wxObjectEventFunction
)&wxDatePickerCtrl::OnKillFocus
, 0, this);
115 SetFormat(wxT("%x"));
117 m_btn
= new wxBitmapButton(this, CTRLID_BTN
, bmp
);
119 m_dlg
= new wxDialog(this, CTRLID_CAL
, wxEmptyString
, wxDefaultPosition
, wxDefaultSize
, wxSIMPLE_BORDER
);
120 m_dlg
->SetFont(GetFont());
122 wxPanel
*panel
=new wxPanel(m_dlg
, CTRLID_PAN
, wxPoint(0, 0), wxDefaultSize
, wxSUNKEN_BORDER
|wxCLIP_CHILDREN
);
123 m_cal
= new wxCalendarCtrl(panel
, CTRLID_CAL
, wxDefaultDateTime
, wxPoint(0,0), wxDefaultSize
, wxSUNKEN_BORDER
);
124 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_SEL_CHANGED
, (wxObjectEventFunction
)&wxDatePickerCtrl::OnSelChange
, 0, this);
125 m_cal
->Connect(wxID_ANY
, wxID_ANY
, wxEVT_KEY_DOWN
, (wxObjectEventFunction
)&wxDatePickerCtrl::OnCalKey
, 0, this);
126 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_DOUBLECLICKED
, (wxObjectEventFunction
)&wxDatePickerCtrl::OnSelChange
, 0, this);
127 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_DAY_CHANGED
, (wxObjectEventFunction
)&wxDatePickerCtrl::OnSelChange
, 0, this);
128 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_MONTH_CHANGED
, (wxObjectEventFunction
)&wxDatePickerCtrl::OnSelChange
, 0, this);
129 m_cal
->Connect(CTRLID_CAL
, CTRLID_CAL
, wxEVT_CALENDAR_YEAR_CHANGED
, (wxObjectEventFunction
)&wxDatePickerCtrl::OnSelChange
, 0, this);
131 wxWindow
*yearControl
= m_cal
->GetYearControl();
133 Connect(wxID_ANY
, wxID_ANY
, wxEVT_SET_FOCUS
, (wxObjectEventFunction
)&wxDatePickerCtrl::OnSetFocus
);
135 wxClientDC
dc(yearControl
);
137 wxCoord width
, dummy
;
138 dc
.GetTextExtent(wxT("2000"), &width
, &dummy
);
139 width
+= ConvertDialogToPixels(wxSize(20,0)).x
;
141 wxSize calSize
= m_cal
->GetBestSize();
142 wxSize yearSize
= yearControl
->GetSize();
145 wxPoint yearPosition
= yearControl
->GetPosition();
153 width
= yearPosition
.x
+ yearSize
.x
+2+CALBORDER
/2;
154 if (width
< calSize
.x
-4)
157 int calPos
= (width
-calSize
.x
)/2;
163 m_cal
->SetSize(calPos
, 0, calSize
.x
, calSize
.y
);
164 yearControl
->SetSize(width
-yearSize
.x
-CALBORDER
/2, yearPosition
.y
, yearSize
.x
, yearSize
.y
);
165 m_cal
->GetMonthControl()->Move(0, 0);
169 panel
->SetClientSize(width
+CALBORDER
/2, calSize
.y
-2+CALBORDER
);
170 m_dlg
->SetClientSize(panel
->GetSize());
176 void wxDatePickerCtrl::Init()
184 m_ignoreDrop
= false;
188 bool wxDatePickerCtrl::Destroy()
204 return wxControl::Destroy();
207 // ----------------------------------------------------------------------------
208 // overridden base class methods
209 // ----------------------------------------------------------------------------
211 void wxDatePickerCtrl::DoMoveWindow(int x
, int y
, int w
, int h
)
213 wxControl::DoMoveWindow(x
, y
, w
, h
);
214 wxSize bs
=m_btn
->GetBestSize();
215 int eh
=m_txt
->GetBestSize().y
;
217 m_txt
->SetSize(0, 0, w
-bs
.x
-1, h
> eh
? eh
: h
);
218 m_btn
->SetSize(w
- bs
.x
, 0, bs
.x
, h
> bs
.y
? bs
.y
: h
);
224 wxSize
wxDatePickerCtrl::DoGetBestSize() const
226 int bh
=m_btn
->GetBestSize().y
;
227 int eh
=m_txt
->GetBestSize().y
;
228 return wxSize(DEFAULT_ITEM_WIDTH
, bh
> eh
? bh
: eh
);
232 bool wxDatePickerCtrl::Show(bool show
)
234 if ( !wxControl::Show(show
) )
252 bool wxDatePickerCtrl::Enable(bool enable
)
254 if ( !wxControl::Enable(enable
) )
265 m_btn
->Enable(enable
);
269 // ----------------------------------------------------------------------------
270 // wxDatePickerCtrl API
271 // ----------------------------------------------------------------------------
273 bool wxDatePickerCtrl::SetFormat(const wxChar
*fmt
)
276 dt
.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
277 wxString str
=dt
.Format(fmt
);
278 wxChar
*p
=(wxChar
*)str
.c_str();
280 m_format
=wxEmptyString
;
285 if (n
== dt
.GetDay())
287 m_format
.Append(wxT("%d"));
290 else if (n
== (int)dt
.GetMonth()+1)
292 m_format
.Append(wxT("%m"));
295 else if (n
== dt
.GetYear())
297 m_format
.Append(wxT("%Y"));
301 m_format
.Append(*p
++);
306 wxStringList valList
;
308 for (c
='0'; c
<= '9'; c
++)
309 valList
.Add(wxString(c
, 1));
310 wxChar
*p
=(wxChar
*)m_format
.c_str();
316 valList
.Add(wxString(*p
++, 1));
318 wxTextValidator
tv(wxFILTER_INCLUDE_CHAR_LIST
);
319 tv
.SetIncludeList(valList
);
321 m_txt
->SetValidator(tv
);
327 wxDateTime
wxDatePickerCtrl::GetValue() const
330 wxString txt
=m_txt
->GetValue();
333 dt
.ParseFormat(txt
, m_format
);
339 void wxDatePickerCtrl::SetValue(const wxDateTime
& date
)
344 m_txt
->SetValue(date
.FormatDate());
346 m_txt
->SetValue(wxEmptyString
);
351 bool wxDatePickerCtrl::GetRange(wxDateTime
*dt1
, wxDateTime
*dt2
) const
354 *dt1
= GetLowerDateLimit();
356 *dt2
= GetUpperDateLimit();
361 void wxDatePickerCtrl::SetRange(const wxDateTime
&dt1
, const wxDateTime
&dt2
)
363 SetLowerDateLimit(dt1
);
364 SetUpperDateLimit(dt2
);
367 // ----------------------------------------------------------------------------
369 // ----------------------------------------------------------------------------
371 void wxDatePickerCtrl::DropDown(bool down
)
377 if (m_txt
->GetValue().IsEmpty())
378 m_cal
->SetDate(wxDateTime::Today());
382 dt
.ParseFormat(m_txt
->GetValue(), m_format
);
385 wxPoint pos
=GetParent()->ClientToScreen(GetPosition());
387 m_dlg
->Move(pos
.x
, pos
.y
+ GetSize().y
);
401 void wxDatePickerCtrl::OnChildSetFocus(wxChildFocusEvent
&ev
)
404 m_ignoreDrop
= false;
406 wxWindow
*w
=(wxWindow
*)ev
.GetEventObject();
417 if (ev
.GetEventObject() == m_btn
)
423 void wxDatePickerCtrl::OnClick(wxCommandEvent
& event
)
427 m_ignoreDrop
= false;
438 void wxDatePickerCtrl::OnSetFocus(wxFocusEvent
&ev
)
443 m_txt
->SetSelection(0, 100);
448 void wxDatePickerCtrl::OnKillFocus(wxFocusEvent
&ev
)
453 dt
.ParseFormat(m_txt
->GetValue(), m_format
);
455 m_txt
->SetValue(wxEmptyString
);
457 m_txt
->SetValue(dt
.Format(m_format
));
461 void wxDatePickerCtrl::OnSelChange(wxCalendarEvent
&ev
)
465 m_txt
->SetValue(m_cal
->GetDate().FormatDate());
466 if (ev
.GetEventType() == wxEVT_CALENDAR_DOUBLECLICKED
)
472 ev
.SetEventObject(this);
474 GetParent()->ProcessEvent(ev
);
478 void wxDatePickerCtrl::OnText(wxCommandEvent
&ev
)
480 ev
.SetEventObject(this);
482 GetParent()->ProcessEvent(ev
);
484 // We'll create an additional event if the date is valid.
485 // If the date isn't valid, the user's probable in the middle of typing
486 wxString txt
=m_txt
->GetValue();
490 dt
.ParseFormat(txt
, m_format
);
495 wxCalendarEvent
cev(m_cal
, wxEVT_CALENDAR_SEL_CHANGED
);
496 cev
.SetEventObject(this);
500 GetParent()->ProcessEvent(cev
);
504 void wxDatePickerCtrl::OnEditKey(wxKeyEvent
& ev
)
506 if (ev
.GetKeyCode() == WXK_DOWN
&& !ev
.HasModifiers())
513 void wxDatePickerCtrl::OnCalKey(wxKeyEvent
& ev
)
515 if (ev
.GetKeyCode() == WXK_ESCAPE
&& !ev
.HasModifiers())