From 1e9febbe4d34784ddbcbace3b06b9c382652eee1 Mon Sep 17 00:00:00 2001 From: "xin.zhang" Date: Mon, 12 May 2025 18:16:01 +0800 Subject: [PATCH] ENH: add some support for fan control jira: [STUDIO-12076] [STUDIO-12373] Change-Id: I04e23acc802987dc7a657274074abb961f692896 (cherry picked from commit 359d52c9139b7a1aae59b990dc03f45ce4a1bc89) (cherry picked from commit 9e16d9a4a6ce059dc134ffd388b753490dff0946) (cherry picked from commit 4cdd1937fea90c3dd1cf0c73a7cd5172346abb40) --- src/slic3r/GUI/DeviceManager.cpp | 30 ++- src/slic3r/GUI/DeviceManager.hpp | 32 ++- src/slic3r/GUI/Widgets/FanControl.cpp | 314 ++++++++++++++------------ src/slic3r/GUI/Widgets/FanControl.hpp | 102 +++++---- 4 files changed, 286 insertions(+), 192 deletions(-) diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index a64d15f98c..dfb4b3bc5f 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -2020,7 +2020,7 @@ int MachineObject::command_control_fan_new(int fan_id, int val, const CommandCal return this->publish_json(j.dump()); } -int MachineObject::command_control_air_duct(int mode_id, const CommandCallBack &cb) +int MachineObject::command_control_air_duct(int mode_id, int submode, const CommandCallBack &cb) { BOOST_LOG_TRIVIAL(info) << "MachineObject::command_control_air_duct, set air duct, d = " << mode_id; m_callback_list[std::to_string(m_sequence_id)] = cb; @@ -2028,6 +2028,7 @@ int MachineObject::command_control_air_duct(int mode_id, const CommandCallBack & j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["command"] = "set_airduct"; j["print"]["modeId"] = mode_id; + j["print"]["submode"] = submode; return this->publish_json(j.dump()); } @@ -6291,6 +6292,7 @@ void MachineObject::parse_new_info(json print) is_support_brtc = get_flag_bits(fun, 31); m_support_mqtt_axis_control = get_flag_bits(fun, 38); m_support_mqtt_bet_ctrl = get_flag_bits(fun, 39); + m_air_duct_data.m_support_cooling_filter = get_flag_bits(fun, 46); } /*aux*/ @@ -6322,9 +6324,9 @@ void MachineObject::parse_new_info(json print) m_air_duct_data.modes.clear(); m_air_duct_data.parts.clear(); - m_air_duct_data.curren_mode = device["airduct"]["modeCur"].get(); - const json& airduct = device["airduct"]; + if (airduct.contains("modeCur")) { m_air_duct_data.curren_mode = airduct["modeCur"].get();} + if (airduct.contains("subMode")) { m_air_duct_data.m_sub_mode = airduct["subMode"].get(); } if (airduct.contains("modeList") && airduct["modeList"].is_array()) { auto list = airduct["modeList"].get>(); @@ -7869,6 +7871,28 @@ bool DeviceManager::load_filaments_blacklist_config() return true; } +string DeviceManager::get_fan_text(const std::string& type_str, const std::string& key) +{ + std::vector filaments; + std::string config_file = Slic3r::resources_dir() + "/printers/" + type_str + ".json"; + boost::nowide::ifstream json_file(config_file.c_str()); + try + { + json jj; + if (json_file.is_open()) { + json_file >> jj; + if (jj.contains("00.00.00.00")) { + json const& printer = jj["00.00.00.00"]; + if (printer.contains("fan") && printer["fan"].contains(key)) { + return printer["fan"][key].get(); + } + } + } + } + catch (...) {} + return string(); +} + bool DeviceManager::is_virtual_slot(int ams_id) { if (ams_id == VIRTUAL_TRAY_MAIN_ID || ams_id == VIRTUAL_TRAY_DEPUTY_ID) diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index 3939fccc7d..07b3e0ef92 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -252,6 +252,11 @@ struct AirMode // If the fan is off, it cannot be controlled and is displayed as off std::vector off; // If the fan is not off or ctrl, it will be displayed as auto + +public: + bool operator ==(const AirMode& other) const { + return (id == other.id) && (ctrl == other.ctrl) && (off == other.off); + }; }; struct AirParts @@ -262,6 +267,11 @@ struct AirParts int state{ 0 };// 100% int range_start{ 0 };// 100% int range_end{ 0 };// 100% + +public: + bool operator ==(const AirParts& other) const { + return (type == other.type) && (id == other.id) && (func == other.func) && (state == other.state) && (range_start == other.range_start) && (range_end == other.range_end); + }; }; struct AirDuctData @@ -269,6 +279,22 @@ struct AirDuctData int curren_mode{ 0 }; std::unordered_map modes; std::vector parts; + + int m_sub_mode = -1;// the submode of airduct, for cooling: 0-filter, 1-cooling + bool m_support_cooling_filter = false;// support switch filter on cooling mode or not + +public: + bool operator ==(const AirDuctData& other) const { + return (curren_mode == other.curren_mode) && (modes == other.modes) && (parts == other.parts) && + (m_sub_mode == other.m_sub_mode) && (m_support_cooling_filter == other.m_support_cooling_filter); + }; + + bool operator !=(const AirDuctData& other) const { + return !(operator==(other)); + }; + + bool IsSupportCoolingFilter() const { return m_support_cooling_filter;} + bool IsCoolingFilerOn() const { return m_sub_mode == 0;} }; struct RatingInfo { @@ -486,7 +512,6 @@ enum AIR_DUCT { AIR_DUCT_HEATING_INTERNAL_FILT, AIR_DUCT_EXHAUST, AIR_DUCT_FULL_COOLING, - AIR_DUCT_NUM, AIR_DUCT_INIT = 0xFF //Initial mode, only used within mc }; @@ -1193,7 +1218,7 @@ public: int command_go_home2(); int command_control_fan(int fan_type, int val); // Old protocol int command_control_fan_new(int fan_id, int val, const CommandCallBack &cb); // New protocol - int command_control_air_duct(int mode_id, const CommandCallBack& cb); + int command_control_air_duct(int mode_id, int submode, const CommandCallBack& cb); int command_task_abort(); /* cancelled the job_id */ int command_task_cancel(std::string job_id); @@ -1537,6 +1562,9 @@ public: static bool get_printer_is_enclosed(std::string type_str); static bool get_printer_can_set_nozzle(std::string type_str);// can set nozzle from studio static bool load_filaments_blacklist_config(); + + static string get_fan_text(const std::string& type_str, const std::string& key); + static std::vector get_resolution_supported(std::string type_str); static std::vector get_compatible_machine(std::string type_str); static std::vector get_unsupport_auto_cali_filaments(std::string type_str); diff --git a/src/slic3r/GUI/Widgets/FanControl.cpp b/src/slic3r/GUI/Widgets/FanControl.cpp index 8be47af2cb..6374d89cb3 100644 --- a/src/slic3r/GUI/Widgets/FanControl.cpp +++ b/src/slic3r/GUI/Widgets/FanControl.cpp @@ -16,7 +16,7 @@ wxDEFINE_EVENT(EVT_FAN_ADD, wxCommandEvent); wxDEFINE_EVENT(EVT_FAN_DEC, wxCommandEvent); wxDEFINE_EVENT(EVT_FAN_CHANGED, wxCommandEvent); -constexpr int time_out = 10; +constexpr int time_out = 6; static bool not_show_fan_speed_warning_dlg = false; /************************************************* @@ -610,7 +610,7 @@ FanControlPopupNew::FanControlPopupNew(wxWindow* parent, MachineObject* obj, con : wxDialog(parent, wxID_ANY, wxEmptyString) { SetBackgroundColour(*wxWHITE); - init_names(); + init_names(obj); m_data = data; m_obj = obj; @@ -624,32 +624,22 @@ FanControlPopupNew::FanControlPopupNew(wxWindow* parent, MachineObject* obj, con m_sizer_fanControl = new wxGridSizer(0, grid_column, FromDIP(3), FromDIP(10)); m_mode_sizer = new wxBoxSizer(wxHORIZONTAL); - - m_button_refresh = new Button(this, wxString(""), "fan_poppingup_refresh", 0, 24); - m_button_refresh->SetBackgroundColor(*wxWHITE); - m_button_refresh->SetBorderColor(*wxWHITE); - m_button_refresh->SetMinSize(wxSize(FromDIP(26), FromDIP(26))); - m_button_refresh->SetMaxSize(wxSize(FromDIP(26), FromDIP(26))); - m_button_refresh->Bind(wxEVT_ENTER_WINDOW, [this](const auto &e) { SetCursor(wxCURSOR_HAND); }); - m_button_refresh->Bind(wxEVT_LEAVE_WINDOW, [this](const auto &e) { SetCursor(wxCURSOR_ARROW); }); - m_button_refresh->Bind(wxEVT_LEFT_DOWN, [this](const auto &e) { - CreateDuct(); - Layout(); - Fit(); - }); m_mode_sizer->Add(m_radio_btn_sizer, 0, wxALIGN_CENTRE_VERTICAL, 0); - m_mode_sizer->Add(m_button_refresh, 0, wxALIGN_CENTRE_VERTICAL, 0); - m_button_refresh->Hide(); - m_cooling_text = new Label(this); - m_cooling_text->SetBackgroundColour(*wxWHITE); - //Control the show or hide of controls based on id + m_mode_text = new Label(this); + m_mode_text->SetBackgroundColour(*wxWHITE); + + m_sub_mode_panel = new wxPanel(this, wxID_ANY); + m_sub_mode_panel->SetBackgroundColour(wxColour(248, 248, 248)); + m_sub_mode_sizer = new wxBoxSizer(wxVERTICAL); + m_sub_mode_panel->SetSizer(m_sub_mode_sizer); m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(23)); m_sizer_main->Add(m_mode_sizer, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, FromDIP(30)); m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(10)); - m_sizer_main->Add(m_cooling_text, 0, wxLEFT | wxRIGHT, FromDIP(30)); + m_sizer_main->Add(m_mode_text, 0, wxLEFT, FromDIP(35)); m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(10)); + m_sizer_main->Add(m_sub_mode_panel, 0, wxLEFT | wxRIGHT, FromDIP(30)); m_sizer_main->Add(m_sizer_fanControl, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, 0); m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(16)); @@ -676,13 +666,9 @@ FanControlPopupNew::FanControlPopupNew(wxWindow* parent, MachineObject* obj, con void FanControlPopupNew::CreateDuct() { m_radio_btn_sizer->Clear(true); - m_mode_switch_btn_list.clear(); - //tips - UpdateTips(m_data.curren_mode); - - //fan or door - UpdateParts(m_data.curren_mode); + //m_radio_btn_sizer->SetCols(m_data.modes.size()); + m_mode_switch_btns.clear(); auto iter = m_data.modes.begin(); while (iter != m_data.modes.end()) { @@ -692,16 +678,25 @@ void FanControlPopupNew::CreateDuct() SendModeSwitchButton *radio_btn = new SendModeSwitchButton(this, text, m_data.curren_mode == mode_id); radio_btn->Bind(wxEVT_LEFT_DOWN, &FanControlPopupNew::on_mode_changed, this); - m_mode_switch_btn_list.emplace_back(radio_btn); + m_mode_switch_btns[mode_id] = radio_btn; m_radio_btn_sizer->Add(radio_btn, wxALL, FromDIP(5)); iter++; } + + //tips + UpdateParts(); } -void FanControlPopupNew::UpdateParts(int mode_id) +void FanControlPopupNew::UpdateParts() { - Freeze(); + auto text = label_text[AIR_DUCT(m_data.curren_mode)]; + if (m_mode_text->GetLabelText() != text) + { + m_mode_text->SetLabelText(text); + m_mode_text->Wrap(FromDIP(400)); + } + UpdatePartSubMode(); for (const auto& part : m_data.parts) { auto part_id = part.id; @@ -710,7 +705,7 @@ void FanControlPopupNew::UpdateParts(int mode_id) auto fan_control = m_fan_control_list[part_id]; if (!fan_control) { - fan_control = new FanControlNew(this, m_data, mode_id, part_id, wxID_ANY, wxDefaultPosition, wxDefaultSize); + fan_control = new FanControlNew(this, m_data, m_data.curren_mode, part_id, wxID_ANY, wxDefaultPosition, wxDefaultSize); m_fan_control_list[part_id] = fan_control; m_sizer_fanControl->Add(fan_control, 0, wxALL, FromDIP(5)); } @@ -718,20 +713,48 @@ void FanControlPopupNew::UpdateParts(int mode_id) fan_control->set_machine_obj(m_obj); fan_control->set_name(part_name); fan_control->update_fan_data(m_data); - fan_control->set_mode_id(mode_id); + fan_control->set_mode_id(m_data.curren_mode); fan_control->update_mode(); } - m_sizer_fanControl->Layout(); - Thaw(); + for (const auto& btn_iter : m_mode_switch_btns) { + if (btn_iter.first == m_data.curren_mode) { + btn_iter.second->setSelected(true); + } else { + btn_iter.second->setSelected(false); + } + } + + Layout(); + Fit(); } -void FanControlPopupNew::UpdateTips(int model) +void FanControlPopupNew::UpdatePartSubMode() { - auto text = label_text[AIR_DUCT(model)]; - m_cooling_text->SetLabelText(text); - m_cooling_text->Wrap(FromDIP(360)); - Layout(); + // Submode for cooling filter + if (AIR_DUCT(m_data.curren_mode) == AIR_DUCT::AIR_DUCT_COOLING_FILT && m_data.IsSupportCoolingFilter()) { + if (!m_cooling_filter_switch_panel) { + m_cooling_filter_switch_panel = new FanControlNewSwitchPanel(m_sub_mode_panel, _L("Filter"), _L("Enabling filtration redirects the right fan to filter gas, which may reduce cooling performance.")); + m_cooling_filter_switch_panel->Bind(EVT_FANCTRL_SWITCH, [this] (wxCommandEvent& evt) + { + if (m_obj && m_obj->is_in_printing()) { + MessageDialog msg_wingow(nullptr, _L("Enabling filtration during printing may reduce cooling and affect print qulity. Please choose carefully"), "", wxICON_WARNING | wxCANCEL | wxOK); + msg_wingow.SetButtonLabel(wxID_OK, _L("Change Anyway")); + if (msg_wingow.ShowModal() != wxID_OK) { return; } + } + + int submode = m_cooling_filter_switch_panel->IsSwitchOn() ? 0 : 1; + command_control_air_duct(m_data.curren_mode, submode); + }); + + m_sub_mode_sizer->Add(m_cooling_filter_switch_panel, 0, wxALL, FromDIP(5)); + } + + m_cooling_filter_switch_panel->SetSwitchOn(m_data.IsCoolingFilerOn()); + } else { + delete m_cooling_filter_switch_panel; + m_cooling_filter_switch_panel = nullptr; + } } void FanControlPopupNew::update_fan_data(MachineObject *obj) @@ -739,17 +762,24 @@ void FanControlPopupNew::update_fan_data(MachineObject *obj) if (!obj) return; + if (m_obj != obj) { + m_obj = obj; + init_names(m_obj); + } + + if (m_air_duct_time_out > 0) { + m_air_duct_time_out--; + return; + } + + if (m_fan_set_time_out > 0) { + m_fan_set_time_out--; + return; + } + if (obj->is_enable_np) { - if (m_fan_set_time_out > 0) { - m_fan_set_time_out--; - return; - } update_fan_data(obj->m_air_duct_data); } else { - if (m_fan_set_time_out > 0) { - m_fan_set_time_out--; - return; - } int cooling_fan_speed = round(obj->cooling_fan_speed / float(25.5)); int big_fan1_speed = round(obj->big_fan1_speed / float(25.5)); int big_fan2_speed = round(obj->big_fan2_speed / float(25.5)); @@ -761,6 +791,8 @@ void FanControlPopupNew::update_fan_data(MachineObject *obj) void FanControlPopupNew::update_fan_data(const AirDuctData &data) { + if (m_data == data) { return; } + m_data = data; for (const auto& part : m_data.parts) { auto part_id = part.id; @@ -774,6 +806,8 @@ void FanControlPopupNew::update_fan_data(const AirDuctData &data) fan_control->set_fan_speed_percent(part_state / 10); } } + + UpdateParts(); } void FanControlPopupNew::update_fan_data(AIR_FUN id, int speed) @@ -795,58 +829,12 @@ void FanControlPopupNew::update_fan_data(AIR_FUN id, int speed) } } -// device change -void FanControlPopupNew::update_device(AirDuctData data, MachineObject* obj) -{ - - //for (int i = 0; i < data.airducts.size(); i++){ - // auto duct = data.airducts[i]; - // if (m_fan_control_list.find(duct.airduct_id) == m_fan_control_list.end()) - // CreateDuct(duct); - // else{ - // auto fan_list = m_fan_control_list[duct.airduct_id]; - // for (auto fan : duct.fans_list){ - // if (fan_list.find(fan.id) == fan_list.end()) - // CreateFanAndDoor(duct.airduct_id, fan); - // else{ - // auto fan_control = fan_list[fan.id]; - // fan_control->update_fan_data(fan); - // } - // } - // } - // m_duct_ctrl[duct.airduct_id] = duct.fans_ctrl[i]; - //} - //m_data = data; - //for (auto fan_list_of_duct : m_fan_control_list){ - // for (auto fan : fan_list_of_duct.second){ - // if (fan.second != nullptr) - // fan.second->set_machine_obj(obj); - // } - //} - ////auto text = wxString::Format("%s", radio_btn_name[AIR_DUCT_mode_e(m_data.curren_duct)]); - //auto text = wxT("The fan controls the temperature during printing to improve print quality.The system automatically adjusts the fan's switch and speed according to dif"); - //m_cooling_text->SetLabelText(text); - //m_cooling_text->Wrap(FromDIP(360)); - - //ChangeCoolingTips(m_data.airducts.size()); - - //if (data.airducts.size() <= 1) - // m_radio_btn_sizer->Show(false); - //else - // m_radio_btn_sizer->Show(true); - - //this->Layout(); - - //Bind(EVT_FAN_CHANGED, [this](wxCommandEvent& e) { - // post_event(e.GetInt(), e.GetString()); - // }); -} - void FanControlPopupNew::on_left_down(wxMouseEvent& evt) { auto mouse_pos = ClientToScreen(evt.GetPosition()); - for (SendModeSwitchButton* sw_it : m_mode_switch_btn_list) { + for (const auto& iter : m_mode_switch_btns) { + SendModeSwitchButton* sw_it = iter.second; auto win_pos = sw_it->ClientToScreen(wxPoint(0, 0)); auto size = sw_it->GetSize(); if (mouse_pos.x > win_pos.x && mouse_pos.x < (win_pos.x + sw_it->GetSize().x) && mouse_pos.y > win_pos.y && @@ -887,45 +875,23 @@ void FanControlPopupNew::on_show(wxShowEvent& evt) wxGetApp().UpdateDarkUIWin(this); } -void FanControlPopupNew::command_control_air_duct(int mode_id) +void FanControlPopupNew::command_control_air_duct(int mode_id, int submode) { - m_air_duct_time_out = time_out; - token.reset(this, nop_deleter_fan_control_popup); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", control air duct, id = " << mode_id; if (m_obj) { - m_obj->command_control_air_duct(mode_id, [this, w = std::weak_ptr(token), mode_id](const json& reply) { - if (w.expired()) - return; - m_air_duct_time_out = 0; - if (reply.contains("errno")) { - int result = reply["errno"].get(); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", control air duct, errno = " << result; - if (result == 0) { - int update_id = mode_id; - if (reply.contains("modeId")) { - update_id = reply["modeId"].get(); - this->UpdateParts(update_id); - this->UpdateTips(update_id); - } - } - this->Layout(); - this->Refresh(); - } - }); + m_obj->command_control_air_duct(mode_id, submode, [](const json& reply) {}); + + m_air_duct_time_out = time_out; + m_data.curren_mode = mode_id; + m_data.m_sub_mode = submode; + this->UpdateParts(); } } void FanControlPopupNew::msw_rescale() { - for (auto btn : m_mode_switch_btn_list) - { - btn->msw_rescale(); - } - - for (auto fan : m_fan_control_list) - { - fan.second->msw_rescale(); - } + for (const auto& btn_iter : m_mode_switch_btns) { btn_iter.second->msw_rescale(); } + for (const auto& fan_iter : m_fan_control_list) { fan_iter.second->msw_rescale(); } } void FanControlPopupNew::paintEvent(wxPaintEvent& evt) @@ -951,19 +917,19 @@ void FanControlPopupNew::on_mode_changed(const wxMouseEvent &event) } /* update buttons*/ - for (size_t i = 0; i < m_mode_switch_btn_list.size(); ++i) + for (const auto& btn_iter : m_mode_switch_btns) { - if (m_mode_switch_btn_list[i]->GetId() == event.GetId()) + if (btn_iter.second->GetId() == event.GetId()) { - if (!m_mode_switch_btn_list[i]->isSelected()) + if (!btn_iter.second->isSelected()) { - m_mode_switch_btn_list[i]->setSelected(true); - command_control_air_duct(i); + btn_iter.second->setSelected(true); + command_control_air_duct(btn_iter.first); } } else { - m_mode_switch_btn_list[i]->setSelected(false); + btn_iter.second->setSelected(false); } } } @@ -973,14 +939,13 @@ void FanControlPopupNew::on_fan_changed(const wxCommandEvent &event) m_fan_set_time_out = time_out; } -void FanControlPopupNew::init_names() { +void FanControlPopupNew::init_names(MachineObject* obj) { //Iint fan/door/func/duct name lists radio_btn_name[AIR_DUCT::AIR_DUCT_COOLING_FILT] = _L("Cooling"); radio_btn_name[AIR_DUCT::AIR_DUCT_HEATING_INTERNAL_FILT] = _L("Heating"); radio_btn_name[AIR_DUCT::AIR_DUCT_EXHAUST] = _L("Exhaust"); radio_btn_name[AIR_DUCT::AIR_DUCT_FULL_COOLING] = _L("Full Cooling"); - radio_btn_name[AIR_DUCT::AIR_DUCT_NUM] = L("Num?"); radio_btn_name[AIR_DUCT::AIR_DUCT_INIT] = L("Init"); fan_func_name[AIR_FUN::FAN_HEAT_BREAK_0_IDX] = _L("Hotend"); @@ -1002,17 +967,80 @@ void FanControlPopupNew::init_names() { label_text[AIR_DUCT::AIR_DUCT_HEATING_INTERNAL_FILT] = _L("Heating mode is suitable for printing ABS/ASA/PC/PA materials and circulates filters the chamber air."); label_text[AIR_DUCT::AIR_DUCT_EXHAUST] = _L("Exhaust"); label_text[AIR_DUCT::AIR_DUCT_FULL_COOLING] = _L("Strong cooling mode is suitable for printing PLA/TPU materials. In this mode, the printouts will be fully cooled."); - label_text[AIR_DUCT::AIR_DUCT_NUM] = _L("Num"); label_text[AIR_DUCT::AIR_DUCT_INIT] = _L("Init"); - /*label_text[AIR_DUCT_mode_e::AIR_DUCT_NONE] = "..."; - label_text[AIR_DUCT_mode_e::AIR_DUCT_COOLING_FILT] = "..."; - label_text[AIR_DUCT_mode_e::AIR_DUCT_HEATING_INTERNAL_FILT] = "..."; - label_text[AIR_DUCT_mode_e::AIR_DUCT_EXHAUST] = "Exhaust"; - label_text[AIR_DUCT_mode_e::AIR_DUCT_FULL_COOLING] = "..."; - label_text[AIR_DUCT_mode_e::AIR_DUCT_NUM] = "Num"; - label_text[AIR_DUCT_mode_e::AIR_DUCT_INIT] = "Init";*/ + // special texts + if (obj) { + const std::string& special_cooling_text = DeviceManager::get_fan_text(obj->printer_type, "special_cooling_text"); + if (!special_cooling_text.empty()) { + L("Cooling mode is suitable for printing PLA/PETG/TPU materials."); //some potential text, add i18n flags + label_text[AIR_DUCT::AIR_DUCT_COOLING_FILT] = special_cooling_text; + } + + const std::string& special_func_aux_text = DeviceManager::get_fan_text(obj->printer_type, "special_func_aux_text"); + if (!special_func_aux_text.empty()) { + L_CONTEXT("Right", "air_duct"); + fan_func_name[AIR_FUN::FAN_REMOTE_COOLING_0_IDX] = _CTX(special_func_aux_text, "air_duct"); + } + } } -}} // namespace Slic3r::GUI +wxDEFINE_EVENT(EVT_FANCTRL_SWITCH, wxCommandEvent); +FanControlNewSwitchPanel::FanControlNewSwitchPanel(wxWindow* parent, const wxString& title, const wxString& tips, bool on) + : wxWindow(parent, wxID_ANY), switch_state_on(on) +{ + Label* label = new Label(this); + label->SetBackgroundColour(wxColour(248, 248, 248)); + label->SetLabelText(title); + + m_bitmap_toggle_off = new ScalableBitmap(this, "toggle_off", 19); + m_bitmap_toggle_on = new ScalableBitmap(this, "toggle_on", 19); + if (switch_state_on) { + m_switch_btn = new wxStaticBitmap(this, wxID_ANY, m_bitmap_toggle_on->bmp()); + } else { + m_switch_btn = new wxStaticBitmap(this, wxID_ANY, m_bitmap_toggle_off->bmp()); + } + m_switch_btn->Bind(wxEVT_LEFT_DOWN, &FanControlNewSwitchPanel::on_left_down, this); + + wxSizer* m_label_sizer = new wxBoxSizer(wxHORIZONTAL); + m_label_sizer->Add(label, 0, wxALIGN_LEFT, 0); + m_label_sizer->AddSpacer(FromDIP(10)); + m_label_sizer->Add(0, 1, wxEXPAND, FromDIP(10)); + m_label_sizer->Add(m_switch_btn, 0, wxALIGN_RIGHT, 0); + + Label* tips_label = new Label(this); + tips_label->SetBackgroundColour(wxColour(248, 248, 248)); + tips_label->SetLabelText(tips); + tips_label->Wrap(FromDIP(400)); + + wxSizer* m_sizer_main = new wxBoxSizer(wxVERTICAL); + m_sizer_main->Add(m_label_sizer, 0, wxALL | wxALIGN_LEFT, FromDIP(5)); + m_sizer_main->Add(tips_label, 0, wxALL | wxALIGN_LEFT, FromDIP(5)); + SetSizer(m_sizer_main); + + SetBackgroundColour(wxColour(248, 248, 248)); + Layout(); +} + +void FanControlNewSwitchPanel::SetSwitchOn(bool on) +{ + if (switch_state_on != on) { + switch_state_on = on; + switch_state_on ? m_switch_btn->SetBitmap(m_bitmap_toggle_on->bmp()) : m_switch_btn->SetBitmap(m_bitmap_toggle_off->bmp()); + Refresh(); + } +} + +void FanControlNewSwitchPanel::on_left_down(wxMouseEvent& event) { + switch_state_on = !switch_state_on; + switch_state_on ? m_switch_btn->SetBitmap(m_bitmap_toggle_on->bmp()) : m_switch_btn->SetBitmap(m_bitmap_toggle_off->bmp()); + event.Skip(); + + wxCommandEvent evt(EVT_FANCTRL_SWITCH); + wxPostEvent(this, evt); + evt.Skip(); +} + +} +} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Widgets/FanControl.hpp b/src/slic3r/GUI/Widgets/FanControl.hpp index f0d2402700..b757cad237 100644 --- a/src/slic3r/GUI/Widgets/FanControl.hpp +++ b/src/slic3r/GUI/Widgets/FanControl.hpp @@ -178,6 +178,25 @@ public: void msw_rescale(); }; +wxDECLARE_EVENT(EVT_FANCTRL_SWITCH, wxCommandEvent); +class FanControlNewSwitchPanel : public wxWindow +{ + bool switch_state_on = false; + wxStaticBitmap* m_switch_btn{ nullptr }; + ScalableBitmap* m_bitmap_toggle_off{ nullptr }; + ScalableBitmap* m_bitmap_toggle_on{ nullptr }; + +public: + FanControlNewSwitchPanel(wxWindow* parent, const wxString& title, const wxString& tips, bool on = true); + +public: + bool IsSwitchOn() const { return switch_state_on; } + void SetSwitchOn(bool on); + +private: + void on_left_down(wxMouseEvent& event); +}; + class FanControlPopupNew : public wxDialog { @@ -189,15 +208,6 @@ public: private: wxBoxSizer* m_sizer_main{ nullptr }; - //old protocol - //FanControl* m_part_fan; - //FanControl* m_aux_fan; - //FanControl* m_cham_fan; - wxWindow* m_line_top; - wxWindow* m_line_bottom; - bool m_is_suppt_cham_fun{ true }; - bool m_is_suppt_aux_fun{ true }; - //new protocol wxGridSizer* m_radio_btn_sizer{ nullptr }; wxGridSizer* m_sizer_fanControl { nullptr }; @@ -205,54 +215,58 @@ private: wxBoxSizer *m_mode_sizer{ nullptr }; wxBoxSizer *m_bottom_sizer{ nullptr }; - AirDuctData m_data; - std::map m_fan_control_list; //> - std::vector m_mode_switch_btn_list; - int m_air_duct_time_out { 0 }; - int m_fan_set_time_out{ 0 }; + // mode switch buttons + std::unordered_map m_mode_switch_btns; // - std::map m_duct_ctrl; + // mode text + Label* m_mode_text; - Button* m_button_refresh; - Label* m_cooling_text; + // submodes + // cooling submode : filter + wxPanel* m_sub_mode_panel{ nullptr }; + wxBoxSizer* m_sub_mode_sizer{ nullptr }; + FanControlNewSwitchPanel* m_cooling_filter_switch_panel{ nullptr }; + + // The fan operates + std::map m_fan_control_list; //> + + // The object MachineObject *m_obj{nullptr}; - - std::string m_strong_str = "Strong string ...wait fill"; - std::string m_filter_str = "Filtering string ...wait fill"; - std::string m_chamber_str = "Chamber string ...wait fill"; - std::string m_normal_str = "Normal string ...wait fill"; //For X version machine + AirDuctData m_data; + int m_air_duct_time_out{ 0 }; + int m_fan_set_time_out{ 0 }; std::map radio_btn_name; std::map fan_func_name; std::map air_door_func_name; std::map label_text; - std::shared_ptr token; +private: + void init_names(MachineObject* obj); - void on_mode_changed(const wxMouseEvent &event); - void on_fan_changed(const wxCommandEvent &event); - void init_names(); - void CreateDuct(); - void UpdateParts(int mode_id); - void UpdateTips(int mode_id); - void BackupOfCreate(); - void update_fans(); //New protocol + void CreateDuct(); + + void UpdateParts(); + void UpdatePartSubMode(); + + void update_fan_data(const AirDuctData& data); + void update_fan_data(AIR_FUN id, int speed); + + void on_mode_changed(const wxMouseEvent& event); + void on_fan_changed(const wxCommandEvent& event); + void on_left_down(wxMouseEvent& evt); + void post_event(int fan_type, wxString speed); + + void on_show(wxShowEvent& evt); + void paintEvent(wxPaintEvent& evt); + + void command_control_air_duct(int mode_id, int submode = -1); public: - void show_cham_fan(bool support_cham_fun); - void show_aux_fan(bool support_aux_fun); - void update_fan_data(MachineObject *obj); - void update_fan_data(const AirDuctData& data); - void update_fan_data(AIR_FUN id, int speed); - void update_device(AirDuctData data, MachineObject *obj); // New protocol - void on_left_down(wxMouseEvent& evt); - void paintEvent(wxPaintEvent& evt); - void post_event(int fan_type, wxString speed); - void on_show(wxShowEvent& evt); - void command_control_air_duct(int mode_id); - - void msw_rescale(); + void update_fan_data(MachineObject *obj); + void msw_rescale(); }; + wxDECLARE_EVENT(EVT_FAN_SWITCH_ON, wxCommandEvent); wxDECLARE_EVENT(EVT_FAN_SWITCH_OFF, wxCommandEvent); wxDECLARE_EVENT(EVT_FAN_ADD, wxCommandEvent);