diff --git a/src/slic3r/GUI/SavePresetDialog.cpp b/src/slic3r/GUI/SavePresetDialog.cpp index f3c8871e76..d272fec2fd 100644 --- a/src/slic3r/GUI/SavePresetDialog.cpp +++ b/src/slic3r/GUI/SavePresetDialog.cpp @@ -1,542 +1,562 @@ -#include "SavePresetDialog.hpp" - -#include -#include -#include -#include -#include - -#include -#include -#include -// BBS: add radio button for project embedded preset logic -#include - -#include "libslic3r/PresetBundle.hpp" - -#include "GUI.hpp" -#include "GUI_App.hpp" -#include "format.hpp" -#include "Tab.hpp" - -using Slic3r::GUI::format_wxstr; - -namespace Slic3r { namespace GUI { - -#define BORDER_W 10 - -//----------------------------------------------- -// SavePresetDialog::Item -//----------------------------------------------- - -SavePresetDialog::Item::Item(Preset::Type type, const std::string &suffix, wxBoxSizer *sizer, SavePresetDialog *parent) : m_type(type), m_parent(parent) -{ - Tab *tab = wxGetApp().get_tab(m_type); - assert(tab); - m_presets = tab->get_presets(); - - const Preset &sel_preset = m_presets->get_selected_preset(); - std::string preset_name = sel_preset.is_default ? "Untitled" : sel_preset.is_system ? (boost::format(("%1% - %2%")) % sel_preset.name % suffix).str() : sel_preset.name; - - // if name contains extension - if (boost::iends_with(preset_name, ".ini")) { - size_t len = preset_name.length() - 4; - preset_name.resize(len); - } - - std::vector values; - for (const Preset &preset : *m_presets) { - // BBS: add project embedded preset logic and refine is_external - if (preset.is_default || preset.is_system) - // if (preset.is_default || preset.is_system || preset.is_external) - continue; - values.push_back(preset.name); - } - - wxStaticText *label_top = new wxStaticText(m_parent, wxID_ANY, from_u8((boost::format(_utf8(L("Save %s as"))) % into_u8(tab->title())).str())); - label_top->SetFont(::Label::Body_13); - label_top->SetForegroundColour(wxColour(38,46,48)); - - - // m_valid_bmp = new wxStaticBitmap(m_parent, wxID_ANY, create_scaled_bitmap("blank_16", m_parent)); - // - // m_combo = new wxComboBox(m_parent, wxID_ANY, from_u8(preset_name), wxDefaultPosition, wxSize(35 * wxGetApp().em_unit(), -1)); - // for (const std::string& value : values) - // m_combo->Append(from_u8(value)); - // - // m_combo->Bind(wxEVT_TEXT, [this](wxCommandEvent&) { update(); }); - //#ifdef __WXOSX__ - // // Under OSX wxEVT_TEXT wasn't invoked after change selection in combobox, - // // So process wxEVT_COMBOBOX too - // m_combo->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) { update(); }); - //#endif //__WXOSX__ - // wxBoxSizer *combo_sizer = new wxBoxSizer(wxHORIZONTAL); - // combo_sizer->Add(m_valid_bmp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W); - // combo_sizer->Add(m_combo, 1, wxEXPAND, BORDER_W); - - - - wxBoxSizer *input_sizer_h = new wxBoxSizer(wxHORIZONTAL); - wxBoxSizer *input_sizer_v = new wxBoxSizer(wxVERTICAL); - - /*m_input_ctrl = new wxTextCtrl(this, wxID_ANY, from_u8(preset_name), wxDefaultPosition, wxDefaultSize,wxBORDER_NONE);*/ - - - m_input_ctrl = new ::TextInput(parent, from_u8(preset_name), wxEmptyString, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); - StateColor input_bg(std::pair(wxColour("#F0F0F1"), StateColor::Disabled), std::pair(*wxWHITE, StateColor::Enabled)); - m_input_ctrl->SetBackgroundColor(input_bg); - m_input_ctrl->Bind(wxEVT_TEXT, [this](wxCommandEvent &) { update(); }); - m_input_ctrl->SetMinSize(wxSize(SAVE_PRESET_DIALOG_INPUT_SIZE)); - m_input_ctrl->SetMaxSize(wxSize(SAVE_PRESET_DIALOG_INPUT_SIZE)); - - - input_sizer_v->Add(m_input_ctrl, 1, wxEXPAND, 0); - input_sizer_h->Add(input_sizer_v, 1, wxALIGN_CENTER, 0); - input_sizer_h->Layout(); - - m_valid_label = new wxStaticText(m_parent, wxID_ANY, ""); - m_valid_label->SetForegroundColour(wxColor(255, 111, 0)); - - sizer->Add(label_top, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, BORDER_W); - sizer->Add(input_sizer_h, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, BORDER_W); - sizer->Add(m_valid_label, 0, wxEXPAND | wxLEFT | wxRIGHT, BORDER_W); - - if (m_type == Preset::TYPE_PRINTER) m_parent->add_info_for_edit_ph_printer(sizer); - - // BBS: add project embedded presets logic - wxBoxSizer *radio_sizer = new wxBoxSizer(wxHORIZONTAL); - - wxBoxSizer *m_sizer_left = new wxBoxSizer(wxHORIZONTAL); - - m_sizer_left->Add(0, 0, 0, wxLEFT, 25); - - m_radio_user = new RadioBox(parent); - m_radio_user->SetBackgroundColour(SAVE_PRESET_DIALOG_DEF_COLOUR); - - m_sizer_left->Add(m_radio_user, 0, wxALIGN_CENTER, 0); - - m_sizer_left->Add(0, 0, 0, wxLEFT, 10); - - auto m_left_text = new wxStaticText(parent, wxID_ANY, _L("User Preset"), wxDefaultPosition, wxDefaultSize, 0); - m_left_text->Wrap(-1); - m_left_text->SetFont(::Label::Body_13); - m_left_text->SetForegroundColour(wxColour(107,107,107)); - m_sizer_left->Add(m_left_text, 0, wxALIGN_CENTER, 0); - - radio_sizer->Add(m_sizer_left, 1, wxALIGN_CENTER, 5); - - wxBoxSizer *m_sizer_right = new wxBoxSizer(wxHORIZONTAL); - - m_sizer_right->Add(0, 0, 0, wxLEFT, 15); - - m_radio_project = new RadioBox(parent); - m_radio_project->SetBackgroundColour(SAVE_PRESET_DIALOG_DEF_COLOUR); - - m_sizer_right->Add(m_radio_project, 0, wxALIGN_CENTER, 0); - - m_sizer_right->Add(0, 0, 0, wxLEFT, 10); - - auto m_right_text = new wxStaticText(parent, wxID_ANY, _L("Preset Inside Project"), wxDefaultPosition, wxDefaultSize, 0); - m_right_text->SetForegroundColour(wxColour(107,107,107)); - m_right_text->SetFont(::Label::Body_13); - m_right_text->Wrap(-1); - m_sizer_right->Add(m_right_text, 0, wxALIGN_CENTER, 0); - - radio_sizer->Add(m_sizer_right, 1, wxEXPAND, 5); - - sizer->Add(radio_sizer, 0, wxEXPAND | wxTOP, BORDER_W); - - auto radio_clicked = [this](wxMouseEvent &e) { - if (m_radio_user->GetId() == e.GetId()) { - m_radio_user->SetValue(true); - m_radio_project->SetValue(false); - m_save_to_project = false; - } - - if (m_radio_project->GetId() == e.GetId()) { - m_radio_user->SetValue(false); - m_radio_project->SetValue(true); - m_save_to_project = true; - } - }; - m_radio_user->Bind(wxEVT_LEFT_DOWN, radio_clicked); - m_radio_project->Bind(wxEVT_LEFT_DOWN, radio_clicked); - - bool is_project_embedded = m_presets->get_edited_preset().is_project_embedded; - if (is_project_embedded) - m_radio_project->SetValue(true); - else - m_radio_user->SetValue(true); - - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", create item: type" << Preset::get_type_string(m_type) << ", preset " << m_preset_name - << ", is_project_embedded = " << is_project_embedded; - update(); -} - -void SavePresetDialog::Item::update() -{ - m_preset_name = into_u8(m_input_ctrl->GetTextCtrl()->GetValue()); - - m_valid_type = Valid; - wxString info_line; - - const char *unusable_symbols = "<>[]:/\\|?*\""; - - const std::string unusable_suffix = PresetCollection::get_suffix_modified(); //"(modified)"; - for (size_t i = 0; i < std::strlen(unusable_symbols); i++) { - if (m_preset_name.find_first_of(unusable_symbols[i]) != std::string::npos) { - info_line = _L("Name is invalid;") + "\n" + _L("illegal characters:") + " " + unusable_symbols; - m_valid_type = NoValid; - break; - } - } - - if (m_valid_type == Valid && m_preset_name.find(unusable_suffix) != std::string::npos) { - info_line = _L("Name is invalid;") + "\n" + _L("illegal suffix:") + "\n\t" + from_u8(PresetCollection::get_suffix_modified()); - m_valid_type = NoValid; - } - - if (m_valid_type == Valid && - (m_preset_name == "Default Setting" || m_preset_name == "Default Filament" || m_preset_name == "Default Printer")) { - info_line = _L("Name is unavailable."); - m_valid_type = NoValid; - } - - const Preset *existing = m_presets->find_preset(m_preset_name, false); - if (m_valid_type == Valid && existing && (existing->is_default || existing->is_system)) { - info_line = _L("Overwrite a system profile is not allowed"); - m_valid_type = NoValid; - } - - if (m_valid_type == Valid && existing && m_preset_name != m_presets->get_selected_preset_name()) { - if (existing->is_compatible) - info_line = from_u8((boost::format(_u8L("Preset \"%1%\" already exists.")) % m_preset_name).str()); - else - info_line = from_u8((boost::format(_u8L("Preset \"%1%\" already exists and is incompatible with current printer.")) % m_preset_name).str()); - info_line += "\n" + _L("Please note that saving action will replace this preset"); - m_valid_type = Warning; - } - - if (m_valid_type == Valid && m_preset_name.empty()) { - info_line = _L("The name is not allowed to be empty."); - m_valid_type = NoValid; - } - - if (m_valid_type == Valid && m_preset_name.find_first_of(' ') == 0) { - info_line = _L("The name is not allowed to start with space character."); - m_valid_type = NoValid; - } - - if (m_valid_type == Valid && m_preset_name.find_last_of(' ') == m_preset_name.length() - 1) { - info_line = _L("The name is not allowed to end with space character."); - m_valid_type = NoValid; - } - - if (m_valid_type == Valid && m_presets->get_preset_name_by_alias(m_preset_name) != m_preset_name) { - info_line = _L("The name cannot be the same as a preset alias name."); - m_valid_type = NoValid; - } - - // BBS: add project embedded presets logic - if (existing) { - if (existing->is_project_embedded) { - m_radio_project->SetValue(true); - m_save_to_project = true; - } else { - m_radio_user->SetValue(true); - m_save_to_project = false; - } - m_radio_user->Disable(); - m_radio_project->Disable(); - } else { - m_radio_user->Enable(); - m_radio_project->Enable(); - - m_radio_user->SetValue(!m_save_to_project); - m_radio_project->SetValue(m_save_to_project); - } - - m_valid_label->SetLabel(info_line); - m_valid_label->Show(!info_line.IsEmpty()); - - // update_valid_bmp(); - - if (m_type == Preset::TYPE_PRINTER) m_parent->update_info_for_edit_ph_printer(m_preset_name); - - m_parent->layout(); -} - -void SavePresetDialog::Item::update_valid_bmp() -{ - std::string bmp_name = m_valid_type == Warning ? "obj_warning" : m_valid_type == NoValid ? "cross" : "blank_16"; - m_valid_bmp->SetBitmap(create_scaled_bitmap(bmp_name, m_parent)); -} - -void SavePresetDialog::Item::accept() -{ - if (m_valid_type == Warning) { - // BBS add sync info - auto it = m_presets->find_preset(m_preset_name, false); - Preset ¤t_preset = *it; - current_preset.sync_info = "delete"; - if (!current_preset.setting_id.empty()) { - BOOST_LOG_TRIVIAL(info) << "delete preset = " << current_preset.name << ", setting_id = " << current_preset.setting_id; - wxGetApp().delete_preset_from_cloud(current_preset.setting_id); - } - m_presets->delete_preset(m_preset_name); - } -} - -void SavePresetDialog::Item::DoSetSize(int x, int y, int width, int height, int sizeFlags /*= wxSIZE_AUTO*/) -{ - wxWindow::DoSetSize(x, y, width, height, sizeFlags); -} - -//----------------------------------------------- -// SavePresetDialog -//----------------------------------------------- - -SavePresetDialog::SavePresetDialog(wxWindow *parent, Preset::Type type, std::string suffix) - : DPIDialog(parent, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) -{ - build(std::vector{type}, suffix); - wxGetApp().UpdateDlgDarkUI(this); -} - -SavePresetDialog::SavePresetDialog(wxWindow *parent, std::vector types, std::string suffix) - : DPIDialog(parent, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) -{ - build(types, suffix); - wxGetApp().UpdateDlgDarkUI(this); -} - -SavePresetDialog::~SavePresetDialog() -{ - for (auto item : m_items) { delete item; } -} - -void SavePresetDialog::build(std::vector types, std::string suffix) -{ - // def setting - SetBackgroundColour(SAVE_PRESET_DIALOG_DEF_COLOUR); - SetFont(wxGetApp().normal_font()); - - // icon - std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str(); - SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); - - if (suffix.empty()) suffix = _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName"); - - wxBoxSizer *m_Sizer_main = new wxBoxSizer(wxVERTICAL); - - m_presets_sizer = new wxBoxSizer(wxVERTICAL); - - // Add first item - for (Preset::Type type : types) AddItem(type, suffix); - - wxBoxSizer *btns; - btns = new wxBoxSizer(wxHORIZONTAL); - btns->Add(0, 0, 1, wxEXPAND, 5); - - m_confirm = new Button(this, _L("OK")); - StateColor btn_bg_green(std::pair(wxColour(0, 137, 123), StateColor::Pressed), - std::pair(wxColour(38, 166, 154), StateColor::Hovered), - std::pair(wxColour(0, 150, 136), StateColor::Normal)); - m_confirm->SetBackgroundColor(btn_bg_green); - m_confirm->SetBorderColor(wxColour(0, 150, 136)); - m_confirm->SetTextColor(wxColour("#FFFFFE")); - m_confirm->SetMinSize(SAVE_PRESET_DIALOG_BUTTON_SIZE); - m_confirm->SetCornerRadius(FromDIP(12)); - m_confirm->Bind(wxEVT_BUTTON, &SavePresetDialog::accept, this); - btns->Add(m_confirm, 0, wxEXPAND, 0); - - auto block_middle = new wxWindow(this, -1); - block_middle->SetBackgroundColour(SAVE_PRESET_DIALOG_DEF_COLOUR); - btns->Add(block_middle, 0, wxRIGHT, 10); - - m_cancel = new Button(this, _L("Cancel")); - m_cancel->SetMinSize(SAVE_PRESET_DIALOG_BUTTON_SIZE); - m_cancel->SetCornerRadius(FromDIP(12)); - m_cancel->Bind(wxEVT_BUTTON, &SavePresetDialog::on_select_cancel, this); - btns->Add(m_cancel, 0, wxEXPAND, 0); - - auto block_right = new wxWindow(this, -1); - block_right->SetBackgroundColour(SAVE_PRESET_DIALOG_DEF_COLOUR); - btns->Add(block_right, 0, wxRIGHT, 40); - - auto m_line = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); - m_line->SetBackgroundColour(wxColour(166, 169, 170)); - - m_Sizer_main->Add( m_line, 0, wxEXPAND, 0 ); - m_Sizer_main->Add(m_presets_sizer, 0, wxEXPAND | wxALL, BORDER_W); - m_Sizer_main->Add(btns, 0, wxEXPAND | wxBOTTOM, BORDER_W + 7); - - SetSizer(m_Sizer_main); - m_Sizer_main->SetSizeHints(this); - - this->Centre(wxBOTH); -} - -void SavePresetDialog::on_select_cancel(wxCommandEvent &event) -{ - EndModal(wxID_CANCEL); -} - -void SavePresetDialog::AddItem(Preset::Type type, const std::string &suffix) { m_items.emplace_back(new Item{type, suffix, m_presets_sizer, this}); } - -std::string SavePresetDialog::get_name() { return m_items.front()->preset_name(); } - -std::string SavePresetDialog::get_name(Preset::Type type) -{ - for (const Item *item : m_items) - if (item->type() == type) return item->preset_name(); - return ""; -} - -void SavePresetDialog::input_name_from_other(std::string new_preset_name) { - //only work for one-item - Item* curr_item = m_items[0]; - curr_item->m_input_ctrl->GetTextCtrl()->SetValue(new_preset_name); -} - -void SavePresetDialog::confirm_from_other() { - for (Item *item : m_items) { - item->accept(); - if (item->type() == Preset::TYPE_PRINTER) update_physical_printers(item->preset_name()); - } -} - -// BBS: add project relate -bool SavePresetDialog::get_save_to_project_selection(Preset::Type type) -{ - for (const Item *item : m_items) - if (item->type() == type) return item->save_to_project(); - return false; -} - -bool SavePresetDialog::enable_ok_btn() const -{ - for (const Item *item : m_items) - if (!item->is_valid()) return false; - - return true; -} - -void SavePresetDialog::add_info_for_edit_ph_printer(wxBoxSizer *sizer) -{ - PhysicalPrinterCollection &printers = wxGetApp().preset_bundle->physical_printers; - m_ph_printer_name = printers.get_selected_printer_name(); - m_old_preset_name = printers.get_selected_printer_preset_name(); - - wxString msg_text = from_u8((boost::format(_u8L("Printer \"%1%\" is selected with preset \"%2%\"")) % - m_ph_printer_name % m_old_preset_name) - .str()); - m_label = new wxStaticText(this, wxID_ANY, msg_text); - m_label->SetFont(wxGetApp().bold_font()); - - m_action = ChangePreset; - m_radio_sizer = new wxBoxSizer(wxHORIZONTAL); - - wxStaticBox *action_stb = new wxStaticBox(this, wxID_ANY, ""); - if (!wxOSX) action_stb->SetBackgroundStyle(wxBG_STYLE_PAINT); - action_stb->SetFont(wxGetApp().bold_font()); - - wxStaticBoxSizer *stb_sizer = new wxStaticBoxSizer(action_stb, wxVERTICAL); - for (int id = 0; id < 3; id++) { - wxRadioButton *btn = new wxRadioButton(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, id == 0 ? wxRB_GROUP : 0); - btn->SetValue(id == int(ChangePreset)); - btn->Bind(wxEVT_RADIOBUTTON, [this, id](wxCommandEvent &) { m_action = (ActionType) id; }); - stb_sizer->Add(btn, 0, wxEXPAND | wxTOP, 5); - } - m_radio_sizer->Add(stb_sizer, 1, wxEXPAND | wxTOP, 2 * BORDER_W); - - sizer->Add(m_label, 0, wxEXPAND | wxLEFT | wxTOP, 3 * BORDER_W); - sizer->Add(m_radio_sizer, 1, wxEXPAND | wxLEFT, 3 * BORDER_W); -} - -void SavePresetDialog::update_info_for_edit_ph_printer(const std::string &preset_name) -{ - bool show = wxGetApp().preset_bundle->physical_printers.has_selection() && m_old_preset_name != preset_name; - - m_label->Show(show); - m_radio_sizer->ShowItems(show); - if (!show) { - this->SetMinSize(wxSize(100, 50)); - return; - } - - if (wxSizerItem *sizer_item = m_radio_sizer->GetItem(size_t(0))) { - if (wxStaticBoxSizer *stb_sizer = static_cast(sizer_item->GetSizer())) { - wxString msg_text = format_wxstr(_L("Please choose an action with \"%1%\" preset after saving."), preset_name); - stb_sizer->GetStaticBox()->SetLabel(msg_text); - - wxString choices[] = {format_wxstr(_L("For \"%1%\", change \"%2%\" to \"%3%\" "), m_ph_printer_name, m_old_preset_name, preset_name), - format_wxstr(_L("For \"%1%\", add \"%2%\" as a new preset"), m_ph_printer_name, preset_name), - format_wxstr(_L("Simply switch to \"%1%\""), preset_name)}; - - size_t n = 0; - for (const wxString &label : choices) stb_sizer->GetItem(n++)->GetWindow()->SetLabel(label); - } - Refresh(); - } -} - -void SavePresetDialog::layout() -{ - this->Layout(); - this->Fit(); -} - -void SavePresetDialog::on_dpi_changed(const wxRect &suggested_rect) -{ - const int &em = em_unit(); - - msw_buttons_rescale(this, em, {wxID_OK, wxID_CANCEL}); - - //for (Item *item : m_items) item->update_valid_bmp(); - - // const wxSize& size = wxSize(45 * em, 35 * em); - //SetMinSize(/*size*/ wxSize(100, 50)); - - m_confirm->SetMinSize(SAVE_PRESET_DIALOG_BUTTON_SIZE); - m_cancel->SetMinSize(SAVE_PRESET_DIALOG_BUTTON_SIZE); - - - Fit(); - Refresh(); -} - -void SavePresetDialog::update_physical_printers(const std::string &preset_name) -{ - if (m_action == UndefAction) return; - - PhysicalPrinterCollection &physical_printers = wxGetApp().preset_bundle->physical_printers; - if (!physical_printers.has_selection()) return; - - std::string printer_preset_name = physical_printers.get_selected_printer_preset_name(); - - if (m_action == Switch) - // unselect physical printer, if it was selected - physical_printers.unselect_printer(); - else { - PhysicalPrinter printer = physical_printers.get_selected_printer(); - - if (m_action == ChangePreset) printer.delete_preset(printer_preset_name); - - if (printer.add_preset(preset_name)) physical_printers.save_printer(printer); - - physical_printers.select_printer(printer.get_full_name(preset_name)); - } -} - -void SavePresetDialog::accept(wxCommandEvent &event) -{ - for (Item *item : m_items) { - item->accept(); - if (item->type() == Preset::TYPE_PRINTER) update_physical_printers(item->preset_name()); - } - - EndModal(wxID_OK); -} - -}} // namespace Slic3r::GUI +#include "SavePresetDialog.hpp" + +#include +#include +#include +#include +#include + +#include +#include +#include +// BBS: add radio button for project embedded preset logic +#include + +#include "libslic3r/PresetBundle.hpp" + +#include "GUI.hpp" +#include "GUI_App.hpp" +#include "format.hpp" +#include "Tab.hpp" + +using Slic3r::GUI::format_wxstr; + +namespace Slic3r { namespace GUI { + +#define BORDER_W 10 + +//----------------------------------------------- +// SavePresetDialog::Item +//----------------------------------------------- + +SavePresetDialog::Item::Item(Preset::Type type, const std::string &suffix, wxBoxSizer *sizer, SavePresetDialog *parent) : m_type(type), m_parent(parent) +{ + Tab *tab = wxGetApp().get_tab(m_type); + assert(tab); + m_presets = tab->get_presets(); + + const Preset &sel_preset = m_presets->get_selected_preset(); + std::string preset_name = sel_preset.is_default ? "Untitled" : sel_preset.is_system ? (boost::format(("%1% - %2%")) % sel_preset.name % suffix).str() : sel_preset.name; + + // if name contains extension + if (boost::iends_with(preset_name, ".ini")) { + size_t len = preset_name.length() - 4; + preset_name.resize(len); + } + + std::vector values; + for (const Preset &preset : *m_presets) { + // BBS: add project embedded preset logic and refine is_external + if (preset.is_default || preset.is_system) + // if (preset.is_default || preset.is_system || preset.is_external) + continue; + values.push_back(preset.name); + } + + wxStaticText *label_top = new wxStaticText(m_parent, wxID_ANY, from_u8((boost::format(_utf8(L("Save %s as"))) % into_u8(tab->title())).str())); + label_top->SetFont(::Label::Body_13); + label_top->SetForegroundColour(wxColour(38,46,48)); + + + // m_valid_bmp = new wxStaticBitmap(m_parent, wxID_ANY, create_scaled_bitmap("blank_16", m_parent)); + // + // m_combo = new wxComboBox(m_parent, wxID_ANY, from_u8(preset_name), wxDefaultPosition, wxSize(35 * wxGetApp().em_unit(), -1)); + // for (const std::string& value : values) + // m_combo->Append(from_u8(value)); + // + // m_combo->Bind(wxEVT_TEXT, [this](wxCommandEvent&) { update(); }); + //#ifdef __WXOSX__ + // // Under OSX wxEVT_TEXT wasn't invoked after change selection in combobox, + // // So process wxEVT_COMBOBOX too + // m_combo->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) { update(); }); + //#endif //__WXOSX__ + // wxBoxSizer *combo_sizer = new wxBoxSizer(wxHORIZONTAL); + // combo_sizer->Add(m_valid_bmp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W); + // combo_sizer->Add(m_combo, 1, wxEXPAND, BORDER_W); + + + + wxBoxSizer *input_sizer_h = new wxBoxSizer(wxHORIZONTAL); + wxBoxSizer *input_sizer_v = new wxBoxSizer(wxVERTICAL); + + /*m_input_ctrl = new wxTextCtrl(this, wxID_ANY, from_u8(preset_name), wxDefaultPosition, wxDefaultSize,wxBORDER_NONE);*/ + + + m_input_ctrl = new ::TextInput(parent, from_u8(preset_name), wxEmptyString, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); + StateColor input_bg(std::pair(wxColour("#F0F0F1"), StateColor::Disabled), std::pair(*wxWHITE, StateColor::Enabled)); + m_input_ctrl->SetBackgroundColor(input_bg); + m_input_ctrl->Bind(wxEVT_TEXT, [this](wxCommandEvent &) { update(); }); + m_input_ctrl->SetMinSize(wxSize(SAVE_PRESET_DIALOG_INPUT_SIZE)); + m_input_ctrl->SetMaxSize(wxSize(SAVE_PRESET_DIALOG_INPUT_SIZE)); + + + input_sizer_v->Add(m_input_ctrl, 1, wxEXPAND, 0); + input_sizer_h->Add(input_sizer_v, 1, wxALIGN_CENTER, 0); + input_sizer_h->Layout(); + + m_valid_label = new wxStaticText(m_parent, wxID_ANY, ""); + m_valid_label->SetForegroundColour(wxColor(255, 111, 0)); + + sizer->Add(label_top, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, BORDER_W); + sizer->Add(input_sizer_h, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, BORDER_W); + sizer->Add(m_valid_label, 0, wxEXPAND | wxLEFT | wxRIGHT, BORDER_W); + + if (m_type == Preset::TYPE_PRINTER) m_parent->add_info_for_edit_ph_printer(sizer); + + // BBS: add project embedded presets logic + wxBoxSizer *radio_sizer = new wxBoxSizer(wxHORIZONTAL); + + wxBoxSizer *m_sizer_left = new wxBoxSizer(wxHORIZONTAL); + + m_sizer_left->Add(0, 0, 0, wxLEFT, 25); + + m_radio_user = new RadioBox(parent); + m_radio_user->SetBackgroundColour(SAVE_PRESET_DIALOG_DEF_COLOUR); + + m_sizer_left->Add(m_radio_user, 0, wxALIGN_CENTER, 0); + + m_sizer_left->Add(0, 0, 0, wxLEFT, 10); + + auto m_left_text = new wxStaticText(parent, wxID_ANY, _L("User Preset"), wxDefaultPosition, wxDefaultSize, 0); + m_left_text->Wrap(-1); + m_left_text->SetFont(::Label::Body_13); + m_left_text->SetForegroundColour(wxColour(107,107,107)); + m_sizer_left->Add(m_left_text, 0, wxALIGN_CENTER, 0); + + radio_sizer->Add(m_sizer_left, 1, wxALIGN_CENTER, 5); + + wxBoxSizer *m_sizer_right = new wxBoxSizer(wxHORIZONTAL); + + m_sizer_right->Add(0, 0, 0, wxLEFT, 15); + + m_radio_project = new RadioBox(parent); + m_radio_project->SetBackgroundColour(SAVE_PRESET_DIALOG_DEF_COLOUR); + + m_sizer_right->Add(m_radio_project, 0, wxALIGN_CENTER, 0); + + m_sizer_right->Add(0, 0, 0, wxLEFT, 10); + + auto m_right_text = new wxStaticText(parent, wxID_ANY, _L("Preset Inside Project"), wxDefaultPosition, wxDefaultSize, 0); + m_right_text->SetForegroundColour(wxColour(107,107,107)); + m_right_text->SetFont(::Label::Body_13); + m_right_text->Wrap(-1); + m_sizer_right->Add(m_right_text, 0, wxALIGN_CENTER, 0); + + radio_sizer->Add(m_sizer_right, 1, wxEXPAND, 5); + + sizer->Add(radio_sizer, 0, wxEXPAND | wxTOP, BORDER_W); + + // Only add the detach checkbox if m_mode is comDevelop + if (parent->m_mode == comDevelop) { + m_detach_checkbox = new wxCheckBox(parent, wxID_ANY, _L("Detach from parent")); + sizer->Add(m_detach_checkbox, 0, wxALIGN_LEFT | wxALL, BORDER_W); + + // Set initial state (unchecked by default) + m_detach_checkbox->SetValue(m_detach); + + // Bind the checkbox event to update the detach state for this item + m_detach_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { m_detach = m_detach_checkbox->GetValue(); }); + } + + auto radio_clicked = [this](wxMouseEvent &e) { + if (m_radio_user->GetId() == e.GetId()) { + m_radio_user->SetValue(true); + m_radio_project->SetValue(false); + m_save_to_project = false; + } + + if (m_radio_project->GetId() == e.GetId()) { + m_radio_user->SetValue(false); + m_radio_project->SetValue(true); + m_save_to_project = true; + } + }; + m_radio_user->Bind(wxEVT_LEFT_DOWN, radio_clicked); + m_radio_project->Bind(wxEVT_LEFT_DOWN, radio_clicked); + + bool is_project_embedded = m_presets->get_edited_preset().is_project_embedded; + if (is_project_embedded) + m_radio_project->SetValue(true); + else + m_radio_user->SetValue(true); + + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", create item: type" << Preset::get_type_string(m_type) << ", preset " << m_preset_name + << ", is_project_embedded = " << is_project_embedded; + update(); +} + +void SavePresetDialog::Item::update() +{ + m_preset_name = into_u8(m_input_ctrl->GetTextCtrl()->GetValue()); + + m_valid_type = Valid; + wxString info_line; + + const char *unusable_symbols = "<>[]:/\\|?*\""; + + const std::string unusable_suffix = PresetCollection::get_suffix_modified(); //"(modified)"; + for (size_t i = 0; i < std::strlen(unusable_symbols); i++) { + if (m_preset_name.find_first_of(unusable_symbols[i]) != std::string::npos) { + info_line = _L("Name is invalid;") + "\n" + _L("illegal characters:") + " " + unusable_symbols; + m_valid_type = NoValid; + break; + } + } + + if (m_valid_type == Valid && m_preset_name.find(unusable_suffix) != std::string::npos) { + info_line = _L("Name is invalid;") + "\n" + _L("illegal suffix:") + "\n\t" + from_u8(PresetCollection::get_suffix_modified()); + m_valid_type = NoValid; + } + + if (m_valid_type == Valid && + (m_preset_name == "Default Setting" || m_preset_name == "Default Filament" || m_preset_name == "Default Printer")) { + info_line = _L("Name is unavailable."); + m_valid_type = NoValid; + } + + const Preset *existing = m_presets->find_preset(m_preset_name, false); + if (m_valid_type == Valid && existing && (existing->is_default || existing->is_system)) { + info_line = _L("Overwrite a system profile is not allowed"); + m_valid_type = NoValid; + } + + if (m_valid_type == Valid && existing && m_preset_name != m_presets->get_selected_preset_name()) { + if (existing->is_compatible) + info_line = from_u8((boost::format(_u8L("Preset \"%1%\" already exists.")) % m_preset_name).str()); + else + info_line = from_u8((boost::format(_u8L("Preset \"%1%\" already exists and is incompatible with current printer.")) % m_preset_name).str()); + info_line += "\n" + _L("Please note that saving action will replace this preset"); + m_valid_type = Warning; + } + + if (m_valid_type == Valid && m_preset_name.empty()) { + info_line = _L("The name is not allowed to be empty."); + m_valid_type = NoValid; + } + + if (m_valid_type == Valid && m_preset_name.find_first_of(' ') == 0) { + info_line = _L("The name is not allowed to start with space character."); + m_valid_type = NoValid; + } + + if (m_valid_type == Valid && m_preset_name.find_last_of(' ') == m_preset_name.length() - 1) { + info_line = _L("The name is not allowed to end with space character."); + m_valid_type = NoValid; + } + + if (m_valid_type == Valid && m_presets->get_preset_name_by_alias(m_preset_name) != m_preset_name) { + info_line = _L("The name cannot be the same as a preset alias name."); + m_valid_type = NoValid; + } + + // BBS: add project embedded presets logic + if (existing) { + if (existing->is_project_embedded) { + m_radio_project->SetValue(true); + m_save_to_project = true; + } else { + m_radio_user->SetValue(true); + m_save_to_project = false; + } + m_radio_user->Disable(); + m_radio_project->Disable(); + } else { + m_radio_user->Enable(); + m_radio_project->Enable(); + + m_radio_user->SetValue(!m_save_to_project); + m_radio_project->SetValue(m_save_to_project); + } + + m_valid_label->SetLabel(info_line); + m_valid_label->Show(!info_line.IsEmpty()); + + // update_valid_bmp(); + + if (m_type == Preset::TYPE_PRINTER) m_parent->update_info_for_edit_ph_printer(m_preset_name); + + m_parent->layout(); +} + +void SavePresetDialog::Item::update_valid_bmp() +{ + std::string bmp_name = m_valid_type == Warning ? "obj_warning" : m_valid_type == NoValid ? "cross" : "blank_16"; + m_valid_bmp->SetBitmap(create_scaled_bitmap(bmp_name, m_parent)); +} + +void SavePresetDialog::Item::accept() +{ + if (m_valid_type == Warning) { + // BBS add sync info + auto it = m_presets->find_preset(m_preset_name, false); + Preset ¤t_preset = *it; + current_preset.sync_info = "delete"; + if (!current_preset.setting_id.empty()) { + BOOST_LOG_TRIVIAL(info) << "delete preset = " << current_preset.name << ", setting_id = " << current_preset.setting_id; + wxGetApp().delete_preset_from_cloud(current_preset.setting_id); + } + m_presets->delete_preset(m_preset_name); + } +} + +void SavePresetDialog::Item::DoSetSize(int x, int y, int width, int height, int sizeFlags /*= wxSIZE_AUTO*/) +{ + wxWindow::DoSetSize(x, y, width, height, sizeFlags); +} + +//----------------------------------------------- +// SavePresetDialog +//----------------------------------------------- + +SavePresetDialog::SavePresetDialog(wxWindow* parent, Preset::Type type, int mode, std::string suffix) + : DPIDialog(parent, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX), m_mode(mode) +{ + build(std::vector{type}, suffix); + wxGetApp().UpdateDlgDarkUI(this); +} + +SavePresetDialog::SavePresetDialog(wxWindow* parent, std::vector types, int mode, std::string suffix) + : DPIDialog(parent, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX), m_mode(mode) +{ + build(types, suffix); + wxGetApp().UpdateDlgDarkUI(this); +} + +SavePresetDialog::~SavePresetDialog() +{ + for (auto item : m_items) { delete item; } +} + +void SavePresetDialog::build(std::vector types, std::string suffix) +{ + // def setting + SetBackgroundColour(SAVE_PRESET_DIALOG_DEF_COLOUR); + SetFont(wxGetApp().normal_font()); + + // icon + std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str(); + SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); + + if (suffix.empty()) suffix = _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName"); + + wxBoxSizer *m_Sizer_main = new wxBoxSizer(wxVERTICAL); + + m_presets_sizer = new wxBoxSizer(wxVERTICAL); + + // Add first item + for (Preset::Type type : types) AddItem(type, suffix); + + wxBoxSizer *btns; + btns = new wxBoxSizer(wxHORIZONTAL); + btns->Add(0, 0, 1, wxEXPAND, 5); + + m_confirm = new Button(this, _L("OK")); + StateColor btn_bg_green(std::pair(wxColour(0, 137, 123), StateColor::Pressed), + std::pair(wxColour(38, 166, 154), StateColor::Hovered), + std::pair(wxColour(0, 150, 136), StateColor::Normal)); + m_confirm->SetBackgroundColor(btn_bg_green); + m_confirm->SetBorderColor(wxColour(0, 150, 136)); + m_confirm->SetTextColor(wxColour("#FFFFFE")); + m_confirm->SetMinSize(SAVE_PRESET_DIALOG_BUTTON_SIZE); + m_confirm->SetCornerRadius(FromDIP(12)); + m_confirm->Bind(wxEVT_BUTTON, &SavePresetDialog::accept, this); + btns->Add(m_confirm, 0, wxEXPAND, 0); + + auto block_middle = new wxWindow(this, -1); + block_middle->SetBackgroundColour(SAVE_PRESET_DIALOG_DEF_COLOUR); + btns->Add(block_middle, 0, wxRIGHT, 10); + + m_cancel = new Button(this, _L("Cancel")); + m_cancel->SetMinSize(SAVE_PRESET_DIALOG_BUTTON_SIZE); + m_cancel->SetCornerRadius(FromDIP(12)); + m_cancel->Bind(wxEVT_BUTTON, &SavePresetDialog::on_select_cancel, this); + btns->Add(m_cancel, 0, wxEXPAND, 0); + + auto block_right = new wxWindow(this, -1); + block_right->SetBackgroundColour(SAVE_PRESET_DIALOG_DEF_COLOUR); + btns->Add(block_right, 0, wxRIGHT, 40); + + auto m_line = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); + m_line->SetBackgroundColour(wxColour(166, 169, 170)); + + m_Sizer_main->Add( m_line, 0, wxEXPAND, 0 ); + m_Sizer_main->Add(m_presets_sizer, 0, wxEXPAND | wxALL, BORDER_W); + m_Sizer_main->Add(btns, 0, wxEXPAND | wxBOTTOM, BORDER_W + 7); + + SetSizer(m_Sizer_main); + m_Sizer_main->SetSizeHints(this); + + this->Centre(wxBOTH); +} + +void SavePresetDialog::on_select_cancel(wxCommandEvent &event) +{ + EndModal(wxID_CANCEL); +} + +void SavePresetDialog::AddItem(Preset::Type type, const std::string &suffix) { m_items.emplace_back(new Item{type, suffix, m_presets_sizer, this}); } + +std::string SavePresetDialog::get_name() { return m_items.front()->preset_name(); } + +std::string SavePresetDialog::get_name(Preset::Type type) +{ + for (const Item *item : m_items) + if (item->type() == type) return item->preset_name(); + return ""; +} + +void SavePresetDialog::input_name_from_other(std::string new_preset_name) { + //only work for one-item + Item* curr_item = m_items[0]; + curr_item->m_input_ctrl->GetTextCtrl()->SetValue(new_preset_name); +} + +void SavePresetDialog::confirm_from_other() { + for (Item *item : m_items) { + item->accept(); + if (item->type() == Preset::TYPE_PRINTER) update_physical_printers(item->preset_name()); + } +} + +// BBS: add project relate +bool SavePresetDialog::get_save_to_project_selection(Preset::Type type) +{ + for (const Item *item : m_items) + if (item->type() == type) return item->save_to_project(); + return false; +} + +bool SavePresetDialog::get_detach_value(Preset::Type type) +{ + for (const Item* item : m_items) + if (item->type() == type) + return item->is_detached(); + return false; +} + +bool SavePresetDialog::enable_ok_btn() const +{ + for (const Item *item : m_items) + if (!item->is_valid()) return false; + + return true; +} + +void SavePresetDialog::add_info_for_edit_ph_printer(wxBoxSizer *sizer) +{ + PhysicalPrinterCollection &printers = wxGetApp().preset_bundle->physical_printers; + m_ph_printer_name = printers.get_selected_printer_name(); + m_old_preset_name = printers.get_selected_printer_preset_name(); + + wxString msg_text = from_u8((boost::format(_u8L("Printer \"%1%\" is selected with preset \"%2%\"")) % + m_ph_printer_name % m_old_preset_name) + .str()); + m_label = new wxStaticText(this, wxID_ANY, msg_text); + m_label->SetFont(wxGetApp().bold_font()); + + m_action = ChangePreset; + m_radio_sizer = new wxBoxSizer(wxHORIZONTAL); + + wxStaticBox *action_stb = new wxStaticBox(this, wxID_ANY, ""); + if (!wxOSX) action_stb->SetBackgroundStyle(wxBG_STYLE_PAINT); + action_stb->SetFont(wxGetApp().bold_font()); + + wxStaticBoxSizer *stb_sizer = new wxStaticBoxSizer(action_stb, wxVERTICAL); + for (int id = 0; id < 3; id++) { + wxRadioButton *btn = new wxRadioButton(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, id == 0 ? wxRB_GROUP : 0); + btn->SetValue(id == int(ChangePreset)); + btn->Bind(wxEVT_RADIOBUTTON, [this, id](wxCommandEvent &) { m_action = (ActionType) id; }); + stb_sizer->Add(btn, 0, wxEXPAND | wxTOP, 5); + } + m_radio_sizer->Add(stb_sizer, 1, wxEXPAND | wxTOP, 2 * BORDER_W); + + sizer->Add(m_label, 0, wxEXPAND | wxLEFT | wxTOP, 3 * BORDER_W); + sizer->Add(m_radio_sizer, 1, wxEXPAND | wxLEFT, 3 * BORDER_W); +} + +void SavePresetDialog::update_info_for_edit_ph_printer(const std::string &preset_name) +{ + bool show = wxGetApp().preset_bundle->physical_printers.has_selection() && m_old_preset_name != preset_name; + + m_label->Show(show); + m_radio_sizer->ShowItems(show); + if (!show) { + this->SetMinSize(wxSize(100, 50)); + return; + } + + if (wxSizerItem *sizer_item = m_radio_sizer->GetItem(size_t(0))) { + if (wxStaticBoxSizer *stb_sizer = static_cast(sizer_item->GetSizer())) { + wxString msg_text = format_wxstr(_L("Please choose an action with \"%1%\" preset after saving."), preset_name); + stb_sizer->GetStaticBox()->SetLabel(msg_text); + + wxString choices[] = {format_wxstr(_L("For \"%1%\", change \"%2%\" to \"%3%\" "), m_ph_printer_name, m_old_preset_name, preset_name), + format_wxstr(_L("For \"%1%\", add \"%2%\" as a new preset"), m_ph_printer_name, preset_name), + format_wxstr(_L("Simply switch to \"%1%\""), preset_name)}; + + size_t n = 0; + for (const wxString &label : choices) stb_sizer->GetItem(n++)->GetWindow()->SetLabel(label); + } + Refresh(); + } +} + +void SavePresetDialog::layout() +{ + this->Layout(); + this->Fit(); +} + +void SavePresetDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + const int &em = em_unit(); + + msw_buttons_rescale(this, em, {wxID_OK, wxID_CANCEL}); + + //for (Item *item : m_items) item->update_valid_bmp(); + + // const wxSize& size = wxSize(45 * em, 35 * em); + //SetMinSize(/*size*/ wxSize(100, 50)); + + m_confirm->SetMinSize(SAVE_PRESET_DIALOG_BUTTON_SIZE); + m_cancel->SetMinSize(SAVE_PRESET_DIALOG_BUTTON_SIZE); + + + Fit(); + Refresh(); +} + +void SavePresetDialog::update_physical_printers(const std::string &preset_name) +{ + if (m_action == UndefAction) return; + + PhysicalPrinterCollection &physical_printers = wxGetApp().preset_bundle->physical_printers; + if (!physical_printers.has_selection()) return; + + std::string printer_preset_name = physical_printers.get_selected_printer_preset_name(); + + if (m_action == Switch) + // unselect physical printer, if it was selected + physical_printers.unselect_printer(); + else { + PhysicalPrinter printer = physical_printers.get_selected_printer(); + + if (m_action == ChangePreset) printer.delete_preset(printer_preset_name); + + if (printer.add_preset(preset_name)) physical_printers.save_printer(printer); + + physical_printers.select_printer(printer.get_full_name(preset_name)); + } +} + +void SavePresetDialog::accept(wxCommandEvent &event) +{ + for (Item *item : m_items) { + item->accept(); + if (item->type() == Preset::TYPE_PRINTER) update_physical_printers(item->preset_name()); + } + + EndModal(wxID_OK); +} + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/SavePresetDialog.hpp b/src/slic3r/GUI/SavePresetDialog.hpp index 3dc42d5192..5e743943c0 100644 --- a/src/slic3r/GUI/SavePresetDialog.hpp +++ b/src/slic3r/GUI/SavePresetDialog.hpp @@ -1,124 +1,135 @@ -#ifndef slic3r_SavePresetDialog_hpp_ -#define slic3r_SavePresetDialog_hpp_ - -//#include - -#include "libslic3r/Preset.hpp" -#include "wxExtensions.hpp" -#include "GUI_Utils.hpp" -#include "Widgets/RadioBox.hpp" -#include "Widgets/Button.hpp" -#include "Widgets/RoundedRectangle.hpp" -#include "Widgets/Label.hpp" -#include "Widgets/TextInput.hpp" - -class wxString; -class wxStaticText; -class wxComboBox; -class wxStaticBitmap; - -#define SAVE_PRESET_DIALOG_DEF_COLOUR wxColour(255, 255, 255) -#define SAVE_PRESET_DIALOG_INPUT_SIZE wxSize(FromDIP(360), FromDIP(24)) -#define SAVE_PRESET_DIALOG_BUTTON_SIZE wxSize(FromDIP(60), FromDIP(24)) - -namespace Slic3r { -namespace GUI { - -class SavePresetDialog : public DPIDialog -{ - enum ActionType - { - ChangePreset, - AddPreset, - Switch, - UndefAction - }; - - class Item : public wxWindow - { - public: - enum ValidationType - { - Valid, - NoValid, - Warning - }; - - Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent); - - void update_valid_bmp(); - void accept(); - virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); - - bool is_valid() const { return m_valid_type != NoValid; } - Preset::Type type() const { return m_type; } - std::string preset_name() const { return m_preset_name; } - //BBS: add project embedded preset relate logic - bool save_to_project() const { return m_save_to_project; } - - Preset::Type m_type; - ValidationType m_valid_type; - std::string m_preset_name; - - SavePresetDialog* m_parent {nullptr}; - wxStaticBitmap* m_valid_bmp {nullptr}; - wxComboBox* m_combo {nullptr}; - TextInput* m_input_ctrl {nullptr}; - wxStaticText* m_valid_label {nullptr}; - - PresetCollection* m_presets {nullptr}; - - //BBS: add project embedded preset relate logic - RadioBox * m_radio_user{nullptr}; - RadioBox * m_radio_project{nullptr}; - bool m_save_to_project {false}; - - void update(); - }; - - std::vector m_items; - - Button* m_confirm {nullptr}; - Button* m_cancel {nullptr}; - wxBoxSizer* m_presets_sizer {nullptr}; - wxStaticText* m_label {nullptr}; - wxBoxSizer* m_radio_sizer {nullptr}; - ActionType m_action {UndefAction}; - - std::string m_ph_printer_name; - std::string m_old_preset_name; - -public: - SavePresetDialog(wxWindow *parent, Preset::Type type, std::string suffix = ""); - SavePresetDialog(wxWindow* parent, std::vector types, std::string suffix = ""); - ~SavePresetDialog(); - - void AddItem(Preset::Type type, const std::string& suffix); - - std::string get_name(); - std::string get_name(Preset::Type type); - void input_name_from_other(std::string new_preset_name); - void confirm_from_other(); - - bool enable_ok_btn() const; - void add_info_for_edit_ph_printer(wxBoxSizer *sizer); - void update_info_for_edit_ph_printer(const std::string &preset_name); - void layout(); - //BBS: add project embedded preset relate logic - bool get_save_to_project_selection(Preset::Type type); - -protected: - void on_dpi_changed(const wxRect& suggested_rect) override; - void on_sys_color_changed() override {} - -private: - void build(std::vector types, std::string suffix = ""); - void on_select_cancel(wxCommandEvent &event); - void update_physical_printers(const std::string &preset_name); - void accept(wxCommandEvent &event); -}; - -} // namespace GUI -} // namespace Slic3r - -#endif +#ifndef slic3r_SavePresetDialog_hpp_ +#define slic3r_SavePresetDialog_hpp_ + +//#include + +#include "libslic3r/Preset.hpp" +#include "wxExtensions.hpp" +#include "GUI_Utils.hpp" +#include "Widgets/RadioBox.hpp" +#include "Widgets/Button.hpp" +#include "Widgets/RoundedRectangle.hpp" +#include "Widgets/Label.hpp" +#include "Widgets/TextInput.hpp" + +class wxString; +class wxStaticText; +class wxComboBox; +class wxStaticBitmap; + +#define SAVE_PRESET_DIALOG_DEF_COLOUR wxColour(255, 255, 255) +#define SAVE_PRESET_DIALOG_INPUT_SIZE wxSize(FromDIP(360), FromDIP(24)) +#define SAVE_PRESET_DIALOG_BUTTON_SIZE wxSize(FromDIP(60), FromDIP(24)) + +namespace Slic3r { +namespace GUI { + +class SavePresetDialog : public DPIDialog +{ + enum ActionType + { + ChangePreset, + AddPreset, + Switch, + UndefAction + }; + + class Item : public wxWindow + { + public: + enum ValidationType + { + Valid, + NoValid, + Warning + }; + + Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent); + + void update_valid_bmp(); + void accept(); + virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); + + bool is_valid() const { return m_valid_type != NoValid; } + Preset::Type type() const { return m_type; } + std::string preset_name() const { return m_preset_name; } + //BBS: add project embedded preset relate logic + bool save_to_project() const { return m_save_to_project; } + + // Method to get detach state + bool is_detached() const { return m_detach; } + + Preset::Type m_type; + ValidationType m_valid_type; + std::string m_preset_name; + + SavePresetDialog* m_parent {nullptr}; + wxStaticBitmap* m_valid_bmp {nullptr}; + wxComboBox* m_combo {nullptr}; + TextInput* m_input_ctrl {nullptr}; + wxStaticText* m_valid_label {nullptr}; + + PresetCollection* m_presets {nullptr}; + + //BBS: add project embedded preset relate logic + RadioBox * m_radio_user{nullptr}; + RadioBox * m_radio_project{nullptr}; + wxCheckBox* m_detach_checkbox{nullptr}; + + bool m_save_to_project {false}; + bool m_detach{false}; + + void update(); + }; + + std::vector m_items; + + Button* m_confirm {nullptr}; + Button* m_cancel {nullptr}; + wxBoxSizer* m_presets_sizer {nullptr}; + wxStaticText* m_label {nullptr}; + wxBoxSizer* m_radio_sizer {nullptr}; + ActionType m_action {UndefAction}; + int m_mode; + + std::string m_ph_printer_name; + std::string m_old_preset_name; + +public: + SavePresetDialog(wxWindow* parent, Preset::Type type, int mode = 0, std::string suffix = ""); + SavePresetDialog(wxWindow* parent, std::vector types, int mode = 0, std::string suffix = ""); + ~SavePresetDialog(); + + void AddItem(Preset::Type type, const std::string& suffix); + + std::string get_name(); + std::string get_name(Preset::Type type); + void input_name_from_other(std::string new_preset_name); + void confirm_from_other(); + + bool enable_ok_btn() const; + void add_info_for_edit_ph_printer(wxBoxSizer *sizer); + void update_info_for_edit_ph_printer(const std::string &preset_name); + void layout(); + //BBS: add project embedded preset relate logic + bool get_save_to_project_selection(Preset::Type type); + + // Method to get the detach state + bool get_detach_value(Preset::Type type); + + +protected: + void on_dpi_changed(const wxRect& suggested_rect) override; + void on_sys_color_changed() override {} + +private: + void build(std::vector types, std::string suffix = ""); + void on_select_cancel(wxCommandEvent &event); + void update_physical_printers(const std::string &preset_name); + void accept(wxCommandEvent &event); +}; + +} // namespace GUI +} // namespace Slic3r + +#endif diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index b87e98c10e..2354d10145 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -5506,17 +5506,18 @@ void Tab::save_preset(std::string name /*= ""*/, bool detach, bool save_to_proje // focus currently.is there anything better than this ? //! m_tabctrl->OnSetFocus(); if (from_input) { - SavePresetDialog dlg(m_parent, m_type, detach ? _u8L("Detached") : ""); + SavePresetDialog dlg(m_parent, m_type, m_mode, detach ? _u8L("Detached") : ""); dlg.Show(false); dlg.input_name_from_other(input_name); wxCommandEvent evt(wxEVT_TEXT, GetId()); dlg.GetEventHandler()->ProcessEvent(evt); dlg.confirm_from_other(); name = input_name; + detach = dlg.get_detach_value(m_type); } if (name.empty()) { - SavePresetDialog dlg(m_parent, m_type, detach ? _u8L("Detached") : ""); + SavePresetDialog dlg(m_parent, m_type, m_mode, detach ? _u8L("Detached") : ""); if (!m_just_edit) { if (dlg.ShowModal() != wxID_OK) return; @@ -5524,6 +5525,7 @@ void Tab::save_preset(std::string name /*= ""*/, bool detach, bool save_to_proje name = dlg.get_name(); //BBS: add project embedded preset relate logic save_to_project = dlg.get_save_to_project_selection(m_type); + detach = dlg.get_detach_value(m_type); } //BBS record current preset name