#include "AboutDialog.hpp" #include "I18N.hpp" #include "libslic3r/Utils.hpp" #include "GUI.hpp" #include "GUI_App.hpp" #include "MainFrame.hpp" #include "format.hpp" #include "Widgets/Button.hpp" #include namespace Slic3r { namespace GUI { AboutDialogLogo::AboutDialogLogo(wxWindow* parent) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize) { this->SetBackgroundColour(*wxWHITE); this->logo = ScalableBitmap(this, Slic3r::var("BambuStudio_192px.png"), wxBITMAP_TYPE_PNG); this->SetMinSize(this->logo.GetBmpSize()); this->Bind(wxEVT_PAINT, &AboutDialogLogo::onRepaint, this); } void AboutDialogLogo::onRepaint(wxEvent &event) { wxPaintDC dc(this); dc.SetBackgroundMode(wxTRANSPARENT); wxSize size = this->GetSize(); int logo_w = this->logo.GetBmpWidth(); int logo_h = this->logo.GetBmpHeight(); dc.DrawBitmap(this->logo.bmp(), (size.GetWidth() - logo_w)/2, (size.GetHeight() - logo_h)/2, true); event.Skip(); } // ----------------------------------------- // CopyrightsDialog // ----------------------------------------- CopyrightsDialog::CopyrightsDialog() : DPIDialog(static_cast(wxGetApp().mainframe), wxID_ANY, from_u8((boost::format("%1% - %2%") % (wxGetApp().is_editor() ? SLIC3R_APP_FULL_NAME : GCODEVIEWER_APP_NAME) % _utf8(L("Portions copyright"))).str()), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { this->SetFont(wxGetApp().normal_font()); this->SetBackgroundColour(*wxWHITE); std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); wxStaticLine *staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); auto sizer = new wxBoxSizer(wxVERTICAL); sizer->Add( staticline1, 0, wxEXPAND | wxALL, 5 ); fill_entries(); m_html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxSize(40 * em_unit(), 20 * em_unit()), wxHW_SCROLLBAR_AUTO); m_html->SetMinSize(wxSize(FromDIP(870),FromDIP(520))); m_html->SetBackgroundColour(*wxWHITE); wxFont font = get_default_font(this); const int fs = font.GetPointSize(); const int fs2 = static_cast(1.2f*fs); int size[] = { fs, fs, fs, fs, fs2, fs2, fs2 }; m_html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); m_html->SetBorders(2); m_html->SetPage(get_html_text()); sizer->Add(m_html, 1, wxEXPAND | wxALL, 15); m_html->Bind(wxEVT_HTML_LINK_CLICKED, &CopyrightsDialog::onLinkClicked, this); SetSizer(sizer); sizer->SetSizeHints(this); CenterOnParent(); wxGetApp().UpdateDlgDarkUI(this); } void CopyrightsDialog::fill_entries() { m_entries = { { "Admesh", "", "https://admesh.readthedocs.io/" }, { "Anti-Grain Geometry", "", "http://antigrain.com" }, { "ArcWelderLib", "", "https://plugins.octoprint.org/plugins/arc_welder" }, { "Boost", "", "http://www.boost.org" }, { "Cereal", "", "http://uscilab.github.io/cereal" }, { "CGAL", "", "https://www.cgal.org" }, { "Clipper", "", "http://www.angusj.co" }, { "libcurl", "", "https://curl.se/libcurl" }, { "Eigen3", "", "http://eigen.tuxfamily.org" }, { "Expat", "", "http://www.libexpat.org" }, { "fast_float", "", "https://github.com/fastfloat/fast_float" }, { "GLEW (The OpenGL Extension Wrangler Library)", "", "http://glew.sourceforge.net" }, { "GLFW", "", "https://www.glfw.org" }, { "GNU gettext", "", "https://www.gnu.org/software/gettext" }, { "ImGUI", "", "https://github.com/ocornut/imgui" }, { "Libigl", "", "https://libigl.github.io" }, { "libnest2d", "", "https://github.com/tamasmeszaros/libnest2d" }, { "lib_fts", "", "https://www.forrestthewoods.com" }, { "Mesa 3D", "", "https://mesa3d.org" }, { "Miniz", "", "https://github.com/richgel999/miniz" }, { "Nanosvg", "", "https://github.com/memononen/nanosvg" }, { "nlohmann/json", "", "https://json.nlohmann.me" }, { "Qhull", "", "http://qhull.org" }, { "Open Cascade", "", "https://www.opencascade.com" }, { "OpenGL", "", "https://www.opengl.org" }, { "PoEdit", "", "https://poedit.net" }, { "PrusaSlicer", "", "https://www.prusa3d.com" }, { "Real-Time DXT1/DXT5 C compression library", "", "https://github.com/Cyan4973/RygsDXTc" }, { "SemVer", "", "https://semver.org" }, { "Shinyprofiler", "", "https://code.google.com/p/shinyprofiler" }, { "SuperSlicer", "", "https://github.com/supermerill/SuperSlicer" }, { "TBB", "", "https://www.intel.cn/content/www/cn/zh/developer/tools/oneapi/onetbb.html" }, { "wxWidgets", "", "https://www.wxwidgets.org" }, { "zlib", "", "http://zlib.net" }, }; } wxString CopyrightsDialog::get_html_text() { wxColour bgr_clr = wxGetApp().get_window_default_clr();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); const auto text_clr = wxGetApp().get_label_clr_default();// wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); const auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue()); const auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()); const wxString copyright_str = _(L("Copyright")) + "© "; wxString text = wxString::Format( "" "" "" "%s
" "%s" "%s.
" "%s.
" "

" "%s
" "%s:
" "
" "", bgr_clr_str, text_clr_str, text_clr_str, _L("License"), _L("Bambu Studio is licensed under "), "https://www.gnu.org/licenses/agpl-3.0.html",_L("GNU Affero General Public License, version 3"), _L("Bambu Studio is based on PrusaSlicer by Prusa Research, which is from Slic3r by Alessandro Ranellucci and the RepRap community"), _L("Libraries"), _L("This software uses open source components whose copyright and other proprietary rights belong to their respective owners")); for (auto& entry : m_entries) { text += format_wxstr( "%s
" , entry.lib_name); text += wxString::Format( "%s

" , entry.link, entry.link); } text += wxString( "
" "
" "" ""); return text; } void CopyrightsDialog::on_dpi_changed(const wxRect &suggested_rect) { const wxFont& font = GetFont(); const int fs = font.GetPointSize(); const int fs2 = static_cast(1.2f*fs); int font_size[] = { fs, fs, fs, fs, fs2, fs2, fs2 }; m_html->SetFonts(font.GetFaceName(), font.GetFaceName(), font_size); const int& em = em_unit(); msw_buttons_rescale(this, em, { wxID_CLOSE }); const wxSize& size = wxSize(40 * em, 20 * em); m_html->SetMinSize(size); m_html->Refresh(); SetMinSize(size); Fit(); Refresh(); } void CopyrightsDialog::onLinkClicked(wxHtmlLinkEvent &event) { wxGetApp().open_browser_with_warning_dialog(event.GetLinkInfo().GetHref()); event.Skip(false); } void CopyrightsDialog::onCloseDialog(wxEvent &) { this->EndModal(wxID_CLOSE); } AboutDialog::AboutDialog() : DPIDialog(static_cast(wxGetApp().mainframe),wxID_ANY,from_u8((boost::format(_utf8(L("About %s"))) % (wxGetApp().is_editor() ? SLIC3R_APP_FULL_NAME : GCODEVIEWER_APP_NAME)).str()),wxDefaultPosition, wxDefaultSize, /*wxCAPTION*/wxDEFAULT_DIALOG_STYLE) { SetFont(wxGetApp().normal_font()); SetBackgroundColour(*wxWHITE); std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); wxPanel *m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(560), FromDIP(237)), wxTAB_TRAVERSAL); wxBoxSizer *panel_versizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *vesizer = new wxBoxSizer(wxVERTICAL); m_panel->SetSizer(panel_versizer); wxBoxSizer *ver_sizer = new wxBoxSizer(wxVERTICAL); auto main_sizer = new wxBoxSizer(wxVERTICAL); main_sizer->Add(m_panel, 1, wxEXPAND | wxALL, 0); main_sizer->Add(ver_sizer, 0, wxEXPAND | wxALL, 0); // logo m_logo_bitmap = ScalableBitmap(this, "BambuStudio_about", 250); m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bitmap.bmp(), wxDefaultPosition,wxDefaultSize, 0); m_logo->SetSizer(vesizer); panel_versizer->Add(m_logo, 1, wxALL | wxEXPAND, 0); // version { vesizer->Add(0, FromDIP(165), 1, wxEXPAND, FromDIP(5)); auto version_text = GUI_App::format_display_version(); #if BBL_INTERNAL_TESTING wxString versionText = BBL_INTERNAL_TESTING == 1 ? _L("Internal Version") : _L("Beta Version"); auto version_string = versionText + " " + std::string(version_text); #else auto version_string = _L("Version") + " " + std::string(version_text); #endif wxStaticText* version = new wxStaticText(this, wxID_ANY, version_string.c_str(), wxDefaultPosition, wxDefaultSize); wxFont version_font = GetFont(); #ifdef __WXMSW__ version_font.SetPointSize(version_font.GetPointSize()-1); #else version_font.SetPointSize(11); #endif version_font.SetPointSize(FromDIP(16)); version->SetFont(version_font); version->SetForegroundColour(wxColour("#FFFFFD")); version->SetBackgroundColour(wxColour("#00AF42")); vesizer->Add(version, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, FromDIP(5)); #if BBL_INTERNAL_TESTING wxString plugin_version = wxString::Format("Plugin Version: %s", wxGetApp().getAgent() ? wxGetApp().getAgent()->get_version() : ""); wxStaticText *plugin_version_text = new wxStaticText(this, wxID_ANY, plugin_version, wxDefaultPosition, wxDefaultSize); plugin_version_text->SetForegroundColour(wxColour("#FFFFFE")); plugin_version_text->SetBackgroundColour(wxColour("#00AF42")); vesizer->Add(plugin_version_text, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, FromDIP(5)); wxString build_time = wxString::Format("Build Time: %s", std::string(SLIC3R_BUILD_TIME)); wxStaticText* build_time_text = new wxStaticText(this, wxID_ANY, build_time, wxDefaultPosition, wxDefaultSize); build_time_text->SetForegroundColour(wxColour("#FFFFFE")); build_time_text->SetBackgroundColour(wxColour("#00AF42")); vesizer->Add(build_time_text, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, FromDIP(5)); #endif vesizer->Add(0, 0, 1, wxEXPAND, FromDIP(5)); } wxBoxSizer *text_sizer_horiz = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *text_sizer = new wxBoxSizer(wxVERTICAL); text_sizer_horiz->Add( 0, 0, 0, wxLEFT, FromDIP(20)); std::vector text_list; text_list.push_back(_L("Bambu Studio is based on PrusaSlicer by PrusaResearch and SuperSlicer by Merill(supermerill).")); text_list.push_back(_L("PrusaSlicer is originally based on Slic3r by Alessandro Ranellucci.")); text_list.push_back(_L("Slic3r was created by Alessandro Ranellucci with the help of many other contributors.")); text_list.push_back(_L("Bambu Studio also referenced some ideas from Cura by Ultimaker.")); text_list.push_back(_L("There many parts of the software that come from community contributions, so we're unable to list them one-by-one, and instead, they'll be attributed in the corresponding code comments.")); text_sizer->Add( 0, 0, 0, wxTOP, FromDIP(33)); bool is_zh = wxGetApp().app_config->get("language") == "zh_CN"; for (int i = 0; i < text_list.size(); i++) { auto staticText = new wxStaticText( this, wxID_ANY, wxEmptyString,wxDefaultPosition,wxSize(FromDIP(520), -1), wxALIGN_LEFT ); staticText->SetForegroundColour(wxColour(107, 107, 107)); staticText->SetBackgroundColour(*wxWHITE); staticText->SetMinSize(wxSize(FromDIP(520), -1)); staticText->SetFont(Label::Body_12); if (is_zh) { wxString find_txt = ""; wxString count_txt = ""; for (auto o = 0; o < text_list[i].length(); o++) { auto size = staticText->GetTextExtent(count_txt); if (size.x < FromDIP(506)) { find_txt += text_list[i][o]; count_txt += text_list[i][o]; } else { find_txt += std::string("\n") + text_list[i][o]; count_txt = text_list[i][o]; } } staticText->SetLabel(find_txt); } else { staticText->SetLabel(text_list[i]); staticText->Wrap(FromDIP(520)); } text_sizer->Add( staticText, 0, wxUP | wxDOWN, FromDIP(3)); } text_sizer_horiz->Add(text_sizer, 1, wxALL,0); ver_sizer->Add(text_sizer_horiz, 0, wxALL,0); ver_sizer->Add( 0, 0, 0, wxTOP, FromDIP(43)); wxBoxSizer *copyright_ver_sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *copyright_hor_sizer = new wxBoxSizer(wxHORIZONTAL); copyright_hor_sizer->Add(copyright_ver_sizer, 0, wxLEFT, FromDIP(20)); wxStaticText *html_text = new wxStaticText(this, wxID_ANY, "Copyright(C) 2021-2024 Lunkuo All Rights Reserved", wxDefaultPosition, wxDefaultSize); html_text->SetForegroundColour(wxColour(107, 107, 107)); copyright_ver_sizer->Add(html_text, 0, wxALL , 0); m_html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER /*NEVER*/); { wxFont font = get_default_font(this); const int fs = font.GetPointSize()-1; int size[] = {fs,fs,fs,fs,fs,fs,fs}; m_html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); m_html->SetMinSize(wxSize(FromDIP(-1), FromDIP(16))); m_html->SetBorders(2); const auto text = from_u8( (boost::format( "" "" "

www.bambulab.com

" "" "") ).str()); m_html->SetPage(text); copyright_ver_sizer->Add(m_html, 0, wxEXPAND, 0); m_html->Bind(wxEVT_HTML_LINK_CLICKED, &AboutDialog::onLinkClicked, this); } //Add "Portions copyright" button Button* button_portions = new Button(this,_L("Portions copyright")); StateColor report_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)); button_portions->SetBackgroundColor(report_bg); StateColor report_bd(std::pair(wxColour(144, 144, 144), StateColor::Disabled), std::pair(wxColour(38, 46, 48), StateColor::Enabled)); button_portions->SetBorderColor(report_bd); StateColor report_text(std::pair(wxColour(144, 144, 144), StateColor::Disabled), std::pair(wxColour(38, 46, 48), StateColor::Enabled)); button_portions->SetTextColor(report_text); button_portions->SetFont(Label::Body_12); button_portions->SetCornerRadius(FromDIP(12)); button_portions->SetMinSize(wxSize(FromDIP(120), FromDIP(24))); wxBoxSizer *copyright_button_ver = new wxBoxSizer(wxVERTICAL); copyright_button_ver->Add( 0, 0, 0, wxTOP, FromDIP(10)); copyright_button_ver->Add(button_portions, 0, wxALL,0); copyright_hor_sizer->AddStretchSpacer(); copyright_hor_sizer->Add(copyright_button_ver, 0, wxRIGHT, FromDIP(20)); ver_sizer->Add(copyright_hor_sizer, 0, wxEXPAND ,0); ver_sizer->Add( 0, 0, 0, wxTOP, FromDIP(30)); button_portions->Bind(wxEVT_BUTTON, &AboutDialog::onCopyrightBtn, this); wxGetApp().UpdateDlgDarkUI(this); SetSizer(main_sizer); Layout(); Fit(); CenterOnParent(); } void AboutDialog::on_dpi_changed(const wxRect &suggested_rect) { m_logo_bitmap.msw_rescale(); m_logo->SetBitmap(m_logo_bitmap.bmp()); const wxFont& font = GetFont(); const int fs = font.GetPointSize() - 1; int font_size[] = { fs, fs, fs, fs, fs, fs, fs }; m_html->SetFonts(font.GetFaceName(), font.GetFaceName(), font_size); const int& em = em_unit(); msw_buttons_rescale(this, em, { wxID_CLOSE, m_copy_rights_btn_id }); m_html->SetMinSize(wxSize(-1, 16 * em)); m_html->Refresh(); const wxSize& size = wxSize(65 * em, 30 * em); SetMinSize(size); Fit(); Refresh(); } void AboutDialog::onLinkClicked(wxHtmlLinkEvent &event) { wxGetApp().open_browser_with_warning_dialog(event.GetLinkInfo().GetHref()); event.Skip(false); } void AboutDialog::onCloseDialog(wxEvent &) { this->EndModal(wxID_CLOSE); } void AboutDialog::onCopyrightBtn(wxEvent &) { CopyrightsDialog dlg; dlg.ShowModal(); } void AboutDialog::onCopyToClipboard(wxEvent&) { wxTheClipboard->Open(); wxTheClipboard->SetData(new wxTextDataObject(_L("Version") + " " + GUI_App::format_display_version())); wxTheClipboard->Close(); } } // namespace GUI } // namespace Slic3r