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_