From 232b2162776e08c0b16d5280b90f5c075f38c667 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 25 Jan 2009 13:47:20 +0000 Subject: [PATCH] added support for wxCAL_SHOW_WEEK_NUMBERS to generic version of wxCalendarCtrl (#10033) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58394 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + include/wx/calctrl.h | 7 +++- include/wx/generic/calctrlg.h | 3 +- interface/wx/calctrl.h | 8 +++- samples/calendar/calendar.cpp | 11 ++++- src/common/calctrlcmn.cpp | 1 + src/generic/calctrlg.cpp | 76 ++++++++++++++++++++++++++++------- 7 files changed, 86 insertions(+), 21 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 4221fca256..d104efc8d4 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -353,6 +353,7 @@ All (GUI): - Also added wxCANCEL_DEFAULT to wxMessageDialog. - Allow copying text in the log dialogs. - Added multisample (anti-aliasing) support to wxGLCanvas (Olivier Playez). +- Added wxCAL_SHOW_WEEK_NUMBERS wxCalendarCtrl style (Sören Meyer-Eppler). - Initialize wx{Client,Paint,Window}DC with fonts/colours of its window. - Added wxNativeContainerWindow to allow embedding wx into native windows. - Added custom controls support to wxFileDialog (Diaa Sami and Marcin Wojdyr). diff --git a/include/wx/calctrl.h b/include/wx/calctrl.h index 64cea8b888..7f29f81f1d 100644 --- a/include/wx/calctrl.h +++ b/include/wx/calctrl.h @@ -30,7 +30,7 @@ enum // show Sunday as the first day of the week (default) wxCAL_SUNDAY_FIRST = 0x0000, - // show Monder as the first day of the week + // show Monday as the first day of the week wxCAL_MONDAY_FIRST = 0x0001, // highlight holidays @@ -66,7 +66,8 @@ enum wxCalendarHitTestResult wxCAL_HITTEST_DAY, // on a day in the calendar wxCAL_HITTEST_INCMONTH, wxCAL_HITTEST_DECMONTH, - wxCAL_HITTEST_SURROUNDING_WEEK + wxCAL_HITTEST_SURROUNDING_WEEK, + wxCAL_HITTEST_WEEK }; // border types for a date @@ -364,6 +365,7 @@ wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_ADV, wxEVT_CALENDAR_SEL_CHANGED, wxCalenda wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_ADV, wxEVT_CALENDAR_PAGE_CHANGED, wxCalendarEvent ) wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_ADV, wxEVT_CALENDAR_DOUBLECLICKED, wxCalendarEvent ) wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_ADV, wxEVT_CALENDAR_WEEKDAY_CLICKED, wxCalendarEvent ) +wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_ADV, wxEVT_CALENDAR_WEEK_CLICKED, wxCalendarEvent ) // deprecated events wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_ADV, wxEVT_CALENDAR_DAY_CHANGED, wxCalendarEvent ) @@ -382,6 +384,7 @@ typedef void (wxEvtHandler::*wxCalendarEventFunction)(wxCalendarEvent&); #define EVT_CALENDAR_SEL_CHANGED(id, fn) wx__DECLARE_CALEVT(SEL_CHANGED, id, fn) #define EVT_CALENDAR_PAGE_CHANGED(id, fn) wx__DECLARE_CALEVT(PAGE_CHANGED, id, fn) #define EVT_CALENDAR_WEEKDAY_CLICKED(id, fn) wx__DECLARE_CALEVT(WEEKDAY_CLICKED, id, fn) +#define EVT_CALENDAR_WEEK_CLICKED(id, fn) wx__DECLARE_CALEVT(WEEK_CLICKED, id, fn) // deprecated events #define EVT_CALENDAR_DAY(id, fn) wx__DECLARE_CALEVT(DAY_CHANGED, id, fn) diff --git a/include/wx/generic/calctrlg.h b/include/wx/generic/calctrlg.h index fb85631c50..9ff4e89b54 100644 --- a/include/wx/generic/calctrlg.h +++ b/include/wx/generic/calctrlg.h @@ -282,7 +282,8 @@ private: // the width and height of one column/row in the calendar wxCoord m_widthCol, m_heightRow, - m_rowOffset; + m_rowOffset, + m_calendarWeekWidth; wxRect m_leftArrowRect, m_rightArrowRect; diff --git a/interface/wx/calctrl.h b/interface/wx/calctrl.h index 11a09e7fa0..ccd01dba9e 100644 --- a/interface/wx/calctrl.h +++ b/interface/wx/calctrl.h @@ -182,7 +182,11 @@ enum wxCalendarHitTestResult { wxCAL_HITTEST_NOWHERE, ///< Hit outside of anything. wxCAL_HITTEST_HEADER, ///< Hit on the header (weekdays). - wxCAL_HITTEST_DAY ///< Hit on a day in the calendar. + wxCAL_HITTEST_DAY, ///< Hit on a day in the calendar. + wxCAL_HITTEST_INCMONTH, ///< Hit on next month arrow (in alternate month selector mode). + wxCAL_HITTEST_DECMONTH, ///< Hit on previous month arrow (in alternate month selector mode). + wxCAL_HITTEST_SURROUNDING_WEEK, ///< Hit on surrounding week of previous/next month (if shown). + wxCAL_HITTEST_WEEK ///< Hit on week of the year number (if shown). }; /** @@ -242,6 +246,8 @@ enum wxCalendarHitTestResult The selected month (and/or year) changed. @event{EVT_CALENDAR_WEEKDAY_CLICKED(id, func)} User clicked on the week day header (only generic). + @event{EVT_CALENDAR_WEEK_CLICKED(id, func)} + User clicked on the week of the year number (only generic). @endEventTable @note Changing the selected date will trigger an EVT_CALENDAR_DAY, MONTH or diff --git a/samples/calendar/calendar.cpp b/samples/calendar/calendar.cpp index f9c5c4e708..47d7dbae30 100644 --- a/samples/calendar/calendar.cpp +++ b/samples/calendar/calendar.cpp @@ -81,6 +81,7 @@ public: void OnCalendar(wxCalendarEvent& event); void OnCalendarWeekDayClick(wxCalendarEvent& event); + void OnCalendarWeekClick(wxCalendarEvent& event); void OnCalendarChange(wxCalendarEvent& event); void OnCalMonthChange(wxCalendarEvent& event); @@ -285,6 +286,7 @@ BEGIN_EVENT_TABLE(MyPanel, wxPanel) EVT_CALENDAR_PAGE_CHANGED(Calendar_CalCtrl, MyPanel::OnCalMonthChange) EVT_CALENDAR_SEL_CHANGED(Calendar_CalCtrl, MyPanel::OnCalendarChange) EVT_CALENDAR_WEEKDAY_CLICKED(Calendar_CalCtrl, MyPanel::OnCalendarWeekDayClick) + EVT_CALENDAR_WEEK_CLICKED(Calendar_CalCtrl, MyPanel::OnCalendarWeekClick) END_EVENT_TABLE() #if wxUSE_DATEPICKCTRL @@ -321,7 +323,7 @@ bool MyApp::OnInit() #ifndef __WXWINCE__ ,wxPoint(50, 50), wxSize(450, 340) #endif - ); + ); frame->Show(true); @@ -684,6 +686,11 @@ void MyPanel::OnCalendarWeekDayClick(wxCalendarEvent& event) wxDateTime::GetWeekDayName(event.GetWeekDay()).c_str()); } +void MyPanel::OnCalendarWeekClick(wxCalendarEvent& event) +{ + wxLogMessage(wxT("Clicked on week %d"), event.GetDate().GetWeekOfYear()); +} + wxCalendarCtrlBase *MyPanel::DoCreateCalendar(const wxDateTime& dt, long style) { wxCalendarCtrlBase *calendar; @@ -729,7 +736,7 @@ void MyPanel::ToggleCalStyle(bool on, int flag) else style &= ~flag; - if ( flag == wxCAL_SEQUENTIAL_MONTH_SELECTION + if ( flag == wxCAL_SEQUENTIAL_MONTH_SELECTION || flag == wxCAL_SHOW_WEEK_NUMBERS) { // changing this style requires recreating the control diff --git a/src/common/calctrlcmn.cpp b/src/common/calctrlcmn.cpp index 9130d781c8..d39926ee81 100644 --- a/src/common/calctrlcmn.cpp +++ b/src/common/calctrlcmn.cpp @@ -38,6 +38,7 @@ wxDEFINE_EVENT( wxEVT_CALENDAR_SEL_CHANGED, wxCalendarEvent ) wxDEFINE_EVENT( wxEVT_CALENDAR_PAGE_CHANGED, wxCalendarEvent ) wxDEFINE_EVENT( wxEVT_CALENDAR_DOUBLECLICKED, wxCalendarEvent ) wxDEFINE_EVENT( wxEVT_CALENDAR_WEEKDAY_CLICKED, wxCalendarEvent ) +wxDEFINE_EVENT( wxEVT_CALENDAR_WEEK_CLICKED, wxCalendarEvent ) // deprecated events wxDEFINE_EVENT( wxEVT_CALENDAR_DAY_CHANGED, wxCalendarEvent ) diff --git a/src/generic/calctrlg.cpp b/src/generic/calctrlg.cpp index 98b15213c5..21d116ccb1 100644 --- a/src/generic/calctrlg.cpp +++ b/src/generic/calctrlg.cpp @@ -96,13 +96,14 @@ wxBEGIN_FLAGS( wxCalendarCtrlStyle ) wxFLAGS_MEMBER(wxCAL_NO_MONTH_CHANGE) wxFLAGS_MEMBER(wxCAL_SEQUENTIAL_MONTH_SELECTION) wxFLAGS_MEMBER(wxCAL_SHOW_SURROUNDING_WEEKS) + wxFLAGS_MEMBER(wxCAL_SHOW_WEEK_NUMBERS) wxEND_FLAGS( wxCalendarCtrlStyle ) IMPLEMENT_DYNAMIC_CLASS_XTI(wxGenericCalendarCtrl, wxControl,"wx/calctrl.h") wxBEGIN_PROPERTIES_TABLE(wxGenericCalendarCtrl) - wxEVENT_RANGE_PROPERTY( Updated , wxEVT_CALENDAR_SEL_CHANGED , wxEVT_CALENDAR_WEEKDAY_CLICKED , wxCalendarEvent ) + wxEVENT_RANGE_PROPERTY( Updated , wxEVT_CALENDAR_SEL_CHANGED , wxEVT_CALENDAR_WEEK_CLICKED , wxCalendarEvent ) wxHIDE_PROPERTY( Children ) wxPROPERTY( Date,wxDateTime, SetDate , GetDate, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) wxPROPERTY_FLAGS( WindowStyle , wxCalendarCtrlStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style @@ -190,7 +191,8 @@ void wxGenericCalendarCtrl::Init() m_userChangedYear = false; m_widthCol = - m_heightRow = 0; + m_heightRow = + m_calendarWeekWidth = 0; wxDateTime::WeekDay wd; for ( wd = wxDateTime::Sun; wd < wxDateTime::Inv_WeekDay; wxNextWDay(wd) ) @@ -772,7 +774,7 @@ size_t wxGenericCalendarCtrl::GetWeek(const wxDateTime& date) const // this is a composite control and it must arrange its parts each time its // size or position changes: the combobox and spinctrl are along the top of -// the available area and the calendar takes up therest of the space +// the available area and the calendar takes up the rest of the space // the static controls are supposed to be always smaller than combo/spin so we // always use the latter for size calculations and position the static to take @@ -787,8 +789,8 @@ wxSize wxGenericCalendarCtrl::DoGetBestSize() const // calc the size of the calendar const_cast(this)->RecalcGeometry(); - wxCoord width = 7*m_widthCol, - height = 7*m_heightRow + m_rowOffset; + wxCoord width = 7*m_widthCol + m_calendarWeekWidth, + height = 7*m_heightRow + m_rowOffset + VERT_MARGIN; if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION) ) { @@ -813,7 +815,7 @@ wxSize wxGenericCalendarCtrl::DoGetBestSize() const } CacheBestSize(best); - + return best; } @@ -855,7 +857,7 @@ void wxGenericCalendarCtrl::DoGetSize(int *width, int *height) const { #ifdef __WXMAC__ wxControl::DoGetSize( width, height ); - + if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION) && m_staticMonth && height ) { wxSize sizeCombo = m_comboMonth->GetEffectiveMinSize(); @@ -900,6 +902,9 @@ void wxGenericCalendarCtrl::RecalcGeometry() } } + m_calendarWeekWidth = HasFlag( wxCAL_SHOW_WEEK_NUMBERS ) + ? dc.GetTextExtent( wxString::Format( wxT( "%d" ), 42 )).GetWidth() + 4 : 0; + // leave some margins m_widthCol += 2; m_heightRow += 2; @@ -926,7 +931,7 @@ void wxGenericCalendarCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) #endif wxCoord y = 0; - wxCoord x0 = wxMax( (GetSize().x - m_widthCol*7) /2 , 0 ); + wxCoord x0 = m_calendarWeekWidth; if ( HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION) ) { @@ -1029,6 +1034,24 @@ void wxGenericCalendarCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) //dc.SetFont(*wxNORMAL_FONT); y += m_heightRow; + + // draw column with calendar week nr + if ( HasFlag( wxCAL_SHOW_WEEK_NUMBERS ) && IsExposed( 0, y, m_calendarWeekWidth, m_heightRow * 6 )) + { + dc.SetBackgroundMode(wxTRANSPARENT); + dc.SetBrush(wxBrush(m_colHeaderBg, wxSOLID)); + dc.SetPen(wxPen(m_colHeaderBg, 1, wxSOLID)); + dc.DrawRectangle( 0, y, m_calendarWeekWidth, m_heightRow * 6 ); + wxDateTime date = GetStartDate(); + for ( size_t i = 0; i < 6; ++i ) + { + const int weekNr = date.GetWeekOfYear(); + wxString text = wxString::Format( wxT( "%d" ), weekNr ); + dc.DrawText( text, m_calendarWeekWidth - dc.GetTextExtent( text ).GetWidth() - 2, y + m_heightRow * i ); + date += wxDateSpan::Week(); + } + } + wxDateTime date = GetStartDate(); #if DEBUG_PAINT @@ -1211,9 +1234,9 @@ void wxGenericCalendarCtrl::RefreshDate(const wxDateTime& date) wxRect rect; // always refresh the whole row at once because our OnPaint() will draw - // the whole row anyhow - and this allows the small optimisation in + // the whole row anyhow - and this allows the small optimization in // OnClick() below to work - rect.x = wxMax( (GetSize().x - m_widthCol*7) /2 , 0 ); + rect.x = m_calendarWeekWidth; rect.y = (m_heightRow * GetWeek(date)) + m_rowOffset; @@ -1279,7 +1302,7 @@ void wxGenericCalendarCtrl::HighlightRange(wxPaintDC* pDC, const wxDateTime& fro { int numpoints; wxPoint corners[8]; // potentially 8 corners in polygon - wxCoord x0 = wxMax( (GetSize().x - m_widthCol*7) /2 , 0 ); + wxCoord x0 = m_calendarWeekWidth; if ( fw == tw ) { @@ -1452,7 +1475,14 @@ void wxGenericCalendarCtrl::OnClick(wxMouseEvent& event) // GenerateAllChangeEvents() here, we know which event to send GenerateEvent(wxEVT_CALENDAR_DAY_CHANGED); } - break; + break; + + case wxCAL_HITTEST_WEEK: + { + wxCalendarEvent send( this, date, wxEVT_CALENDAR_WEEK_CLICKED ); + HandleWindowEvent( send ); + } + break; case wxCAL_HITTEST_HEADER: { @@ -1490,7 +1520,7 @@ wxCalendarHitTestResult wxGenericCalendarCtrl::HitTest(const wxPoint& pos, RecalcGeometry(); // the position where the calendar really begins - wxCoord x0 = wxMax((GetSize().x - m_widthCol*7)/2, 0); + wxCoord x0 = m_calendarWeekWidth; if ( HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION) ) { @@ -1531,12 +1561,28 @@ wxCalendarHitTestResult wxGenericCalendarCtrl::HitTest(const wxPoint& pos, return wxCAL_HITTEST_INCMONTH; } - } + if ( pos.x - x0 < 0 ) + if ( pos.x >= 0 && pos.y > m_rowOffset + m_heightRow && pos.y <= m_rowOffset + m_heightRow * 7 ) + { + if ( date ) + { + *date = GetStartDate(); + *date += wxDateSpan::Week() * (( pos.y - m_rowOffset ) / m_heightRow - 1 ); + } + if ( wd ) + *wd = ( GetWindowStyle() & wxCAL_MONDAY_FIRST ) ? wxDateTime::Mon : wxDateTime::Sun; + return wxCAL_HITTEST_WEEK; + } + else // early exit -> the rest of the function checks for clicks on days + return wxCAL_HITTEST_NOWHERE; + // header: week days int wday = (pos.x - x0) / m_widthCol; - if ( pos.y < (m_heightRow + m_rowOffset) ) + if ( wday > 6 ) + return wxCAL_HITTEST_NOWHERE; + if ( pos.y < (m_heightRow + m_rowOffset)) { if ( pos.y > m_rowOffset ) { -- 2.47.2