/* Copyright (C) 2020 - 2024, Thornwave Labs Inc * Written by Razvan Turiac <razvan.turiac@thornwave.com> * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated * documentation files (the “Software”), to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * Attribution shall be given to Thornwave Labs Inc. and shall be made visible to the final user. * * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include <gui_timers_dialog.h> GuiTimersDialog::GuiTimersDialog(wxWindow *parent, const std::vector<PowermonSchedule> &schedules): wxDialog(parent, wxID_ANY, wxT("Powermon Timers"), wxDefaultPosition, wxDefaultSize), mSchedules(schedules) { const size_t BORDER_SIZE = FromDIP(6); mTimerListBox = new wxListBox(this, ID_LISTBOX_TIMER_LIST, wxDefaultPosition, FromDIP(wxSize(240, 370)), 0, nullptr, wxLB_SINGLE | wxLB_NEEDED_SB); mAddButton = new wxButton(this, ID_BUTTON_ADD, wxT("Add New Timer"), wxDefaultPosition, FromDIP(wxSize(120, 40))); mDeleteButton = new wxButton(this, ID_BUTTON_DELETE, wxT("Delete Timer"), wxDefaultPosition, FromDIP(wxSize(120, 40))); mSaveButton = new wxButton(this, ID_BUTTON_SAVE, wxT("Save Timers"), wxDefaultPosition, FromDIP(wxSize(120, 40))); mCancelButton = new wxButton(this, ID_BUTTON_CANCEL, wxT("Cancel"), wxDefaultPosition, FromDIP(wxSize(120, 40))); mTimerNameText = new wxTextCtrl(this, ID_TEXT_TIMER_NAME, wxT(""), wxDefaultPosition, FromDIP(wxSize(180, 30))); mTimerNameText->SetMaxLength(MAX_TIMER_NAME_LENGTH); mStartCheckBox = new wxCheckBox(this, ID_CHECKBOX_START, wxT("Enable start time"), wxDefaultPosition, wxDefaultSize); mStartHourChoice = new wxChoice(this, ID_CHOICE_TIMER_VALUE, wxDefaultPosition, FromDIP(wxSize(90, 30))); mStartHourChoice->Append(wxT("12 AM")); mStartHourChoice->Append(wxT("1 AM")); mStartHourChoice->Append(wxT("2 AM")); mStartHourChoice->Append(wxT("3 AM")); mStartHourChoice->Append(wxT("4 AM")); mStartHourChoice->Append(wxT("5 AM")); mStartHourChoice->Append(wxT("6 AM")); mStartHourChoice->Append(wxT("7 AM")); mStartHourChoice->Append(wxT("8 AM")); mStartHourChoice->Append(wxT("9 AM")); mStartHourChoice->Append(wxT("10 AM")); mStartHourChoice->Append(wxT("11 AM")); mStartHourChoice->Append(wxT("12 PM")); mStartHourChoice->Append(wxT("1 PM")); mStartHourChoice->Append(wxT("2 PM")); mStartHourChoice->Append(wxT("3 PM")); mStartHourChoice->Append(wxT("4 PM")); mStartHourChoice->Append(wxT("5 PM")); mStartHourChoice->Append(wxT("6 PM")); mStartHourChoice->Append(wxT("7 PM")); mStartHourChoice->Append(wxT("8 PM")); mStartHourChoice->Append(wxT("9 PM")); mStartHourChoice->Append(wxT("10 PM")); mStartHourChoice->Append(wxT("11 PM")); mEndCheckBox = new wxCheckBox(this, ID_CHECKBOX_END, wxT("Enable start time"), wxDefaultPosition, wxDefaultSize); mEndHourChoice = new wxChoice(this, ID_CHOICE_TIMER_VALUE, wxDefaultPosition, FromDIP(wxSize(90, 30))); mEndHourChoice->Append(wxT("12 AM")); mEndHourChoice->Append(wxT("1 AM")); mEndHourChoice->Append(wxT("2 AM")); mEndHourChoice->Append(wxT("3 AM")); mEndHourChoice->Append(wxT("4 AM")); mEndHourChoice->Append(wxT("5 AM")); mEndHourChoice->Append(wxT("6 AM")); mEndHourChoice->Append(wxT("7 AM")); mEndHourChoice->Append(wxT("8 AM")); mEndHourChoice->Append(wxT("9 AM")); mEndHourChoice->Append(wxT("10 AM")); mEndHourChoice->Append(wxT("11 AM")); mEndHourChoice->Append(wxT("12 PM")); mEndHourChoice->Append(wxT("1 PM")); mEndHourChoice->Append(wxT("2 PM")); mEndHourChoice->Append(wxT("3 PM")); mEndHourChoice->Append(wxT("4 PM")); mEndHourChoice->Append(wxT("5 PM")); mEndHourChoice->Append(wxT("6 PM")); mEndHourChoice->Append(wxT("7 PM")); mEndHourChoice->Append(wxT("8 PM")); mEndHourChoice->Append(wxT("9 PM")); mEndHourChoice->Append(wxT("10 PM")); mEndHourChoice->Append(wxT("11 PM")); mStartMinuteChoice = new wxChoice(this, ID_CHOICE_TIMER_VALUE, wxDefaultPosition, FromDIP(wxSize(90, 30))); mEndMinuteChoice = new wxChoice(this, ID_CHOICE_TIMER_VALUE, wxDefaultPosition, FromDIP(wxSize(90, 30))); for(uint32_t i = 0; i < 60; i++) { wxString str; str.Printf(wxT("%u"), i); mStartMinuteChoice->Append(str); mEndMinuteChoice->Append(str); } mRepeatModeChoice = new wxChoice(this, ID_CHOICE_TIMER_REPEAT_MODE, wxDefaultPosition, FromDIP(wxSize(140, 30))); mRepeatModeChoice->Append(wxT("Day of Week")); mRepeatModeChoice->Append(wxT("Day of Month")); mMondayCheckBox = new wxCheckBox(this, ID_CHOICE_TIMER_VALUE, wxT("Monday"), wxDefaultPosition, wxDefaultSize); mTuesdayCheckBox = new wxCheckBox(this, ID_CHOICE_TIMER_VALUE, wxT("Tuesday"), wxDefaultPosition, wxDefaultSize); mWednesdayCheckBox = new wxCheckBox(this, ID_CHOICE_TIMER_VALUE, wxT("Wednesday"), wxDefaultPosition, wxDefaultSize); mThursdayCheckBox = new wxCheckBox(this, ID_CHOICE_TIMER_VALUE, wxT("Thursday"), wxDefaultPosition, wxDefaultSize); mFridayCheckBox = new wxCheckBox(this, ID_CHOICE_TIMER_VALUE, wxT("Friday"), wxDefaultPosition, wxDefaultSize); mSaturdayCheckBox = new wxCheckBox(this, ID_CHOICE_TIMER_VALUE, wxT("Saturday"), wxDefaultPosition, wxDefaultSize); mSundayCheckBox = new wxCheckBox(this, ID_CHOICE_TIMER_VALUE, wxT("Sunday"), wxDefaultPosition, wxDefaultSize); mDayOfMonthChoice = new wxChoice(this, ID_CHOICE_TIMER_VALUE, wxDefaultPosition, FromDIP(wxSize(100, 30))); for(uint32_t i = 1; i < 32; i++) { wxString str; str.Printf(wxT("%u"), i); mDayOfMonthChoice->Append(str); } //main window sizer wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); SetSizer(main_sizer); wxBoxSizer *main_h_sizer, *main_v_sizer; wxBoxSizer *h_sizer, *v_sizer; main_h_sizer = new wxBoxSizer(wxHORIZONTAL); //timer list main_v_sizer = new wxBoxSizer(wxVERTICAL); main_v_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Timer List")), 0, wxALIGN_LEFT, BORDER_SIZE); main_v_sizer->Add(mTimerListBox, 1, wxEXPAND | wxALL, 0); main_h_sizer->Add(main_v_sizer, 1, wxEXPAND | wxALL, 10); main_v_sizer = new wxBoxSizer(wxVERTICAL); //start of a row main_v_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Timer Name")), 0, wxBOTTOM, BORDER_SIZE); main_v_sizer->Add(mTimerNameText, 0, wxALL, 0); main_v_sizer->AddSpacer(FromDIP(20)); //start of a row main_v_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Start Time")), 0, wxBOTTOM, BORDER_SIZE); main_v_sizer->Add(mStartCheckBox, 0, wxBOTTOM, BORDER_SIZE); h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Hour")), 0, wxALIGN_CENTER, 0); h_sizer->Add(mStartHourChoice, 0, wxALL | wxALIGN_CENTER, 0); h_sizer->AddSpacer(FromDIP(20)); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Minute")), 0, wxALIGN_CENTER, 0); h_sizer->Add(mStartMinuteChoice, 0, wxALL | wxALIGN_CENTER, 0); main_v_sizer->Add(h_sizer, 0, wxALL, 0); main_v_sizer->AddSpacer(FromDIP(20)); //start of a row main_v_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("End Time")), 0, wxBOTTOM, BORDER_SIZE); main_v_sizer->Add(mEndCheckBox, 0, wxBOTTOM, BORDER_SIZE); h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Hour")), 0, wxALIGN_CENTER, 0); h_sizer->Add(mEndHourChoice, 0, wxALL | wxALIGN_CENTER, 0); h_sizer->AddSpacer(20); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Minute")), 0, wxALIGN_CENTER, 0); h_sizer->Add(mEndMinuteChoice, 0, wxALL | wxALIGN_CENTER, 0); main_v_sizer->Add(h_sizer, 0, wxALL, 0); main_v_sizer->AddSpacer(FromDIP(20)); //start of a row h_sizer = new wxBoxSizer(wxHORIZONTAL); v_sizer = new wxBoxSizer(wxVERTICAL); v_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Repeat Mode")), 0, wxBOTTOM, BORDER_SIZE); v_sizer->Add(mRepeatModeChoice, 0, wxALL, 0); h_sizer->Add(v_sizer, 0, wxLEFT | wxRIGHT, 10); h_sizer->AddSpacer(FromDIP(20)); v_sizer = new wxBoxSizer(wxVERTICAL); v_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Day Of Month")), 0, wxBOTTOM, BORDER_SIZE); v_sizer->Add(mDayOfMonthChoice, 0, wxALL, 0); h_sizer->Add(v_sizer, 0, wxLEFT | wxRIGHT, 10); main_v_sizer->Add(h_sizer, 0, wxALL, 0); main_v_sizer->AddSpacer(FromDIP(20)); //start of a row h_sizer = new wxBoxSizer(wxHORIZONTAL); v_sizer = new wxBoxSizer(wxVERTICAL); v_sizer->Add(mMondayCheckBox, 0, wxALL, FromDIP(2)); v_sizer->Add(mTuesdayCheckBox, 0, wxALL, FromDIP(2)); v_sizer->Add(mWednesdayCheckBox, 0, wxALL, FromDIP(2)); v_sizer->Add(mThursdayCheckBox, 0, wxALL, FromDIP(2)); h_sizer->Add(v_sizer, 0, wxLEFT | wxRIGHT, BORDER_SIZE); v_sizer = new wxBoxSizer(wxVERTICAL); v_sizer->Add(mFridayCheckBox, 0, wxALL, FromDIP(2)); v_sizer->Add(mSaturdayCheckBox, 0, wxALL, FromDIP(2)); v_sizer->Add(mSundayCheckBox, 0, wxALL, FromDIP(2)); h_sizer->Add(v_sizer, 0, wxLEFT | wxRIGHT, BORDER_SIZE); main_v_sizer->Add(h_sizer, 0, wxEXPAND | wxALIGN_LEFT | wxTOP | wxBOTTOM, BORDER_SIZE); main_h_sizer->Add(main_v_sizer, 0, wxEXPAND | wxALIGN_LEFT | wxALL, BORDER_SIZE); main_sizer->Add(main_h_sizer, 0, wxALL, 0); //start of a row h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(mAddButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, BORDER_SIZE); h_sizer->Add(mDeleteButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, BORDER_SIZE); h_sizer->Add(mCancelButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, BORDER_SIZE); h_sizer->Add(mSaveButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, BORDER_SIZE); main_sizer->Add(h_sizer, 0, wxALL, 0); main_sizer->SetSizeHints(this); Centre(); SetFocus(); for(const auto &s: mSchedules) mTimerListBox->Append(wxString(s.getName(), wxConvUTF8)); listUpdated(); mAddButton->Enable(mTimerListBox->GetCount() < MAX_TIMER_COUNT); mDeleteButton->Enable(mTimerListBox->GetCount() > 0); } void GuiTimersDialog::OnAddButtonClicked(wxCommandEvent &event) { PowermonSchedule schedule; mSchedules.push_back(schedule); mTimerListBox->Append(wxString(schedule.getName(), wxConvUTF8)); mTimerListBox->SetSelection(mTimerListBox->GetCount() - 1); mTimerListBox->Refresh(); mAddButton->Enable(mTimerListBox->GetCount() < MAX_TIMER_COUNT); mDeleteButton->Enable(true); listUpdated(); } void GuiTimersDialog::OnDeleteButtonClicked(wxCommandEvent &event) { const long index = mTimerListBox->GetSelection(); mSchedules.erase(mSchedules.begin() + index); mTimerListBox->Delete(index); mTimerListBox->SetSelection(-1); mTimerListBox->Refresh(); mAddButton->Enable(true); mDeleteButton->Enable(mTimerListBox->GetCount() > 0); listUpdated(); } void GuiTimersDialog::OnSaveButtonClicked(wxCommandEvent &event) { //check for the validity of the schedules bool valid = true; if (mSchedules.size() >= 2) { for(uint32_t i = 0; i < mSchedules.size() - 1; i++) { for(uint32_t j = i + 1; j < mSchedules.size(); j++) { if (mSchedules[i] == mSchedules[j]) { valid = false; break; } if (valid == false) break; } } } if (valid) { EndModal(wxID_OK); } else { wxMessageDialog msg(this, wxT("Duplicate timer"), wxT("Error"), wxOK | wxSTAY_ON_TOP | wxCENTRE | wxICON_ERROR); msg.ShowModal(); } } void GuiTimersDialog::OnTimerNameChanged(wxCommandEvent &event) { if (mTimerNameText->IsModified() == false) return; const long index = mTimerListBox->GetSelection(); if (index >= 0) { PowermonSchedule &s = mSchedules[index]; const wxString name = mTimerNameText->GetValue(); s.setName(name.mb_str()); mTimerListBox->SetString(index, name); } } void GuiTimersDialog::OnCancelButtonClicked(wxCommandEvent &event) { EndModal(wxID_CANCEL); } void GuiTimersDialog::OnTimerListSelected(wxCommandEvent &event) { listUpdated(); } void GuiTimersDialog::listUpdated(void) { const long index = mTimerListBox->GetSelection(); if (index >= 0) { //enable controls mTimerNameText->Enable(true); mStartCheckBox->Enable(true); mEndCheckBox->Enable(true); mRepeatModeChoice->Enable(true); const PowermonSchedule &s = mSchedules[index]; mTimerNameText->SetValue(wxString(s.getName(), wxConvUTF8)); bool enabled = s.getStartHour() < 24; mStartCheckBox->SetValue(enabled); mStartHourChoice->SetSelection(enabled ? s.getStartHour() : -1); mStartMinuteChoice->SetSelection(enabled ? s.getStartMinute() : -1); mStartHourChoice->Enable(enabled); mStartMinuteChoice->Enable(enabled); enabled = s.getEndHour() < 24; mEndCheckBox->SetValue(enabled); mEndHourChoice->SetSelection(enabled ? s.getEndHour() : -1); mEndMinuteChoice->SetSelection(enabled ? s.getEndMinute() : -1); mEndHourChoice->Enable(enabled); mEndMinuteChoice->Enable(enabled); const bool dom = s.isRepeatDOM(); mRepeatModeChoice->SetSelection(dom); mDayOfMonthChoice->Enable(dom); mMondayCheckBox->Enable(!dom); mTuesdayCheckBox->Enable(!dom); mWednesdayCheckBox->Enable(!dom); mThursdayCheckBox->Enable(!dom); mFridayCheckBox->Enable(!dom); mSaturdayCheckBox->Enable(!dom); mSundayCheckBox->Enable(!dom); if (dom) { mDayOfMonthChoice->SetSelection(s.getRepeat() - 1); mMondayCheckBox->SetValue(0); mTuesdayCheckBox->SetValue(0); mWednesdayCheckBox->SetValue(0); mThursdayCheckBox->SetValue(0); mFridayCheckBox->SetValue(0); mSaturdayCheckBox->SetValue(0); mSundayCheckBox->SetValue(0); } else { mDayOfMonthChoice->SetSelection(-1); const uint8_t mask = s.getRepeat(); mMondayCheckBox->SetValue(mask & (1 << 0)); mTuesdayCheckBox->SetValue(mask & (1 << 1)); mWednesdayCheckBox->SetValue(mask & (1 << 2)); mThursdayCheckBox->SetValue(mask & (1 << 3)); mFridayCheckBox->SetValue(mask & (1 << 4)); mSaturdayCheckBox->SetValue(mask & (1 << 5)); mSundayCheckBox->SetValue(mask & (1 << 6)); } } else { mTimerNameText->Enable(false); mStartCheckBox->Enable(false); mEndCheckBox->Enable(false); mStartHourChoice->Enable(false); mStartMinuteChoice->Enable(false); mEndHourChoice->Enable(false); mEndMinuteChoice->Enable(false); mRepeatModeChoice->Enable(false); mMondayCheckBox->Enable(false); mTuesdayCheckBox->Enable(false); mWednesdayCheckBox->Enable(false); mThursdayCheckBox->Enable(false); mFridayCheckBox->Enable(false); mSaturdayCheckBox->Enable(false); mSundayCheckBox->Enable(false); mDayOfMonthChoice->Enable(false); mTimerNameText->SetValue(wxT("")); mStartCheckBox->SetValue(0); mStartHourChoice->SetSelection(-1); mStartMinuteChoice->SetSelection(-1); mEndCheckBox->SetValue(0); mEndHourChoice->SetSelection(-1); mEndMinuteChoice->SetSelection(-1); mRepeatModeChoice->SetSelection(-1); mDayOfMonthChoice->SetSelection(-1); mMondayCheckBox->SetValue(0); mTuesdayCheckBox->SetValue(0); mWednesdayCheckBox->SetValue(0); mThursdayCheckBox->SetValue(0); mFridayCheckBox->SetValue(0); mSaturdayCheckBox->SetValue(0); mSundayCheckBox->SetValue(0); } Refresh(); } void GuiTimersDialog::OnTimerRepeatModeChanged(wxCommandEvent &event) { const long index = mTimerListBox->GetSelection(); if (index >= 0) { const bool dom = mRepeatModeChoice->GetSelection(); mMondayCheckBox->SetValue(!dom); mTuesdayCheckBox->SetValue(!dom); mWednesdayCheckBox->SetValue(!dom); mThursdayCheckBox->SetValue(!dom); mFridayCheckBox->SetValue(!dom); mSaturdayCheckBox->SetValue(!dom); mSundayCheckBox->SetValue(!dom); mDayOfMonthChoice->Enable(dom); mMondayCheckBox->Enable(!dom); mTuesdayCheckBox->Enable(!dom); mWednesdayCheckBox->Enable(!dom); mThursdayCheckBox->Enable(!dom); mFridayCheckBox->Enable(!dom); mSaturdayCheckBox->Enable(!dom); mSundayCheckBox->Enable(!dom); PowermonSchedule &s = mSchedules[index]; if (dom) { mDayOfMonthChoice->SetSelection(0); s.setRepeatDOM(); s.setRepeat(1); } else { mDayOfMonthChoice->SetSelection(-1); s.setRepeatDOW(); s.setRepeat(0); } Refresh(); } } void GuiTimersDialog::OnTimerValueChanged(wxCommandEvent &event) { const long index = mTimerListBox->GetSelection(); if (index >= 0) { PowermonSchedule &s = mSchedules[index]; s.setStartHour(mStartHourChoice->GetSelection()); s.setStartMinute(mStartMinuteChoice->GetSelection()); s.setEndHour(mEndHourChoice->GetSelection()); s.setEndMinute(mEndMinuteChoice->GetSelection()); if (mRepeatModeChoice->GetSelection()) { //day of month mode s.setRepeatDOM(); s.setRepeat(mDayOfMonthChoice->GetSelection() + 1); } else { s.setRepeatDOW(); uint8_t mask = 0; if (mMondayCheckBox->GetValue()) mask |= (1 << 0); if (mTuesdayCheckBox->GetValue()) mask |= (1 << 1); if (mWednesdayCheckBox->GetValue()) mask |= (1 << 2); if (mThursdayCheckBox->GetValue()) mask |= (1 << 3); if (mFridayCheckBox->GetValue()) mask |= (1 << 4); if (mSaturdayCheckBox->GetValue()) mask |= (1 << 5); if (mSundayCheckBox->GetValue()) mask |= (1 << 6); s.setRepeat(mask); } Refresh(); } } void GuiTimersDialog::OnStartTimeCheckValueChanged(wxCommandEvent &event) { const long index = mTimerListBox->GetSelection(); PowermonSchedule &s = mSchedules[index]; const bool enabled = mStartCheckBox->GetValue(); mStartHourChoice->Enable(enabled); mStartMinuteChoice->Enable(enabled); mStartHourChoice->SetSelection(enabled ? 0 : -1); mStartMinuteChoice->SetSelection(enabled ? 0 : -1); s.setStartHour(enabled ? 0 : 24); s.setStartMinute(0); } void GuiTimersDialog::OnEndTimeCheckValueChanged(wxCommandEvent &event) { const long index = mTimerListBox->GetSelection(); PowermonSchedule &s = mSchedules[index]; const bool enabled = mEndCheckBox->GetValue(); mEndHourChoice->Enable(enabled); mEndMinuteChoice->Enable(enabled); mEndHourChoice->SetSelection(enabled ? 0 : -1); mEndMinuteChoice->SetSelection(enabled ? 0 : -1); s.setEndHour(enabled ? 0 : 24); s.setEndMinute(0); } BEGIN_EVENT_TABLE(GuiTimersDialog, wxDialog) EVT_CHECKBOX(ID_CHECKBOX_START, GuiTimersDialog::OnStartTimeCheckValueChanged) EVT_CHECKBOX(ID_CHECKBOX_END, GuiTimersDialog::OnEndTimeCheckValueChanged) EVT_CHECKBOX(ID_CHOICE_TIMER_VALUE, GuiTimersDialog::OnTimerValueChanged) EVT_BUTTON(ID_BUTTON_ADD, GuiTimersDialog::OnAddButtonClicked) EVT_BUTTON(ID_BUTTON_DELETE, GuiTimersDialog::OnDeleteButtonClicked) EVT_BUTTON(ID_BUTTON_SAVE, GuiTimersDialog::OnSaveButtonClicked) EVT_BUTTON(ID_BUTTON_CANCEL, GuiTimersDialog::OnCancelButtonClicked) EVT_CHOICE(ID_CHOICE_TIMER_VALUE, GuiTimersDialog::OnTimerValueChanged) EVT_CHOICE(ID_CHOICE_TIMER_REPEAT_MODE, GuiTimersDialog::OnTimerRepeatModeChanged) EVT_LISTBOX(ID_LISTBOX_TIMER_LIST, GuiTimersDialog::OnTimerListSelected) EVT_TEXT(ID_TEXT_TIMER_NAME, GuiTimersDialog::OnTimerNameChanged) END_EVENT_TABLE()