#!/usr/bin/env ruby
# wxRuby2 Sample Code. Copyright (c) 2004-2006 Kevin B. Smith
# Freely reusable code: see SAMPLES-LICENSE.TXT for details

begin
  require 'wx'
rescue LoadError => no_wx_err
  begin
    require 'rubygems'
    require 'wx'
  rescue LoadError
    raise no_wx_err
  end
end
include Wx

require 'date'


Calendar_File_About = ID_ABOUT
Calendar_File_Quit = ID_EXIT
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


def format_date(d)
    return "#{d.year}-#{d.mon}-#{d.day}"
end

class MyCalendar < CalendarCtrl
    def initialize(parent, display_frame, initial_date, calendar_flags)
        super(parent, -1, 
                    initial_date,
                    DEFAULT_POSITION,
                    DEFAULT_SIZE,
                    calendar_flags | RAISED_BORDER)

        @display = display_frame
        @date = initial_date
        @weekday_names = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']

        id = get_id
    evt_calendar(id) {|event| on_calendar(event)}
    evt_calendar_month(id) {on_cal_month_change}
    evt_calendar_year(id) {on_cal_year_change}
    evt_calendar_sel_changed(id) {|event| on_calendar_change(event)}
    evt_calendar_weekday_clicked(id) {|event| on_calendar_weekday_click(event)}
    end

  def on_calendar(event)
        @date = event.get_date
        @display.set_date(@date)
    end

  def on_calendar_change(event)
        @date = event.get_date
        log_status("Selected date: #{format_date(@date)}")
    end

  def on_cal_month_change
        log_status("Calendar month changed")
    end

  def on_cal_year_change
        log_status("Calendar year changed")
    end

  def on_calendar_weekday_click(event)
        wday = event.get_week_day
        log_status("Clicked on #{@weekday_names[wday]}")
    end
    
    attr_reader :date
end

class MyFrame < Frame
    def initialize(title)
        super(nil, -1, title)
        @panel = Wx::Panel.new(self)
        add_menu_bar
        add_status_bar

        @calendar_flags = CAL_MONDAY_FIRST | CAL_SHOW_HOLIDAYS

        now = DateTime.now
        @calendar = MyCalendar.new(@panel, self, now, @calendar_flags)

        @sizer = BoxSizer.new(VERTICAL)
        configure_window

  	evt_menu(Calendar_File_Quit) {on_quit}
  	evt_menu(Calendar_File_About) {on_about}

  	evt_menu(Calendar_Cal_Monday) {|event| on_cal_monday(event)}
  	evt_menu(Calendar_Cal_Holidays) {|event| on_cal_holidays(event)}
  	evt_menu(Calendar_Cal_Special) {|event| on_cal_special(event)}

  	evt_menu(Calendar_Cal_Month) {|event| on_cal_allow_month(event)}
  	evt_menu(Calendar_Cal_Year) {|event| on_cal_allow_year(event)}

  	evt_menu(Calendar_Cal_SeqMonth) {|event| on_cal_seq_month(event)}
  	evt_menu(Calendar_Cal_SurroundWeeks) {|event| on_cal_show_surrounding_weeks(event)}

  	evt_update_ui(Calendar_Cal_Year) {|event| on_allow_year_update(event)}
    end
    
    def add_menu_bar
        # create a menu bar
    menu_file = Menu.new

    menu_file.append(Calendar_File_About, "&About...\tCtrl-A", "Show about dialog")
    menu_file.append_separator()
    menu_file.append(Calendar_File_Quit, "E&xit\tAlt-X", "Quit self program")

    menu_cal = Menu.new
    menu_cal.append(Calendar_Cal_Monday,
                        "Monday &first weekday\tCtrl-F",
                        "Toggle between Mon and Sun as the first week day",
                        ITEM_CHECK)
    menu_cal.append(Calendar_Cal_Holidays, "Show &holidays\tCtrl-H",
                        "Toggle highlighting the holidays",
                        ITEM_CHECK)
    menu_cal.append(Calendar_Cal_Special, "Highlight &special dates\tCtrl-S",
                        "Test custom highlighting",
                        ITEM_CHECK)
    menu_cal.append(Calendar_Cal_SurroundWeeks,
                        "Show s&urrounding weeks\tCtrl-W",
                        "Show the neighbouring weeks in the prev/next month",
                        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",
                        ITEM_CHECK)
    menu_cal.append(Calendar_Cal_Month, "&Month can be changed\tCtrl-M",
                        "Allow changing the month in the calendar",
                        ITEM_CHECK)
    menu_cal.append(Calendar_Cal_Year, "&Year can be changed\tCtrl-Y",
                        "Allow changing the year in the calendar",
                        ITEM_CHECK)

        # now append the freshly created menu to the menu bar...
    menu_bar = MenuBar.new
    menu_bar.append(menu_file, "&File")
    menu_bar.append(menu_cal, "&Calendar")

    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)

        # ... and attach self menu bar to the frame
    set_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.set_size_hints(@panel)
        layout
        @panel.set_sizer(@sizer)
    end
    
  def on_quit
    # true is to force the frame to close
    close(true)
    end

  def on_about
        message_box("wxRuby CalendarCtrl sample\nby Kevin Smith\n" +
                 "based on the wxWidgets version by Vadim Zeitlin",
                 "About Calendar", OK | 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, 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, CAL_SHOW_SURROUNDING_WEEKS)
    end

	def on_allow_year_update(event)
        event.enable( get_menu_bar().is_checked(Calendar_Cal_Month))
    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 = CalendarDateAttr.new(CAL_BORDER_ROUND, RED)
      attr_green_square = CalendarDateAttr.new(CAL_BORDER_SQUARE, 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.new( self, "The selected date is #{str}", 
                             "Date chosen" ).show_modal
    end
    
end


class RbApp < App
    def on_init()
  	    frame = MyFrame.new("Calendar Windows sample")
    frame.show(true)
    end
end

a = RbApp.new
a.main_loop()