# Copyright (c) 2023 M.J.N. Corino, The Netherlands # # This software is released under the MIT license. # # Some parts are # Copyright 2004-2007, wxRuby development team # released under the MIT-like wxRuby2 license # Adapted for wxRuby3 ### require 'wx' require 'date' module CalendarTest include Wx Calendar_Cal_Monday = 200 Calendar_Cal_Holidays = 201 Calendar_Cal_Special = 202 Calendar_Cal_Month = 203 Calendar_Cal_Year = 204 Calendar_Cal_SeqMonth = 205 Calendar_Cal_SurroundWeeks = 206 Calendar_DatePicker_AskDate = 300 Calendar_DatePicker_ShowCentury = 301 Calendar_DatePicker_DropDown = 302 Calendar_DatePicker_AllowNone = 303 Calendar_DatePicker_StartWithNone = 304 class MyCalendar < CalendarCtrl attr_reader :date def initialize(parent, display_frame, initial_date, calendar_flags) super( parent, :date => initial_date, :style => calendar_flags | Wx::RAISED_BORDER) @display = display_frame @date = initial_date @weekday_names = %w|Sun Mon Tue Wed Thu Fri Sat| evt_calendar self, :on_calendar evt_calendar_sel_changed self, :on_calendar_change evt_calendar_weekday_clicked self, :on_calendar_weekday_click evt_right_down :on_hit_test end def on_calendar(event) @display.date = event.date end def on_calendar_change(event) @date = event.date Wx.log_status("Selected date: #{@date.strftime('%A %d %B %Y')}") end def on_calendar_weekday_click(event) wday = event.week_day Wx.log_status("Clicked on #{@weekday_names[wday]}") end def on_hit_test(event) hit = hit_test(event.position) case hit when Time, DateTime Wx.log_status("Hit-test: date #{hit}") when Fixnum Wx.log_status("Hit-test: weekday header #{hit}") when NilClass Wx.log_status("Hit-test: Nothing") end end end class MyFrame < Frame def initialize(title) super(nil, -1, title) @panel = Wx::Panel.new(self) add_menu_bar add_status_bar @calendar_flags = Wx::CAL_MONDAY_FIRST | Wx::CAL_SHOW_HOLIDAYS @calendar = MyCalendar.new(@panel, self, Wx::DEFAULT_DATE_TIME, @calendar_flags) @sizer = Wx::BoxSizer.new(Wx::VERTICAL) configure_window evt_menu Wx::ID_EXIT, :on_quit evt_menu Wx::ID_ABOUT, :on_about evt_menu Calendar_DatePicker_AskDate, :on_ask_date evt_update_ui Calendar_DatePicker_StartWithNone, :on_update_ui_start_with_none evt_menu Calendar_Cal_Monday, :on_cal_monday evt_menu Calendar_Cal_Holidays, :on_cal_holidays evt_menu Calendar_Cal_Special, :on_cal_special evt_menu Calendar_Cal_Month, :on_cal_allow_month evt_menu Calendar_Cal_Year, :on_cal_allow_year if Wx::PLATFORM == 'WXOSX' evt_menu Calendar_Cal_SeqMonth, :on_cal_seq_month evt_menu Calendar_Cal_SurroundWeeks, :on_cal_show_surrounding_weeks evt_update_ui Calendar_Cal_Year, :on_allow_year_update end def add_menu_bar # create a menu bar menu_file = Wx::Menu.new menu_file.append(Wx::ID_ABOUT, "&About...\tCtrl-A", "Show about dialog") menu_file.append_separator menu_file.append(Wx::ID_EXIT, "E&xit\tAlt-X", "Quit self program") menu_cal = Wx::Menu.new menu_cal.append(Calendar_Cal_Monday, "Monday &first weekday\tCtrl-F", "Toggle between Mon and Sun as the first week day", Wx::ITEM_CHECK) menu_cal.append(Calendar_Cal_Holidays, "Show &holidays\tCtrl-H", "Toggle highlighting the holidays", Wx::ITEM_CHECK) menu_cal.append(Calendar_Cal_Special, "Highlight &special dates\tCtrl-S", "Test custom highlighting", Wx::ITEM_CHECK) menu_cal.append(Calendar_Cal_SurroundWeeks, "Show s&urrounding weeks\tCtrl-W", "Show the neighbouring weeks in the prev/next month", Wx::ITEM_CHECK) menu_cal.append_separator menu_cal.append(Calendar_Cal_SeqMonth, "To&ggle month selector style\tCtrl-G", "Use another style for the calendar controls", Wx::ITEM_CHECK) menu_cal.append(Calendar_Cal_Month, "&Month can be changed\tCtrl-M", "Allow changing the month in the calendar", Wx::ITEM_CHECK) menu_cal.append(Calendar_Cal_Year, "&Year can be changed\tCtrl-Y", "Allow changing the year in the calendar", Wx::ITEM_CHECK) if Wx::PLATFORM == 'WXOSX' menu_date = Wx::Menu.new menu_date.append_check_item(Calendar_DatePicker_ShowCentury, "Al&ways show century") menu_date.append_check_item(Calendar_DatePicker_DropDown, "Use &drop down control") menu_date.append_check_item(Calendar_DatePicker_AllowNone, "Allow &no date") menu_date.append_check_item(Calendar_DatePicker_StartWithNone, "Start &with no date") menu_date.append_separator menu_date.append(Calendar_DatePicker_AskDate, "&Choose date...\tCtrl-D", "Show dialog with DatePickerCtrl") # now append the freshly created menu to the menu bar... menu_bar = Wx::MenuBar.new menu_bar.append(menu_file, "&File") menu_bar.append(menu_cal, "&Calendar") menu_bar.append(menu_date, "&Date picker") menu_bar.check(Calendar_Cal_Monday, true) menu_bar.check(Calendar_Cal_Holidays, true) menu_bar.check(Calendar_Cal_Month, true) menu_bar.check(Calendar_Cal_Year, true) if Wx::PLATFORM == 'WXOSX' menu_bar.check(Calendar_DatePicker_ShowCentury, true) # ... and attach self menu bar to the frame self.menu_bar = menu_bar end def add_status_bar # create a status bar just for fun (by default with 1 pane only) create_status_bar set_status_text("Welcome to Windows!") end def configure_window @sizer.add(@calendar, 0, Wx::ALIGN_CENTRE|Wx::ALL, 5) @sizer.size_hints = @panel layout @panel.sizer = @sizer end def on_quit # true is to force the frame to close close(true) end def on_about Wx.message_box("wxRuby CalendarCtrl sample\nby Kevin Smith\n" + "based on the wxWidgets version by Vadim Zeitlin", "About Calendar", Wx::OK | Wx::ICON_INFORMATION, self) end def on_cal_monday(event) enable = get_menu_bar.is_checked(event.get_id) toggle_cal_style(enable, CAL_MONDAY_FIRST) end def on_cal_holidays(event) enable = get_menu_bar.is_checked(event.get_id) @calendar.enable_holiday_display(enable) end def on_cal_special(event) highlight_special(get_menu_bar.is_checked(event.get_id)) end def on_cal_allow_month(event) allow = get_menu_bar.is_checked(event.get_id) @calendar.enable_month_change(allow) end def on_cal_allow_year(event) allow = get_menu_bar.is_checked(event.get_id) @calendar.enable_year_change(allow) end def on_cal_seq_month(event) allow = get_menu_bar.is_checked(event.get_id) toggle_cal_style(allow, Wx::CAL_SEQUENTIAL_MONTH_SELECTION) end def on_cal_show_surrounding_weeks(event) allow = get_menu_bar.is_checked(event.get_id) toggle_cal_style(allow, Wx::CAL_SHOW_SURROUNDING_WEEKS) end def on_allow_year_update(event) event.enable( get_menu_bar.is_checked(Calendar_Cal_Month)) end def on_update_ui_start_with_none(event) event.enable( get_menu_bar.is_checked(Calendar_DatePicker_AllowNone)) end def on_ask_date(_event) dt = @calendar.get_date style = Wx::DP_DEFAULT style |= Wx::DP_SHOWCENTURY if get_menu_bar.is_checked(Calendar_DatePicker_ShowCentury) style |= Wx::DP_DROPDOWN if get_menu_bar.is_checked(Calendar_DatePicker_DropDown) if get_menu_bar.is_checked(Calendar_DatePicker_AllowNone) style |= Wx::DP_ALLOWNONE dt = nil if get_menu_bar.is_checked(Calendar_DatePicker_StartWithNone) end CalendarTest.MyDialog(self, dt, style) do |dlg| if dlg.show_modal == Wx::ID_OK if (dt = dlg.get_date) today = Time.now if dt.day == today.day && dt.month == today.month Wx.message_box("Happy birthday", "Calendar Sample") end @calendar.set_date(dt) Wx.log_status("Changed the date to your input") else Wx.log_status("No date entered") end end end end def toggle_cal_style(on,flag) style = @calendar.get_window_style_flag date = @calendar.date @sizer.detach(@calendar) @calendar.destroy if on style |= flag else style &= ~flag end @calendar = MyCalendar.new(@panel, self, date, style) @sizer.add(@calendar, 0, Wx::ALIGN_CENTRE|Wx::ALL, 5) @panel.layout end def highlight_special(on) if on attr_red_circle = Wx::CalendarDateAttr.new(Wx::CAL_BORDER_ROUND, Wx::RED) attr_green_square = Wx::CalendarDateAttr.new(Wx::CAL_BORDER_SQUARE, Wx::GREEN) # This wraps correctly, but causes problems because the colour is freed # when the attribute is reset. # # attr_header_like = CalendarDateAttr.new(BLUE, LIGHT_GREY) @calendar.set_attr(17, attr_red_circle) @calendar.set_attr(29, attr_green_square) # @calendar.set_attr(13, attr_header_like) else @calendar.reset_attr(17) @calendar.reset_attr(29) # @calendar.reset_attr(13) end @calendar.refresh end def set_date(d) str = "%s-%s-%s" % [ d.year, d.mon, d.day ] Wx.MessageDialog( self, "The selected date is #{str}", "Date chosen" ) { |dlg| dlg.show_modal } end alias :date= :set_date end class MyDialog < Dialog def initialize(parent, dt, picker_style) super(parent, :style => Wx::DEFAULT_DIALOG_STYLE|Wx::RESIZE_BORDER) sizer_buttons = Wx::StdDialogButtonSizer.new sizer_buttons.add_button(Wx::Button.new(self, Wx::ID_OK)) sizer_buttons.add_button(Wx::Button.new(self, Wx::ID_CANCEL)) sizer_buttons.realize sizer_text = Wx::BoxSizer.new(Wx::HORIZONTAL) sizer_text.add(Wx::StaticText.new(self, Wx::ID_ANY, "Date in ISO format:"), 0, Wx::ALL|Wx::ALIGN_CENTRE_VERTICAL, 10) @text = Wx::TextCtrl.new(self) sizer_text.add(@text, 1, Wx::ALL|Wx::ALIGN_CENTRE_VERTICAL, 10) sizer_top = Wx::BoxSizer.new(Wx::VERTICAL) sizer_top.add(Wx::StaticText.new(self, Wx::ID_ANY, "Enter your birthday date (not before 20th century):"), 0, Wx::ALL, 10) @picker = Wx::DatePickerCtrl.new(self, Wx::ID_ANY, dt, Wx::DEFAULT_POSITION, Wx::DEFAULT_SIZE, picker_style) @picker.set_range(DateTime.new(1900, 1, 1), nil) sizer_top.add(@picker, 0, Wx::ALL|Wx::EXPAND, 10) sizer_top.add_stretch_spacer(1) sizer_top.add(sizer_text, 0, Wx::EXPAND) sizer_top.add(sizer_buttons, 0, Wx::ALL|Wx::ALIGN_CENTER, 10) set_sizer_and_fit(sizer_top) layout evt_date_changed(@picker, :on_date_changed) end def get_date @picker.get_value end def on_date_changed(event) if (dt = event.get_date) @text.set_value(dt.to_s) else @text.set_value("") end end end end module CalendarSample include WxRuby::Sample if defined? WxRuby::Sample def self.describe { file: __FILE__, summary: 'wxRuby Calendar example.', description: 'wxRuby example demonstrating the Wx::CalendarCtrl and Wx::DatePickerCtrl.' } end def self.run execute(__FILE__) end if $0 == __FILE__ Wx::App.run { CalendarTest::MyFrame.new("Calendar Windows sample").show(true) } end end