#include "Preferences.hpp" #include "OptionsGroup.hpp" #include "GUI_App.hpp" #include "MainFrame.hpp" #include "Plater.hpp" #include "MsgDialog.hpp" #include "I18N.hpp" #include "libslic3r/AppConfig.hpp" #include #include "Notebook.hpp" #include "OG_CustomCtrl.hpp" #include "wx/graphics.h" #include "Widgets/CheckBox.hpp" #include "Widgets/ComboBox.hpp" #include "Widgets/RadioBox.hpp" #include "Widgets/TextInput.hpp" #include #include namespace Slic3r { namespace GUI { WX_DEFINE_LIST(RadioSelectorList); wxDEFINE_EVENT(EVT_PREFERENCES_SELECT_TAB, wxCommandEvent); // @class: PreferencesDialog // @ret: items // @birth: created by onion wxBoxSizer *PreferencesDialog::create_item_title(wxString title, wxWindow *parent, wxString tooltip) { wxBoxSizer *m_sizer_title = new wxBoxSizer(wxHORIZONTAL); auto m_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, 0); m_title->SetForegroundColour(DESIGN_GRAY800_COLOR); m_title->SetFont(::Label::Head_13); m_title->Wrap(-1); //m_title->SetToolTip(tooltip); auto m_line = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); m_line->SetBackgroundColour(DESIGN_GRAY400_COLOR); m_sizer_title->Add(m_title, 0, wxALIGN_CENTER | wxALL, 3); m_sizer_title->Add(0, 0, 0, wxLEFT, 9); //m_sizer_title->Add(m_line, 0, wxEXPAND, 0); wxBoxSizer *sizer_line = new wxBoxSizer(wxVERTICAL); sizer_line->Add( m_line, 0, wxEXPAND, 0 ); m_sizer_title->Add( sizer_line, 1, wxALIGN_CENTER, 0 ); //m_sizer_title->Add( 0, 0, 0, wxEXPAND|wxLEFT, 80 ); return m_sizer_title; } wxBoxSizer *PreferencesDialog::create_item_combobox(wxString title, wxWindow *parent, wxString tooltip, std::string param, std::vector vlist) { wxBoxSizer *m_sizer_combox = new wxBoxSizer(wxHORIZONTAL); m_sizer_combox->Add(0, 0, 0, wxEXPAND | wxLEFT, 23); auto combo_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, DESIGN_TITLE_SIZE, 0); combo_title->SetForegroundColour(DESIGN_GRAY900_COLOR); combo_title->SetFont(::Label::Body_13); combo_title->SetToolTip(tooltip); combo_title->Wrap(-1); m_sizer_combox->Add(combo_title, 0, wxALIGN_CENTER | wxALL, 3); auto combobox = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, DESIGN_LARGE_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY); combobox->SetFont(::Label::Body_13); combobox->GetDropDown().SetFont(::Label::Body_13); std::vector::iterator iter; for (iter = vlist.begin(); iter != vlist.end(); iter++) { combobox->Append(*iter); } auto use_inch = app_config->get(param); if (!use_inch.empty()) { combobox->SetSelection(atoi(use_inch.c_str())); } m_sizer_combox->Add(combobox, 0, wxALIGN_CENTER, 0); //// save config combobox->GetDropDown().Bind(wxEVT_COMBOBOX, [this, param](wxCommandEvent &e) { app_config->set(param, std::to_string(e.GetSelection())); app_config->save(); e.Skip(); }); return m_sizer_combox; } wxBoxSizer *PreferencesDialog::create_item_language_combobox( wxString title, wxWindow *parent, wxString tooltip, int padding_left, std::string param, std::vector vlist) { wxBoxSizer *m_sizer_combox = new wxBoxSizer(wxHORIZONTAL); m_sizer_combox->Add(0, 0, 0, wxEXPAND | wxLEFT, 23); auto combo_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, DESIGN_TITLE_SIZE, 0); combo_title->SetForegroundColour(DESIGN_GRAY900_COLOR); combo_title->SetFont(::Label::Body_13); combo_title->SetToolTip(tooltip); combo_title->Wrap(-1); m_sizer_combox->Add(combo_title, 0, wxALIGN_CENTER | wxALL, 3); auto combobox = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, DESIGN_LARGE_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY); combobox->SetFont(::Label::Body_13); combobox->GetDropDown().SetFont(::Label::Body_13); std::vector::iterator iter; for (size_t i = 0; i < vlist.size(); ++i) { auto language_name = vlist[i]->Description; if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_CHINESE_SIMPLIFIED)) { //language_name = _L(vlist[i]->Description); //language_name = _L("Chinese (Simplified)"); language_name = wxString::FromUTF8("\xe4\xb8\xad\xe6\x96\x87\x28\xe7\xae\x80\xe4\xbd\x93\x29"); } else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_SPANISH)) { language_name = wxString::FromUTF8("\x45\x73\x70\x61\xc3\xb1\x6f\x6c"); } else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_GERMAN)) { language_name = wxString::FromUTF8("Deutsch"); } else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_SWEDISH)) { language_name = wxString::FromUTF8("\x53\x76\x65\x6e\x73\x6b\x61"); //Svenska } else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_DUTCH)) { language_name = wxString::FromUTF8("Nederlands"); } else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_FRENCH)) { language_name = wxString::FromUTF8("\x46\x72\x61\x6E\xC3\xA7\x61\x69\x73"); } else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_HUNGARIAN)) { language_name = wxString::FromUTF8("Magyar"); } if (app_config->get(param) == vlist[i]->CanonicalName) { m_current_language_selected = i; } combobox->Append(language_name); } combobox->SetSelection(m_current_language_selected); m_sizer_combox->Add(combobox, 0, wxALIGN_CENTER, 0); combobox->Bind(wxEVT_LEFT_DOWN, [this, combobox](wxMouseEvent &e) { m_current_language_selected = combobox->GetSelection(); e.Skip(); }); combobox->Bind(wxEVT_COMBOBOX, [this, param, vlist, combobox](wxCommandEvent &e) { if (combobox->GetSelection() == m_current_language_selected) return; if (e.GetString().mb_str() != app_config->get(param)) { { // the dialog needs to be destroyed before the call to switch_language() // or sometimes the application crashes into wxDialogBase() destructor // so we put it into an inner scope MessageDialog msg_wingow(nullptr, _L("Switching the language requires application restart.\n") + "\n" + _L("Do you want to continue?"), L("Language selection"), wxICON_QUESTION | wxOK | wxCANCEL); if (msg_wingow.ShowModal() == wxID_CANCEL) { combobox->SetSelection(m_current_language_selected); return; } } auto check = [this](bool yes_or_no) { // if (yes_or_no) // return true; int act_btns = UnsavedChangesDialog::ActionButtons::SAVE; return wxGetApp().check_and_keep_current_preset_changes(_L("Switching application language"), _L("Switching application language while some presets are modified."), act_btns); }; m_current_language_selected = combobox->GetSelection(); if (m_current_language_selected >= 0 && m_current_language_selected < vlist.size()) { app_config->set(param, vlist[m_current_language_selected]->CanonicalName.ToUTF8().data()); app_config->save(); wxGetApp().load_language(vlist[m_current_language_selected]->CanonicalName, false); Close(); // Reparent(nullptr); GetParent()->RemoveChild(this); wxGetApp().recreate_GUI(_L("Changing application language")); } } e.Skip(); }); return m_sizer_combox; } wxBoxSizer *PreferencesDialog::create_item_region_combobox(wxString title, wxWindow *parent, wxString tooltip, std::vector vlist) { std::vector local_regions = {"Asia-Pacific", "China", "Europe", "North America", "Others"}; wxBoxSizer *m_sizer_combox = new wxBoxSizer(wxHORIZONTAL); m_sizer_combox->Add(0, 0, 0, wxEXPAND | wxLEFT, 23); auto combo_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, DESIGN_TITLE_SIZE, 0); combo_title->SetForegroundColour(DESIGN_GRAY900_COLOR); combo_title->SetFont(::Label::Body_13); combo_title->SetToolTip(tooltip); combo_title->Wrap(-1); m_sizer_combox->Add(combo_title, 0, wxALIGN_CENTER | wxALL, 3); auto combobox = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, DESIGN_LARGE_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY); combobox->SetFont(::Label::Body_13); combobox->GetDropDown().SetFont(::Label::Body_13); m_sizer_combox->Add(combobox, 0, wxALIGN_CENTER, 0); std::vector::iterator iter; for (iter = vlist.begin(); iter != vlist.end(); iter++) { combobox->Append(*iter); } AppConfig * config = GUI::wxGetApp().app_config; int current_region = 0; if (!config->get("region").empty()) { std::string country_code = config->get("region"); for (auto i = 0; i < vlist.size(); i++) { if (local_regions[i].ToStdString() == country_code) { combobox->SetSelection(i); current_region = i; } } } combobox->GetDropDown().Bind(wxEVT_COMBOBOX, [this, combobox, current_region, local_regions](wxCommandEvent &e) { auto region_index = e.GetSelection(); auto region = local_regions[region_index]; auto area = ""; if (region == "CHN" || region == "China") area = "CN"; else if (region == "USA") area = "US"; else if (region == "Asia-Pacific") area = "Others"; else if (region == "Europe") area = "US"; else if (region == "North America") area = "US"; else area = "Others"; NetworkAgent* agent = wxGetApp().getAgent(); AppConfig* config = GUI::wxGetApp().app_config; if (agent) { MessageDialog msg_wingow(this, _L("Changing the region will log out your account.\n") + "\n" + _L("Do you want to continue?"), L("Region selection"), wxICON_QUESTION | wxOK | wxCANCEL); if (msg_wingow.ShowModal() == wxID_CANCEL) { combobox->SetSelection(current_region); return; } else { wxGetApp().request_user_logout(); if (agent) { agent->set_country_code(area); } config->set("region", region.ToStdString()); EndModal(wxID_CANCEL); } } else { config->set("region", region.ToStdString()); } e.Skip(); }); return m_sizer_combox; } wxBoxSizer *PreferencesDialog::create_item_loglevel_combobox(wxString title, wxWindow *parent, wxString tooltip, std::vector vlist) { wxBoxSizer *m_sizer_combox = new wxBoxSizer(wxHORIZONTAL); m_sizer_combox->Add(0, 0, 0, wxEXPAND | wxLEFT, 23); auto combo_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, DESIGN_TITLE_SIZE, 0); combo_title->SetForegroundColour(DESIGN_GRAY900_COLOR); combo_title->SetFont(::Label::Body_13); combo_title->SetToolTip(tooltip); combo_title->Wrap(-1); m_sizer_combox->Add(combo_title, 0, wxALIGN_CENTER | wxALL, 3); auto combobox = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, DESIGN_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY); combobox->SetFont(::Label::Body_13); combobox->GetDropDown().SetFont(::Label::Body_13); std::vector::iterator iter; for (iter = vlist.begin(); iter != vlist.end(); iter++) { combobox->Append(*iter); } auto severity_level = app_config->get("severity_level"); if (!severity_level.empty()) { combobox->SetValue(severity_level); } m_sizer_combox->Add(combobox, 0, wxALIGN_CENTER, 0); //// save config combobox->GetDropDown().Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &e) { auto level = Slic3r::get_string_logging_level(e.GetSelection()); Slic3r::set_logging_level(Slic3r::level_string_to_boost(level)); app_config->set("severity_level",level); app_config->save(); e.Skip(); }); return m_sizer_combox; } wxBoxSizer *PreferencesDialog::create_item_multiple_combobox( wxString title, wxWindow *parent, wxString tooltip, int padding_left, std::string param, std::vector vlista, std::vector vlistb) { std::vector params; Split(app_config->get(param), "/", params); std::vector::iterator iter; wxBoxSizer *m_sizer_tcombox= new wxBoxSizer(wxHORIZONTAL); m_sizer_tcombox->Add(0, 0, 0, wxEXPAND | wxLEFT, 23); auto combo_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, DESIGN_TITLE_SIZE, 0); combo_title->SetToolTip(tooltip); combo_title->Wrap(-1); combo_title->SetForegroundColour(DESIGN_GRAY900_COLOR); combo_title->SetFont(::Label::Body_13); m_sizer_tcombox->Add(combo_title, 0, wxALIGN_CENTER | wxALL, 3); auto combobox_left = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, DESIGN_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY); combobox_left->SetFont(::Label::Body_13); combobox_left->GetDropDown().SetFont(::Label::Body_13); for (iter = vlista.begin(); iter != vlista.end(); iter++) { combobox_left->Append(*iter); } combobox_left->SetValue(std::string(params[0].mb_str())); m_sizer_tcombox->Add(combobox_left, 0, wxALIGN_CENTER, 0); auto combo_title_add = new wxStaticText(parent, wxID_ANY, wxT("+"), wxDefaultPosition, wxDefaultSize, 0); combo_title->SetForegroundColour(DESIGN_GRAY900_COLOR); combo_title->SetFont(::Label::Body_13); combo_title_add->Wrap(-1); m_sizer_tcombox->Add(combo_title_add, 0, wxALIGN_CENTER | wxALL, 3); auto combobox_right = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, DESIGN_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY); combobox_right->SetFont(::Label::Body_13); combobox_right->GetDropDown().SetFont(::Label::Body_13); for (iter = vlistb.begin(); iter != vlistb.end(); iter++) { combobox_right->Append(*iter); } combobox_right->SetValue(std::string(params[1].mb_str())); m_sizer_tcombox->Add(combobox_right, 0, wxALIGN_CENTER, 0); // save config combobox_left->GetDropDown().Bind(wxEVT_COMBOBOX, [this, param, combobox_right](wxCommandEvent &e) { auto config = e.GetString() + wxString("/") + combobox_right->GetValue(); app_config->set(param, std::string(config.mb_str())); app_config->save(); e.Skip(); }); combobox_right->GetDropDown().Bind(wxEVT_COMBOBOX, [this, param, combobox_left](wxCommandEvent &e) { auto config = combobox_left->GetValue() + wxString("/") + e.GetString(); app_config->set(param, std::string(config.mb_str())); app_config->save(); e.Skip(); }); return m_sizer_tcombox; } wxBoxSizer *PreferencesDialog::create_item_backup_input(wxString title, wxWindow *parent, wxString tooltip, std::string param) { wxBoxSizer *m_sizer_input = new wxBoxSizer(wxHORIZONTAL); auto input_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, DESIGN_TITLE_SIZE, 0); input_title->SetForegroundColour(DESIGN_GRAY900_COLOR); input_title->SetFont(::Label::Body_13); input_title->SetToolTip(tooltip); input_title->Wrap(-1); auto input = new ::TextInput(parent, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, DESIGN_INPUT_SIZE, wxTE_PROCESS_ENTER); input->GetTextCtrl()->SetFont(::Label::Body_13); input->GetTextCtrl()->SetValue(app_config->get(param)); auto second_title = new wxStaticText(parent, wxID_ANY, _L("Second"), wxDefaultPosition, DESIGN_TITLE_SIZE, 0); second_title->SetForegroundColour(DESIGN_GRAY900_COLOR); second_title->SetFont(::Label::Body_13); second_title->SetToolTip(tooltip); second_title->Wrap(-1); m_sizer_input->Add(0, 0, 0, wxEXPAND | wxLEFT, 23); m_sizer_input->Add(input_title, 0, wxALIGN_CENTER | wxALL, 3); m_sizer_input->Add(input, 0, wxALIGN_CENTER, 0); m_sizer_input->Add(0, 0, 0, wxEXPAND | wxLEFT, 3); m_sizer_input->Add(second_title, 0, wxALIGN_CENTER| wxALL, 3); input->GetTextCtrl()->Bind(wxEVT_COMMAND_TEXT_UPDATED, [this, param, input](wxCommandEvent &e) { m_backup_interval_time = input->GetTextCtrl()->GetValue(); e.Skip(); }); input->GetTextCtrl()->Bind(wxEVT_TEXT_ENTER, [this, param, input](wxCommandEvent &e) { m_backup_interval_time = input->GetTextCtrl()->GetValue(); app_config->set("backup_interval", std::string(m_backup_interval_time.mb_str())); app_config->save(); e.Skip(); }); input->GetTextCtrl()->Bind(wxEVT_KILL_FOCUS, [this, param, input](wxFocusEvent &e) { m_backup_interval_time = input->GetTextCtrl()->GetValue(); app_config->set("backup_interval", std::string(m_backup_interval_time.mb_str())); app_config->save(); e.Skip(); }); if (app_config->get("backup_switch") == "true") { input->Enable(true); } else { input->Enable(false); } if (param == "backup_interval") { m_backup_interval_textinput = input; } return m_sizer_input; } wxBoxSizer *PreferencesDialog::create_item_switch(wxString title, wxWindow *parent, wxString tooltip ,std::string param) { wxBoxSizer *m_sizer_switch = new wxBoxSizer(wxHORIZONTAL); auto switch_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, DESIGN_TITLE_SIZE, 0); switch_title->SetForegroundColour(DESIGN_GRAY900_COLOR); switch_title->SetFont(::Label::Body_13); switch_title->SetToolTip(tooltip); switch_title->Wrap(-1); auto switchbox = new ::SwitchButton(parent, wxID_ANY); /*auto index = app_config->get(param); if (!index.empty()) { combobox->SetSelection(atoi(index.c_str())); }*/ m_sizer_switch->Add(0, 0, 0, wxEXPAND | wxLEFT, 23); m_sizer_switch->Add(switch_title, 0, wxALIGN_CENTER | wxALL, 3); m_sizer_switch->Add( 0, 0, 1, wxEXPAND, 0 ); m_sizer_switch->Add(switchbox, 0, wxALIGN_CENTER, 0); m_sizer_switch->Add( 0, 0, 0, wxEXPAND|wxLEFT, 40 ); //// save config switchbox->Bind(wxEVT_TOGGLEBUTTON, [this, param](wxCommandEvent &e) { /* app_config->set(param, std::to_string(e.GetSelection())); app_config->save();*/ e.Skip(); }); return m_sizer_switch; } wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxWindow *parent, wxString tooltip, int padding_left, std::string param) { wxBoxSizer *m_sizer_checkbox = new wxBoxSizer(wxHORIZONTAL); m_sizer_checkbox->Add(0, 0, 0, wxEXPAND | wxLEFT, 23); auto checkbox = new ::CheckBox(parent); checkbox->SetValue((app_config->get(param) == "true") ? true : false); m_sizer_checkbox->Add(checkbox, 0, wxALIGN_CENTER, 0); m_sizer_checkbox->Add(0, 0, 0, wxEXPAND | wxLEFT, 8); auto checkbox_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, 0); checkbox_title->SetForegroundColour(DESIGN_GRAY900_COLOR); checkbox_title->SetFont(::Label::Body_13); auto size = checkbox_title->GetTextExtent(title); checkbox_title->SetMinSize(wxSize(size.x + FromDIP(40), -1)); checkbox_title->Wrap(-1); m_sizer_checkbox->Add(checkbox_title, 0, wxALIGN_CENTER | wxALL, 3); //// save config checkbox->Bind(wxEVT_TOGGLEBUTTON, [this, checkbox, param](wxCommandEvent &e) { app_config->set_bool(param, checkbox->GetValue()); app_config->save(); // backup if (param == "backup_switch") { bool pbool = app_config->get("backup_switch") == "true" ? true : false; if (m_backup_interval_textinput != nullptr) { m_backup_interval_textinput->Enable(pbool); } } if (param == "sync_user_preset") { bool sync = app_config->get("sync_user_preset") == "true" ? true : false; if (sync) { wxGetApp().start_sync_user_preset(true); } else { wxGetApp().stop_sync_user_preset(); } } #ifdef __WXMSW__ if (param == "associate_3mf") { bool pbool = app_config->get("associate_3mf") == "true" ? true : false; if (pbool) { wxGetApp().associate_files(L"3mf"); } else { wxGetApp().disassociate_files(L"3mf"); } } if (param == "associate_stl") { bool pbool = app_config->get("associate_stl") == "true" ? true : false; if (pbool) { wxGetApp().associate_files(L"stl"); } else { wxGetApp().disassociate_files(L"stl"); } } if (param == "associate_step") { bool pbool = app_config->get("associate_step") == "true" ? true : false; if (pbool) { wxGetApp().associate_files(L"step"); } else { wxGetApp().disassociate_files(L"step"); } } #endif // __WXMSW__ e.Skip(); }); //// for debug mode if (param == "developer_mode") { m_developer_mode_ckeckbox = checkbox; } if (param == "dump_video") { m_dump_video_ckeckbox = checkbox; } checkbox->SetToolTip(tooltip); return m_sizer_checkbox; } wxWindow* PreferencesDialog::create_item_downloads(wxWindow* parent, int padding_left, std::string param) { wxString download_path = wxString::FromUTF8(app_config->get("download_path")); auto item_panel = new wxWindow(parent, wxID_ANY); item_panel->SetBackgroundColour(*wxWHITE); wxBoxSizer* m_sizer_checkbox = new wxBoxSizer(wxHORIZONTAL); m_sizer_checkbox->Add(0, 0, 0, wxEXPAND | wxLEFT, 23); auto m_staticTextPath = new wxStaticText(item_panel, wxID_ANY, download_path, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END); //m_staticTextPath->SetMaxSize(wxSize(FromDIP(440), -1)); m_staticTextPath->SetForegroundColour(DESIGN_GRAY600_COLOR); m_staticTextPath->SetFont(::Label::Body_13); m_staticTextPath->Wrap(-1); auto m_button_download = new Button(item_panel, _L("Browse")); StateColor abort_bg(std::pair(wxColour(255, 255, 255), StateColor::Disabled), std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), std::pair(wxColour(255, 255, 255), StateColor::Enabled), std::pair(wxColour(255, 255, 255), StateColor::Normal)); m_button_download->SetBackgroundColor(abort_bg); StateColor abort_bd(std::pair(wxColour(144, 144, 144), StateColor::Disabled), std::pair(wxColour(38, 46, 48), StateColor::Enabled)); m_button_download->SetBorderColor(abort_bd); StateColor abort_text(std::pair(wxColour(144, 144, 144), StateColor::Disabled), std::pair(wxColour(38, 46, 48), StateColor::Enabled)); m_button_download->SetTextColor(abort_text); m_button_download->SetFont(Label::Body_10); m_button_download->SetMinSize(wxSize(FromDIP(58), FromDIP(22))); m_button_download->SetSize(wxSize(FromDIP(58), FromDIP(22))); m_button_download->SetCornerRadius(FromDIP(12)); m_button_download->Bind(wxEVT_BUTTON, [this, m_staticTextPath, item_panel](auto& e) { wxString defaultPath = wxT("/"); wxDirDialog dialog(this, _L("Choose Download Directory"), defaultPath, wxDD_NEW_DIR_BUTTON); if (dialog.ShowModal() == wxID_OK) { wxString download_path = dialog.GetPath(); std::string download_path_str = download_path.ToUTF8().data(); app_config->set("download_path", download_path_str); m_staticTextPath->SetLabelText(download_path); item_panel->Layout(); } }); m_sizer_checkbox->Add(m_staticTextPath, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5)); m_sizer_checkbox->Add(m_button_download, 0, wxALL, FromDIP(5)); item_panel->SetSizer(m_sizer_checkbox); item_panel->Layout(); return item_panel; } wxWindow *PreferencesDialog ::create_item_radiobox(wxString title, wxWindow *parent, wxString tooltip, int padding_left, int groupid, std::string param) { wxWindow *item = new wxWindow(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, FromDIP(28))); item->SetBackgroundColour(*wxWHITE); RadioBox *radiobox = new RadioBox(item); radiobox->SetPosition(wxPoint(padding_left, (item->GetSize().GetHeight() - radiobox->GetSize().GetHeight()) / 2)); radiobox->Bind(wxEVT_LEFT_DOWN, &PreferencesDialog::OnSelectRadio, this); RadioSelector *rs = new RadioSelector; rs->m_groupid = groupid; rs->m_param_name = param; rs->m_radiobox = radiobox; rs->m_selected = false; m_radio_group.Append(rs); wxStaticText *text = new wxStaticText(item, wxID_ANY, title, wxDefaultPosition, wxDefaultSize); text->SetPosition(wxPoint(padding_left + radiobox->GetSize().GetWidth() + 10, (item->GetSize().GetHeight() - text->GetSize().GetHeight()) / 2)); radiobox->SetToolTip(tooltip); text->SetToolTip(tooltip); return item; } PreferencesDialog::PreferencesDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos, const wxSize &size, long style) : DPIDialog(parent, id, _L("Preferences"), pos, size, style) { SetBackgroundColour(*wxWHITE); create(); } void PreferencesDialog::create() { app_config = get_app_config(); m_backup_interval_time = app_config->get("backup_interval"); // set icon for dialog std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); SetSizeHints(wxDefaultSize, wxDefaultSize); auto main_sizer = new wxBoxSizer(wxVERTICAL); m_scrolledWindow = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL); m_scrolledWindow->SetScrollRate(5, 5); m_sizer_body = new wxBoxSizer(wxVERTICAL); auto m_top_line = new wxPanel(m_scrolledWindow, wxID_ANY, wxDefaultPosition, wxSize(DESIGN_RESOUTION_PREFERENCES.x, 1), wxTAB_TRAVERSAL); m_top_line->SetBackgroundColour(DESIGN_GRAY400_COLOR); m_sizer_body->Add(m_top_line, 0, wxEXPAND, 0); auto general_page = create_general_page(); #if !BBL_RELEASE_TO_PUBLIC auto debug_page = create_debug_page(); #endif /* create_gui_page(); create_sync_page(); create_shortcuts_page();*/ m_sizer_body->Add(0, 0, 0, wxTOP, FromDIP(28)); m_sizer_body->Add(general_page, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(38)); #if !BBL_RELEASE_TO_PUBLIC m_sizer_body->Add(debug_page, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(38)); #endif m_sizer_body->Add(0, 0, 0, wxBOTTOM, FromDIP(28)); m_scrolledWindow->SetSizerAndFit(m_sizer_body); main_sizer->Add(m_scrolledWindow, 1, wxEXPAND); SetSizer(main_sizer); Layout(); Fit(); int screen_height = wxGetDisplaySize().GetY(); if (this->GetSize().GetY() > screen_height) this->SetSize(this->GetSize().GetX() + FromDIP(40), screen_height * 4 / 5); CenterOnParent(); wxPoint start_pos = this->GetPosition(); if (start_pos.y < 0) { this->SetPosition(wxPoint(start_pos.x, 0)); } //select first auto event = wxCommandEvent(EVT_PREFERENCES_SELECT_TAB); event.SetInt(0); event.SetEventObject(this); wxPostEvent(this, event); } PreferencesDialog::~PreferencesDialog() { m_radio_group.DeleteContents(true); m_hash_selector.clear(); } void PreferencesDialog::on_dpi_changed(const wxRect &suggested_rect) { this->Refresh(); } void PreferencesDialog::Split(const std::string &src, const std::string &separator, std::vector &dest) { std::string str = src; std::string substring; std::string::size_type start = 0, index; dest.clear(); index = str.find_first_of(separator, start); do { if (index != std::string::npos) { substring = str.substr(start, index - start); dest.push_back(substring); start = index + separator.size(); index = str.find(separator, start); if (start == std::string::npos) break; } } while (index != std::string::npos); substring = str.substr(start); dest.push_back(substring); } wxWindow* PreferencesDialog::create_general_page() { auto page = new wxWindow(m_scrolledWindow, wxID_ANY); page->SetBackgroundColour(*wxWHITE); wxBoxSizer *sizer_page = new wxBoxSizer(wxVERTICAL); auto title_general_settings = create_item_title(_L("General Settings"), page, _L("General Settings")); // bbs supported languages wxLanguage supported_languages[]{ wxLANGUAGE_ENGLISH, wxLANGUAGE_CHINESE_SIMPLIFIED, wxLANGUAGE_GERMAN, wxLANGUAGE_FRENCH, wxLANGUAGE_SPANISH, wxLANGUAGE_SWEDISH, wxLANGUAGE_DUTCH, wxLANGUAGE_HUNGARIAN }; auto translations = wxTranslations::Get()->GetAvailableTranslations(SLIC3R_APP_KEY); std::vector language_infos; language_infos.emplace_back(wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH)); for (size_t i = 0; i < translations.GetCount(); ++i) { const wxLanguageInfo *langinfo = wxLocale::FindLanguageInfo(translations[i]); if (langinfo == nullptr) continue; int language_num = sizeof(supported_languages) / sizeof(supported_languages[0]); for (auto si = 0; si < language_num; si++) { if (langinfo == wxLocale::GetLanguageInfo(supported_languages[si])) { language_infos.emplace_back(langinfo); } } //if (langinfo != nullptr) language_infos.emplace_back(langinfo); } sort_remove_duplicates(language_infos); std::sort(language_infos.begin(), language_infos.end(), [](const wxLanguageInfo *l, const wxLanguageInfo *r) { return l->Description < r->Description; }); auto item_language = create_item_language_combobox(_L("Language"), page, _L("Language"), 50, "language", language_infos); std::vector Regions = {_L("Asia-Pacific"), _L("China"), _L("Europe"), _L("North America"), _L("Others")}; auto item_region= create_item_region_combobox(_L("Login Region"), page, _L("Login Region"), Regions); std::vector Units = {_L("Metric"), _L("Imperial")}; auto item_currency = create_item_combobox(_L("Units"), page, _L("Units"), "use_inches", Units); auto item_hints = create_item_checkbox(_L("Show \"Tip of the day\" notification after start"), page, _L("If enabled, useful hints are displayed at startup."), 50, "show_hints"); auto title_sync_settings = create_item_title(_L("User sync"), page, _L("User sync")); auto item_user_sync = create_item_checkbox(_L("Auto sync user presets(Printer/Filament/Process)"), page, _L("User Sync"), 50, "sync_user_preset"); #ifdef _WIN32 auto title_associate_file = create_item_title(_L("Associate files to BambuStudio"), page, _L("Associate files to BambuStudio")); // associate file auto item_associate_3mf = create_item_checkbox(_L("Associate .3mf files to BambuStudio"), page, _L("If enabled, sets BambuStudio as default application to open .3mf files"), 50, "associate_3mf"); auto item_associate_stl = create_item_checkbox(_L("Associate .stl files to BambuStudio"), page, _L("If enabled, sets BambuStudio as default application to open .stl files"), 50, "associate_stl"); auto item_associate_step = create_item_checkbox(_L("Associate .step/.stp files to BambuStudio"), page, _L("If enabled, sets BambuStudio as default application to open .step files"), 50, "associate_step"); #endif // _WIN32 auto title_backup = create_item_title(_L("Backup"), page, _L("Backup")); //auto item_backup = create_item_switch(_L("Backup switch"), page, _L("Backup switch"), "units"); auto item_backup = create_item_checkbox(_L("Auto-Backup"), page,_L("Auto-Backup"), 50, "backup_switch"); auto item_backup_interval = create_item_backup_input(_L("Backup interval"), page, _L("Backup interval"), "backup_interval"); //downloads auto title_downloads = create_item_title(_L("Downloads"), page, _L("Downloads")); auto item_downloads = create_item_downloads(page,50,"download_path"); sizer_page->Add(title_general_settings, 0, wxEXPAND, 0); sizer_page->Add(item_language, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_region, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_currency, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_hints, 0, wxTOP, FromDIP(3)); sizer_page->Add(title_sync_settings, 0, wxTOP | wxEXPAND, FromDIP(20)); sizer_page->Add(item_user_sync, 0, wxTOP, FromDIP(3)); #ifdef _WIN32 sizer_page->Add(title_associate_file, 0, wxTOP| wxEXPAND, FromDIP(20)); sizer_page->Add(item_associate_3mf, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_associate_stl, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_associate_step, 0, wxTOP, FromDIP(3)); #endif // _WIN32 sizer_page->Add(title_backup, 0, wxTOP| wxEXPAND, FromDIP(20)); sizer_page->Add(item_backup, 0, wxTOP,FromDIP(3)); sizer_page->Add(item_backup_interval, 0, wxTOP,FromDIP(3)); //sizer_page->Add(0, 0, 0, wxTOP, 26); sizer_page->Add(title_downloads, 0, wxTOP| wxEXPAND, FromDIP(20)); sizer_page->Add(item_downloads, 0, wxEXPAND, FromDIP(3)); page->SetSizer(sizer_page); page->Layout(); sizer_page->Fit(page); return page; } void PreferencesDialog::create_gui_page() { auto page = new wxWindow(this, wxID_ANY); wxBoxSizer *sizer_page = new wxBoxSizer(wxVERTICAL); auto title_index_and_tip = create_item_title(_L("Home page and daily tips"), page, _L("Home page and daily tips")); auto item_home_page = create_item_checkbox(_L("Show home page on startup"), page, _L("Show home page on startup"), 50, "show_home_page"); //auto item_daily_tip = create_item_checkbox(_L("Show daily tip on startup"), page, _L("Show daily tip on startup"), 50, "show_daily_tips"); sizer_page->Add(title_index_and_tip, 0, wxTOP, 26); sizer_page->Add(item_home_page, 0, wxTOP, 6); //sizer_page->Add(item_daily_tip, 0, wxTOP, 6); page->SetSizer(sizer_page); page->Layout(); sizer_page->Fit(page); } void PreferencesDialog::create_sync_page() { auto page = new wxWindow(this, wxID_ANY); wxBoxSizer *sizer_page = new wxBoxSizer(wxVERTICAL); auto title_sync_settingy = create_item_title(_L("Sync settings"), page, _L("Sync settings")); auto item_user_sync = create_item_checkbox(_L("User sync"), page, _L("User sync"), 50, "user_sync_switch"); auto item_preset_sync = create_item_checkbox(_L("Preset sync"), page, _L("Preset sync"), 50, "preset_sync_switch"); auto item_preferences_sync = create_item_checkbox(_L("Preferences sync"), page, _L("Preferences sync"), 50, "preferences_sync_switch"); sizer_page->Add(title_sync_settingy, 0, wxTOP, 26); sizer_page->Add(item_user_sync, 0, wxTOP, 6); sizer_page->Add(item_preset_sync, 0, wxTOP, 6); sizer_page->Add(item_preferences_sync, 0, wxTOP, 6); page->SetSizer(sizer_page); page->Layout(); sizer_page->Fit(page); } void PreferencesDialog::create_shortcuts_page() { auto page = new wxWindow(this, wxID_ANY); wxBoxSizer *sizer_page = new wxBoxSizer(wxVERTICAL); auto title_view_control = create_item_title(_L("View control settings"), page, _L("View control settings")); std::vector keyboard_supported; Split(app_config->get("keyboard_supported"), "/", keyboard_supported); std::vector mouse_supported; Split(app_config->get("mouse_supported"), "/", mouse_supported); auto item_rotate_view = create_item_multiple_combobox(_L("Rotate of view"), page, _L("Rotate of view"), 10, "rotate_view", keyboard_supported, mouse_supported); auto item_move_view = create_item_multiple_combobox(_L("Move of view"), page, _L("Move of view"), 10, "move_view", keyboard_supported, mouse_supported); auto item_zoom_view = create_item_multiple_combobox(_L("Zoom of view"), page, _L("Zoom of view"), 10, "rotate_view", keyboard_supported, mouse_supported); auto title_other = create_item_title(_L("Other"), page, _L("Other")); auto item_other = create_item_checkbox(_L("Mouse wheel reverses when zooming"), page, _L("Mouse wheel reverses when zooming"), 50, "mouse_wheel"); sizer_page->Add(title_view_control, 0, wxTOP, 26); sizer_page->Add(item_rotate_view, 0, wxTOP, 8); sizer_page->Add(item_move_view, 0, wxTOP, 8); sizer_page->Add(item_zoom_view, 0, wxTOP, 8); // sizer_page->Add(item_precise_control, 0, wxTOP, 0); sizer_page->Add(title_other, 0, wxTOP, 20); sizer_page->Add(item_other, 0, wxTOP, 5); page->SetSizer(sizer_page); page->Layout(); sizer_page->Fit(page); } wxBoxSizer* PreferencesDialog::create_debug_page() { //wxBoxSizer *sizer_page = new wxBoxSizer(wxVERTICAL); m_developer_mode_def = app_config->get("developer_mode"); m_dump_video_def = app_config->get("dump_video"); m_backup_interval_def = app_config->get("backup_interval"); m_iot_environment_def = app_config->get("iot_environment"); wxBoxSizer *bSizer = new wxBoxSizer(wxVERTICAL); auto title_develop_mode = create_item_title(_L("Develop mode"), m_scrolledWindow, _L("Develop mode")); auto item_develop_mode = create_item_checkbox(_L("Develop mode"), m_scrolledWindow, _L("Develop mode"), 50, "developer_mode"); auto item_dump_video = create_item_checkbox(_L("Dump video"), m_scrolledWindow, _L("Dump video"), 50, "dump_video"); auto title_log_level = create_item_title(_L("Log Level"), m_scrolledWindow, _L("Log Level")); auto log_level_list = std::vector{_L("fatal"), _L("error"), _L("warning"), _L("info"), _L("debug"), _L("trace")}; auto loglevel_combox = create_item_loglevel_combobox(_L("Log Level"), m_scrolledWindow, _L("Log Level"), log_level_list); auto title_host = create_item_title(_L("Host Setting"), m_scrolledWindow, _L("Host Setting")); auto radio1 = create_item_radiobox(_L("DEV host: api-dev.bambu-lab.com/v1"), m_scrolledWindow, wxEmptyString, 50, 1, "dev_host"); auto radio2 = create_item_radiobox(_L("QA host: api-qa.bambu-lab.com/v1"), m_scrolledWindow, wxEmptyString, 50, 1, "qa_host"); auto radio3 = create_item_radiobox(_L("PRE host: api-pre.bambu-lab.com/v1"), m_scrolledWindow, wxEmptyString, 50, 1, "pre_host"); auto radio4 = create_item_radiobox(_L("Product host"), m_scrolledWindow, wxEmptyString, 50, 1, "product_host"); if (m_iot_environment_def == ENV_DEV_HOST) { on_select_radio("dev_host"); } else if (m_iot_environment_def == ENV_QAT_HOST) { on_select_radio("qa_host"); } else if (m_iot_environment_def == ENV_PRE_HOST) { on_select_radio("pre_host"); } else if (m_iot_environment_def == ENV_PRODUCT_HOST) { on_select_radio("product_host"); } wxButton *debug_button = new wxButton(m_scrolledWindow, wxID_ANY, _L("debug save button"), wxDefaultPosition, wxDefaultSize, 0); debug_button->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { // success message box MessageDialog dialog(this, _L("save debug settings"), _L("DEBUG settings have saved successfully!"), wxNO_DEFAULT | wxYES_NO | wxICON_INFORMATION); switch (dialog.ShowModal()) { case wxID_NO: { if (m_developer_mode_def != app_config->get("developer_mode")) { app_config->set_bool("developer_mode", m_developer_mode_def == "true" ? true : false); m_developer_mode_ckeckbox->SetValue(m_developer_mode_def == "true" ? true : false); } if (m_dump_video_def != app_config->get("dump_video")) { app_config->set_bool("dump_video", m_dump_video_def == "true" ? true : false); m_dump_video_ckeckbox->SetValue(m_dump_video_def == "true" ? true : false); } if (m_backup_interval_def != m_backup_interval_time) { m_backup_interval_textinput->GetTextCtrl()->SetValue(m_backup_interval_def); } if (m_iot_environment_def == ENV_DEV_HOST) { on_select_radio("dev_host"); } else if (m_iot_environment_def == ENV_QAT_HOST) { on_select_radio("qa_host"); } else if (m_iot_environment_def == ENV_PRE_HOST) { on_select_radio("pre_host"); } else if (m_iot_environment_def == ENV_PRODUCT_HOST) { on_select_radio("product_host"); } break; } case wxID_YES: { // bbs domain changed auto param = get_select_radio(1); std::map iot_environment_map; iot_environment_map["dev_host"] = ENV_DEV_HOST; iot_environment_map["qa_host"] = ENV_QAT_HOST; iot_environment_map["pre_host"] = ENV_PRE_HOST; iot_environment_map["product_host"] = ENV_PRODUCT_HOST; if (iot_environment_map[param] != m_iot_environment_def) { NetworkAgent* agent = wxGetApp().getAgent(); if (param == "dev_host") { app_config->set("iot_environment", ENV_DEV_HOST); } else if (param == "qa_host") { app_config->set("iot_environment", ENV_QAT_HOST); } else if (param == "pre_host") { app_config->set("iot_environment", ENV_PRE_HOST); } else if (param == "product_host") { app_config->set("iot_environment", ENV_PRODUCT_HOST); } AppConfig* config = GUI::wxGetApp().app_config; std::string country_code = config->get_country_code(); if (agent) { wxGetApp().request_user_logout(); agent->set_country_code(country_code); } wxMessageBox(_L("Switch cloud environment, Please login again!")); } // bbs backup //app_config->set("backup_interval", std::string(m_backup_interval_time.mb_str())); app_config->save(); Slic3r::set_backup_interval(boost::lexical_cast(app_config->get("backup_interval"))); // bbs developer mode auto developer_mode = app_config->get("developer_mode"); if (developer_mode == "true") { Slic3r::GUI::wxGetApp().save_mode(comDevelop); Slic3r::GUI::wxGetApp().mainframe->show_log_window(); } else { Slic3r::GUI::wxGetApp().save_mode(comAdvanced); } this->Close(); break; } } }); bSizer->Add(title_develop_mode, 0, wxTOP | wxEXPAND, FromDIP(20)); bSizer->Add(item_develop_mode, 0, wxTOP,FromDIP(3)); bSizer->Add(item_dump_video, 0, wxTOP, FromDIP(3)); bSizer->Add(title_log_level, 0, wxTOP| wxEXPAND, FromDIP(20)); bSizer->Add(loglevel_combox, 0, wxTOP, FromDIP(3)); bSizer->Add(title_host, 0, wxTOP| wxEXPAND, FromDIP(20)); bSizer->Add(radio1, 0, wxEXPAND | wxTOP, FromDIP(3)); bSizer->Add(radio2, 0, wxEXPAND | wxTOP, FromDIP(3)); bSizer->Add(radio3, 0, wxEXPAND | wxTOP, FromDIP(3)); bSizer->Add(radio4, 0, wxEXPAND | wxTOP, FromDIP(3)); bSizer->Add(debug_button, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, FromDIP(15)); return bSizer; } void PreferencesDialog::on_select_radio(std::string param) { RadioSelectorList::Node *node = m_radio_group.GetFirst(); auto groupid = 0; while (node) { RadioSelector *rs = node->GetData(); if (rs->m_param_name == param) groupid = rs->m_groupid; node = node->GetNext(); } node = m_radio_group.GetFirst(); while (node) { RadioSelector *rs = node->GetData(); if (rs->m_groupid == groupid && rs->m_param_name == param) rs->m_radiobox->SetValue(true); if (rs->m_groupid == groupid && rs->m_param_name != param) rs->m_radiobox->SetValue(false); node = node->GetNext(); } } wxString PreferencesDialog::get_select_radio(int groupid) { RadioSelectorList::Node *node = m_radio_group.GetFirst(); while (node) { RadioSelector *rs = node->GetData(); if (rs->m_groupid == groupid && rs->m_radiobox->GetValue()) { return rs->m_param_name; } node = node->GetNext(); } return wxEmptyString; } void PreferencesDialog::OnSelectRadio(wxMouseEvent &event) { RadioSelectorList::Node *node = m_radio_group.GetFirst(); auto groupid = 0; while (node) { RadioSelector *rs = node->GetData(); if (rs->m_radiobox->GetId() == event.GetId()) groupid = rs->m_groupid; node = node->GetNext(); } node = m_radio_group.GetFirst(); while (node) { RadioSelector *rs = node->GetData(); if (rs->m_groupid == groupid && rs->m_radiobox->GetId() == event.GetId()) rs->m_radiobox->SetValue(true); if (rs->m_groupid == groupid && rs->m_radiobox->GetId() != event.GetId()) rs->m_radiobox->SetValue(false); node = node->GetNext(); } } }} // namespace Slic3r::GUI