BambuStudio/slic3r/GUI/CalibrationWizardSavePage.cpp

1631 lines
59 KiB
C++
Raw Normal View History

2024-12-20 06:44:50 +00:00
#include "CalibrationWizardSavePage.hpp"
#include "I18N.hpp"
#include "Widgets/Label.hpp"
#include "MsgDialog.hpp"
namespace Slic3r { namespace GUI {
#define CALIBRATION_SAVE_INPUT_SIZE wxSize(FromDIP(240), FromDIP(24))
#define FLOW_RATE_MAX_VALUE 1.15
static wxString get_default_name(wxString filament_name, CalibMode mode){
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) {
if (filament_name.compare(it->name) == 0) {
if (!it->alias.empty())
filament_name = from_u8(it->alias);
else
filament_name = from_u8(it->name);
}
}
switch (mode)
{
case Slic3r::CalibMode::Calib_None:
break;
case Slic3r::CalibMode::Calib_PA_Line:
if (filament_name.StartsWith("Generic")) {
filament_name.Replace("Generic", "Brand", false);
}
break;
case Slic3r::CalibMode::Calib_PA_Tower:
break;
case Slic3r::CalibMode::Calib_Flow_Rate:
filament_name += " Flow Rate Calibrated";
break;
case Slic3r::CalibMode::Calib_Temp_Tower:
filament_name += " Temperature Calibrated";
break;
case Slic3r::CalibMode::Calib_Vol_speed_Tower:
filament_name += " Max Vol Speed Calibrated";
break;
case Slic3r::CalibMode::Calib_VFA_Tower:
break;
case Slic3r::CalibMode::Calib_Retraction_tower:
break;
default:
break;
}
return filament_name;
}
static wxString get_tray_name_by_tray_id(int tray_id)
{
wxString tray_name;
if (tray_id == VIRTUAL_TRAY_ID) {
tray_name = "Ext";
}
else {
char prefix = 'A' + (tray_id / 4);
char suffix = '0' + 1 + tray_id % 4;
tray_name = std::string(1, prefix) + std::string(1, suffix);
}
return tray_name;
}
CalibrationCommonSavePage::CalibrationCommonSavePage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: CalibrationWizardPage(parent, id, pos, size, style)
{
;
}
enum class GridTextInputType {
K,
N,
FlowRatio,
Name
};
class GridTextInput : public TextInput
{
public:
GridTextInput(wxWindow* parent, wxString text, wxString label, wxSize size, int col_idx, GridTextInputType type);
int get_col_idx() { return m_col_idx; }
void set_col_idx(int idx) { m_col_idx = idx; }
GridTextInputType get_type() { return m_type; }
void set_type(GridTextInputType type) { m_type = type; }
private:
int m_col_idx;
GridTextInputType m_type;
};
GridTextInput::GridTextInput(wxWindow* parent, wxString text, wxString label, wxSize size, int col_idx, GridTextInputType type)
: TextInput(parent, text, label, "", wxDefaultPosition, size, wxTE_PROCESS_ENTER)
, m_col_idx(col_idx)
, m_type(type)
{
}
class GridComboBox : public ComboBox {
public:
GridComboBox(wxWindow* parent, wxSize size, int col_idx);
int get_col_idx() { return m_col_idx; }
void set_col_idx(int idx) { m_col_idx = idx; }
private:
int m_col_idx;
};
GridComboBox::GridComboBox(wxWindow* parent, wxSize size, int col_idx)
: ComboBox(parent, wxID_ANY, "", wxDefaultPosition, size, 0, nullptr)
, m_col_idx(col_idx)
{
}
CaliPASaveAutoPanel::CaliPASaveAutoPanel(
wxWindow* parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style)
: wxPanel(parent, id, pos, size, style)
{
SetBackgroundColour(*wxWHITE);
m_top_sizer = new wxBoxSizer(wxVERTICAL);
create_panel(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
void CaliPASaveAutoPanel::create_panel(wxWindow* parent)
{
m_complete_text_panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
m_complete_text_panel->SetBackgroundColour(*wxWHITE);
m_complete_text_panel->Hide();
wxBoxSizer* complete_text_sizer = new wxBoxSizer(wxVERTICAL);
auto complete_text = new Label(m_complete_text_panel, _L("We found the best Flow Dynamics Calibration Factor"));
complete_text->SetFont(Label::Head_14);
complete_text_sizer->Add(complete_text, 0, wxEXPAND);
m_complete_text_panel->SetSizer(complete_text_sizer);
m_part_failed_panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
m_part_failed_panel->SetBackgroundColour(wxColour(238, 238, 238));
wxBoxSizer* part_failed_sizer = new wxBoxSizer(wxVERTICAL);
m_part_failed_panel->SetSizer(part_failed_sizer);
part_failed_sizer->AddSpacer(FromDIP(10));
auto part_failed_text = new Label(m_part_failed_panel, _L("Part of the calibration failed! You may clean the plate and retry. The failed test result would be dropped."));
part_failed_text->SetFont(Label::Body_14);
part_failed_sizer->Add(part_failed_text, 0, wxLEFT | wxRIGHT, FromDIP(20));
part_failed_sizer->AddSpacer(FromDIP(10));
m_top_sizer->Add(m_part_failed_panel, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
m_top_sizer->Add(m_complete_text_panel, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
m_grid_panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
m_grid_panel->SetBackgroundColour(*wxWHITE);
m_top_sizer->Add(m_grid_panel, 0, wxALIGN_CENTER);
m_top_sizer->AddSpacer(FromDIP(10));
auto naming_hints = new Label(parent, _L("*We recommend you to add brand, material, type, and even humidity level in the Name"));
naming_hints->SetFont(Label::Body_14);
naming_hints->SetForegroundColour(wxColour(157, 157, 157));
m_top_sizer->Add(naming_hints, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
}
std::vector<std::pair<int, std::string>> CaliPASaveAutoPanel::default_naming(std::vector<std::pair<int, std::string>> preset_names)
{
std::unordered_set<std::string> set;
int i = 1;
for (auto& item : preset_names) {
if (!set.insert(item.second).second) {
item.second = get_default_name(item.second, CalibMode::Calib_PA_Line).ToUTF8().data();
item.second += "_" + std::to_string(i);
i++;
}
else {
item.second = get_default_name(item.second, CalibMode::Calib_PA_Line).ToUTF8().data();
}
}
return preset_names;
}
void CaliPASaveAutoPanel::sync_cali_result(const std::vector<PACalibResult>& cali_result, const std::vector<PACalibResult>& history_result)
{
m_history_results = history_result;
m_calib_results.clear();
for (auto& item : cali_result) {
if (item.confidence == 0)
m_calib_results[item.tray_id] = item;
}
m_grid_panel->DestroyChildren();
auto grid_sizer = new wxBoxSizer(wxHORIZONTAL);
const int COLUMN_GAP = FromDIP(20);
const int ROW_GAP = FromDIP(30);
wxBoxSizer* left_title_sizer = new wxBoxSizer(wxVERTICAL);
left_title_sizer->AddSpacer(FromDIP(52));
auto k_title = new Label(m_grid_panel, _L("Factor K"));
k_title->SetFont(Label::Head_14);
left_title_sizer->Add(k_title, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
auto n_title = new Label(m_grid_panel, _L("Factor N"));
n_title->SetFont(Label::Head_14);
// hide n value
n_title->Hide();
left_title_sizer->Add(n_title, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
auto brand_title = new Label(m_grid_panel, _L("Name"));
brand_title->SetFont(Label::Head_14);
left_title_sizer->Add(brand_title, 0, wxALIGN_CENTER);
grid_sizer->Add(left_title_sizer);
grid_sizer->AddSpacer(COLUMN_GAP);
m_is_all_failed = true;
bool part_failed = false;
if (cali_result.empty())
part_failed = true;
std::vector<std::pair<int, std::string>> preset_names;
for (auto& info : m_obj->selected_cali_preset) {
preset_names.push_back({ info.tray_id, info.name });
}
preset_names = default_naming(preset_names);
for (auto& item : cali_result) {
bool result_failed = false;
if (item.confidence != 0) {
result_failed = true;
part_failed = true;
}
else {
m_is_all_failed = false;
}
wxBoxSizer* column_data_sizer = new wxBoxSizer(wxVERTICAL);
auto tray_title = new Label(m_grid_panel, "");
tray_title->SetFont(Label::Head_14);
wxString tray_name = get_tray_name_by_tray_id(item.tray_id);
tray_title->SetLabel(tray_name);
auto k_value = new GridTextInput(m_grid_panel, "", "", CALIBRATION_SAVE_INPUT_SIZE, item.tray_id, GridTextInputType::K);
auto n_value = new GridTextInput(m_grid_panel, "", "", CALIBRATION_SAVE_INPUT_SIZE, item.tray_id, GridTextInputType::N);
k_value->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
n_value->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
auto k_value_failed = new Label(m_grid_panel, _L("Failed"));
auto n_value_failed = new Label(m_grid_panel, _L("Failed"));
auto comboBox_tray_name = new GridComboBox(m_grid_panel, CALIBRATION_SAVE_INPUT_SIZE, item.tray_id);
auto tray_name_failed = new Label(m_grid_panel, " - ");
wxArrayString selections;
static std::vector<PACalibResult> filtered_results;
filtered_results.clear();
for (auto history : history_result) {
if (history.filament_id == item.filament_id) {
filtered_results.push_back(history);
selections.push_back(from_u8(history.name));
}
}
comboBox_tray_name->Set(selections);
column_data_sizer->Add(tray_title, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
column_data_sizer->Add(k_value, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
column_data_sizer->Add(n_value, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
column_data_sizer->Add(k_value_failed, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
column_data_sizer->Add(n_value_failed, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
column_data_sizer->Add(comboBox_tray_name, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
column_data_sizer->Add(tray_name_failed, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
auto set_edit_mode = [this, k_value, n_value, k_value_failed, n_value_failed, comboBox_tray_name, tray_name_failed](std::string str) {
if (str == "normal") {
comboBox_tray_name->Show();
tray_name_failed->Show(false);
k_value->Show();
n_value->Show();
k_value_failed->Show(false);
n_value_failed->Show(false);
}
if (str == "failed") {
comboBox_tray_name->Show(false);
tray_name_failed->Show();
k_value->Show(false);
n_value->Show(false);
k_value_failed->Show();
n_value_failed->Show();
}
// hide n value
n_value->Hide();
n_value_failed->Hide();
m_grid_panel->Layout();
m_grid_panel->Update();
};
if (!result_failed) {
set_edit_mode("normal");
auto k_str = wxString::Format("%.3f", item.k_value);
auto n_str = wxString::Format("%.3f", item.n_coef);
k_value->GetTextCtrl()->SetValue(k_str);
n_value->GetTextCtrl()->SetValue(n_str);
for (auto& name : preset_names) {
if (item.tray_id == name.first) {
comboBox_tray_name->SetValue(from_u8(name.second));
}
}
comboBox_tray_name->Bind(wxEVT_COMBOBOX, [this, comboBox_tray_name, k_value, n_value](auto& e) {
int selection = comboBox_tray_name->GetSelection();
auto history = filtered_results[selection];
});
}
else {
set_edit_mode("failed");
}
grid_sizer->Add(column_data_sizer);
grid_sizer->AddSpacer(COLUMN_GAP);
}
m_grid_panel->SetSizer(grid_sizer, true);
m_grid_panel->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
SetFocusIgnoringChildren();
});
if (part_failed) {
m_part_failed_panel->Show();
m_complete_text_panel->Show();
if (m_is_all_failed) {
m_complete_text_panel->Hide();
}
}
else {
m_complete_text_panel->Show();
m_part_failed_panel->Hide();
}
wxGetApp().UpdateDarkUIWin(this);
Layout();
}
void CaliPASaveAutoPanel::save_to_result_from_widgets(wxWindow* window, bool* out_is_valid, wxString* out_msg) {
if (!window)
return;
//operate
auto input = dynamic_cast<GridTextInput*>(window);
if (input && input->IsShown()) {
int tray_id = input->get_col_idx();
if (input->get_type() == GridTextInputType::K) {
float k = 0.0f;
if (!CalibUtils::validate_input_k_value(input->GetTextCtrl()->GetValue(), &k)) {
*out_msg = wxString::Format(_L("Please input a valid value (K in %.1f~%.1f)"), MIN_PA_K_VALUE, MAX_PA_K_VALUE);
*out_is_valid = false;
}
else
m_calib_results[tray_id].k_value = k;
}
else if (input->get_type() == GridTextInputType::N) {
}
}
auto comboBox = dynamic_cast<GridComboBox*>(window);
if (comboBox && comboBox->IsShown()) {
int tray_id = comboBox->get_col_idx();
wxString name = comboBox->GetTextCtrl()->GetValue().ToStdString();
if (name.IsEmpty()) {
*out_msg = _L("Please enter the name you want to save to printer.");
*out_is_valid = false;
}
else if (name.Length() > 40) {
*out_msg = _L("The name cannot exceed 40 characters.");
*out_is_valid = false;
}
m_calib_results[tray_id].name = into_u8(name);
}
auto childern = window->GetChildren();
for (auto child : childern) {
save_to_result_from_widgets(child, out_is_valid, out_msg);
}
};
bool CaliPASaveAutoPanel::get_result(std::vector<PACalibResult>& out_result) {
bool is_valid = true;
wxString err_msg;
// Check if the input value is valid and save to m_calib_results
save_to_result_from_widgets(m_grid_panel, &is_valid, &err_msg);
if (is_valid) {
// Check for duplicate names
struct PACalibResult {
size_t operator()(const std::pair<std::string ,std::string>& item) const {
return std::hash<string>()(item.first) * std::hash<string>()(item.second);
}
};
std::unordered_set<std::pair<std::string, std::string>, PACalibResult> set;
for (auto& result : m_calib_results) {
if (!set.insert({ result.second.name, result.second.filament_id }).second) {
MessageDialog msg_dlg(nullptr, _L("Only one of the results with the same name will be saved. Are you sure you want to override the other results?"), wxEmptyString, wxICON_WARNING | wxYES_NO);
if (msg_dlg.ShowModal() != wxID_YES) {
return false;
}
else {
break;
}
}
}
// Check for duplicate names from history
for (auto& result : m_history_results) {
if (!set.insert({ result.name, result.filament_id }).second) {
MessageDialog msg_dlg(nullptr, wxString::Format(_L("There is already a historical calibration result with the same name: %s. Only one of the results with the same name is saved. Are you sure you want to override the historical result?"), result.name), wxEmptyString, wxICON_WARNING | wxYES_NO);
if (msg_dlg.ShowModal() != wxID_YES) {
return false;
}
}
}
for (auto& result : m_calib_results) {
out_result.push_back(result.second);
}
return true;
}
else {
MessageDialog msg_dlg(nullptr, err_msg, wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return false;
}
}
CaliPASaveManualPanel::CaliPASaveManualPanel(
wxWindow* parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style)
: wxPanel(parent, id, pos, size, style)
{
SetBackgroundColour(*wxWHITE);
m_top_sizer = new wxBoxSizer(wxVERTICAL);
create_panel(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
void CaliPASaveManualPanel::create_panel(wxWindow* parent)
{
auto complete_text_panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
complete_text_panel->SetBackgroundColour(*wxWHITE);
wxBoxSizer* complete_text_sizer = new wxBoxSizer(wxVERTICAL);
m_complete_text = new Label(complete_text_panel, _L("Please find the best line on your plate"));
m_complete_text->SetFont(Label::Head_14);
m_complete_text->Wrap(CALIBRATION_TEXT_MAX_LENGTH);
complete_text_sizer->Add(m_complete_text, 0);
complete_text_panel->SetSizer(complete_text_sizer);
m_top_sizer->Add(complete_text_panel, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
m_picture_panel = new CaliPagePicture(parent);
set_save_img();
m_top_sizer->Add(m_picture_panel, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
auto k_value_text = new Label(parent, _L("Factor K"));
k_value_text->SetFont(::Label::Head_14);
k_value_text->Wrap(-1);
auto n_value_text = new Label(parent, _L("Factor N"));
n_value_text->SetFont(::Label::Head_14);
n_value_text->Wrap(-1);
n_value_text->Hide();
m_k_val = new TextInput(parent, wxEmptyString, "", "", wxDefaultPosition, CALIBRATION_OPTIMAL_INPUT_SIZE, 0);
m_k_val->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_n_val = new TextInput(parent, wxEmptyString, "", "", wxDefaultPosition, CALIBRATION_OPTIMAL_INPUT_SIZE, 0);
m_n_val->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_n_val->Hide();
m_top_sizer->Add(k_value_text, 0);
m_top_sizer->Add(m_k_val, 0);
m_top_sizer->AddSpacer(FromDIP(20));
auto save_text = new Label(parent, _L("Name"));
save_text->SetFont(Label::Head_14);
m_top_sizer->Add(save_text, 0, 0, 0);
m_save_name_input = new TextInput(parent, "", "", "", wxDefaultPosition, { CALIBRATION_TEXT_MAX_LENGTH, FromDIP(24) }, 0);
m_top_sizer->Add(m_save_name_input, 0, 0, 0);
m_top_sizer->AddSpacer(FromDIP(10));
auto naming_hints = new Label(parent, _L("*We recommend you to add brand, material, type, and even humidity level in the Name"));
naming_hints->SetFont(Label::Body_14);
naming_hints->SetForegroundColour(wxColour(157, 157, 157));
m_top_sizer->Add(naming_hints, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
SetFocusIgnoringChildren();
});
}
void CaliPASaveManualPanel::set_save_img() {
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_calibration_manual_result_CN", 330));
} else {
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_calibration_manual_result", 330));
}
}
void CaliPASaveManualPanel::set_pa_cali_method(ManualPaCaliMethod method)
{
if (method == ManualPaCaliMethod::PA_LINE) {
m_complete_text->SetLabel(_L("Please find the best line on your plate"));
set_save_img();
} else if (method == ManualPaCaliMethod::PA_PATTERN) {
m_complete_text->SetLabel(_L("Please find the corner with perfect degree of extrusion"));
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_pattern_manual_result_CN", 350));
} else {
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_pattern_manual_result", 350));
}
}
}
void CaliPASaveManualPanel::set_default_name(const wxString& name) {
m_save_name_input->GetTextCtrl()->SetValue(name);
}
bool CaliPASaveManualPanel::get_result(PACalibResult& out_result) {
// Check if the value is valid
float k;
if (!CalibUtils::validate_input_k_value(m_k_val->GetTextCtrl()->GetValue(), &k)) {
MessageDialog msg_dlg(nullptr, wxString::Format(_L("Please input a valid value (K in %.1f~%.1f)"), MIN_PA_K_VALUE, MAX_PA_K_VALUE), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return false;
}
wxString name = m_save_name_input->GetTextCtrl()->GetValue();
if (!CalibUtils::validate_input_name(name))
return false;
out_result.k_value = k;
out_result.name = into_u8(name);
if (m_obj) {
assert(m_obj->selected_cali_preset.size() <= 1);
if (!m_obj->selected_cali_preset.empty()) {
out_result.tray_id = m_obj->selected_cali_preset[0].tray_id;
out_result.nozzle_diameter = m_obj->selected_cali_preset[0].nozzle_diameter;
out_result.filament_id = m_obj->selected_cali_preset[0].filament_id;
out_result.setting_id = m_obj->selected_cali_preset[0].setting_id;
}
else {
BOOST_LOG_TRIVIAL(trace) << "CaliPASaveManual: obj->selected_cali_preset is empty";
return false;
}
}
else {
BOOST_LOG_TRIVIAL(trace) << "CaliPASaveManual::get_result(): obj is nullptr";
return false;
}
return true;
}
bool CaliPASaveManualPanel::Show(bool show) {
if (show) {
if (m_obj) {
if (!m_obj->selected_cali_preset.empty()) {
wxString default_name = get_default_name(m_obj->selected_cali_preset[0].name, CalibMode::Calib_PA_Line);
set_default_name(default_name);
m_k_val->GetTextCtrl()->SetLabel("");
m_n_val->GetTextCtrl()->SetLabel("");
}
}
else {
BOOST_LOG_TRIVIAL(trace) << "CaliPASaveManual::Show(): obj is nullptr";
}
}
return wxPanel::Show(show);
}
void CaliPASaveManualPanel::msw_rescale()
{
m_picture_panel->msw_rescale();
}
CaliPASaveP1PPanel::CaliPASaveP1PPanel(
wxWindow* parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style)
: wxPanel(parent, id, pos, size, style)
{
SetBackgroundColour(*wxWHITE);
m_top_sizer = new wxBoxSizer(wxVERTICAL);
create_panel(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
void CaliPASaveP1PPanel::create_panel(wxWindow* parent)
{
auto complete_text_panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
complete_text_panel->SetBackgroundColour(*wxWHITE);
wxBoxSizer* complete_text_sizer = new wxBoxSizer(wxVERTICAL);
m_complete_text = new Label(complete_text_panel, _L("Please find the best line on your plate"));
m_complete_text->SetFont(Label::Head_14);
m_complete_text->Wrap(CALIBRATION_TEXT_MAX_LENGTH);
complete_text_sizer->Add(m_complete_text, 0, wxEXPAND);
complete_text_panel->SetSizer(complete_text_sizer);
m_top_sizer->Add(complete_text_panel, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
m_picture_panel = new CaliPagePicture(parent);
set_save_img();
m_top_sizer->Add(m_picture_panel, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
auto value_sizer = new wxBoxSizer(wxHORIZONTAL);
auto k_value_text = new Label(parent, _L("Factor K"));
k_value_text->Wrap(-1);
k_value_text->SetFont(::Label::Head_14);
auto n_value_text = new Label(parent, _L("Factor N"));
n_value_text->Wrap(-1);
n_value_text->SetFont(::Label::Head_14);
m_k_val = new TextInput(parent, wxEmptyString, "", "", wxDefaultPosition, CALIBRATION_OPTIMAL_INPUT_SIZE, 0);
m_k_val->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_n_val = new TextInput(parent, wxEmptyString, "", "", wxDefaultPosition, CALIBRATION_OPTIMAL_INPUT_SIZE, 0);
m_n_val->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
n_value_text->Hide();
m_n_val->Hide();
value_sizer->Add(k_value_text, 0, wxALIGN_CENTER_VERTICAL, 0);
value_sizer->AddSpacer(FromDIP(10));
value_sizer->Add(m_k_val, 0);
value_sizer->AddSpacer(FromDIP(50));
value_sizer->Add(n_value_text, 0, wxALIGN_CENTER_VERTICAL, 0);
value_sizer->AddSpacer(FromDIP(10));
value_sizer->Add(m_n_val, 0);
m_top_sizer->Add(value_sizer, 0, wxALIGN_CENTER);
m_top_sizer->AddSpacer(FromDIP(20));
Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
SetFocusIgnoringChildren();
});
}
void CaliPASaveP1PPanel::set_save_img() {
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_calibration_manual_result_CN", 350));
} else {
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_calibration_manual_result", 350));
}
}
void CaliPASaveP1PPanel::set_pa_cali_method(ManualPaCaliMethod method)
{
if (method == ManualPaCaliMethod::PA_LINE) {
m_complete_text->SetLabel(_L("Please find the best line on your plate"));
set_save_img();
}
else if (method == ManualPaCaliMethod::PA_PATTERN) {
m_complete_text->SetLabel(_L("Please find the corner with perfect degree of extrusion"));
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_pattern_manual_result_CN", 350));
} else {
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_pattern_manual_result", 350));
}
}
}
bool CaliPASaveP1PPanel::get_result(float* out_k, float* out_n){
// Check if the value is valid
if (!CalibUtils::validate_input_k_value(m_k_val->GetTextCtrl()->GetValue(), out_k)) {
MessageDialog msg_dlg(nullptr, wxString::Format(_L("Please input a valid value (K in %.1f~%.1f)"), MIN_PA_K_VALUE, MAX_PA_K_VALUE), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return false;
}
return true;
}
bool CaliPASaveP1PPanel::Show(bool show) {
if (show) {
m_k_val->GetTextCtrl()->SetLabel("");
m_n_val->GetTextCtrl()->SetLabel("");
}
return wxPanel::Show(show);
}
void CaliPASaveP1PPanel::msw_rescale()
{
m_picture_panel->msw_rescale();
}
CaliSavePresetValuePanel::CaliSavePresetValuePanel(
wxWindow *parent,
wxWindowID id,
const wxPoint &pos,
const wxSize &size,
long style)
: wxPanel(parent, id, pos, size, style)
{
SetBackgroundColour(*wxWHITE);
m_top_sizer = new wxBoxSizer(wxVERTICAL);
create_panel(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
void CaliSavePresetValuePanel::create_panel(wxWindow *parent)
{
m_picture_panel = new CaliPagePicture(parent);
m_value_title = new Label(parent, _L("Input Value"));
m_value_title->SetFont(Label::Head_14);
m_value_title->Wrap(-1);
m_input_value = new TextInput(parent, wxEmptyString, "", "", wxDefaultPosition, CALIBRATION_OPTIMAL_INPUT_SIZE, wxTE_PROCESS_ENTER);
m_input_value->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_save_name_title = new Label(parent, _L("Save to Filament Preset"));
m_save_name_title->Wrap(-1);
m_save_name_title->SetFont(Label::Head_14);
m_input_name = new TextInput(parent, wxEmptyString, "", "", wxDefaultPosition, {CALIBRATION_TEXT_MAX_LENGTH, FromDIP(24)}, 0);
m_top_sizer->Add(m_picture_panel, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
m_top_sizer->Add(m_value_title, 0);
m_top_sizer->AddSpacer(FromDIP(10));
m_top_sizer->Add(m_input_value, 0);
m_top_sizer->AddSpacer(FromDIP(20));
m_top_sizer->Add(m_save_name_title, 0);
m_top_sizer->AddSpacer(FromDIP(10));
m_top_sizer->Add(m_input_name, 0);
m_top_sizer->AddSpacer(FromDIP(20));
}
void CaliSavePresetValuePanel::set_img(const std::string& bmp_name_in)
{
m_picture_panel->set_bmp(ScalableBitmap(this, bmp_name_in, 400));
}
void CaliSavePresetValuePanel::set_value_title(const wxString& title) {
m_value_title->SetLabel(title);
}
void CaliSavePresetValuePanel::set_save_name_title(const wxString& title) {
m_save_name_title->SetLabel(title);
}
void CaliSavePresetValuePanel::get_value(double& value)
{
m_input_value->GetTextCtrl()->GetValue().ToDouble(&value);
}
void CaliSavePresetValuePanel::get_save_name(std::string& name)
{
name = into_u8(m_input_name->GetTextCtrl()->GetValue());
}
void CaliSavePresetValuePanel::set_save_name(const std::string& name)
{
m_input_name->GetTextCtrl()->SetValue(name);
}
void CaliSavePresetValuePanel::msw_rescale()
{
m_picture_panel->msw_rescale();
}
CalibrationPASavePage::CalibrationPASavePage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: CalibrationCommonSavePage(parent, id, pos, size, style)
{
SetBackgroundColour(*wxWHITE);
m_cali_mode = CalibMode::Calib_PA_Line;
m_page_type = CaliPageType::CALI_PAGE_PA_SAVE;
m_top_sizer = new wxBoxSizer(wxVERTICAL);
create_page(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
void CalibrationPASavePage::create_page(wxWindow* parent)
{
m_page_caption = new CaliPageCaption(parent, m_cali_mode);
m_page_caption->show_prev_btn(true);
m_top_sizer->Add(m_page_caption, 0, wxEXPAND, 0);
wxArrayString steps;
steps.Add(_L("Preset"));
steps.Add(_L("Calibration"));
steps.Add(_L("Record Factor"));
m_step_panel = new CaliPageStepGuide(parent, steps);
m_step_panel->set_steps(2);
m_top_sizer->Add(m_step_panel, 0, wxEXPAND, 0);
m_manual_panel = new CaliPASaveManualPanel(parent, wxID_ANY);
m_auto_panel = new CaliPASaveAutoPanel(parent, wxID_ANY);
m_p1p_panel = new CaliPASaveP1PPanel(parent, wxID_ANY);
m_help_panel = new PAPageHelpPanel(parent);
m_manual_panel->Hide();
m_p1p_panel->Hide();
m_top_sizer->Add(m_manual_panel, 0, wxEXPAND);
m_top_sizer->Add(m_auto_panel, 0, wxEXPAND);
m_top_sizer->Add(m_p1p_panel, 0, wxEXPAND);
m_top_sizer->Add(m_help_panel, 0, wxEXPAND);
m_top_sizer->AddSpacer(FromDIP(20));
m_action_panel = new CaliPageActionPanel(parent, m_cali_mode, CaliPageType::CALI_PAGE_PA_SAVE);
m_top_sizer->Add(m_action_panel, 0, wxEXPAND, 0);
}
void CalibrationPASavePage::sync_cali_result(MachineObject* obj)
{
// only auto need sync cali_result
if (obj && m_cali_method == CalibrationMethod::CALI_METHOD_AUTO) {
m_auto_panel->sync_cali_result(obj->pa_calib_results, obj->pa_calib_tab);
} else {
std::vector<PACalibResult> empty_result;
m_auto_panel->sync_cali_result(empty_result, empty_result);
}
}
void CalibrationPASavePage::show_panels(CalibrationMethod method, const PrinterSeries printer_ser) {
if (printer_ser == PrinterSeries::SERIES_X1) {
if (method == CalibrationMethod::CALI_METHOD_MANUAL) {
m_manual_panel->set_pa_cali_method(curr_obj->manual_pa_cali_method);
m_manual_panel->Show();
m_auto_panel->Show(false);
}
else {
m_auto_panel->Show();
m_manual_panel->Show(false);
}
m_p1p_panel->Show(false);
}
else if (curr_obj->cali_version >= 0) {
m_auto_panel->Show(false);
m_manual_panel->set_pa_cali_method(curr_obj->manual_pa_cali_method);
m_manual_panel->Show();
m_p1p_panel->Show(false);
} else {
m_auto_panel->Show(false);
m_manual_panel->Show(false);
m_p1p_panel->set_pa_cali_method(curr_obj->manual_pa_cali_method);
m_p1p_panel->Show();
assert(false);
}
Layout();
}
void CalibrationPASavePage::set_cali_method(CalibrationMethod method)
{
CalibrationWizardPage::set_cali_method(method);
if (curr_obj) {
show_panels(method, curr_obj->get_printer_series());
}
}
void CalibrationPASavePage::on_device_connected(MachineObject* obj)
{
curr_obj = obj;
m_auto_panel->set_machine_obj(curr_obj);
m_manual_panel->set_machine_obj(curr_obj);
if (curr_obj)
show_panels(m_cali_method, curr_obj->get_printer_series());
}
void CalibrationPASavePage::update(MachineObject* obj)
{
CalibrationWizardPage::update(obj);
if (m_auto_panel && m_auto_panel->IsShown())
m_auto_panel->set_machine_obj(obj);
if (m_manual_panel && m_manual_panel->IsShown())
m_manual_panel->set_machine_obj(obj);
}
bool CalibrationPASavePage::Show(bool show) {
if (show) {
if (curr_obj) {
show_panels(m_cali_method, curr_obj->get_printer_series());
sync_cali_result(curr_obj);
}
}
return wxPanel::Show(show);
}
void CalibrationPASavePage::msw_rescale()
{
CalibrationWizardPage::msw_rescale();
m_manual_panel->msw_rescale();
m_p1p_panel->msw_rescale();
m_help_panel->msw_rescale();
}
CalibrationFlowX1SavePage::CalibrationFlowX1SavePage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: CalibrationCommonSavePage(parent, id, pos, size, style)
{
SetBackgroundColour(*wxWHITE);
m_cali_mode = CalibMode::Calib_Flow_Rate;
m_page_type = CaliPageType::CALI_PAGE_FLOW_SAVE;
m_top_sizer = new wxBoxSizer(wxVERTICAL);
create_page(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
void CalibrationFlowX1SavePage::create_page(wxWindow* parent)
{
m_page_caption = new CaliPageCaption(parent, m_cali_mode);
m_page_caption->show_prev_btn(true);
m_top_sizer->Add(m_page_caption, 0, wxEXPAND, 0);
wxArrayString steps;
steps.Add(_L("Preset"));
steps.Add(_L("Calibration"));
steps.Add(_L("Record Factor"));
m_step_panel = new CaliPageStepGuide(parent, steps);
m_step_panel->set_steps(2);
m_top_sizer->Add(m_step_panel, 0, wxEXPAND, 0);
m_complete_text_panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
m_complete_text_panel->SetBackgroundColour(*wxWHITE);
m_complete_text_panel->Hide();
wxBoxSizer* complete_text_sizer = new wxBoxSizer(wxVERTICAL);
auto complete_text = new Label(m_complete_text_panel, _L("We found the best flow ratio for you"));
complete_text->SetFont(Label::Head_14);
complete_text_sizer->Add(complete_text, 0, wxEXPAND);
m_complete_text_panel->SetSizer(complete_text_sizer);
m_part_failed_panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
m_part_failed_panel->SetBackgroundColour(wxColour(238, 238, 238));
wxBoxSizer* part_failed_sizer = new wxBoxSizer(wxVERTICAL);
m_part_failed_panel->SetSizer(part_failed_sizer);
part_failed_sizer->AddSpacer(FromDIP(10));
auto part_failed_text = new Label(m_part_failed_panel, _L("Part of the calibration failed! You may clean the plate and retry. The failed test result would be dropped."));
part_failed_text->SetFont(Label::Body_14);
part_failed_sizer->Add(part_failed_text, 0, wxLEFT | wxRIGHT, FromDIP(20));
part_failed_sizer->AddSpacer(FromDIP(10));
m_top_sizer->Add(m_part_failed_panel, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
m_top_sizer->Add(m_complete_text_panel, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
m_grid_panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
m_grid_panel->SetBackgroundColour(*wxWHITE);
m_top_sizer->Add(m_grid_panel, 0, wxALIGN_CENTER);
m_action_panel = new CaliPageActionPanel(parent, m_cali_mode, CaliPageType::CALI_PAGE_FLOW_SAVE);
m_top_sizer->Add(m_action_panel, 0, wxEXPAND, 0);
}
void CalibrationFlowX1SavePage::sync_cali_result(const std::vector<FlowRatioCalibResult>& cali_result)
{
m_save_results.clear();
m_grid_panel->DestroyChildren();
wxBoxSizer* grid_sizer = new wxBoxSizer(wxHORIZONTAL);
const int COLUMN_GAP = FromDIP(20);
const int ROW_GAP = FromDIP(30);
wxBoxSizer* left_title_sizer = new wxBoxSizer(wxVERTICAL);
left_title_sizer->AddSpacer(FromDIP(49));
auto flow_ratio_title = new Label(m_grid_panel, _L("Flow Ratio"));
flow_ratio_title->SetFont(Label::Head_14);
left_title_sizer->Add(flow_ratio_title, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP + FromDIP(10));
auto brand_title = new Label(m_grid_panel, _L("Save to Filament Preset"));
brand_title->SetFont(Label::Head_14);
left_title_sizer->Add(brand_title, 0, wxALIGN_CENTER);
grid_sizer->Add(left_title_sizer);
grid_sizer->AddSpacer(COLUMN_GAP);
m_is_all_failed = true;
bool part_failed = false;
if (cali_result.empty())
part_failed = true;
for (auto& item : cali_result) {
bool result_failed = false;
if (item.confidence != 0 || item.flow_ratio < 1e-3 || item.flow_ratio > FLOW_RATE_MAX_VALUE) {
result_failed = true;
part_failed = true;
}
else {
m_is_all_failed = false;
}
wxBoxSizer* column_data_sizer = new wxBoxSizer(wxVERTICAL);
auto tray_title = new Label(m_grid_panel, "");
tray_title->SetFont(Label::Head_14);
wxString tray_name = get_tray_name_by_tray_id(item.tray_id);
tray_title->SetLabel(tray_name);
auto flow_ratio_value = new GridTextInput(m_grid_panel, "", "", CALIBRATION_SAVE_INPUT_SIZE, item.tray_id, GridTextInputType::FlowRatio);
flow_ratio_value->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
auto flow_ratio_value_failed = new Label(m_grid_panel, _L("Failed"));
auto save_name_input = new GridTextInput(m_grid_panel, "", "", { CALIBRATION_TEXT_MAX_LENGTH, FromDIP(24) }, item.tray_id, GridTextInputType::Name);
auto save_name_input_failed = new Label(m_grid_panel, " - ");
column_data_sizer->Add(tray_title, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
column_data_sizer->Add(flow_ratio_value, 0, wxALIGN_LEFT | wxBOTTOM, ROW_GAP);
column_data_sizer->Add(flow_ratio_value_failed, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
column_data_sizer->Add(save_name_input, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
column_data_sizer->Add(save_name_input_failed, 0, wxALIGN_CENTER | wxBOTTOM, ROW_GAP);
auto set_edit_mode = [this, flow_ratio_value, flow_ratio_value_failed, save_name_input, save_name_input_failed](std::string str) {
if (str == "normal") {
save_name_input->Show();
save_name_input_failed->Show(false);
flow_ratio_value->Show();
flow_ratio_value_failed->Show(false);
}
if (str == "failed") {
save_name_input->Show(false);
save_name_input_failed->Show();
flow_ratio_value->Show(false);
flow_ratio_value_failed->Show();
}
m_grid_panel->Layout();
m_grid_panel->Update();
};
if (!result_failed) {
set_edit_mode("normal");
auto flow_ratio_str = wxString::Format("%.3f", item.flow_ratio);
flow_ratio_value->GetTextCtrl()->SetValue(flow_ratio_str);
for (auto& info : curr_obj->selected_cali_preset) {
if (item.tray_id == info.tray_id) {
save_name_input->GetTextCtrl()->SetValue(get_default_name(info.name, CalibMode::Calib_Flow_Rate) + "_" + tray_name);
break;
}
else {
BOOST_LOG_TRIVIAL(trace) << "CalibrationFlowX1Save : obj->selected_cali_preset doesn't contain correct tray_id";
}
}
}
else {
set_edit_mode("failed");
}
grid_sizer->Add(column_data_sizer);
grid_sizer->AddSpacer(COLUMN_GAP);
}
m_grid_panel->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
m_grid_panel->SetFocusIgnoringChildren();
});
m_grid_panel->SetSizer(grid_sizer, true);
if (part_failed) {
m_part_failed_panel->Show();
m_complete_text_panel->Show();
if (m_is_all_failed) {
m_complete_text_panel->Hide();
}
}
else {
m_complete_text_panel->Show();
m_part_failed_panel->Hide();
}
wxGetApp().UpdateDarkUIWin(this);
Layout();
}
void CalibrationFlowX1SavePage::save_to_result_from_widgets(wxWindow* window, bool* out_is_valid, wxString* out_msg)
{
if (!window)
return;
//operate
auto input = dynamic_cast<GridTextInput*>(window);
if (input && input->IsShown()) {
int tray_id = input->get_col_idx();
if (input->get_type() == GridTextInputType::FlowRatio) {
float flow_ratio = 0.0f;
if (!CalibUtils::validate_input_flow_ratio(input->GetTextCtrl()->GetValue(), &flow_ratio)) {
*out_msg = _L("Please input a valid value (0.0 < flow ratio < 2.0)");
*out_is_valid = false;
}
m_save_results[tray_id].second = flow_ratio;
}
else if (input->get_type() == GridTextInputType::Name) {
if (input->GetTextCtrl()->GetValue().IsEmpty()) {
*out_msg = _L("Please enter the name of the preset you want to save.");
*out_is_valid = false;
}
m_save_results[tray_id].first = input->GetTextCtrl()->GetValue().ToStdString();
}
}
auto childern = window->GetChildren();
for (auto child : childern) {
save_to_result_from_widgets(child, out_is_valid, out_msg);
}
}
bool CalibrationFlowX1SavePage::get_result(std::vector<std::pair<wxString, float>>& out_results)
{
bool is_valid = true;
wxString err_msg;
// Check if the value is valid and save to m_calib_results
save_to_result_from_widgets(m_grid_panel, &is_valid, &err_msg);
if (is_valid) {
// obj->cali_result contain failure results, so use m_save_results to record value
for (auto& item : m_save_results) {
out_results.push_back(item.second);
}
return true;
}
else {
MessageDialog msg_dlg(nullptr, err_msg, wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return false;
}
}
bool CalibrationFlowX1SavePage::Show(bool show) {
if (show) {
if (curr_obj) {
sync_cali_result(curr_obj->flow_ratio_results);
}
}
return wxPanel::Show(show);
}
void CalibrationFlowX1SavePage::msw_rescale()
{
CalibrationWizardPage::msw_rescale();
}
CalibrationFlowCoarseSavePage::CalibrationFlowCoarseSavePage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: CalibrationCommonSavePage(parent, id, pos, size, style)
{
SetBackgroundColour(*wxWHITE);
m_cali_mode = CalibMode::Calib_Flow_Rate;
m_page_type = CaliPageType::CALI_PAGE_COARSE_SAVE;
m_top_sizer = new wxBoxSizer(wxVERTICAL);
create_page(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
void CalibrationFlowCoarseSavePage::create_page(wxWindow* parent)
{
m_page_caption = new CaliPageCaption(parent, m_cali_mode);
m_page_caption->show_prev_btn(true);
m_top_sizer->Add(m_page_caption, 0, wxEXPAND, 0);
wxArrayString steps;
steps.Add(_L("Preset"));
steps.Add(_L("Calibration1"));
steps.Add(_L("Calibration2"));
steps.Add(_L("Record Factor"));
m_step_panel = new CaliPageStepGuide(parent, steps);
m_step_panel->set_steps(1);
m_top_sizer->Add(m_step_panel, 0, wxEXPAND, 0);
auto complete_text = new Label(parent, _L("Please find the best object on your plate"));
complete_text->SetFont(Label::Head_14);
complete_text->Wrap(-1);
m_top_sizer->Add(complete_text, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
m_picture_panel = new CaliPagePicture(parent);
set_save_img();
m_top_sizer->Add(m_picture_panel, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
auto coarse_value_sizer = new wxBoxSizer(wxVERTICAL);
auto coarse_value_text = new Label(parent, _L("Fill in the value above the block with smoothest top surface"));
coarse_value_text->SetFont(Label::Head_14);
coarse_value_text->Wrap(-1);
m_optimal_block_coarse = new ComboBox(parent, wxID_ANY, "", wxDefaultPosition, CALIBRATION_OPTIMAL_INPUT_SIZE, 0, nullptr, wxCB_READONLY);
wxArrayString coarse_block_items;
for (int i = 0; i < 9; i++) {
coarse_block_items.Add(std::to_string(-20 + (i * 5)));
}
m_optimal_block_coarse->Set(coarse_block_items);
m_coarse_calc_result_text = new Label(parent, "");
coarse_value_sizer->Add(coarse_value_text, 0, 0);
coarse_value_sizer->Add(m_optimal_block_coarse, 0, 0);
coarse_value_sizer->Add(m_coarse_calc_result_text, 0);
m_top_sizer->Add(coarse_value_sizer, 0, 0, 0);
m_top_sizer->AddSpacer(FromDIP(20));
auto checkBox_panel = new wxPanel(parent);
checkBox_panel->SetBackgroundColour(*wxWHITE);
auto cb_sizer = new wxBoxSizer(wxHORIZONTAL);
checkBox_panel->SetSizer(cb_sizer);
m_checkBox_skip_calibration = new CheckBox(checkBox_panel);
cb_sizer->Add(m_checkBox_skip_calibration);
auto cb_text = new Label(checkBox_panel, _L("Skip Calibration2"));
cb_sizer->Add(cb_text);
cb_text->Bind(wxEVT_LEFT_DOWN, [this](auto&) {
m_checkBox_skip_calibration->SetValue(!m_checkBox_skip_calibration->GetValue());
wxCommandEvent event(wxEVT_TOGGLEBUTTON);
event.SetEventObject(m_checkBox_skip_calibration);
m_checkBox_skip_calibration->GetEventHandler()->ProcessEvent(event);
});
m_top_sizer->Add(checkBox_panel, 0, 0, 0);
auto save_panel = new wxPanel(parent);
save_panel->SetBackgroundColour(*wxWHITE);
auto save_sizer = new wxBoxSizer(wxVERTICAL);
save_panel->SetSizer(save_sizer);
auto save_text = new Label(save_panel, _L("Save to Filament Preset"));
save_text->Wrap(-1);
save_text->SetFont(Label::Head_14);
save_sizer->Add(save_text, 0, 0, 0);
m_save_name_input = new TextInput(save_panel, "", "", "", wxDefaultPosition, {CALIBRATION_TEXT_MAX_LENGTH, FromDIP(24)}, 0);
save_sizer->Add(m_save_name_input, 0, 0, 0);
m_top_sizer->Add(save_panel, 0, 0, 0);
save_panel->Hide();
m_top_sizer->AddSpacer(FromDIP(20));
m_checkBox_skip_calibration->Bind(wxEVT_TOGGLEBUTTON, [this, save_panel](wxCommandEvent &e) {
if (m_checkBox_skip_calibration->GetValue()) {
m_skip_fine_calibration = true;
save_panel->Show();
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_COARSE_SAVE);
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, false);
}
else {
m_skip_fine_calibration = false;
save_panel->Hide();
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_COARSE_SAVE, false);
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2);
}
Layout();
Fit();
e.Skip();
});
m_optimal_block_coarse->Bind(wxEVT_COMBOBOX, [this](auto& e) {
m_coarse_flow_ratio = m_curr_flow_ratio * (100.0f + stof(m_optimal_block_coarse->GetValue().ToStdString())) / 100.0f;
m_coarse_calc_result_text->SetLabel(wxString::Format(_L("flow ratio : %s "), std::to_string(m_coarse_flow_ratio)));
});
m_sending_panel = new CaliPageSendingPanel(parent);
m_sending_panel->get_sending_progress_bar()->set_cancel_callback_fina([this]() {
on_cali_cancel_job();
});
m_sending_panel->Hide();
m_top_sizer->Add(m_sending_panel, 0, wxALIGN_CENTER);
m_action_panel = new CaliPageActionPanel(parent, m_cali_mode, CaliPageType::CALI_PAGE_COARSE_SAVE);
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_COARSE_SAVE, false);
m_top_sizer->Add(m_action_panel, 0, wxEXPAND, 0);
}
void CalibrationFlowCoarseSavePage::set_save_img() {
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
m_picture_panel->set_bmp(ScalableBitmap(this, "flow_rate_calibration_coarse_result_CN", 350));
} else {
m_picture_panel->set_bmp(ScalableBitmap(this, "flow_rate_calibration_coarse_result", 350));
}
}
void CalibrationFlowCoarseSavePage::set_default_options(const wxString& name) {
m_optimal_block_coarse->SetSelection(-1);
m_coarse_calc_result_text->SetLabelText("");
m_checkBox_skip_calibration->SetValue(false);
m_save_name_input->GetTextCtrl()->SetValue(name);
wxCommandEvent event(wxEVT_TOGGLEBUTTON);
event.SetEventObject(m_checkBox_skip_calibration);
m_checkBox_skip_calibration->GetEventHandler()->ProcessEvent(event);
}
bool CalibrationFlowCoarseSavePage::is_skip_fine_calibration() {
return m_skip_fine_calibration;
}
void CalibrationFlowCoarseSavePage::set_curr_flow_ratio(const float value) {
m_curr_flow_ratio = value;
}
bool CalibrationFlowCoarseSavePage::get_result(float* out_value, wxString* out_name) {
// Check if the value is valid
if (m_optimal_block_coarse->GetSelection() == -1 || m_coarse_flow_ratio <= 0.0 || m_coarse_flow_ratio >= 2.0) {
MessageDialog msg_dlg(nullptr, _L("Please choose a block with smoothest top surface"), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return false;
}
if (m_save_name_input->GetTextCtrl()->GetValue().IsEmpty()) {
MessageDialog msg_dlg(nullptr, _L("Please enter the name of the preset you want to save."), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return false;
}
*out_value = m_coarse_flow_ratio;
*out_name = m_save_name_input->GetTextCtrl()->GetValue();
return true;
}
bool CalibrationFlowCoarseSavePage::Show(bool show) {
if (show) {
if (curr_obj) {
assert(curr_obj->selected_cali_preset.size() <= 1);
if (!curr_obj->selected_cali_preset.empty()) {
wxString default_name = get_default_name(curr_obj->selected_cali_preset[0].name, CalibMode::Calib_Flow_Rate);
set_default_options(default_name);
set_curr_flow_ratio(curr_obj->cache_flow_ratio);
}
}
else {
BOOST_LOG_TRIVIAL(trace) << "CalibrationFlowCoarseSave::Show(): obj is nullptr";
}
}
return wxPanel::Show(show);
}
void CalibrationFlowCoarseSavePage::on_cali_start_job()
{
m_sending_panel->reset();
m_sending_panel->Show();
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, false);
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, false);
Layout();
Fit();
}
void CalibrationFlowCoarseSavePage::on_cali_finished_job()
{
m_sending_panel->reset();
m_sending_panel->Show(false);
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, true);
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, true);
Layout();
Fit();
}
void CalibrationFlowCoarseSavePage::on_cali_cancel_job()
{
BOOST_LOG_TRIVIAL(info) << "CalibrationWizard::print_job: enter canceled";
if (CalibUtils::print_job) {
if (CalibUtils::print_job->is_running()) {
BOOST_LOG_TRIVIAL(info) << "calibration_print_job: canceled";
CalibUtils::print_job->cancel();
}
CalibUtils::print_job->join();
}
m_sending_panel->reset();
m_sending_panel->Show(false);
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, true);
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, true);
Layout();
Fit();
}
void CalibrationFlowCoarseSavePage::msw_rescale()
{
CalibrationWizardPage::msw_rescale();
m_picture_panel->msw_rescale();
}
CalibrationFlowFineSavePage::CalibrationFlowFineSavePage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: CalibrationCommonSavePage(parent, id, pos, size, style)
{
SetBackgroundColour(*wxWHITE);
m_cali_mode = CalibMode::Calib_Flow_Rate;
m_page_type = CaliPageType::CALI_PAGE_FINE_SAVE;
m_top_sizer = new wxBoxSizer(wxVERTICAL);
create_page(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
void CalibrationFlowFineSavePage::create_page(wxWindow* parent)
{
m_page_caption = new CaliPageCaption(parent, m_cali_mode);
m_page_caption->show_prev_btn(true);
m_top_sizer->Add(m_page_caption, 0, wxEXPAND, 0);
wxArrayString steps;
steps.Add(_L("Preset"));
steps.Add(_L("Calibration1"));
steps.Add(_L("Calibration2"));
steps.Add(_L("Record Factor"));
m_step_panel = new CaliPageStepGuide(parent, steps);
m_step_panel->set_steps(3);
m_top_sizer->Add(m_step_panel, 0, wxEXPAND, 0);
auto complete_text = new Label(parent, _L("Please find the best object on your plate"));
complete_text->SetFont(Label::Head_14);
complete_text->Wrap(-1);
m_top_sizer->Add(complete_text, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
m_picture_panel = new CaliPagePicture(parent);
set_save_img();
m_top_sizer->Add(m_picture_panel, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
auto fine_value_sizer = new wxBoxSizer(wxVERTICAL);
auto fine_value_text = new Label(parent, _L("Fill in the value above the block with smoothest top surface"));
fine_value_text->Wrap(-1);
fine_value_text->SetFont(::Label::Head_14);
m_optimal_block_fine = new ComboBox(parent, wxID_ANY, "", wxDefaultPosition, CALIBRATION_OPTIMAL_INPUT_SIZE, 0, nullptr, wxCB_READONLY);
wxArrayString fine_block_items;
for (int i = 0; i < 10; i++) {
fine_block_items.Add(std::to_string(-9 + (i)));
}
m_optimal_block_fine->Set(fine_block_items);
m_fine_calc_result_text = new Label(parent, "");
fine_value_sizer->Add(fine_value_text, 0, 0);
fine_value_sizer->Add(m_optimal_block_fine, 0, 0);
fine_value_sizer->Add(m_fine_calc_result_text, 0);
m_top_sizer->Add(fine_value_sizer, 0, 0, 0);
m_top_sizer->AddSpacer(FromDIP(20));
auto save_text = new Label(parent, _L("Save to Filament Preset"));
save_text->Wrap(-1);
save_text->SetFont(Label::Head_14);
m_top_sizer->Add(save_text, 0, 0, 0);
m_save_name_input = new TextInput(parent, "", "", "", wxDefaultPosition, {CALIBRATION_TEXT_MAX_LENGTH, FromDIP(24)}, 0);
m_top_sizer->Add(m_save_name_input, 0, 0, 0);
m_top_sizer->AddSpacer(FromDIP(20));
m_optimal_block_fine->Bind(wxEVT_COMBOBOX, [this](auto& e) {
m_fine_flow_ratio = m_curr_flow_ratio * (100.0f + stof(m_optimal_block_fine->GetValue().ToStdString())) / 100.0f;
m_fine_calc_result_text->SetLabel(wxString::Format(_L("flow ratio : %s "), std::to_string(m_fine_flow_ratio)));
});
m_action_panel = new CaliPageActionPanel(parent, m_cali_mode, CaliPageType::CALI_PAGE_FINE_SAVE);
m_top_sizer->Add(m_action_panel, 0, wxEXPAND, 0);
}
void CalibrationFlowFineSavePage::set_save_img() {
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
m_picture_panel->set_bmp(ScalableBitmap(this, "flow_rate_calibration_fine_result_CN", 350));
} else {
m_picture_panel->set_bmp(ScalableBitmap(this, "flow_rate_calibration_fine_result", 350));
}
}
void CalibrationFlowFineSavePage::set_default_options(const wxString &name) {
m_optimal_block_fine->SetSelection(-1);
m_fine_calc_result_text->SetLabelText("");
m_save_name_input->GetTextCtrl()->SetValue(name);
}
void CalibrationFlowFineSavePage::set_curr_flow_ratio(const float value) {
m_curr_flow_ratio = value;
}
bool CalibrationFlowFineSavePage::get_result(float* out_value, wxString* out_name) {
// Check if the value is valid
if (m_optimal_block_fine->GetSelection() == -1 || m_fine_flow_ratio <= 0.0 || m_fine_flow_ratio >= 2.0) {
MessageDialog msg_dlg(nullptr, _L("Please choose a block with smoothest top surface."), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return false;
}
if (m_save_name_input->GetTextCtrl()->GetValue().IsEmpty()) {
MessageDialog msg_dlg(nullptr, _L("Please enter the name of the preset you want to save."), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return false;
}
*out_value = m_fine_flow_ratio;
*out_name = m_save_name_input->GetTextCtrl()->GetValue();
return true;
}
bool CalibrationFlowFineSavePage::Show(bool show) {
if (show) {
if (curr_obj) {
assert(curr_obj->selected_cali_preset.size() <= 1);
if (!curr_obj->selected_cali_preset.empty()) {
wxString default_name = get_default_name(curr_obj->selected_cali_preset[0].name, CalibMode::Calib_Flow_Rate);
set_default_options(default_name);
set_curr_flow_ratio(curr_obj->cache_flow_ratio);
}
}
else {
BOOST_LOG_TRIVIAL(trace) << "CalibrationFlowFineSave::Show(): obj is nullptr";
}
}
return wxPanel::Show(show);
}
void CalibrationFlowFineSavePage::msw_rescale()
{
CalibrationWizardPage::msw_rescale();
m_picture_panel->msw_rescale();
}
CalibrationMaxVolumetricSpeedSavePage::CalibrationMaxVolumetricSpeedSavePage(
wxWindow *parent,
wxWindowID id,
const wxPoint &pos,
const wxSize &size,
long style)
: CalibrationCommonSavePage(parent, id, pos, size, style)
{
SetBackgroundColour(*wxWHITE);
m_cali_mode = CalibMode::Calib_Vol_speed_Tower;
m_page_type = CaliPageType::CALI_PAGE_COMMON_SAVE;
m_top_sizer = new wxBoxSizer(wxVERTICAL);
create_page(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
void CalibrationMaxVolumetricSpeedSavePage::create_page(wxWindow *parent)
{
m_page_caption = new CaliPageCaption(parent, m_cali_mode);
m_page_caption->show_prev_btn(true);
m_top_sizer->Add(m_page_caption, 0, wxEXPAND, 0);
wxArrayString steps;
steps.Add(_L("Preset"));
steps.Add(_L("Calibration"));
steps.Add(_L("Record Factor"));
m_step_panel = new CaliPageStepGuide(parent, steps);
m_step_panel->set_steps(2);
m_top_sizer->Add(m_step_panel, 0, wxEXPAND, 0);
m_save_preset_panel = new CaliSavePresetValuePanel(parent, wxID_ANY);
set_save_img();
m_top_sizer->Add(m_save_preset_panel, 0, wxEXPAND);
m_action_panel = new CaliPageActionPanel(parent, m_cali_mode, CaliPageType::CALI_PAGE_COMMON_SAVE);
m_top_sizer->Add(m_action_panel, 0, wxEXPAND, 0);
}
void CalibrationMaxVolumetricSpeedSavePage::set_save_img() {
m_save_preset_panel->set_img("max_volumetric_speed_calibration");
}
bool CalibrationMaxVolumetricSpeedSavePage::get_save_result(double& value, std::string& name) {
// Check if the value is valid
m_save_preset_panel->get_save_name(name);
m_save_preset_panel->get_value(value);
if (value < 0 || value > 60) {
MessageDialog msg_dlg(nullptr, _L("Please input a valid value (0 <= Max Volumetric Speed <= 60)"), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return false;
}
if (name.empty()) {
MessageDialog msg_dlg(nullptr, _L("Please enter the name of the preset you want to save."), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return false;
}
return true;
}
bool CalibrationMaxVolumetricSpeedSavePage::Show(bool show) {
if (show) {
if (curr_obj) {
assert(curr_obj->selected_cali_preset.size() <= 1);
if (!curr_obj->selected_cali_preset.empty()) {
wxString default_name = get_default_name(curr_obj->selected_cali_preset[0].name, CalibMode::Calib_Vol_speed_Tower);
m_save_preset_panel->set_save_name(default_name.ToStdString());
}
}
else {
BOOST_LOG_TRIVIAL(trace) << "CalibrationMaxVolumetricSpeedSave::Show(): obj is nullptr";
}
}
return wxPanel::Show(show);
}
}}