From b61da88d51007ab98bc4a3a6f2027d22650162f8 Mon Sep 17 00:00:00 2001 From: tao wang Date: Wed, 7 Dec 2022 10:46:15 +0800 Subject: [PATCH] NEW:add fan control Change-Id: I3b5c7cf638306aaac81459c2f25e37008a5a8a2f --- resources/images/fan_control_add.svg | 4 + resources/images/fan_control_decrease.svg | 3 + resources/images/fan_dash_bk.svg | 11 + resources/images/fan_icon.svg | 6 + resources/images/fan_scale_0.svg | 3 + resources/images/fan_scale_1.svg | 3 + resources/images/fan_scale_10.svg | 3 + resources/images/fan_scale_2.svg | 3 + resources/images/fan_scale_3.svg | 3 + resources/images/fan_scale_4.svg | 3 + resources/images/fan_scale_5.svg | 3 + resources/images/fan_scale_6.svg | 3 + resources/images/fan_scale_7.svg | 3 + resources/images/fan_scale_8.svg | 3 + resources/images/fan_scale_9.svg | 3 + src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/DeviceManager.cpp | 18 +- src/slic3r/GUI/DeviceManager.hpp | 2 + src/slic3r/GUI/StatusPanel.cpp | 142 ++++- src/slic3r/GUI/StatusPanel.hpp | 13 +- src/slic3r/GUI/Widgets/FanControl.cpp | 629 +++++++++++++++++++ src/slic3r/GUI/Widgets/FanControl.hpp | 171 +++++ src/slic3r/GUI/Widgets/ImageSwitchButton.cpp | 192 ++++++ src/slic3r/GUI/Widgets/ImageSwitchButton.hpp | 42 ++ 24 files changed, 1240 insertions(+), 28 deletions(-) create mode 100644 resources/images/fan_control_add.svg create mode 100644 resources/images/fan_control_decrease.svg create mode 100644 resources/images/fan_dash_bk.svg create mode 100644 resources/images/fan_icon.svg create mode 100644 resources/images/fan_scale_0.svg create mode 100644 resources/images/fan_scale_1.svg create mode 100644 resources/images/fan_scale_10.svg create mode 100644 resources/images/fan_scale_2.svg create mode 100644 resources/images/fan_scale_3.svg create mode 100644 resources/images/fan_scale_4.svg create mode 100644 resources/images/fan_scale_5.svg create mode 100644 resources/images/fan_scale_6.svg create mode 100644 resources/images/fan_scale_7.svg create mode 100644 resources/images/fan_scale_8.svg create mode 100644 resources/images/fan_scale_9.svg create mode 100644 src/slic3r/GUI/Widgets/FanControl.cpp create mode 100644 src/slic3r/GUI/Widgets/FanControl.hpp diff --git a/resources/images/fan_control_add.svg b/resources/images/fan_control_add.svg new file mode 100644 index 000000000..19d9e41cc --- /dev/null +++ b/resources/images/fan_control_add.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/images/fan_control_decrease.svg b/resources/images/fan_control_decrease.svg new file mode 100644 index 000000000..7a68c36d1 --- /dev/null +++ b/resources/images/fan_control_decrease.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/fan_dash_bk.svg b/resources/images/fan_dash_bk.svg new file mode 100644 index 000000000..47d451080 --- /dev/null +++ b/resources/images/fan_dash_bk.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/resources/images/fan_icon.svg b/resources/images/fan_icon.svg new file mode 100644 index 000000000..67a607195 --- /dev/null +++ b/resources/images/fan_icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/images/fan_scale_0.svg b/resources/images/fan_scale_0.svg new file mode 100644 index 000000000..c8ea0d609 --- /dev/null +++ b/resources/images/fan_scale_0.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/fan_scale_1.svg b/resources/images/fan_scale_1.svg new file mode 100644 index 000000000..42fd9700e --- /dev/null +++ b/resources/images/fan_scale_1.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/fan_scale_10.svg b/resources/images/fan_scale_10.svg new file mode 100644 index 000000000..4fd205258 --- /dev/null +++ b/resources/images/fan_scale_10.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/fan_scale_2.svg b/resources/images/fan_scale_2.svg new file mode 100644 index 000000000..558b253ae --- /dev/null +++ b/resources/images/fan_scale_2.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/fan_scale_3.svg b/resources/images/fan_scale_3.svg new file mode 100644 index 000000000..df944e6fe --- /dev/null +++ b/resources/images/fan_scale_3.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/fan_scale_4.svg b/resources/images/fan_scale_4.svg new file mode 100644 index 000000000..21cdc9d47 --- /dev/null +++ b/resources/images/fan_scale_4.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/fan_scale_5.svg b/resources/images/fan_scale_5.svg new file mode 100644 index 000000000..2aa01a20a --- /dev/null +++ b/resources/images/fan_scale_5.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/fan_scale_6.svg b/resources/images/fan_scale_6.svg new file mode 100644 index 000000000..2ec6641f4 --- /dev/null +++ b/resources/images/fan_scale_6.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/fan_scale_7.svg b/resources/images/fan_scale_7.svg new file mode 100644 index 000000000..8a0d2a147 --- /dev/null +++ b/resources/images/fan_scale_7.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/fan_scale_8.svg b/resources/images/fan_scale_8.svg new file mode 100644 index 000000000..9bc4ffe1a --- /dev/null +++ b/resources/images/fan_scale_8.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/fan_scale_9.svg b/resources/images/fan_scale_9.svg new file mode 100644 index 000000000..9430f66bb --- /dev/null +++ b/resources/images/fan_scale_9.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index ca4871b94..5b129230c 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -56,6 +56,8 @@ set(SLIC3R_GUI_SOURCES GUI/Widgets/TempInput.hpp GUI/Widgets/AMSControl.cpp GUI/Widgets/AMSControl.hpp + GUI/Widgets/FanControl.cpp + GUI/Widgets/FanControl.hpp GUI/Widgets/Scrollbar.cpp GUI/Widgets/Scrollbar.hpp GUI/Widgets/ScrolledWindow.cpp diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index 026803088..c3e7d7c22 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -364,6 +364,7 @@ MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string cooling_fan_speed = 0; big_fan1_speed = 0; big_fan2_speed = 0; + fan_gear = 0; /* printing */ mc_print_stage = 0; @@ -1379,6 +1380,13 @@ int MachineObject::command_control_fan(FanType fan_type, bool on_off) return this->publish_gcode(gcode); } +int MachineObject::command_control_fan_val(FanType fan_type, int val) +{ + std::string gcode = (boost::format("M106 P%1% S%2% \n") % (int)fan_type % (val)).str(); + return this->publish_gcode(gcode); +} + + int MachineObject::command_task_abort() { json j; @@ -2322,7 +2330,13 @@ int MachineObject::parse_json(std::string payload) wifi_signal = jj["wifi_signal"].get(); /* cooling */ - if (jj.contains("cooling_fan_speed")) { + if (jj.contains("fan_gear")) { + fan_gear = jj["fan_gear"].get(); + big_fan2_speed = (int)((fan_gear & 0x00FF0000) >> 16); + big_fan1_speed = (int)((fan_gear & 0x0000FF00) >> 8); + cooling_fan_speed= (int)((fan_gear & 0x000000FF) >> 0); + } + /* if (jj.contains("cooling_fan_speed")) { cooling_fan_speed = stoi(jj["cooling_fan_speed"].get()); } if (jj.contains("big_fan1_speed")) { @@ -2330,7 +2344,7 @@ int MachineObject::parse_json(std::string payload) } if (jj.contains("big_fan2_speed")) { big_fan2_speed = stoi(jj["big_fan2_speed"].get()); - } + }*/ if (jj.contains("heatbreak_fan_speed")) { heatbreak_fan_speed = stoi(jj["heatbreak_fan_speed"].get()); } diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index f931eaf58..2eb3095f8 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -476,6 +476,7 @@ public: int cooling_fan_speed = 0; int big_fan1_speed = 0; int big_fan2_speed = 0; + uint32_t fan_gear = 0; /* signals */ std::string wifi_signal; @@ -637,6 +638,7 @@ public: int command_auto_leveling(); int command_go_home(); int command_control_fan(FanType fan_type, bool on_off); + int command_control_fan_val(FanType fan_type, int val); int command_task_abort(); int command_task_pause(); int command_task_resume(); diff --git a/src/slic3r/GUI/StatusPanel.cpp b/src/slic3r/GUI/StatusPanel.cpp index abbe25a42..3c6a376fc 100644 --- a/src/slic3r/GUI/StatusPanel.cpp +++ b/src/slic3r/GUI/StatusPanel.cpp @@ -72,6 +72,7 @@ static wxColour TEXT_LIGHT_FONT_COL = wxColour(107, 107, 107); #define TASK_BUTTON_SIZE2 (wxSize(-1, FromDIP(24))) #define Z_BUTTON_SIZE (wxSize(FromDIP(52), FromDIP(52))) #define MISC_BUTTON_SIZE (wxSize(FromDIP(68), FromDIP(55))) +#define MISC_BUTTON_3FAN_SIZE (wxSize(FromDIP(45), FromDIP(55))) #define TEMP_CTRL_MIN_SIZE (wxSize(FromDIP(122), FromDIP(52))) #define AXIS_MIN_SIZE (wxSize(FromDIP(220), FromDIP(220))) #define EXTRUDER_IMAGE_SIZE (wxSize(FromDIP(48), FromDIP(76))) @@ -728,7 +729,7 @@ wxBoxSizer *StatusBasePanel::create_temp_control(wxWindow *parent) line->SetLineColour(STATIC_BOX_LINE_COL); sizer->Add(line, 0, wxEXPAND | wxLEFT | wxRIGHT, 12); - wxBoxSizer *m_misc_ctrl_sizer = create_misc_control(parent); + m_misc_ctrl_sizer = create_misc_control(parent); sizer->Add(m_misc_ctrl_sizer, 0, wxEXPAND, 0); return sizer; @@ -772,31 +773,47 @@ wxBoxSizer *StatusBasePanel::create_misc_control(wxWindow *parent) sizer->Add(line, 0, wxEXPAND | wxLEFT | wxRIGHT, 12); line_sizer = new wxBoxSizer(wxHORIZONTAL); - m_switch_nozzle_fan = new ImageSwitchButton(parent, m_bitmap_fan_on, m_bitmap_fan_off); - m_switch_nozzle_fan->SetMinSize(MISC_BUTTON_SIZE); + m_switch_nozzle_fan = new FanSwitchButton(parent, m_bitmap_fan_on, m_bitmap_fan_off); + m_switch_nozzle_fan->SetMinSize(MISC_BUTTON_3FAN_SIZE); + m_switch_nozzle_fan->SetMaxSize(MISC_BUTTON_3FAN_SIZE); m_switch_nozzle_fan->SetValue(false); - m_switch_nozzle_fan->SetLabels(_L("Part Cooling"), _L("Part Cooling")); + m_switch_nozzle_fan->SetLabels(_L("Part"), _L("Part")); m_switch_nozzle_fan->SetPadding(FromDIP(3)); m_switch_nozzle_fan->SetBorderWidth(FromDIP(2)); m_switch_nozzle_fan->SetFont(::Label::Body_10); m_switch_nozzle_fan->SetTextColor(StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_FAN_TEXT_COL, (int) StateColor::Normal))); - line_sizer->Add(m_switch_nozzle_fan, 1, wxALIGN_CENTER | wxALL, 0); + line = new StaticLine(parent, true); line->SetLineColour(STATIC_BOX_LINE_COL); - line_sizer->Add(line, 0, wxEXPAND | wxTOP | wxBOTTOM, 4); + - m_switch_printing_fan = new ImageSwitchButton(parent, m_bitmap_fan_on, m_bitmap_fan_off); + m_switch_printing_fan = new FanSwitchButton(parent, m_bitmap_fan_on, m_bitmap_fan_off); m_switch_printing_fan->SetValue(false); - m_switch_printing_fan->SetMinSize(MISC_BUTTON_SIZE); + m_switch_printing_fan->SetMinSize(MISC_BUTTON_3FAN_SIZE); + m_switch_printing_fan->SetMaxSize(MISC_BUTTON_3FAN_SIZE); m_switch_printing_fan->SetPadding(FromDIP(3)); m_switch_printing_fan->SetBorderWidth(FromDIP(2)); m_switch_printing_fan->SetFont(::Label::Body_10); - m_switch_printing_fan->SetLabels(_L("Aux Cooling"), _L("Aux Cooling")); + m_switch_printing_fan->SetLabels(_L("Aux"), _L("Aux")); m_switch_printing_fan->SetTextColor( StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_FAN_TEXT_COL, (int) StateColor::Normal))); + m_switch_cham_fan = new FanSwitchButton(parent, m_bitmap_fan_on, m_bitmap_fan_off); + m_switch_cham_fan->SetValue(false); + m_switch_cham_fan->SetMinSize(MISC_BUTTON_3FAN_SIZE); + m_switch_cham_fan->SetMaxSize(MISC_BUTTON_3FAN_SIZE); + m_switch_cham_fan->SetPadding(FromDIP(3)); + m_switch_cham_fan->SetBorderWidth(FromDIP(2)); + m_switch_cham_fan->SetFont(::Label::Body_10); + m_switch_cham_fan->SetLabels(_L("Cham"), _L("Cham")); + m_switch_cham_fan->SetTextColor( + StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int)StateColor::Disabled), std::make_pair(NORMAL_FAN_TEXT_COL, (int)StateColor::Normal))); + + line_sizer->Add(m_switch_nozzle_fan, 1, wxALIGN_CENTER | wxALL, 0); + //line_sizer->Add(line, 0, wxEXPAND | wxTOP | wxBOTTOM, 4); line_sizer->Add(m_switch_printing_fan, 1, wxALIGN_CENTER | wxALL, 0); + line_sizer->Add(m_switch_cham_fan, 1, wxALIGN_CENTER | wxALL, 0); sizer->Add(line_sizer, 0, wxEXPAND, FromDIP(5)); @@ -825,6 +842,7 @@ void StatusBasePanel::reset_temp_misc_control() m_switch_lamp->SetValue(false); m_switch_nozzle_fan->SetValue(false); m_switch_printing_fan->SetValue(false); + m_switch_cham_fan->SetValue(false); } wxBoxSizer *StatusBasePanel::create_axis_control(wxWindow *parent) @@ -1125,6 +1143,7 @@ void StatusPanel::update_camera_state(MachineObject* obj) StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style, const wxString &name) : StatusBasePanel(parent, id, pos, size, style) + , m_fan_control_popup(FanControlPopup(this)) { create_tasklist_info(); update_tasklist_info(); @@ -1148,6 +1167,7 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co m_switch_lamp->SetValue(false); m_switch_printing_fan->SetValue(false); m_switch_nozzle_fan->SetValue(false); + m_switch_cham_fan->SetValue(false); /* set default enable state */ m_button_pause_resume->Enable(false); @@ -1183,7 +1203,8 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co m_tempCtrl_nozzle->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this); m_switch_lamp->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_lamp_switch), NULL, this); m_switch_nozzle_fan->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); // TODO - m_switch_printing_fan->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_printing_fan_switch), NULL, this); + m_switch_printing_fan->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); + m_switch_cham_fan->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); m_bpButton_xy->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_xy), NULL, this); // TODO m_bpButton_z_10->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_up_10), NULL, this); m_bpButton_z_1->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_up_1), NULL, this); @@ -1200,6 +1221,8 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co Bind(EVT_AMS_ON_FILAMENT_EDIT, &StatusPanel::on_filament_edit, this); Bind(EVT_AMS_GUIDE_WIKI, &StatusPanel::on_ams_guide, this); Bind(EVT_AMS_RETRY, &StatusPanel::on_ams_retry, this); + Bind(EVT_FAN_CHANGED, &StatusPanel::on_fan_changed, this); + m_switch_speed->Connect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_switch_speed), NULL, this); m_calibration_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_calibration), NULL, this); @@ -1222,7 +1245,8 @@ StatusPanel::~StatusPanel() m_tempCtrl_nozzle->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this); m_switch_lamp->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_lamp_switch), NULL, this); m_switch_nozzle_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); - m_switch_printing_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_printing_fan_switch), NULL, this); + m_switch_printing_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); + m_switch_cham_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); m_bpButton_xy->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_xy), NULL, this); m_bpButton_z_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_up_10), NULL, this); m_bpButton_z_1->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_up_1), NULL, this); @@ -1421,7 +1445,6 @@ void StatusPanel::update(MachineObject *obj) else show_printing_status(); - update_temp_ctrl(obj); update_misc_ctrl(obj); @@ -1588,6 +1611,7 @@ void StatusPanel::show_printing_status(bool ctrl_area, bool temp_area) m_switch_lamp->Enable(); m_switch_nozzle_fan->Enable(); m_switch_printing_fan->Enable(); + m_switch_cham_fan->Enable(); m_bpButton_xy->Enable(); m_text_tasklist_caption->SetForegroundColour(GROUP_TITLE_FONT_COL); m_bpButton_z_10->Enable(); @@ -1619,6 +1643,7 @@ void StatusPanel::show_printing_status(bool ctrl_area, bool temp_area) m_switch_lamp->Enable(false); m_switch_nozzle_fan->Enable(false); m_switch_printing_fan->Enable(false); + m_switch_cham_fan->Enable(false); } else { m_tempCtrl_nozzle->Enable(); m_tempCtrl_bed->Enable(); @@ -1628,6 +1653,7 @@ void StatusPanel::show_printing_status(bool ctrl_area, bool temp_area) m_switch_lamp->Enable(); m_switch_nozzle_fan->Enable(); m_switch_printing_fan->Enable(); + m_switch_cham_fan->Enable(); } } @@ -1688,17 +1714,51 @@ void StatusPanel::update_misc_ctrl(MachineObject *obj) // update extruder icon update_extruder_status(obj); + bool is_suppt_cham_fun = obj->is_function_supported(PrinterFunction::FUNC_CHAMBER_FAN); + //update cham fan + if (m_current_support_cham_fan != is_suppt_cham_fun) { + if (is_suppt_cham_fun) { + m_switch_cham_fan->Show(); + m_switch_nozzle_fan->SetMaxSize(MISC_BUTTON_3FAN_SIZE); + m_switch_printing_fan->SetMaxSize(MISC_BUTTON_3FAN_SIZE); + } + else { + m_switch_cham_fan->Hide(); + m_switch_nozzle_fan->SetMaxSize(MISC_BUTTON_SIZE); + m_switch_printing_fan->SetMaxSize(MISC_BUTTON_SIZE); + } + m_misc_ctrl_sizer->Layout(); + } + // nozzle fan - if (m_switch_nozzle_fan_timeout > 0) + if (m_switch_nozzle_fan_timeout > 0) { m_switch_nozzle_fan_timeout--; - else - m_switch_nozzle_fan->SetValue(obj->cooling_fan_speed > 0); + } else{ + int speed = floor(obj->cooling_fan_speed / float(25.5)); + m_switch_nozzle_fan->SetValue(speed > 0 ? true : false); + m_switch_nozzle_fan->setFanValue(speed * 10); + m_fan_control_popup.update_fan_data(MachineObject::FanType::COOLING_FAN, obj); + } // printing fan - if (m_switch_printing_fan_timeout > 0) + if (m_switch_printing_fan_timeout > 0) { m_switch_printing_fan_timeout--; - else - m_switch_printing_fan->SetValue(obj->big_fan1_speed > 0); + }else{ + int speed = floor(obj->big_fan1_speed / float(25.5)); + m_switch_printing_fan->SetValue(speed > 0 ? true : false); + m_switch_printing_fan->setFanValue(speed * 10); + m_fan_control_popup.update_fan_data(MachineObject::FanType::BIG_COOLING_FAN, obj); + } + + // cham fan + if (m_switch_cham_fan_timeout > 0) { + m_switch_cham_fan_timeout--; + }else{ + int speed = floor(obj->big_fan2_speed / float(25.5)); + m_switch_cham_fan->SetValue(speed > 0 ? true : false); + m_switch_cham_fan->setFanValue(speed * 10); + m_fan_control_popup.update_fan_data(MachineObject::FanType::CHAMBER_FAN, obj); + } bool light_on = obj->chamber_light != MachineObject::LIGHT_EFFECT::LIGHT_EFFECT_OFF; BOOST_LOG_TRIVIAL(trace) << "light: " << light_on ? "on" : "off"; @@ -1718,6 +1778,8 @@ void StatusPanel::update_misc_ctrl(MachineObject *obj) wxString text_speed = wxString::Format("%d%%", obj->printing_speed_mag); m_switch_speed->SetLabels(text_speed, text_speed); } + + m_current_support_cham_fan = is_suppt_cham_fun?true:false; } void StatusPanel::update_extruder_status(MachineObject* obj) @@ -2510,6 +2572,28 @@ void StatusPanel::on_ams_retry(wxCommandEvent& event) } } +void StatusPanel::on_fan_changed(wxCommandEvent& event) +{ + auto type = event.GetInt(); + auto speed = atoi(event.GetString().c_str()); + + if (type == MachineObject::FanType::COOLING_FAN) { + set_hold_count(this->m_switch_nozzle_fan_timeout); + m_switch_nozzle_fan->SetValue(speed > 0 ? true : false); + m_switch_nozzle_fan->setFanValue(speed * 10); + } + else if (type == MachineObject::FanType::BIG_COOLING_FAN) { + set_hold_count(this->m_switch_printing_fan_timeout); + m_switch_printing_fan->SetValue(speed > 0 ? true : false); + m_switch_printing_fan->setFanValue(speed * 10); + } + else if (type == MachineObject::FanType::CHAMBER_FAN) { + set_hold_count(this->m_switch_cham_fan_timeout); + m_switch_cham_fan->SetValue(speed > 0 ? true : false); + m_switch_cham_fan->setFanValue(speed * 10); + } +} + void StatusPanel::on_bed_temp_kill_focus(wxFocusEvent &event) { event.Skip(); @@ -2595,7 +2679,7 @@ void StatusPanel::on_switch_speed(wxCommandEvent &event) void StatusPanel::on_printing_fan_switch(wxCommandEvent &event) { - if (!obj) return; + /* if (!obj) return; bool value = m_switch_printing_fan->GetValue(); @@ -2607,12 +2691,19 @@ void StatusPanel::on_printing_fan_switch(wxCommandEvent &event) obj->command_control_fan(MachineObject::FanType::BIG_COOLING_FAN, false); m_switch_printing_fan->SetValue(false); set_hold_count(this->m_switch_printing_fan_timeout); - } + }*/ } void StatusPanel::on_nozzle_fan_switch(wxCommandEvent &event) { - if (!obj) return; + auto pos = m_switch_nozzle_fan->GetScreenPosition(); + pos.y = pos.y + m_switch_nozzle_fan->GetSize().y; + m_fan_control_popup.SetPosition(pos); + m_fan_control_popup.Popup(); + + + + /*if (!obj) return; bool value = m_switch_nozzle_fan->GetValue(); @@ -2624,7 +2715,7 @@ void StatusPanel::on_nozzle_fan_switch(wxCommandEvent &event) obj->command_control_fan(MachineObject::FanType::COOLING_FAN, false); m_switch_nozzle_fan->SetValue(false); set_hold_count(this->m_switch_nozzle_fan_timeout); - } + }*/ } void StatusPanel::on_lamp_switch(wxCommandEvent &event) { @@ -2797,6 +2888,7 @@ void StatusPanel::set_default() m_temp_bed_timeout = 0; m_switch_nozzle_fan_timeout = 0; m_switch_printing_fan_timeout = 0; + m_switch_cham_fan_timeout = 0; m_show_ams_group = false; reset_printing_values(); @@ -2955,7 +3047,11 @@ void StatusPanel::msw_rescale() m_switch_nozzle_fan->Rescale(); m_switch_printing_fan->SetImages(m_bitmap_fan_on, m_bitmap_fan_off); m_switch_printing_fan->SetMinSize(MISC_BUTTON_SIZE); - m_switch_printing_fan->Rescale(); + m_switch_printing_fan->Rescale(); + m_switch_cham_fan->SetImages(m_bitmap_fan_on, m_bitmap_fan_off); + m_switch_cham_fan->SetMinSize(MISC_BUTTON_SIZE); + m_switch_cham_fan->Rescale(); + m_ams_control->msw_rescale(); // m_filament_step->Rescale(); diff --git a/src/slic3r/GUI/StatusPanel.hpp b/src/slic3r/GUI/StatusPanel.hpp index 44ba509d6..35cd3c15a 100644 --- a/src/slic3r/GUI/StatusPanel.hpp +++ b/src/slic3r/GUI/StatusPanel.hpp @@ -28,6 +28,7 @@ #include "Widgets/ProgressBar.hpp" #include "Widgets/ImageSwitchButton.hpp" #include "Widgets/AMSControl.hpp" +#include "Widgets/FanControl.hpp" #include "HMS.hpp" #include "Widgets/ErrorMsgStaticText.hpp" class StepIndicator; @@ -149,16 +150,20 @@ protected: ImageSwitchButton *m_switch_speed; /* TempInput */ + wxBoxSizer * m_misc_ctrl_sizer; TempInput * m_tempCtrl_nozzle; int m_temp_nozzle_timeout {0}; StaticLine * m_line_nozzle; TempInput * m_tempCtrl_bed; int m_temp_bed_timeout {0}; TempInput * m_tempCtrl_frame; - ImageSwitchButton *m_switch_nozzle_fan; + bool m_current_support_cham_fan{true}; + FanSwitchButton *m_switch_nozzle_fan; int m_switch_nozzle_fan_timeout{0}; - ImageSwitchButton *m_switch_printing_fan; + FanSwitchButton *m_switch_printing_fan; int m_switch_printing_fan_timeout{0}; + FanSwitchButton *m_switch_cham_fan; + int m_switch_cham_fan_timeout{0}; float m_fixed_aspect_ratio{1.8}; @@ -267,6 +272,7 @@ protected: SecondaryCheckDialog* abort_dlg = nullptr; SecondaryCheckDialog* ctrl_e_hint_dlg = nullptr; SecondaryCheckDialog* sdcard_hint_dlg = nullptr; + FanControlPopup m_fan_control_popup{nullptr}; wxString m_request_url; bool m_start_loading_thumbnail = false; @@ -333,7 +339,8 @@ protected: void on_ams_guide(wxCommandEvent &event); void on_ams_retry(wxCommandEvent &event); - void on_switch_speed(wxCommandEvent &event); + void on_fan_changed(wxCommandEvent& event); + void on_switch_speed(wxCommandEvent& event); void on_lamp_switch(wxCommandEvent &event); void on_printing_fan_switch(wxCommandEvent &event); void on_nozzle_fan_switch(wxCommandEvent &event); diff --git a/src/slic3r/GUI/Widgets/FanControl.cpp b/src/slic3r/GUI/Widgets/FanControl.cpp new file mode 100644 index 000000000..65a9e2232 --- /dev/null +++ b/src/slic3r/GUI/Widgets/FanControl.cpp @@ -0,0 +1,629 @@ +#include "FanControl.hpp" +#include "Label.hpp" +#include "../BitmapCache.hpp" +#include "../I18N.hpp" + +#include +#include + +namespace Slic3r { namespace GUI { + +wxDEFINE_EVENT(EVT_FAN_SWITCH_ON, wxCommandEvent); +wxDEFINE_EVENT(EVT_FAN_SWITCH_OFF, wxCommandEvent); +wxDEFINE_EVENT(EVT_FAN_ADD, wxCommandEvent); +wxDEFINE_EVENT(EVT_FAN_DEC, wxCommandEvent); +wxDEFINE_EVENT(EVT_FAN_CHANGED, wxCommandEvent); + +/************************************************* +Description:Fan +**************************************************/ +Fan::Fan(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size) +{ + create(parent, id, pos, size); +} + +void Fan::create(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size) +{ + m_current_speeds = 0; + + wxWindow::Create(parent, id, pos, size, wxBORDER_NONE); + SetBackgroundColour(*wxWHITE); + + m_rotate_offsets.push_back(RotateOffSet{ 2.5, wxPoint(-FromDIP(16), FromDIP(11)) }); + m_rotate_offsets.push_back(RotateOffSet{ 2.2, wxPoint(-FromDIP(20), FromDIP(11)) }); + m_rotate_offsets.push_back(RotateOffSet{ 1.7, wxPoint(-FromDIP(24), FromDIP(12)) }); + m_rotate_offsets.push_back(RotateOffSet{ 1.2, wxPoint(-FromDIP(22), FromDIP(4)) }); + m_rotate_offsets.push_back(RotateOffSet{ 0.7, wxPoint(-FromDIP(17), -FromDIP(6)) }); + m_rotate_offsets.push_back(RotateOffSet{ 0.3, wxPoint(-FromDIP(8), -FromDIP(11)) }); + m_rotate_offsets.push_back(RotateOffSet{ 6.1, wxPoint(-FromDIP(0), -FromDIP(9)) }); + m_rotate_offsets.push_back(RotateOffSet{ 5.5, wxPoint(-FromDIP(4), -FromDIP(2)) }); + m_rotate_offsets.push_back(RotateOffSet{ 5.1, wxPoint(-FromDIP(3), FromDIP(5)) }); + m_rotate_offsets.push_back(RotateOffSet{ 4.6, wxPoint(-FromDIP(3), FromDIP(14)) }); + m_rotate_offsets.push_back(RotateOffSet{ 4.0, wxPoint(-FromDIP(2), FromDIP(11)) }); + + //auto m_bitmap_pointer = ScalableBitmap(this, "fan_pointer", FromDIP(25)); + //m_img_pointer = m_bitmap_pointer.bmp().ConvertToImage(); + + /*m_bitmap_scale_0 = ScalableBitmap(this, "fan_dash_board_level_0", FromDIP(13)); + m_bitmap_scale_1 = ScalableBitmap(this, "fan_dash_board_level_1", FromDIP(13)); + m_bitmap_scale_2 = ScalableBitmap(this, "fan_dash_board_level_2", FromDIP(13)); + m_bitmap_scale_3 = ScalableBitmap(this, "fan_dash_board_level_3", FromDIP(10)); + m_bitmap_scale_4 = ScalableBitmap(this, "fan_dash_board_level_4", FromDIP(5)); + m_bitmap_scale_5 = ScalableBitmap(this, "fan_dash_board_level_5", FromDIP(5)); + m_bitmap_scale_6 = ScalableBitmap(this, "fan_dash_board_level_6", FromDIP(10)); + m_bitmap_scale_7 = ScalableBitmap(this, "fan_dash_board_level_7", FromDIP(13)); + m_bitmap_scale_8 = ScalableBitmap(this, "fan_dash_board_level_8", FromDIP(13)); + m_bitmap_scale_9 = ScalableBitmap(this, "fan_dash_board_level_9", FromDIP(13));*/ + + m_bitmap_bk = ScalableBitmap(this, "fan_dash_bk", FromDIP(80)); + + for (auto i = 0; i <= 10; i++) { + auto a = wxString::Format("fan_scale_%d", i); + auto m_bitmap_scale = ScalableBitmap(this, wxString::Format("fan_scale_%d", i).ToStdString(), FromDIP(46)); + m_bitmap_scales.push_back(m_bitmap_scale); + } + + /* m_bitmap_scale_0 = ScalableBitmap(this, "fan_scale_0", FromDIP(60)); + m_bitmap_scale_1 = ScalableBitmap(this, "fan_scale_1", FromDIP(60)); + m_bitmap_scale_2 = ScalableBitmap(this, "fan_scale_2", FromDIP(60)); + m_bitmap_scale_3 = ScalableBitmap(this, "fan_scale_3", FromDIP(60)); + m_bitmap_scale_4 = ScalableBitmap(this, "fan_scale_4", FromDIP(60)); + m_bitmap_scale_5 = ScalableBitmap(this, "fan_scale_5", FromDIP(60)); + m_bitmap_scale_6 = ScalableBitmap(this, "fan_scale_6", FromDIP(60)); + m_bitmap_scale_7 = ScalableBitmap(this, "fan_scale_7", FromDIP(60)); + m_bitmap_scale_8 = ScalableBitmap(this, "fan_scale_8", FromDIP(60)); + m_bitmap_scale_9 = ScalableBitmap(this, "fan_scale_9", FromDIP(60)); + m_bitmap_scale_10 = ScalableBitmap(this, "fan_scale_10", FromDIP(60));*/ + +#ifdef __APPLE__ + SetMinSize(wxSize(FromDIP(94), FromDIP(81) + FromDIP(6))); + SetMaxSize(wxSize(FromDIP(94), FromDIP(81) + FromDIP(6))); +#else + SetMinSize(wxSize(m_bitmap_bk.GetBmpSize().x, m_bitmap_bk.GetBmpSize().y + FromDIP(6))); + SetMaxSize(wxSize(m_bitmap_bk.GetBmpSize().x, m_bitmap_bk.GetBmpSize().y + FromDIP(6))); +#endif // __APPLE__ + + Bind(wxEVT_PAINT, &Fan::paintEvent, this); +} + +void Fan::set_fan_speeds(int g) +{ + m_current_speeds = g; + Refresh(); +} + +void Fan::post_event(wxCommandEvent &&event) +{ + /*event.SetString(m_info.can_id); + event.SetEventObject(m_parent); + wxPostEvent(m_parent, event); + event.Skip();*/ +} + +void Fan::paintEvent(wxPaintEvent& evt) +{ + wxPaintDC dc(this); + render(dc); +} + +void Fan::render(wxDC& dc) +{ +#ifdef __WXMSW__ + wxSize size = GetSize(); + wxMemoryDC memdc; + wxBitmap bmp(size.x, size.y); + memdc.SelectObject(bmp); + memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 }); + + { + wxGCDC dc2(memdc); + doRender(dc2); + } + + memdc.SelectObject(wxNullBitmap); + dc.DrawBitmap(bmp, 0, 0); +#else + doRender(dc); +#endif +} + +void Fan::doRender(wxDC& dc) +{ + auto rpm = wxT("rpm"); + + wxSize size = GetSize(); + dc.DrawBitmap(m_bitmap_bk.bmp(), wxPoint(0,0)); + + //fan scale + /*auto central_point = wxPoint(size.x / 2, size.y / 2 + FromDIP(15)); + dc.DrawBitmap(m_bitmap_scale_0.bmp(), central_point.x - FromDIP(38), central_point.y); + dc.DrawBitmap(m_bitmap_scale_1.bmp(), central_point.x - FromDIP(40), central_point.y - FromDIP(17)); + dc.DrawBitmap(m_bitmap_scale_2.bmp(), central_point.x - FromDIP(40), central_point.y - FromDIP(36)); + dc.DrawBitmap(m_bitmap_scale_3.bmp(), central_point.x - FromDIP(32), central_point.y - FromDIP(48)); + dc.DrawBitmap(m_bitmap_scale_4.bmp(), central_point.x - FromDIP(18), central_point.y - FromDIP(53)); + dc.DrawBitmap(m_bitmap_scale_5.bmp(), central_point.x - FromDIP(0), central_point.y - FromDIP(53)); + dc.DrawBitmap(m_bitmap_scale_6.bmp(), central_point.x + FromDIP(18), central_point.y - FromDIP(48)); + dc.DrawBitmap(m_bitmap_scale_7.bmp(), central_point.x + FromDIP(31), central_point.y - FromDIP(36)); + dc.DrawBitmap(m_bitmap_scale_8.bmp(), central_point.x + FromDIP(36), central_point.y - FromDIP(17)); + dc.DrawBitmap(m_bitmap_scale_9.bmp(), central_point.x + FromDIP(28), central_point.y);*/ + + //fan pointer + //auto pointer_central_point = wxPoint((size.x - m_img_pointer.GetSize().x) / 2, (size.y - m_img_pointer.GetSize().y) / 2); + //auto bmp = m_img_pointer.Rotate(m_rotate_offsets[m_current_speeds].rotate, wxPoint(size.x / 2,size.y / 2)); + auto central_point = wxPoint((size.x - m_bitmap_scales[m_current_speeds].GetBmpSize().x) / 2, (size.y - m_bitmap_scales[m_current_speeds].GetBmpSize().y) / 2 - FromDIP(4)); + dc.DrawBitmap(m_bitmap_scales[m_current_speeds].bmp(), central_point.x, central_point.y); + + //fan val + dc.SetTextForeground(DRAW_TEXT_COLOUR); + dc.SetFont(::Label::Head_14); + auto speeds = wxString::Format("%d%%", m_current_speeds * 10); + dc.DrawText(speeds, (size.x - dc.GetTextExtent(speeds).x) / 2, size.y - dc.GetTextExtent(speeds).y - FromDIP(10)); + + //rpm + dc.SetFont(::Label::Body_13); + dc.DrawText(rpm, (size.x - dc.GetTextExtent(rpm).x) / 2, size.y - dc.GetTextExtent(rpm).y); +} + +void Fan::msw_rescale() { + m_bitmap_bk.msw_rescale(); +} + +void Fan::DoSetSize(int x, int y, int width, int height, int sizeFlags) +{ + wxWindow::DoSetSize(x, y, width, height, sizeFlags); +} + + +/************************************************* +Description:FanOperate +**************************************************/ +FanOperate::FanOperate(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size) +{ + m_current_speeds = 0; + m_min_speeds = 1; + m_max_speeds = 10; + create(parent, id, pos, size); +} + +void FanOperate::create(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size) +{ + + wxWindow::Create(parent, id, pos, size, wxBORDER_NONE); + SetBackgroundColour(*wxWHITE); + + m_bitmap_add = ScalableBitmap(this, "fan_control_add", FromDIP(11)); + m_bitmap_decrease = ScalableBitmap(this, "fan_control_decrease", FromDIP(11)); + + SetMinSize(wxSize(FromDIP(SIZE_OF_FAN_OPERATE.x), FromDIP(SIZE_OF_FAN_OPERATE.y))); + Bind(wxEVT_PAINT, &FanOperate::paintEvent, this); + Bind(wxEVT_ENTER_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_HAND);}); + Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_ARROW);}); + Bind(wxEVT_LEFT_DOWN, &FanOperate::on_left_down, this); +} + +void FanOperate::on_left_down(wxMouseEvent& event) +{ + auto mouse_pos = ClientToScreen(event.GetPosition()); + auto win_pos = ClientToScreen(wxPoint(0, 0)); + + auto decrease_fir = GetSize().x / 3 + win_pos.x; + auto add_fir = GetSize().x / 3 * 2 + win_pos.x; + + if (mouse_pos.x > win_pos.x && mouse_pos.x < decrease_fir && mouse_pos.y > win_pos.y && mouse_pos.y < (win_pos.y + GetSize().y)) { + decrease_fan_speeds(); + return; + } + + if (mouse_pos.x > add_fir && mouse_pos.x < (win_pos.x + GetSize().x) && mouse_pos.y > win_pos.y && mouse_pos.y < (win_pos.y + GetSize().y)) { + add_fan_speeds(); + return; + } +} + +void FanOperate::set_fan_speeds(int g) +{ + m_current_speeds = g; + Refresh(); +} + +void FanOperate::add_fan_speeds() +{ + if (m_current_speeds + 1 > m_max_speeds) return; + set_fan_speeds(++m_current_speeds); + post_event(wxCommandEvent(EVT_FAN_ADD)); + post_event(wxCommandEvent(EVT_FAN_SWITCH_ON)); +} + +void FanOperate::decrease_fan_speeds() +{ + //turn off + if (m_current_speeds - 1 < m_min_speeds) { + m_current_speeds = 0; + set_fan_speeds(m_current_speeds); + post_event(wxCommandEvent(EVT_FAN_SWITCH_OFF)); + } + else { + set_fan_speeds(--m_current_speeds); + } + post_event(wxCommandEvent(EVT_FAN_DEC)); + +} + +void FanOperate::post_event(wxCommandEvent &&event) +{ + event.SetInt(m_current_speeds); + event.SetEventObject(this); + wxPostEvent(this, event); + event.Skip(); +} + +void FanOperate::paintEvent(wxPaintEvent& evt) +{ + wxPaintDC dc(this); + render(dc); +} + +void FanOperate::render(wxDC& dc) +{ +#ifdef __WXMSW__ + wxSize size = GetSize(); + wxMemoryDC memdc; + wxBitmap bmp(size.x, size.y); + memdc.SelectObject(bmp); + memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 }); + + { + wxGCDC dc2(memdc); + doRender(dc2); + } + + memdc.SelectObject(wxNullBitmap); + dc.DrawBitmap(bmp, 0, 0); +#else + doRender(dc); +#endif +} + +void FanOperate::doRender(wxDC& dc) +{ + wxSize size = GetSize(); + dc.SetPen(wxPen(DRAW_OPERATE_LINE_COLOUR)); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRoundedRectangle(0,0,size.x,size.y,5); + + //splt + auto left_fir = size.x / 3; + + dc.DrawLine(left_fir, FromDIP(4), left_fir, size.y - FromDIP(4)); + dc.DrawLine(left_fir * 2, FromDIP(4), left_fir * 2, size.y - FromDIP(4)); + + dc.DrawBitmap(m_bitmap_decrease.bmp(), (left_fir - m_bitmap_decrease.GetBmpSize().x) / 2, (size.y - m_bitmap_decrease.GetBmpSize().y) / 2); + dc.DrawBitmap(m_bitmap_add.bmp(), (left_fir * 2 + (left_fir - m_bitmap_decrease.GetBmpSize().x) / 2), (size.y - m_bitmap_add.GetBmpSize().y) / 2); + + //txt + dc.SetFont(::Label::Body_12); + dc.SetTextForeground(StateColor::darkModeColorFor(wxColour(0x898989))); + wxString text = wxString::Format("%d%%", m_current_speeds * 10); + wxSize text_size = dc.GetTextExtent(text); + dc.DrawText(text, wxPoint(left_fir + (left_fir- text_size.x) / 2, (size.y- text_size.y) / 2 + 2)); +} + +void FanOperate::msw_rescale() { +} + +/************************************************* +Description:FanControl +**************************************************/ +FanControl::FanControl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size) + :wxWindow(parent, id, pos, size) +{ + auto m_bitmap_fan = new ScalableBitmap(this, "fan_icon", 18); + m_bitmap_toggle_off = new ScalableBitmap(this, "toggle_off", 14); + m_bitmap_toggle_on = new ScalableBitmap(this, "toggle_on", 14); + + + + SetBackgroundColour(*wxWHITE); + + wxBoxSizer* m_sizer_main = new wxBoxSizer(wxHORIZONTAL); + + m_fan = new Fan(this, wxID_ANY, wxDefaultPosition, wxDefaultSize); + m_sizer_main->Add(m_fan, 1, wxEXPAND | wxALL, 0); + + + m_sizer_main->Add(0, 0, 0, wxLEFT, FromDIP(18)); + + wxBoxSizer* sizer_control = new wxBoxSizer(wxVERTICAL); + wxBoxSizer* sizer_control_top = new wxBoxSizer(wxHORIZONTAL); + + + auto m_static_bitmap_fan = new wxStaticBitmap(this, wxID_ANY, m_bitmap_fan->bmp(), wxDefaultPosition, wxDefaultSize); + + + m_static_name = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END|wxALIGN_CENTER_HORIZONTAL); + m_static_name->SetForegroundColour(wxColour(DRAW_TEXT_COLOUR)); + m_static_name->SetBackgroundColour(*wxWHITE); + m_static_name->SetMinSize(wxSize(FromDIP(50), -1)); + m_static_name->SetMaxSize(wxSize(FromDIP(50), -1)); + + + m_switch_button = new wxStaticBitmap(this, wxID_ANY, m_bitmap_toggle_off->bmp(), wxDefaultPosition, wxDefaultSize, 0); + m_switch_button->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_HAND); }); + m_switch_button->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_RIGHT_ARROW); }); + m_switch_button->Bind(wxEVT_LEFT_DOWN, &FanControl::on_swith_fan, this); + + + sizer_control_top->Add(m_static_bitmap_fan, 0, wxALIGN_CENTER, 5); + sizer_control_top->Add(m_static_name, 0, wxALIGN_CENTER, 0); + sizer_control_top->Add( 0, 0, 1, wxEXPAND, 0 ); + sizer_control_top->Add(m_switch_button, 0, wxALIGN_CENTER, 0); + + + sizer_control->Add(sizer_control_top, 0, wxALIGN_CENTER, 0); + sizer_control->Add(0, 0, 0, wxTOP, FromDIP(15)); + + m_fan_operate = new FanOperate(this, wxID_ANY, wxDefaultPosition, wxDefaultSize); + sizer_control->Add(m_fan_operate, 0, wxALIGN_CENTER, 0); + + + m_sizer_main->Add(sizer_control, 0, wxALIGN_CENTER, 0); + + + this->SetSizer(m_sizer_main); + this->Layout(); + m_sizer_main->Fit(this); + + m_fan_operate->Bind(EVT_FAN_SWITCH_ON, [this](wxCommandEvent& e) { + m_current_speed = e.GetInt(); + m_switch_button->SetBitmap(m_bitmap_toggle_on->bmp()); + m_switch_fan = true; + m_fan->set_fan_speeds(m_current_speed); + }); + m_fan_operate->Bind(EVT_FAN_SWITCH_OFF, [this](wxCommandEvent& e) { + m_current_speed = e.GetInt(); + m_switch_button->SetBitmap(m_bitmap_toggle_off->bmp()); + m_switch_fan = false; + m_fan->set_fan_speeds(m_current_speed); + }); + + m_fan_operate->Bind(EVT_FAN_ADD, [this](wxCommandEvent& e) { + m_current_speed = e.GetInt(); + m_fan->set_fan_speeds(m_current_speed); + command_control_fan(); + }); + + m_fan_operate->Bind(EVT_FAN_DEC, [this](wxCommandEvent& e) { + m_current_speed = e.GetInt(); + m_fan->set_fan_speeds(m_current_speed); + command_control_fan(); + }); +} + +void FanControl::on_left_down(wxMouseEvent& evt) +{ + auto mouse_pos = ClientToScreen(evt.GetPosition()); + auto tag_pos = m_fan_operate->ScreenToClient(mouse_pos); + evt.SetPosition(tag_pos); + m_fan_operate->on_left_down(evt); +} + +void FanControl::command_control_fan() +{ + if (m_current_speed < 0 || m_current_speed > 10) { return; } + int speed = floor(m_current_speed * float(25.5)); + m_obj->command_control_fan_val(m_type, speed); + post_event(wxCommandEvent(EVT_FAN_CHANGED)); +} + +void FanControl::on_swith_fan(wxMouseEvent& evt) +{ + int speed = 0; + if (m_switch_fan) { + speed = 0; + m_switch_button->SetBitmap(m_bitmap_toggle_off->bmp()); + m_switch_fan = false; + } + else { + speed = 255; + m_switch_button->SetBitmap(m_bitmap_toggle_on->bmp()); + m_switch_fan = true; + } + + set_fan_speed(speed); + command_control_fan(); +} + +void FanControl::on_swith_fan(bool on) +{ + m_switch_fan = on; + if (m_switch_fan) { + m_switch_button->SetBitmap(m_bitmap_toggle_on->bmp()); + } + else { + m_switch_button->SetBitmap(m_bitmap_toggle_off->bmp()); + } +} + +void FanControl::set_machine_obj(MachineObject* obj) +{ + m_obj = obj; +} + +void FanControl::set_type(MachineObject::FanType type) +{ + m_type = type; +} + +void FanControl::set_name(wxString name) +{ + m_static_name->SetLabelText(name); +} + +void FanControl::set_fan_speed(int g) +{ + if (g < 0 || g > 255) return; + int speed = floor(float(g) / float(25.5)); + + if (m_current_speed != speed) { + m_current_speed = speed; + m_fan->set_fan_speeds(speed); + m_fan_operate->set_fan_speeds(m_current_speed); + + if (m_current_speed <= 0) { + on_swith_fan(false); + } + else { + on_swith_fan(true); + } + } + +} + +void FanControl::set_fan_switch(bool s) +{ + +} + +void FanControl::post_event(wxCommandEvent&& event) +{ + event.SetInt(m_type); + event.SetString(wxString::Format("%d", m_current_speed)); + event.SetEventObject(GetParent()); + wxPostEvent(GetParent(), event); + event.Skip(); +} + + +/************************************************* +Description:FanControlPopup +**************************************************/ +FanControlPopup::FanControlPopup(wxWindow* parent) + :wxPopupTransientWindow(parent, wxBORDER_NONE) +{ + this->SetSizeHints(wxDefaultSize, wxDefaultSize); + + m_sizer_main = new wxBoxSizer(wxVERTICAL); + m_part_fan = new FanControl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize); + m_part_fan->set_type(MachineObject::FanType::COOLING_FAN); + m_part_fan->set_name(_L("Part")); + + m_aux_fan = new FanControl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize); + m_aux_fan->set_type(MachineObject::FanType::BIG_COOLING_FAN); + m_aux_fan->set_name(_L("Aux")); + + m_cham_fan = new FanControl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize); + m_cham_fan->set_type(MachineObject::FanType::CHAMBER_FAN); + m_cham_fan->set_name(_L("Cham")); + + m_line_top = new wxWindow(this, wxID_ANY); + m_line_top->SetSize(wxSize(-1, 1)); + m_line_top->SetBackgroundColour(0xF1F1F1); + + m_line_bottom = new wxWindow(this, wxID_ANY); + m_line_bottom->SetSize(wxSize(-1, 1)); + m_line_bottom->SetBackgroundColour(0xF1F1F1); + + + m_sizer_main->Add(m_part_fan, 0, wxALL, FromDIP(14)); + m_sizer_main->Add(m_line_top, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(8)); + m_sizer_main->Add(m_aux_fan, 0, wxALL, FromDIP(14)); + m_sizer_main->Add(m_line_bottom, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(8)); + m_sizer_main->Add(m_cham_fan, 0, wxALL, FromDIP(14)); + + + this->SetSizer(m_sizer_main); + this->Layout(); + m_sizer_main->Fit(this); + + this->Centre(wxBOTH); + Bind(wxEVT_PAINT, &FanControlPopup::paintEvent, this); + +#if __APPLE__ + Bind(wxEVT_LEFT_DOWN, &FanControlPopup::on_left_down, this); +#endif + + SetBackgroundColour(*wxWHITE); +} + +void FanControlPopup::update_fan_data(MachineObject::FanType type, MachineObject* obj) +{ + bool is_suppt_cham_fun = obj->is_function_supported(PrinterFunction::FUNC_CHAMBER_FAN); + if (is_suppt_cham_fun) { + m_cham_fan->Show(); + m_line_bottom->Show(); + } + else { + m_cham_fan->Hide(); + m_line_bottom->Hide(); + } + + if (type == MachineObject::FanType::COOLING_FAN && obj->cooling_fan_speed >= 0) { + m_part_fan->set_fan_speed(obj->cooling_fan_speed); + } + + if (type == MachineObject::FanType::BIG_COOLING_FAN && obj->big_fan1_speed >= 0) { + m_aux_fan->set_fan_speed(obj->big_fan1_speed); + } + + if (type == MachineObject::FanType::CHAMBER_FAN && obj->big_fan2_speed >= 0) { + m_cham_fan->set_fan_speed(obj->big_fan2_speed); + } + + m_part_fan->set_machine_obj(obj); + m_aux_fan->set_machine_obj(obj); + m_cham_fan->set_machine_obj(obj); + + Bind(EVT_FAN_CHANGED, [this](wxCommandEvent& e) { + post_event(e.GetInt(), e.GetString()); + }); + + Layout(); + Fit(); +} + +void FanControlPopup::on_left_down(wxMouseEvent& evt) +{ + auto mouse_pos = ClientToScreen(evt.GetPosition()); + + auto part_tag_pos = m_part_fan->ScreenToClient(mouse_pos); + evt.SetPosition(part_tag_pos); + m_part_fan->on_left_down(evt); + + auto aux_tag_pos = m_aux_fan->ScreenToClient(mouse_pos); + evt.SetPosition(aux_tag_pos); + m_aux_fan->on_left_down(evt); + + auto cham_tag_pos = m_cham_fan->ScreenToClient(mouse_pos); + evt.SetPosition(cham_tag_pos); + m_cham_fan->on_left_down(evt); + evt.Skip(); +} + +void FanControlPopup::OnDismiss() +{ + +} + +void FanControlPopup::post_event(int fan_type, wxString speed) +{ + wxCommandEvent event(EVT_FAN_CHANGED); + event.SetInt(fan_type); + event.SetString(speed); + event.SetEventObject(GetParent()); + wxPostEvent(GetParent(), event); + event.Skip(); +} + +bool FanControlPopup::ProcessLeftDown(wxMouseEvent& event) +{ + return wxPopupTransientWindow::ProcessLeftDown(event); +} + +void FanControlPopup::paintEvent(wxPaintEvent& evt) +{ + wxPaintDC dc(this); + dc.SetPen(wxColour(0xAC, 0xAC, 0xAC)); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0); +} +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Widgets/FanControl.hpp b/src/slic3r/GUI/Widgets/FanControl.hpp new file mode 100644 index 000000000..bfd5694de --- /dev/null +++ b/src/slic3r/GUI/Widgets/FanControl.hpp @@ -0,0 +1,171 @@ +#ifndef slic3r_GUI_FANCONTROL_hpp_ +#define slic3r_GUI_FANCONTROL_hpp_ + +#include "../wxExtensions.hpp" +#include "StaticBox.hpp" +#include "StepCtrl.hpp" +#include "Button.hpp" +#include "../DeviceManager.hpp" +#include "slic3r/GUI/Event.hpp" +#include +#include +#include +#include + + +namespace Slic3r { +namespace GUI { + + +/************************************************* +Description:Fan +**************************************************/ +#define SIZE_OF_FAN_OPERATE wxSize(100, 28) + +#define DRAW_TEXT_COLOUR wxColour(0x898989) +#define DRAW_OPERATE_LINE_COLOUR wxColour(0xDEDEDE) + +struct RotateOffSet +{ + float rotate; + wxPoint offset; +}; + +class Fan : public wxWindow +{ +public: + Fan(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize); + ~Fan() {}; + void post_event(wxCommandEvent&& event); + void paintEvent(wxPaintEvent& evt); + void render(wxDC& dc); + void doRender(wxDC& dc); + void msw_rescale(); + void create(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size); + void set_fan_speeds(int g); + +private: + int m_current_speeds; + std::vector m_rotate_offsets; + +protected: + std::vector m_scale_pos_array; + + ScalableBitmap m_bitmap_bk; + ScalableBitmap m_bitmap_scale_0; + ScalableBitmap m_bitmap_scale_1; + ScalableBitmap m_bitmap_scale_2; + ScalableBitmap m_bitmap_scale_3; + ScalableBitmap m_bitmap_scale_4; + ScalableBitmap m_bitmap_scale_5; + ScalableBitmap m_bitmap_scale_6; + ScalableBitmap m_bitmap_scale_7; + ScalableBitmap m_bitmap_scale_8; + ScalableBitmap m_bitmap_scale_9; + ScalableBitmap m_bitmap_scale_10; + + std::vector m_bitmap_scales; + + wxImage m_img_pointer; + + virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); +}; + +/************************************************* +Description:FanOperate +**************************************************/ +class FanOperate : public wxWindow +{ +public: + FanOperate(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize); + ~FanOperate() {}; + void post_event(wxCommandEvent&& event); + void paintEvent(wxPaintEvent& evt); + void render(wxDC& dc); + void doRender(wxDC& dc); + void msw_rescale(); + void create(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size); + void on_left_down(wxMouseEvent& event); + +public: + void set_fan_speeds(int g); + void add_fan_speeds(); + void decrease_fan_speeds(); +private: + int m_current_speeds; + int m_min_speeds; + int m_max_speeds; + ScalableBitmap m_bitmap_add; + ScalableBitmap m_bitmap_decrease; +}; + +/************************************************* +Description:FanControl +**************************************************/ +class FanControl : public wxWindow +{ +public: + FanControl(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize); + ~FanControl() {}; + +protected: + MachineObject::FanType m_type; + MachineObject* m_obj; + wxStaticText* m_static_name{ nullptr }; + wxStaticBitmap* m_switch_button{ nullptr }; + ScalableBitmap* m_bitmap_toggle_off{ nullptr }; + ScalableBitmap* m_bitmap_toggle_on{ nullptr }; + + Fan* m_fan{ nullptr }; + FanOperate* m_fan_operate{ nullptr }; + bool m_switch_fan{ false }; + int m_current_speed{0}; +public: + void command_control_fan(); + void set_machine_obj(MachineObject* obj); + void set_type(MachineObject::FanType type); + void set_name(wxString name); + void set_fan_speed(int g); + void set_fan_switch(bool s); + void post_event(wxCommandEvent&& event); + void on_swith_fan(wxMouseEvent& evt); + void on_swith_fan(bool on); + void on_left_down(wxMouseEvent& event); +}; + + +/************************************************* +Description:FanControlPopup +**************************************************/ +class FanControlPopup : public wxPopupTransientWindow +{ +public: + FanControlPopup(wxWindow* parent); + ~FanControlPopup() {}; + +private: + wxBoxSizer* m_sizer_main; + FanControl* m_part_fan; + FanControl* m_aux_fan; + FanControl* m_cham_fan; + wxWindow* m_line_top; + wxWindow* m_line_bottom; + +public: + void update_fan_data(MachineObject::FanType type, MachineObject* obj); + void on_left_down(wxMouseEvent& evt); + void paintEvent(wxPaintEvent& evt); + void post_event(int fan_type, wxString speed); + virtual void OnDismiss() wxOVERRIDE; + virtual bool ProcessLeftDown(wxMouseEvent& event) wxOVERRIDE; +}; + +wxDECLARE_EVENT(EVT_FAN_SWITCH_ON, wxCommandEvent); +wxDECLARE_EVENT(EVT_FAN_SWITCH_OFF, wxCommandEvent); +wxDECLARE_EVENT(EVT_FAN_ADD, wxCommandEvent); +wxDECLARE_EVENT(EVT_FAN_DEC, wxCommandEvent); +wxDECLARE_EVENT(EVT_FAN_CHANGED, wxCommandEvent); + +}} // namespace Slic3r::GUI + +#endif diff --git a/src/slic3r/GUI/Widgets/ImageSwitchButton.cpp b/src/slic3r/GUI/Widgets/ImageSwitchButton.cpp index af8c015fa..7240cc42a 100644 --- a/src/slic3r/GUI/Widgets/ImageSwitchButton.cpp +++ b/src/slic3r/GUI/Widgets/ImageSwitchButton.cpp @@ -15,6 +15,16 @@ EVT_PAINT(ImageSwitchButton::paintEvent) END_EVENT_TABLE() +BEGIN_EVENT_TABLE(FanSwitchButton, StaticBox) + +EVT_LEFT_DOWN(FanSwitchButton::mouseDown) +EVT_ENTER_WINDOW(FanSwitchButton::mouseEnterWindow) +EVT_LEAVE_WINDOW(FanSwitchButton::mouseLeaveWindow) +EVT_LEFT_UP(FanSwitchButton::mouseReleased) +EVT_PAINT(FanSwitchButton::paintEvent) + +END_EVENT_TABLE() + static const wxColour DEFAULT_HOVER_COL = wxColour(0, 174, 66); static const wxColour DEFAULT_PRESS_COL = wxColour(238, 238, 238); @@ -171,6 +181,188 @@ void ImageSwitchButton::mouseLeaveWindow(wxMouseEvent &event) } void ImageSwitchButton::sendButtonEvent() +{ + wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId()); + event.SetEventObject(this); + GetEventHandler()->ProcessEvent(event); +} + +FanSwitchButton::FanSwitchButton(wxWindow* parent, ScalableBitmap& img_on, ScalableBitmap& img_off, long style) + : text_color(std::make_pair(0x6B6B6B, (int)StateColor::Disabled), std::make_pair(*wxBLACK, (int)StateColor::Normal)) +{ + radius = 0; + m_padding = 0; + m_speed = 0; + m_on = img_on; + m_off = img_off; + background_color = StateColor(std::make_pair(*wxWHITE, (int)StateColor::Disabled), std::make_pair(DEFAULT_PRESS_COL, (int)StateColor::Pressed), + std::make_pair(*wxWHITE, (int)StateColor::Normal)); + border_color = StateColor(std::make_pair(*wxWHITE, (int)StateColor::Disabled), std::make_pair(DEFAULT_HOVER_COL, (int)StateColor::Focused), + std::make_pair(DEFAULT_HOVER_COL, (int)StateColor::Hovered), std::make_pair(*wxWHITE, (int)StateColor::Normal)); + + StaticBox::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style); + + messureSize(); + Refresh(); +} + +void FanSwitchButton::SetLabels(wxString const& lbl_on, wxString const& lbl_off) +{ + labels[0] = lbl_on; + labels[1] = lbl_off; + auto fina_txt = GetValue() ? labels[0] : labels[1]; + SetToolTip(fina_txt); + messureSize(); + Refresh(); +} + +void FanSwitchButton::SetImages(ScalableBitmap& img_on, ScalableBitmap& img_off) +{ + m_on = img_on; + m_off = img_off; + messureSize(); + Refresh(); +} + +void FanSwitchButton::SetTextColor(StateColor const& color) +{ + text_color = color; + state_handler.update_binds(); + messureSize(); + Refresh(); +} + +void FanSwitchButton::SetValue(bool value) +{ + m_on_off = value; + messureSize(); + Refresh(); +} + +void FanSwitchButton::SetPadding(int padding) +{ + m_padding = padding; + messureSize(); + Refresh(); +} + +void FanSwitchButton::messureSize() +{ + wxClientDC dc(this); + dc.SetFont(GetFont()); + textSize = dc.GetTextExtent(GetValue() ? labels[0] : labels[1]); +} + +void FanSwitchButton::paintEvent(wxPaintEvent& evt) +{ + wxPaintDC dc(this); + render(dc); +} + +void FanSwitchButton::render(wxDC& dc) +{ + StaticBox::render(dc); + int states = state_handler.states(); + wxSize size = GetSize(); + + wxSize szIcon; + wxSize szContent = textSize; + ScalableBitmap& icon = GetValue() ? m_on : m_off; + + //int content_height = icon.GetBmpHeight() + textSize.y + m_padding; + int content_height = m_padding; + + wxPoint pt = wxPoint((size.x - icon.GetBmpWidth()) / 2, (size.y - content_height) / 2); + + pt.x = (size.x - textSize.x) / 2; + dc.SetFont(GetFont()); + if (!IsEnabled()) + dc.SetTextForeground(text_color.colorForStates(StateColor::Disabled)); + else + dc.SetTextForeground(text_color.colorForStates(states)); + + auto fina_txt = GetValue() ? labels[0] : labels[1]; + if (dc.GetTextExtent(fina_txt).x > size.x) { + wxString forment_txt = wxEmptyString; + for (auto i = 0; i < fina_txt.length(); i++) { + forment_txt = fina_txt.SubString(0, i) + "..."; + if (dc.GetTextExtent(forment_txt).x > size.x) { + pt.x = (size.x - dc.GetTextExtent(forment_txt).x) / 2; + dc.DrawText(forment_txt, wxPoint(pt.x, content_height)); + break; + } + } + } + else { + dc.DrawText(fina_txt, wxPoint(pt.x, content_height)); + } + + pt = wxPoint((size.x - icon.GetBmpWidth()) / 2, content_height + textSize.y); + if (icon.bmp().IsOk()) { + dc.DrawBitmap(icon.bmp(), pt); + pt.y += m_padding + icon.GetBmpHeight(); + } + + auto speed = wxString::Format("%d%%", m_speed); + + dc.SetFont(GetFont()); + if (!IsEnabled()) + dc.SetTextForeground(text_color.colorForStates(StateColor::Disabled)); + else + dc.SetTextForeground(text_color.colorForStates(states)); + + pt.x = (size.x - dc.GetTextExtent(speed).x) / 2; + dc.DrawText(speed, pt); +} + +void FanSwitchButton::Rescale() +{ + messureSize(); +} + +void FanSwitchButton::setFanValue(int val) +{ + m_speed = val; + Refresh(); +} + +void FanSwitchButton::mouseDown(wxMouseEvent& event) +{ + event.Skip(); + pressedDown = true; + SetFocus(); + CaptureMouse(); +} + +void FanSwitchButton::mouseReleased(wxMouseEvent& event) +{ + event.Skip(); + if (pressedDown) { + pressedDown = false; + ReleaseMouse(); + //m_on_off = !m_on_off; + Refresh(); + sendButtonEvent(); + } +} + +void FanSwitchButton::mouseEnterWindow(wxMouseEvent& event) +{ + if (!hover) { + hover = true; + Refresh(); + } +} + +void FanSwitchButton::mouseLeaveWindow(wxMouseEvent& event) +{ + if (hover) { + hover = false; + Refresh(); + } +} + +void FanSwitchButton::sendButtonEvent() { wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId()); event.SetEventObject(this); diff --git a/src/slic3r/GUI/Widgets/ImageSwitchButton.hpp b/src/slic3r/GUI/Widgets/ImageSwitchButton.hpp index 4cf12abd7..787ce5514 100644 --- a/src/slic3r/GUI/Widgets/ImageSwitchButton.hpp +++ b/src/slic3r/GUI/Widgets/ImageSwitchButton.hpp @@ -50,4 +50,46 @@ private: StateColor text_color; }; +class FanSwitchButton : public StaticBox +{ +public: + FanSwitchButton(wxWindow* parent, ScalableBitmap& img_on, ScalableBitmap& img_off, long style = 0); + void SetLabels(wxString const& lbl_on, wxString const& lbl_off); + void SetImages(ScalableBitmap& img_on, ScalableBitmap& img_off); + void SetTextColor(StateColor const& color); + void SetValue(bool value); + void SetPadding(int padding); + + bool GetValue() { return m_on_off; } + void Rescale(); + void setFanValue(int val); + +private: + void messureSize(); + void paintEvent(wxPaintEvent& evt); + void render(wxDC& dc); + void mouseDown(wxMouseEvent& event); + void mouseReleased(wxMouseEvent& event); + void mouseEnterWindow(wxMouseEvent& event); + void mouseLeaveWindow(wxMouseEvent& event); + void sendButtonEvent(); + + DECLARE_EVENT_TABLE() + +private: + ScalableBitmap m_on; + ScalableBitmap m_off; + bool m_on_off; + int m_padding; // size between icon and text + bool pressedDown = false; + bool hover = false; + + wxSize textSize; + wxSize minSize; + int m_speed; + + wxString labels[2]; + StateColor text_color; +}; + #endif // !slic3r_GUI_SwitchButton_hpp_