#include "ReleaseNote.hpp" #include "I18N.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/Thread.hpp" #include "GUI.hpp" #include "GUI_App.hpp" #include "GUI_Preview.hpp" #include "MainFrame.hpp" #include "format.hpp" #include "Widgets/ProgressDialog.hpp" #include "Widgets/RoundedRectangle.hpp" #include "Widgets/StaticBox.hpp" #include "Widgets/WebView.hpp" #include #include #include #include #include #include "Plater.hpp" #include "BitmapCache.hpp" namespace Slic3r { namespace GUI { wxDEFINE_EVENT(EVT_SECONDARY_CHECK_CONFIRM, wxCommandEvent); ReleaseNoteDialog::ReleaseNoteDialog(Plater *plater /*= nullptr*/) : DPIDialog(static_cast(wxGetApp().mainframe), wxID_ANY, _L("Release Note"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) { std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); SetBackgroundColour(*wxWHITE); wxBoxSizer *m_sizer_main = new wxBoxSizer(wxVERTICAL); auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1)); m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0); m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(30)); wxBoxSizer *m_sizer_body = new wxBoxSizer(wxHORIZONTAL); m_sizer_body->Add(0, 0, 0, wxLEFT, FromDIP(38)); auto sm = create_scaled_bitmap("BambuStudio", nullptr, 70); auto brand = new wxStaticBitmap(this, wxID_ANY, sm, wxDefaultPosition, wxSize(FromDIP(70), FromDIP(70))); m_sizer_body->Add(brand, 0, wxALL, 0); m_sizer_body->Add(0, 0, 0, wxRIGHT, FromDIP(25)); wxBoxSizer *m_sizer_right = new wxBoxSizer(wxVERTICAL); m_text_up_info = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0); m_text_up_info->SetFont(::Label::Head_14); m_text_up_info->SetForegroundColour(wxColour(0x26, 0x2E, 0x30)); m_text_up_info->Wrap(-1); m_sizer_right->Add(m_text_up_info, 0, 0, 0); m_sizer_right->Add(0, 0, 1, wxTOP, FromDIP(15)); m_vebview_release_note = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(560), FromDIP(430)), wxVSCROLL); m_vebview_release_note->SetScrollRate(5, 5); m_vebview_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8)); m_vebview_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430))); m_sizer_right->Add(m_vebview_release_note, 0, wxEXPAND | wxRIGHT, FromDIP(20)); m_sizer_body->Add(m_sizer_right, 1, wxBOTTOM | wxEXPAND, FromDIP(30)); m_sizer_main->Add(m_sizer_body, 0, wxEXPAND, 0); SetSizer(m_sizer_main); Layout(); m_sizer_main->Fit(this); Centre(wxBOTH); } ReleaseNoteDialog::~ReleaseNoteDialog() {} void ReleaseNoteDialog::on_dpi_changed(const wxRect &suggested_rect) { } void ReleaseNoteDialog::update_release_note(wxString release_note, std::string version) { m_text_up_info->SetLabel(wxString::Format(_L("version %s update information :"), version)); wxBoxSizer * sizer_text_release_note = new wxBoxSizer(wxVERTICAL); auto m_staticText_release_note = new wxStaticText(m_vebview_release_note, wxID_ANY, release_note, wxDefaultPosition, wxDefaultSize, 0); m_staticText_release_note->Wrap(FromDIP(530)); sizer_text_release_note->Add(m_staticText_release_note, 0, wxALL, 5); m_vebview_release_note->SetSizer(sizer_text_release_note); m_vebview_release_note->Layout(); m_vebview_release_note->Fit(); } void UpdateVersionDialog::alter_choice(wxCommandEvent& event) { wxGetApp().set_skip_version(m_remind_choice->GetValue()); } UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent) : DPIDialog(parent, wxID_ANY, _L("New version of Bambu Studio"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) { std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); SetBackgroundColour(*wxWHITE); wxBoxSizer *m_sizer_main = new wxBoxSizer(wxVERTICAL); auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1)); m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0); m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(30)); wxBoxSizer *m_sizer_body = new wxBoxSizer(wxHORIZONTAL); m_sizer_body->Add(0, 0, 0, wxLEFT, FromDIP(38)); auto sm = create_scaled_bitmap("BambuStudio", nullptr, 70); auto brand = new wxStaticBitmap(this, wxID_ANY, sm, wxDefaultPosition, wxSize(FromDIP(70), FromDIP(70))); m_sizer_body->Add(brand, 0, wxALL, 0); m_sizer_body->Add(0, 0, 0, wxRIGHT, FromDIP(25)); wxBoxSizer *m_sizer_right = new wxBoxSizer(wxVERTICAL); m_text_up_info = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0); m_text_up_info->SetFont(::Label::Head_14); m_text_up_info->SetForegroundColour(wxColour(0x26, 0x2E, 0x30)); m_text_up_info->Wrap(-1); m_sizer_right->Add(m_text_up_info, 0, 0, 0); m_sizer_right->Add(0, 0, 1, wxTOP, FromDIP(15)); m_simplebook_release_note = new wxSimplebook(this); m_simplebook_release_note->SetSize(wxSize(FromDIP(560), FromDIP(430))); m_simplebook_release_note->SetMinSize(wxSize(FromDIP(560), FromDIP(430))); m_simplebook_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430))); m_simplebook_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8)); m_scrollwindows_release_note = new wxScrolledWindow(m_simplebook_release_note, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(560), FromDIP(430)), wxVSCROLL); m_scrollwindows_release_note->SetScrollRate(5, 5); m_scrollwindows_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8)); //webview m_vebview_release_note = CreateTipView(m_simplebook_release_note); m_vebview_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8)); m_vebview_release_note->SetSize(wxSize(FromDIP(560), FromDIP(430))); m_vebview_release_note->SetMinSize(wxSize(FromDIP(560), FromDIP(430))); m_vebview_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430))); fs::path ph(data_dir()); ph /= "resources/tooltip/common/releasenote.html"; if (!fs::exists(ph)) { ph = resources_dir(); ph /= "tooltip/releasenote.html"; } auto url = ph.string(); std::replace(url.begin(), url.end(), '\\', '/'); url = "file:///" + url; m_vebview_release_note->LoadURL(from_u8(url)); m_simplebook_release_note->AddPage(m_scrollwindows_release_note, wxEmptyString, false); m_simplebook_release_note->AddPage(m_vebview_release_note, wxEmptyString, false); m_remind_choice = new wxCheckBox( this, wxID_ANY, _L("Don't remind me of this version again"), wxDefaultPosition, wxDefaultSize, 0 ); m_remind_choice->SetValue(false); m_remind_choice->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &UpdateVersionDialog::alter_choice,this); auto sizer_button = new wxBoxSizer(wxHORIZONTAL); StateColor btn_bg_green(std::pair(wxColour(27, 136, 68), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered), std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal)); StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), std::pair(*wxWHITE, StateColor::Normal)); m_button_ok = new Button(this, _L("OK")); m_button_ok->SetBackgroundColor(btn_bg_green); m_button_ok->SetBorderColor(*wxWHITE); m_button_ok->SetTextColor(*wxWHITE); m_button_ok->SetFont(Label::Body_12); m_button_ok->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_button_ok->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); m_button_ok->SetCornerRadius(FromDIP(12)); m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { EndModal(wxID_YES); }); m_button_cancel = new Button(this, _L("Cancel")); m_button_cancel->SetBackgroundColor(btn_bg_white); m_button_cancel->SetBorderColor(wxColour(38, 46, 48)); m_button_cancel->SetFont(Label::Body_12); m_button_cancel->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_button_cancel->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); m_button_cancel->SetCornerRadius(FromDIP(12)); m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { EndModal(wxID_NO); }); sizer_button->Add(m_remind_choice, 0, wxALL | wxEXPAND, FromDIP(5)); sizer_button->AddStretchSpacer(); sizer_button->Add(m_button_ok, 0, wxALL, FromDIP(5)); sizer_button->Add(m_button_cancel, 0, wxALL, FromDIP(5)); m_sizer_right->Add(m_simplebook_release_note, 0, wxEXPAND | wxRIGHT, FromDIP(20)); m_sizer_right->Add(sizer_button, 0, wxEXPAND | wxRIGHT, FromDIP(20)); m_sizer_body->Add(m_sizer_right, 1, wxBOTTOM | wxEXPAND, FromDIP(8)); m_sizer_main->Add(m_sizer_body, 0, wxEXPAND, 0); m_sizer_main->Add(0, 0, 0, wxBOTTOM, 10); SetSizer(m_sizer_main); Layout(); m_sizer_main->Fit(this); Centre(wxBOTH); } UpdateVersionDialog::~UpdateVersionDialog() {} wxWebView* UpdateVersionDialog::CreateTipView(wxWindow* parent) { wxWebView* tipView = WebView::CreateWebView(parent, ""); tipView->Bind(wxEVT_WEBVIEW_LOADED, &UpdateVersionDialog::OnLoaded, this); tipView->Bind(wxEVT_WEBVIEW_NAVIGATED, &UpdateVersionDialog::OnTitleChanged, this); tipView->Bind(wxEVT_WEBVIEW_ERROR, &UpdateVersionDialog::OnError, this); return tipView; } void UpdateVersionDialog::OnLoaded(wxWebViewEvent& event) { event.Skip(); } void UpdateVersionDialog::OnTitleChanged(wxWebViewEvent& event) { //ShowReleaseNote(); event.Skip(); } void UpdateVersionDialog::OnError(wxWebViewEvent& event) { event.Skip(); } static std::string url_encode(const std::string& value) { std::ostringstream escaped; escaped.fill('0'); escaped << std::hex; for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) { std::string::value_type c = (*i); // Keep alphanumeric and other accepted characters intact if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { escaped << c; continue; } // Any other characters are percent-encoded escaped << std::uppercase; escaped << '%' << std::setw(2) << int((unsigned char)c); escaped << std::nouppercase; } return escaped.str(); } bool UpdateVersionDialog::ShowReleaseNote(std::string content) { auto script = "window.showMarkdown('" + url_encode(content) + "', true);"; RunScript(script); return true; } void UpdateVersionDialog::RunScript(std::string script) { WebView::RunScript(m_vebview_release_note, script); script.clear(); } void UpdateVersionDialog::on_dpi_changed(const wxRect &suggested_rect) { m_button_ok->Rescale(); m_button_cancel->Rescale(); } std::vector UpdateVersionDialog::splitWithStl(std::string str,std::string pattern) { std::string::size_type pos; std::vector result; str += pattern; int size = str.size(); for (int i = 0; i < size; i++) { pos = str.find(pattern, i); if (pos < size) { std::string s = str.substr(i, pos - i); result.push_back(s); i = pos + pattern.size() - 1; } } return result; } void UpdateVersionDialog::update_version_info(wxString release_note, wxString version) { //bbs check whether the web display is used bool use_web_link = false; std::string url_line = ""; auto split_array = splitWithStl(release_note.ToStdString(), "###"); for (auto i = 0; i < split_array.size(); i++) { std::string url = split_array[i]; if (std::strstr (url.c_str(), "http://") != NULL || std::strstr (url.c_str(), "https://") != NULL) { use_web_link = true; url_line = url; break; } } if (use_web_link) { m_simplebook_release_note->SetSelection(1); m_vebview_release_note->LoadURL(from_u8(url_line)); } else { m_simplebook_release_note->SetSelection(0); m_text_up_info->SetLabel(wxString::Format(_L("Click to download new version in default browser: %s"), version)); wxBoxSizer* sizer_text_release_note = new wxBoxSizer(wxVERTICAL); auto m_staticText_release_note = new wxStaticText(m_scrollwindows_release_note, wxID_ANY, release_note, wxDefaultPosition, wxDefaultSize, 0); m_staticText_release_note->Wrap(FromDIP(530)); sizer_text_release_note->Add(m_staticText_release_note, 0, wxALL, 5); m_scrollwindows_release_note->SetSizer(sizer_text_release_note); m_scrollwindows_release_note->Layout(); m_scrollwindows_release_note->Fit(); } } SecondaryCheckDialog::SecondaryCheckDialog(wxWindow* parent, wxWindowID id, const wxString& title, enum ButtonStyle btn_style, const wxPoint& pos, const wxSize& size, long style) :DPIDialog(parent, id, title, pos, size, style) { std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); SetBackgroundColour(*wxWHITE); m_sizer_main = new wxBoxSizer(wxVERTICAL); auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(480), 1)); m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0); m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5)); wxBoxSizer* m_sizer_right = new wxBoxSizer(wxVERTICAL); m_sizer_right->Add(0, 0, 1, wxTOP, FromDIP(15)); m_vebview_release_note = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL); m_vebview_release_note->SetScrollRate(0, 5); m_vebview_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8)); m_vebview_release_note->SetMinSize(wxSize(FromDIP(280), FromDIP(280))); auto sizer_button = new wxBoxSizer(wxHORIZONTAL); StateColor btn_bg_green(std::pair(wxColour(27, 136, 68), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered), std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal)); StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), std::pair(*wxWHITE, StateColor::Normal)); m_button_ok = new Button(this, _L("OK")); m_button_ok->SetBackgroundColor(btn_bg_green); m_button_ok->SetBorderColor(*wxWHITE); m_button_ok->SetTextColor(*wxWHITE); m_button_ok->SetFont(Label::Body_12); m_button_ok->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_button_ok->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); m_button_ok->SetCornerRadius(FromDIP(12)); m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { wxCommandEvent evt(EVT_SECONDARY_CHECK_CONFIRM, GetId()); e.SetEventObject(this); GetEventHandler()->ProcessEvent(evt); if (this->IsModal()) EndModal(wxID_YES); else this->Close(); }); m_button_cancel = new Button(this, _L("Cancel")); m_button_cancel->SetBackgroundColor(btn_bg_white); m_button_cancel->SetBorderColor(wxColour(38, 46, 48)); m_button_cancel->SetFont(Label::Body_12); m_button_cancel->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_button_cancel->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); m_button_cancel->SetCornerRadius(FromDIP(12)); m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { if (this->IsModal()) EndModal(wxID_NO); else this->Close(); }); if (btn_style != CONFIRM_AND_CANCEL) m_button_cancel->Hide(); else m_button_cancel->Show(); sizer_button->AddStretchSpacer(); sizer_button->Add(m_button_ok, 0, wxALL, FromDIP(5)); sizer_button->Add(m_button_cancel, 0, wxALL, FromDIP(5)); m_sizer_right->Add(m_vebview_release_note, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(20)); m_sizer_right->Add(sizer_button, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(20)); SetSizer(m_sizer_right); Layout(); m_sizer_main->Fit(this); CenterOnParent(); } void SecondaryCheckDialog::update_text(wxString text) { wxBoxSizer* sizer_text_release_note = new wxBoxSizer(wxVERTICAL); auto m_staticText_release_note = new Label(m_vebview_release_note, text); m_staticText_release_note->Wrap(FromDIP(260)); m_staticText_release_note->SetSize(wxSize(FromDIP(260), -1)); m_staticText_release_note->SetMaxSize(wxSize(FromDIP(260), -1)); m_staticText_release_note->SetMinSize(wxSize(FromDIP(260), -1)); wxBoxSizer* top_blank_sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer* bottom_blank_sizer = new wxBoxSizer(wxVERTICAL); top_blank_sizer->Add(FromDIP(5), 0, wxALIGN_CENTER | wxALL, FromDIP(5)); bottom_blank_sizer->Add(FromDIP(5), 0, wxALIGN_CENTER | wxALL, FromDIP(5)); sizer_text_release_note->Add(top_blank_sizer, 0, wxALIGN_CENTER | wxALL, FromDIP(5)); sizer_text_release_note->Add(m_staticText_release_note, 0, wxALIGN_CENTER, FromDIP(5)); sizer_text_release_note->Add(bottom_blank_sizer, 0, wxALIGN_CENTER | wxALL, FromDIP(5)); m_vebview_release_note->SetSizer(sizer_text_release_note); auto text_size = m_staticText_release_note->GetSize(); if (text_size.y < FromDIP(280)) m_vebview_release_note->SetMinSize(wxSize(FromDIP(280), text_size.y + FromDIP(25))); else m_vebview_release_note->SetMinSize(wxSize(FromDIP(300), FromDIP(280))); m_vebview_release_note->Layout(); m_sizer_main->Layout(); m_sizer_main->Fit(this); } wxString SecondaryCheckDialog::format_text(wxStaticText* st, wxString str, int warp) { if (wxGetApp().app_config->get("language") != "zh_CN") { return str; } wxString out_txt = str; wxString count_txt = ""; int new_line_pos = 0; for (int i = 0; i < str.length(); i++) { if (str[i] == '\n') { count_txt = ""; continue; } auto text_size = st->GetTextExtent(count_txt); if (text_size.x < warp) { count_txt += str[i]; } else { out_txt.insert(i - 1, '\n'); count_txt = ""; } } return out_txt; } SecondaryCheckDialog::~SecondaryCheckDialog() { } void SecondaryCheckDialog::on_dpi_changed(const wxRect& suggested_rect) { m_button_ok->Rescale(); m_button_cancel->Rescale(); } }} // namespace Slic3r::GUI