wxWidgets/samples/calendar/calendar.cpp
Scott Talbert 82735e8612 Use wxSpinCtrl best size in wxGenericCalendarCtrl::DoGetBestSize
This fixes the wxGenericCalendarCtrl on wxGTK3 where the SpinCtrl is
much wider than on other platforms and should also ensure that the
control is always big enough in all locales under Mac.

Closes https://github.com/wxWidgets/wxWidgets/pull/2604

Closes #11444.
2021-12-01 23:23:34 +01:00

1073 lines
33 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: calendar.cpp
// Purpose: wxCalendarCtrl sample
// Author: Vadim Zeitlin
// Modified by:
// Created: 02.01.00
// Copyright: (c) Vadim Zeitlin
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
// for all others, include the necessary headers
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/log.h"
#include "wx/frame.h"
#include "wx/panel.h"
#include "wx/stattext.h"
#include "wx/menu.h"
#include "wx/layout.h"
#include "wx/msgdlg.h"
#include "wx/icon.h"
#include "wx/button.h"
#include "wx/sizer.h"
#include "wx/textctrl.h"
#include "wx/settings.h"
#endif
#include "wx/calctrl.h"
#include "wx/splitter.h"
#if wxUSE_DATEPICKCTRL
#include "wx/datectrl.h"
#if wxUSE_DATEPICKCTRL_GENERIC
#include "wx/generic/datectrl.h"
#endif // wxUSE_DATEPICKCTRL_GENERIC
#endif // wxUSE_DATEPICKCTRL
#if wxUSE_TIMEPICKCTRL
#include "wx/timectrl.h"
#if wxUSE_TIMEPICKCTRL_GENERIC
#include "wx/generic/timectrl.h"
#endif // wxUSE_TIMEPICKCTRL_GENERIC
#endif // wxUSE_TIMEPICKCTRL
#include "../sample.xpm"
#ifdef wxHAS_NATIVE_CALENDARCTRL
#include "wx/generic/calctrlg.h"
#endif
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// Define a new application type, each program should derive a class from wxApp
class MyApp : public wxApp
{
public:
MyApp();
// override base class virtuals
// ----------------------------
// this one is called on application startup and is a good place for the app
// initialization (doing it here and not in the ctor allows to have an error
// return: if OnInit() returns false, the application terminates)
virtual bool OnInit() wxOVERRIDE;
private:
wxLocale m_locale;
};
class MyPanel : public wxPanel
{
public:
MyPanel(wxWindow *parent);
void OnCalendar(wxCalendarEvent& event);
void OnCalendarWeekDayClick(wxCalendarEvent& event);
void OnCalendarWeekClick(wxCalendarEvent& event);
void OnCalendarChange(wxCalendarEvent& event);
void OnCalMonthChange(wxCalendarEvent& event);
wxCalendarCtrlBase *GetCal() const { return m_calendar; }
// turn on/off the specified style bit on the calendar control
void ToggleCalStyle(bool on, int style);
bool IsUsingGeneric() const { return m_usingGeneric; }
void ToggleUseGeneric()
{
m_usingGeneric = !m_usingGeneric;
RecreateCalendar(m_calendar->GetWindowStyle());
}
void HighlightSpecial(bool on);
void LimitDateRange(bool on);
wxDateTime GetDate() const { return m_calendar->GetDate(); }
void SetDate(const wxDateTime& dt) { m_calendar->SetDate(dt); }
private:
wxCalendarCtrlBase *DoCreateCalendar(const wxDateTime& dt, long style);
void RecreateCalendar(long style);
wxCalendarCtrlBase *m_calendar;
wxStaticText *m_date;
wxSizer *m_sizer;
bool m_usingGeneric;
wxDECLARE_EVENT_TABLE();
};
// Define a new frame type: this is going to be our main frame
class MyFrame : public wxFrame
{
public:
// ctor(s)
MyFrame(const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
// event handlers (these functions should _not_ be virtual)
void OnAbout(wxCommandEvent& event);
void OnClearLog(wxCommandEvent& event);
void OnQuit(wxCommandEvent& event);
#if wxUSE_DATEPICKCTRL
void OnAskDate(wxCommandEvent& event);
void OnUpdateUIStartWithNone(wxUpdateUIEvent& event);
#endif // wxUSE_DATEPICKCTRL
#if wxUSE_TIMEPICKCTRL
void OnAskTime(wxCommandEvent& event);
#endif // wxUSE_TIMEPICKCTRL
#ifdef wxHAS_NATIVE_CALENDARCTRL
void OnCalGeneric(wxCommandEvent& WXUNUSED(event))
{
m_panel->ToggleUseGeneric();
}
#endif // wxHAS_NATIVE_CALENDARCTRL
void OnCalAutoWeekday(wxCommandEvent& event);
void OnCalSunday(wxCommandEvent& event);
void OnCalMonday(wxCommandEvent& event);
void OnCalHolidays(wxCommandEvent& event);
void OnCalSpecial(wxCommandEvent& event);
void OnCalAllowMonth(wxCommandEvent& event);
void OnCalLimitDates(wxCommandEvent& event);
void OnCalSeqMonth(wxCommandEvent& event);
void OnCalShowSurroundingWeeks(wxCommandEvent& event);
void OnCalShowWeekNumbers(wxCommandEvent& event);
void OnSetDate(wxCommandEvent& event);
void OnToday(wxCommandEvent& event);
void OnBeginDST(wxCommandEvent& event);
void OnCalToggleResizable(wxCommandEvent& event);
void OnUpdateUIGenericOnly(wxUpdateUIEvent& event)
{
event.Enable(m_panel->IsUsingGeneric());
}
void OnCalRClick(wxMouseEvent& event);
private:
MyPanel *m_panel;
wxTextCtrl *m_logWindow;
// any class wishing to process wxWidgets events must use this macro
wxDECLARE_EVENT_TABLE();
};
#if wxUSE_DATEPICKCTRL
// Define a simple modal dialog which asks the user for a date
class MyDateDialog : public wxDialog
{
public:
MyDateDialog(wxWindow *parent, const wxDateTime& dt, int dtpStyle);
wxDateTime GetDate() const
{
#if wxUSE_DATEPICKCTRL_GENERIC
if ( m_datePickerGeneric )
return m_datePickerGeneric->GetValue();
#endif // wxUSE_DATEPICKCTRL_GENERIC
return m_datePicker->GetValue();
}
private:
void OnDateChange(wxDateEvent& event);
wxDatePickerCtrl *m_datePicker;
#if wxUSE_DATEPICKCTRL_GENERIC
wxDatePickerCtrlGeneric *m_datePickerGeneric;
#endif // wxUSE_DATEPICKCTRL_GENERIC
wxStaticText *m_dateText;
wxDECLARE_EVENT_TABLE();
};
#endif // wxUSE_DATEPICKCTRL
#if wxUSE_TIMEPICKCTRL
// Another simple dialog, this one asking for time.
class MyTimeDialog : public wxDialog
{
public:
MyTimeDialog(wxWindow* parent);
wxDateTime GetTime() const
{
#if wxUSE_TIMEPICKCTRL_GENERIC
if ( m_timePickerGeneric )
return m_timePickerGeneric->GetValue();
#endif // wxUSE_TIMEPICKCTRL_GENERIC
return m_timePicker->GetValue();
}
private:
void OnTimeChange(wxDateEvent& event);
wxTimePickerCtrl* m_timePicker;
#if wxUSE_TIMEPICKCTRL_GENERIC
wxTimePickerCtrlGeneric* m_timePickerGeneric;
#endif // wxUSE_TIMEPICKCTRL_GENERIC
wxStaticText* m_timeText;
wxDECLARE_EVENT_TABLE();
};
#endif // wxUSE_TIMEPICKCTRL
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// IDs for the controls and the menu commands
enum
{
// menu items
Calendar_File_About = wxID_ABOUT,
Calendar_File_ClearLog = wxID_CLEAR,
Calendar_File_Quit = wxID_EXIT,
Calendar_Cal_Generic = 200,
Calendar_Cal_AutoWeekday,
Calendar_Cal_Sunday,
Calendar_Cal_Monday,
Calendar_Cal_Holidays,
Calendar_Cal_Special,
Calendar_Cal_Month,
Calendar_Cal_LimitDates,
Calendar_Cal_SeqMonth,
Calendar_Cal_SurroundWeeks,
Calendar_Cal_WeekNumbers,
Calendar_Cal_SetDate,
Calendar_Cal_Today,
Calendar_Cal_BeginDST,
Calendar_Cal_Resizable,
#if wxUSE_DATEPICKCTRL
Calendar_DatePicker_AskDate = 300,
Calendar_DatePicker_ShowCentury,
Calendar_DatePicker_DropDown,
Calendar_DatePicker_AllowNone,
Calendar_DatePicker_StartWithNone,
#if wxUSE_DATEPICKCTRL_GENERIC
Calendar_DatePicker_Generic,
#endif // wxUSE_DATEPICKCTRL_GENERIC
#endif // wxUSE_DATEPICKCTRL
#if wxUSE_TIMEPICKCTRL
Calendar_TimePicker_AskTime = 400,
#if wxUSE_TIMEPICKCTRL_GENERIC
Calendar_TimePicker_Generic,
#endif // wxUSE_TIMEPICKCTRL_GENERIC
#endif // wxUSE_TIMEPICKCTRL
Calendar_CalCtrl = 1000
};
// ----------------------------------------------------------------------------
// event tables and other macros for wxWidgets
// ----------------------------------------------------------------------------
// the event tables connect the wxWidgets events with the functions (event
// handlers) which process them. It can be also done at run-time, but for the
// simple menu events like this the static method is much simpler.
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(Calendar_File_About, MyFrame::OnAbout)
EVT_MENU(Calendar_File_ClearLog, MyFrame::OnClearLog)
EVT_MENU(Calendar_File_Quit, MyFrame::OnQuit)
#if wxUSE_DATEPICKCTRL
EVT_MENU(Calendar_DatePicker_AskDate, MyFrame::OnAskDate)
EVT_UPDATE_UI(Calendar_DatePicker_StartWithNone,
MyFrame::OnUpdateUIStartWithNone)
#endif // wxUSE_DATEPICKCTRL
#if wxUSE_TIMEPICKCTRL
EVT_MENU(Calendar_TimePicker_AskTime, MyFrame::OnAskTime)
#endif // wxUSE_TIMEPICKCTRL
#ifdef wxHAS_NATIVE_CALENDARCTRL
EVT_MENU(Calendar_Cal_Generic, MyFrame::OnCalGeneric)
#endif // wxHAS_NATIVE_CALENDARCTRL
EVT_MENU(Calendar_Cal_AutoWeekday, MyFrame::OnCalAutoWeekday)
EVT_MENU(Calendar_Cal_Sunday, MyFrame::OnCalSunday)
EVT_MENU(Calendar_Cal_Monday, MyFrame::OnCalMonday)
EVT_MENU(Calendar_Cal_Holidays, MyFrame::OnCalHolidays)
EVT_MENU(Calendar_Cal_Special, MyFrame::OnCalSpecial)
EVT_MENU(Calendar_Cal_Month, MyFrame::OnCalAllowMonth)
EVT_MENU(Calendar_Cal_LimitDates, MyFrame::OnCalLimitDates)
EVT_MENU(Calendar_Cal_SeqMonth, MyFrame::OnCalSeqMonth)
EVT_MENU(Calendar_Cal_SurroundWeeks, MyFrame::OnCalShowSurroundingWeeks)
EVT_MENU(Calendar_Cal_WeekNumbers, MyFrame::OnCalShowWeekNumbers)
EVT_MENU(Calendar_Cal_SetDate, MyFrame::OnSetDate)
EVT_MENU(Calendar_Cal_Today, MyFrame::OnToday)
EVT_MENU(Calendar_Cal_BeginDST, MyFrame::OnBeginDST)
EVT_MENU(Calendar_Cal_Resizable, MyFrame::OnCalToggleResizable)
EVT_UPDATE_UI(Calendar_Cal_SeqMonth, MyFrame::OnUpdateUIGenericOnly)
#ifdef __WXGTK20__
EVT_UPDATE_UI(Calendar_Cal_AutoWeekday, MyFrame::OnUpdateUIGenericOnly)
EVT_UPDATE_UI(Calendar_Cal_Sunday, MyFrame::OnUpdateUIGenericOnly)
EVT_UPDATE_UI(Calendar_Cal_Monday, MyFrame::OnUpdateUIGenericOnly)
EVT_UPDATE_UI(Calendar_Cal_Holidays, MyFrame::OnUpdateUIGenericOnly)
#endif
EVT_UPDATE_UI(Calendar_Cal_Special, MyFrame::OnUpdateUIGenericOnly)
EVT_UPDATE_UI(Calendar_Cal_SurroundWeeks, MyFrame::OnUpdateUIGenericOnly)
wxEND_EVENT_TABLE()
wxBEGIN_EVENT_TABLE(MyPanel, wxPanel)
EVT_CALENDAR(Calendar_CalCtrl, MyPanel::OnCalendar)
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)
wxEND_EVENT_TABLE()
// Create a new application object: this macro will allow wxWidgets to create
// the application object during program execution (it's better than using a
// static object for many reasons) and also declares the accessor function
// wxGetApp() which will return the reference of the right type (i.e. MyApp and
// not wxApp)
wxIMPLEMENT_APP(MyApp);
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// the application class
// ----------------------------------------------------------------------------
MyApp::MyApp() :
// Locale affects on the language used in the calendar, and may affect
// on the first day of the week.
m_locale(wxLANGUAGE_DEFAULT)
{
}
// `Main program' equivalent: the program execution "starts" here
bool MyApp::OnInit()
{
if ( !wxApp::OnInit() )
return false;
// Create the main application window
MyFrame *frame = new MyFrame("Calendar wxWidgets sample"
,wxPoint(50, 50), wxSize(460, 340)
);
frame->Show(true);
// success: wxApp::OnRun() will be called which will enter the main message
// loop and the application will run. If we returned false here, the
// application would exit immediately.
return true;
}
// ----------------------------------------------------------------------------
// main frame
// ----------------------------------------------------------------------------
// frame constructor
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size)
{
// set the frame icon
SetIcon(wxICON(sample));
// create a menu bar
wxMenuBar *menuBar = new wxMenuBar;
wxMenu *menuFile = new wxMenu;
menuFile->Append(Calendar_File_About, "&About\tCtrl-A", "Show about dialog");
menuFile->AppendSeparator();
menuFile->Append(Calendar_File_ClearLog, "&Clear log\tCtrl-L");
menuFile->AppendSeparator();
menuFile->Append(Calendar_File_Quit, "E&xit\tAlt-X", "Quit this program");
menuBar->Append(menuFile, "&File");
wxMenu *menuCal = new wxMenu;
#ifdef wxHAS_NATIVE_CALENDARCTRL
menuCal->AppendCheckItem(Calendar_Cal_Generic, "Use &generic version\tCtrl-G",
"Toggle between native and generic control");
menuCal->AppendSeparator();
#endif // wxHAS_NATIVE_CALENDARCTRL
menuCal->AppendRadioItem(Calendar_Cal_AutoWeekday,
"Automatic &first weekday\tCtrl-V");
menuCal->AppendRadioItem(Calendar_Cal_Sunday,
"Sunday &first weekday\tCtrl-Z");
menuCal->AppendRadioItem(Calendar_Cal_Monday,
"Monday &first weekday\tCtrl-F");
menuCal->Append(Calendar_Cal_Holidays, "Show &holidays\tCtrl-H",
"Toggle highlighting the holidays",
true);
menuCal->Append(Calendar_Cal_Special, "Highlight &special dates\tCtrl-S",
"Test custom highlighting",
true);
menuCal->Append(Calendar_Cal_SurroundWeeks,
"Show s&urrounding weeks\tCtrl-W",
"Show the neighbouring weeks in the prev/next month",
true);
menuCal->Append(Calendar_Cal_WeekNumbers,
"Show &week numbers",
"Toggle week numbers",
true);
menuCal->AppendSeparator();
menuCal->Append(Calendar_Cal_SeqMonth,
"Toggle month selector st&yle\tCtrl-Y",
"Use another style for the calendar controls",
true);
menuCal->Append(Calendar_Cal_Month, "&Month can be changed\tCtrl-M",
"Allow changing the month in the calendar",
true);
menuCal->AppendCheckItem(Calendar_Cal_LimitDates, "Toggle date ra&nge\tCtrl-N",
"Limit the valid dates");
menuCal->AppendSeparator();
menuCal->Append(Calendar_Cal_SetDate, "Call &SetDate(2005-12-24)", "Set date to 2005-12-24.");
menuCal->Append(Calendar_Cal_Today, "Call &Today()", "Set to the current date.");
menuCal->Append(Calendar_Cal_BeginDST, "Call SetDate(GetBeginDST())");
menuCal->AppendSeparator();
menuCal->AppendCheckItem(Calendar_Cal_Resizable, "Make &resizable\tCtrl-R");
menuBar->Append(menuCal, "&Calendar");
#if wxUSE_DATEPICKCTRL
wxMenu *menuDate = new wxMenu;
menuDate->AppendCheckItem(Calendar_DatePicker_ShowCentury,
"Al&ways show century");
menuDate->AppendCheckItem(Calendar_DatePicker_DropDown,
"Use &drop down control");
menuDate->AppendCheckItem(Calendar_DatePicker_AllowNone,
"Allow &no date");
menuDate->AppendCheckItem(Calendar_DatePicker_StartWithNone,
"Start &with no date");
#if wxUSE_DATEPICKCTRL_GENERIC
menuDate->AppendCheckItem(Calendar_DatePicker_Generic,
"Use &generic version of the control");
#endif // wxUSE_DATEPICKCTRL_GENERIC
menuDate->AppendSeparator();
menuDate->Append(Calendar_DatePicker_AskDate, "&Choose date...\tCtrl-D", "Show dialog with wxDatePickerCtrl");
menuBar->Append(menuDate, "&Date picker");
#endif // wxUSE_DATEPICKCTRL
#if wxUSE_TIMEPICKCTRL
wxMenu *menuTime = new wxMenu;
#if wxUSE_TIMEPICKCTRL_GENERIC
menuTime->AppendCheckItem(Calendar_TimePicker_Generic,
"Use &generic version of the control");
menuTime->AppendSeparator();
#endif // wxUSE_TIMEPICKCTRL_GENERIC
menuTime->Append(Calendar_TimePicker_AskTime, "&Choose time...\tCtrl-T", "Show dialog with wxTimePickerCtrl");
menuBar->Append(menuTime, "&Time picker");
#endif // wxUSE_TIMEPICKCTRL
menuBar->Check(Calendar_Cal_AutoWeekday, true);
menuBar->Check(Calendar_Cal_Sunday, false);
menuBar->Check(Calendar_Cal_Monday, false);
menuBar->Check(Calendar_Cal_Holidays, true);
menuBar->Check(Calendar_Cal_Month, true);
menuBar->Check(Calendar_Cal_LimitDates, false);
#if wxUSE_DATEPICKCTRL
menuBar->Check(Calendar_DatePicker_ShowCentury, true);
#endif // wxUSE_DATEPICKCTRL
// ... and attach this menu bar to the frame
SetMenuBar(menuBar);
wxSplitterWindow *splitter = new wxSplitterWindow(this, wxID_ANY,
wxDefaultPosition, wxDefaultSize,
wxSP_NOBORDER);
m_panel = new MyPanel(splitter);
m_logWindow = new wxTextCtrl(splitter, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize,
wxTE_READONLY | wxTE_MULTILINE);
splitter->SplitHorizontally(m_panel, m_logWindow);
splitter->SetMinimumPaneSize(20);
wxLog::SetActiveTarget(new wxLogTextCtrl(m_logWindow));
}
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox("wxCalendarCtrl sample\n(c) 2000--2008 Vadim Zeitlin",
"About Calendar", wxOK | wxICON_INFORMATION, this);
}
void MyFrame::OnClearLog(wxCommandEvent& WXUNUSED(event))
{
m_logWindow->Clear();
}
void MyFrame::OnCalAutoWeekday(wxCommandEvent&)
{
m_panel->ToggleCalStyle(false, wxCAL_SUNDAY_FIRST);
m_panel->ToggleCalStyle(false, wxCAL_MONDAY_FIRST);
}
void MyFrame::OnCalSunday(wxCommandEvent& event)
{
m_panel->ToggleCalStyle(false, wxCAL_MONDAY_FIRST);
m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_SUNDAY_FIRST);
}
void MyFrame::OnCalMonday(wxCommandEvent& event)
{
m_panel->ToggleCalStyle(false, wxCAL_SUNDAY_FIRST);
m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_MONDAY_FIRST);
}
void MyFrame::OnCalHolidays(wxCommandEvent& event)
{
m_panel->GetCal()->EnableHolidayDisplay(event.IsChecked());
}
void MyFrame::OnCalSpecial(wxCommandEvent& event)
{
m_panel->HighlightSpecial(GetMenuBar()->IsChecked(event.GetId()));
}
void MyFrame::OnCalLimitDates(wxCommandEvent& event)
{
m_panel->LimitDateRange(GetMenuBar()->IsChecked(event.GetId()));
}
void MyFrame::OnCalAllowMonth(wxCommandEvent& event)
{
m_panel->GetCal()->EnableMonthChange(event.IsChecked());
}
void MyFrame::OnCalSeqMonth(wxCommandEvent& event)
{
m_panel->ToggleCalStyle(event.IsChecked(),
wxCAL_SEQUENTIAL_MONTH_SELECTION);
}
void MyFrame::OnCalShowSurroundingWeeks(wxCommandEvent& event)
{
m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_SHOW_SURROUNDING_WEEKS);
}
void MyFrame::OnCalShowWeekNumbers(wxCommandEvent& event)
{
m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_SHOW_WEEK_NUMBERS);
}
void MyFrame::OnSetDate(wxCommandEvent &WXUNUSED(event))
{
m_panel->SetDate(wxDateTime(24, wxDateTime::Dec, 2005, 22, 00, 00));
}
void MyFrame::OnToday(wxCommandEvent &WXUNUSED(event))
{
m_panel->SetDate(wxDateTime::Today());
}
void MyFrame::OnBeginDST(wxCommandEvent &WXUNUSED(event))
{
m_panel->SetDate(wxDateTime::GetBeginDST(m_panel->GetDate().GetYear()));
}
void MyFrame::OnCalToggleResizable(wxCommandEvent& event)
{
wxSizer * const sizer = m_panel->GetSizer();
wxSizerItem * const item = sizer->GetItem(m_panel->GetCal());
if ( event.IsChecked() )
{
item->SetProportion(1);
item->SetFlag(wxEXPAND);
}
else // not resizable
{
item->SetProportion(0);
item->SetFlag(wxALIGN_CENTER);
}
sizer->Layout();
}
void MyFrame::OnCalRClick(wxMouseEvent& event)
{
wxDateTime dt;
wxDateTime::WeekDay wd;
const wxPoint pt = event.GetPosition();
wxString msg = wxString::Format("Point (%d, %d) is ", pt.x, pt.y);
switch ( m_panel->GetCal()->HitTest(pt, &dt, &wd) )
{
default:
wxFAIL_MSG( "unexpected" );
wxFALLTHROUGH;
case wxCAL_HITTEST_NOWHERE:
msg += "nowhere";
break;
case wxCAL_HITTEST_HEADER:
msg += wxString::Format("over %s", wxDateTime::GetWeekDayName(wd));
break;
case wxCAL_HITTEST_DAY:
msg += wxString::Format("over %s", dt.FormatISODate());
break;
case wxCAL_HITTEST_INCMONTH:
msg += "over next month button";
break;
case wxCAL_HITTEST_DECMONTH:
msg += "over previous month button";
break;
case wxCAL_HITTEST_SURROUNDING_WEEK:
msg += "over a day from another month";
break;
}
wxLogMessage("%s", msg);
}
#if wxUSE_DATEPICKCTRL
void MyFrame::OnUpdateUIStartWithNone(wxUpdateUIEvent& event)
{
// it only makes sense to start with invalid date if we can have no date
event.Enable( GetMenuBar()->IsChecked(Calendar_DatePicker_AllowNone) );
}
void MyFrame::OnAskDate(wxCommandEvent& WXUNUSED(event))
{
wxDateTime dt = m_panel->GetCal()->GetDate();
int style = wxDP_DEFAULT;
if ( GetMenuBar()->IsChecked(Calendar_DatePicker_ShowCentury) )
style |= wxDP_SHOWCENTURY;
if ( GetMenuBar()->IsChecked(Calendar_DatePicker_DropDown) )
style |= wxDP_DROPDOWN;
if ( GetMenuBar()->IsChecked(Calendar_DatePicker_AllowNone) )
{
style |= wxDP_ALLOWNONE;
if ( GetMenuBar()->IsChecked(Calendar_DatePicker_StartWithNone) )
dt = wxDefaultDateTime;
}
MyDateDialog dlg(this, dt, style);
if ( dlg.ShowModal() == wxID_OK )
{
dt = dlg.GetDate();
if ( dt.IsValid() )
{
const wxDateTime today = wxDateTime::Today();
if ( dt.GetDay() == today.GetDay() &&
dt.GetMonth() == today.GetMonth() )
{
wxMessageBox("Happy birthday!", "Calendar Sample");
}
m_panel->SetDate(dt);
wxLogStatus("Changed the date to your input");
}
else
{
wxLogStatus("No date entered");
}
}
}
#endif // wxUSE_DATEPICKCTRL
#if wxUSE_TIMEPICKCTRL
void MyFrame::OnAskTime(wxCommandEvent& WXUNUSED(event))
{
MyTimeDialog dlg(this);
if ( dlg.ShowModal() == wxID_OK )
{
wxLogMessage("You entered %s", dlg.GetTime().FormatISOTime());
}
}
#endif // wxUSE_TIMEPICKCTRL
// ----------------------------------------------------------------------------
// MyPanel
// ----------------------------------------------------------------------------
MyPanel::MyPanel(wxWindow *parent)
: wxPanel(parent, wxID_ANY)
{
#ifdef wxHAS_NATIVE_CALENDARCTRL
m_usingGeneric = false;
#else
m_usingGeneric = true;
#endif
wxString date;
date.Printf("Selected date: %s",
wxDateTime::Today().FormatISODate());
m_date = new wxStaticText(this, wxID_ANY, date);
m_calendar = DoCreateCalendar(wxDefaultDateTime,
wxCAL_SHOW_HOLIDAYS);
// adjust to vertical/horizontal display
bool horizontal = ( wxSystemSettings::GetMetric(wxSYS_SCREEN_X) > wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) );
m_sizer = new wxBoxSizer( horizontal ? wxHORIZONTAL : wxVERTICAL );
m_sizer->Add(m_date, 0, wxALIGN_CENTER | wxALL, 10 );
m_sizer->Add(m_calendar, 0, wxALIGN_CENTER | wxALIGN_LEFT);
SetSizer( m_sizer );
m_sizer->SetSizeHints( this );
}
void MyPanel::OnCalendar(wxCalendarEvent& event)
{
// clicking the same date twice unmarks it (convenient for testing)
static wxDateTime s_dateLast;
const bool mark = !s_dateLast.IsValid() || event.GetDate() != s_dateLast;
s_dateLast = event.GetDate();
m_calendar->Mark(event.GetDate().GetDay(), mark);
wxLogMessage("Selected (and %smarked) %s from calendar.",
mark ? "" : "un", s_dateLast.FormatISODate());
}
void MyPanel::OnCalendarChange(wxCalendarEvent& event)
{
wxString s;
s.Printf("Selected date: %s", event.GetDate().FormatISODate());
m_date->SetLabel(s);
wxLogStatus(s);
}
void MyPanel::OnCalMonthChange(wxCalendarEvent& event)
{
wxLogStatus("Calendar month changed to %s %d",
wxDateTime::GetMonthName(event.GetDate().GetMonth()),
event.GetDate().GetYear());
}
void MyPanel::OnCalendarWeekDayClick(wxCalendarEvent& event)
{
wxLogMessage("Clicked on %s",
wxDateTime::GetWeekDayName(event.GetWeekDay()));
}
void MyPanel::OnCalendarWeekClick(wxCalendarEvent& event)
{
wxLogMessage("Clicked on week %d", event.GetDate().GetWeekOfYear());
}
wxCalendarCtrlBase *MyPanel::DoCreateCalendar(const wxDateTime& dt, long style)
{
wxCalendarCtrlBase *calendar;
#ifdef wxHAS_NATIVE_CALENDARCTRL
if ( m_usingGeneric )
calendar = new wxGenericCalendarCtrl(this, Calendar_CalCtrl,
dt,
wxDefaultPosition,
wxDefaultSize,
style);
else
#endif // wxHAS_NATIVE_CALENDARCTRL
calendar = new wxCalendarCtrl(this, Calendar_CalCtrl,
dt,
wxDefaultPosition,
wxDefaultSize,
style);
calendar->Bind(wxEVT_RIGHT_DOWN,
&MyFrame::OnCalRClick,
( MyFrame * )wxGetTopLevelParent(this));
return calendar;
}
void MyPanel::RecreateCalendar(long style)
{
wxCalendarCtrlBase *calendar = DoCreateCalendar(m_calendar->GetDate(), style);
m_sizer->Replace(m_calendar, calendar);
delete m_calendar;
m_calendar = calendar;
m_sizer->Layout();
}
void MyPanel::ToggleCalStyle(bool on, int flag)
{
long style = m_calendar->GetWindowStyle();
if ( on )
style |= flag;
else
style &= ~flag;
if ( flag == wxCAL_SEQUENTIAL_MONTH_SELECTION
|| flag == wxCAL_SHOW_WEEK_NUMBERS)
{
// changing this style requires recreating the control
RecreateCalendar(style);
}
else // just changing the style is enough
{
m_calendar->SetWindowStyle(style);
m_calendar->Refresh();
}
}
void MyPanel::HighlightSpecial(bool on)
{
if ( on )
{
wxCalendarDateAttr
*attrRedCircle = new wxCalendarDateAttr(wxCAL_BORDER_ROUND, *wxRED),
*attrGreenSquare = new wxCalendarDateAttr(wxCAL_BORDER_SQUARE, *wxGREEN),
*attrHeaderLike = new wxCalendarDateAttr(*wxBLUE, *wxLIGHT_GREY);
m_calendar->SetAttr(17, attrRedCircle);
m_calendar->SetAttr(29, attrGreenSquare);
m_calendar->SetAttr(13, attrHeaderLike);
}
else // off
{
m_calendar->ResetAttr(17);
m_calendar->ResetAttr(29);
m_calendar->ResetAttr(13);
}
m_calendar->Refresh();
}
// Toggle a restricted date range to the six months centered on today's date.
void MyPanel::LimitDateRange(bool on)
{
if ( on )
{
// limit the choice of date to 3 months around today
const wxDateSpan diff = wxDateSpan::Months(3);
const wxDateTime today = wxDateTime::Today();
// Set the restricted date range.
if ( m_calendar->SetDateRange(today - diff, today + diff) )
{
wxLogStatus("Date range limited to 3 months around today.");
wxDateTime firstValidDate;
wxDateTime lastValidDate;
if ( m_calendar->GetDateRange(&firstValidDate, &lastValidDate) )
{
wxLogMessage("First valid date: %s, last valid date: %s",
firstValidDate.FormatISODate(),
lastValidDate.FormatISODate());
}
else
{
wxLogWarning("Failed to get back the valid dates range.");
}
}
else
{
wxLogWarning("Date range not supported.");
}
}
else // off
{
// Remove the date restrictions.
if ( m_calendar->SetDateRange() )
{
wxLogStatus("Date choice is unlimited now.");
}
else
{
wxLogWarning("Date range not supported.");
}
}
m_calendar->Refresh();
}
// ----------------------------------------------------------------------------
// MyDateDialog
// ----------------------------------------------------------------------------
#if wxUSE_DATEPICKCTRL
wxBEGIN_EVENT_TABLE(MyDateDialog, wxDialog)
EVT_DATE_CHANGED(wxID_ANY, MyDateDialog::OnDateChange)
wxEND_EVENT_TABLE()
MyDateDialog::MyDateDialog(wxWindow *parent, const wxDateTime& dt, int dtpStyle)
: wxDialog(parent, wxID_ANY, wxString("Calendar: Choose a date"))
{
wxWindow* datePickerWindow = NULL;
#if wxUSE_DATEPICKCTRL_GENERIC
m_datePickerGeneric = NULL;
m_datePicker = NULL;
wxFrame *frame = (wxFrame *)wxGetTopLevelParent(parent);
if ( frame && frame->GetMenuBar()->IsChecked(Calendar_DatePicker_Generic) )
{
m_datePickerGeneric = new wxDatePickerCtrlGeneric(this, wxID_ANY, dt,
wxDefaultPosition,
wxDefaultSize,
dtpStyle);
m_datePickerGeneric->SetRange(wxDateTime(1, wxDateTime::Jan, 1900),
wxDefaultDateTime);
datePickerWindow = m_datePickerGeneric;
}
else
#endif // wxUSE_DATEPICKCTRL_GENERIC
{
m_datePicker = new wxDatePickerCtrl(this, wxID_ANY, dt,
wxDefaultPosition, wxDefaultSize,
dtpStyle);
m_datePicker->SetRange(wxDateTime(1, wxDateTime::Jan, 1900),
wxDefaultDateTime);
datePickerWindow = m_datePicker;
}
m_dateText = new wxStaticText(this, wxID_ANY,
dt.IsValid() ? dt.FormatISODate()
: wxString());
const wxSizerFlags flags = wxSizerFlags().Centre().Border();
wxFlexGridSizer* const sizerMain = new wxFlexGridSizer(2);
sizerMain->Add(new wxStaticText(this, wxID_ANY, "Enter &date:"), flags);
sizerMain->Add(datePickerWindow, flags);
sizerMain->Add(new wxStaticText(this, wxID_ANY, "Date in ISO format:"),
flags);
sizerMain->Add(m_dateText, flags);
wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
sizerTop->Add(sizerMain, flags);
sizerTop->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), flags);
SetSizerAndFit(sizerTop);
}
void MyDateDialog::OnDateChange(wxDateEvent& event)
{
const wxDateTime dt = event.GetDate();
if ( dt.IsValid() )
m_dateText->SetLabel(dt.FormatISODate());
else
m_dateText->SetLabel(wxEmptyString);
}
#endif // wxUSE_DATEPICKCTRL
// ----------------------------------------------------------------------------
// MyTimeDialog
// ----------------------------------------------------------------------------
#if wxUSE_TIMEPICKCTRL
wxBEGIN_EVENT_TABLE(MyTimeDialog, wxDialog)
EVT_TIME_CHANGED(wxID_ANY, MyTimeDialog::OnTimeChange)
wxEND_EVENT_TABLE()
MyTimeDialog::MyTimeDialog(wxWindow *parent)
: wxDialog(parent, wxID_ANY, wxString("Calendar: Choose time"))
{
wxWindow* timePickerWindow = NULL;
#if wxUSE_TIMEPICKCTRL_GENERIC
m_timePickerGeneric = NULL;
m_timePicker = NULL;
wxFrame *frame = (wxFrame *)wxGetTopLevelParent(parent);
if ( frame && frame->GetMenuBar()->IsChecked(Calendar_TimePicker_Generic) )
{
m_timePickerGeneric = new wxTimePickerCtrlGeneric(this, wxID_ANY);
timePickerWindow = m_timePickerGeneric;
}
else
#endif // wxUSE_TIMEPICKCTRL_GENERIC
m_timePicker = new wxTimePickerCtrl(this, wxID_ANY);
if ( !timePickerWindow )
timePickerWindow = m_timePicker;
m_timeText = new wxStaticText(this, wxID_ANY, GetTime().FormatISOTime());
const wxSizerFlags flags = wxSizerFlags().Centre().Border();
wxFlexGridSizer* const sizerMain = new wxFlexGridSizer(2);
sizerMain->Add(new wxStaticText(this, wxID_ANY, "Enter &time:"), flags);
sizerMain->Add(timePickerWindow, flags);
sizerMain->Add(new wxStaticText(this, wxID_ANY, "Time in ISO format:"),
flags);
sizerMain->Add(m_timeText, flags);
wxSizer* sizerTop = new wxBoxSizer(wxVERTICAL);
sizerTop->Add(sizerMain, flags);
sizerTop->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), flags);
SetSizerAndFit(sizerTop);
}
void MyTimeDialog::OnTimeChange(wxDateEvent& event)
{
m_timeText->SetLabel(event.GetDate().FormatISOTime());
}
#endif // wxUSE_TIMEPICKCTRL