2022-07-15 15:37:19 +00:00
# include "MainFrame.hpp"
# include <wx/panel.h>
# include <wx/notebook.h>
# include <wx/listbook.h>
# include <wx/simplebook.h>
# include <wx/icon.h>
# include <wx/sizer.h>
# include <wx/menu.h>
# include <wx/progdlg.h>
# include <wx/tooltip.h>
//#include <wx/glcanvas.h>
# include <wx/filename.h>
# include <wx/debug.h>
# include <boost/algorithm/string/predicate.hpp>
# include <boost/log/trivial.hpp>
# include "libslic3r/Print.hpp"
# include "libslic3r/Polygon.hpp"
# include "libslic3r/SLAPrint.hpp"
# include "libslic3r/PresetBundle.hpp"
# include "Tab.hpp"
# include "ProgressStatusBar.hpp"
# include "3DScene.hpp"
# include "ParamsDialog.hpp"
# include "wxExtensions.hpp"
# include "GUI_ObjectList.hpp"
# include "Mouse3DController.hpp"
//#include "RemovableDriveManager.hpp"
# include "InstanceCheck.hpp"
# include "I18N.hpp"
# include "GLCanvas3D.hpp"
# include "Plater.hpp"
# include "WebViewDialog.hpp"
# include "../Utils/Process.hpp"
# include "format.hpp"
// BBS
# include "PartPlate.hpp"
# include "Preferences.hpp"
# include "Widgets/ProgressDialog.hpp"
# include "BindDialog.hpp"
# include "../Utils/MacDarkMode.hpp"
# include <fstream>
# include <string_view>
# include "GUI_App.hpp"
# include "UnsavedChangesDialog.hpp"
# include "MsgDialog.hpp"
# include "Notebook.hpp"
# include "GUI_Factories.hpp"
# include "GUI_ObjectList.hpp"
# include "NotificationManager.hpp"
# include "MarkdownTip.hpp"
2022-08-12 03:20:17 +00:00
# include "NetworkTestDialog.hpp"
2022-07-15 15:37:19 +00:00
# ifdef _WIN32
# include <dbt.h>
# include <shlobj.h>
# endif // _WIN32
namespace Slic3r {
namespace GUI {
wxDEFINE_EVENT ( EVT_SELECT_TAB , wxCommandEvent ) ;
wxDEFINE_EVENT ( EVT_HTTP_ERROR , wxCommandEvent ) ;
wxDEFINE_EVENT ( EVT_USER_LOGIN , wxCommandEvent ) ;
// BBS: backup
wxDEFINE_EVENT ( EVT_BACKUP_POST , wxCommandEvent ) ;
wxDEFINE_EVENT ( EVT_LOAD_URL , wxCommandEvent ) ;
enum class ERescaleTarget
{
Mainframe ,
SettingsDialog
} ;
# ifdef __APPLE__
class BambuStudioTaskBarIcon : public wxTaskBarIcon
{
public :
BambuStudioTaskBarIcon ( wxTaskBarIconType iconType = wxTBI_DEFAULT_TYPE ) : wxTaskBarIcon ( iconType ) { }
//wxMenu *CreatePopupMenu() override {
//wxMenu *menu = new wxMenu;
//BBS do not support multi instances in mac
//if(wxGetApp().app_config->get("single_instance") == "0") {
// // Only allow opening a new PrusaSlicer instance on OSX if "single_instance" is disabled,
// // as starting new instances would interfere with the locking mechanism of "single_instance" support.
// append_menu_item(menu, wxID_ANY, _L("Open new instance"), _L("Open a new PrusaSlicer instance"),
// [](wxCommandEvent&) { start_new_slicer(); }, "", nullptr);
//}
//append_menu_item(menu, wxID_ANY, _L("G-code Viewer") + dots, _L("Open G-code Viewer"),
// [](wxCommandEvent&) { start_new_gcodeviewer_open_file(); }, "", nullptr);
//return menu;
//}
} ;
/*class GCodeViewerTaskBarIcon : public wxTaskBarIcon
{
public :
GCodeViewerTaskBarIcon ( wxTaskBarIconType iconType = wxTBI_DEFAULT_TYPE ) : wxTaskBarIcon ( iconType ) { }
wxMenu * CreatePopupMenu ( ) override {
wxMenu * menu = new wxMenu ;
append_menu_item ( menu , wxID_ANY , _L ( " Open PrusaSlicer " ) , _L ( " Open a new PrusaSlicer " ) ,
[ ] ( wxCommandEvent & ) { start_new_slicer ( nullptr , true ) ; } , " " , nullptr ) ;
//append_menu_item(menu, wxID_ANY, _L("G-code Viewer") + dots, _L("Open new G-code Viewer"),
// [](wxCommandEvent&) { start_new_gcodeviewer_open_file(); }, "", nullptr);
return menu ;
}
} ; */
# endif // __APPLE__
// Load the icon either from the exe, or from the ico file.
static wxIcon main_frame_icon ( GUI_App : : EAppMode app_mode )
{
# if _WIN32
std : : wstring path ( size_t ( MAX_PATH ) , wchar_t ( 0 ) ) ;
int len = int ( : : GetModuleFileName ( nullptr , path . data ( ) , MAX_PATH ) ) ;
if ( len > 0 & & len < MAX_PATH ) {
path . erase ( path . begin ( ) + len , path . end ( ) ) ;
//BBS: remove GCodeViewer as seperate APP logic
/*if (app_mode == GUI_App::EAppMode::GCodeViewer) {
// Only in case the slicer was started with --gcodeviewer parameter try to load the icon from prusa-gcodeviewer.exe
// Otherwise load it from the exe.
for ( const std : : wstring_view exe_name : { std : : wstring_view ( L " prusa-slicer.exe " ) , std : : wstring_view ( L " prusa-slicer-console.exe " ) } )
if ( boost : : iends_with ( path , exe_name ) ) {
path . erase ( path . end ( ) - exe_name . size ( ) , path . end ( ) ) ;
path + = L " prusa-gcodeviewer.exe " ;
break ;
}
} */
}
return wxIcon ( path , wxBITMAP_TYPE_ICO ) ;
# else // _WIN32
return wxIcon ( Slic3r : : var ( " BambuStudio_128px.png " ) , wxBITMAP_TYPE_PNG ) ;
# endif // _WIN32
}
// BBS
# ifdef __WINDOWS__
# define BORDERLESS_FRAME_STYLE (wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxCLOSE_BOX)
# else
2022-07-27 08:24:45 +00:00
# define BORDERLESS_FRAME_STYLE (wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxCLOSE_BOX)
2022-07-15 15:37:19 +00:00
# endif
wxDEFINE_EVENT ( EVT_SYNC_CLOUD_PRESET , SimpleEvent ) ;
MainFrame : : MainFrame ( ) :
DPIFrame ( NULL , wxID_ANY , " " , wxDefaultPosition , wxDefaultSize , BORDERLESS_FRAME_STYLE , " mainframe " )
// BBS
, m_recent_projects ( 9 )
, m_settings_dialog ( this )
, diff_dialog ( this )
{
# ifdef __WXOSX__
set_miniaturizable ( GetHandle ( ) ) ;
# endif
2022-07-22 09:46:10 +00:00
2022-07-15 15:37:19 +00:00
//reset developer_mode to false and user_mode to comAdvanced
wxGetApp ( ) . app_config - > set_bool ( " developer_mode " , false ) ;
if ( wxGetApp ( ) . app_config - > get ( " user_mode " ) = = " develop " ) {
wxGetApp ( ) . app_config - > set ( " user_mode " , " advanced " ) ;
}
wxGetApp ( ) . app_config - > set_bool ( " dump_video " , false ) ;
//reset log level
auto loglevel = wxGetApp ( ) . app_config - > get ( " severity_level " ) ;
Slic3r : : set_logging_level ( Slic3r : : level_string_to_boost ( loglevel ) ) ;
// BBS
m_recent_projects . SetMenuPathStyle ( wxFH_PATH_SHOW_ALWAYS ) ;
MarkdownTip : : Recreate ( this ) ;
// Fonts were created by the DPIFrame constructor for the monitor, on which the window opened.
wxGetApp ( ) . update_fonts ( this ) ;
2022-07-22 09:46:10 +00:00
# ifdef __WINDOWS__
m_topbar = new BBLTopbar ( this ) ;
# else
2022-07-15 15:37:19 +00:00
auto panel_topbar = new wxPanel ( this , wxID_ANY ) ;
panel_topbar - > SetBackgroundColour ( wxColour ( 38 , 46 , 48 ) ) ;
auto sizer_tobar = new wxBoxSizer ( wxVERTICAL ) ;
panel_topbar - > SetSizer ( sizer_tobar ) ;
panel_topbar - > Layout ( ) ;
2022-07-22 09:46:10 +00:00
# endif
2022-07-15 15:37:19 +00:00
//wxAuiToolBar* toolbar = new wxAuiToolBar();
/*
# ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
this - > SetFont ( this - > normal_font ( ) ) ;
# endif
// Font is already set in DPIFrame constructor
*/
# ifdef __APPLE__
// Initialize the docker task bar icon.
switch ( wxGetApp ( ) . get_app_mode ( ) ) {
default :
case GUI_App : : EAppMode : : Editor :
m_taskbar_icon = std : : make_unique < BambuStudioTaskBarIcon > ( wxTBI_DOCK ) ;
2022-07-26 05:35:56 +00:00
m_taskbar_icon - > SetIcon ( wxIcon ( Slic3r : : var ( " BambuStudio-mac_256px.ico " ) , wxBITMAP_TYPE_ICO ) , " BambuStudio " ) ;
2022-07-15 15:37:19 +00:00
break ;
case GUI_App : : EAppMode : : GCodeViewer :
break ;
}
# endif // __APPLE__
// Load the icon either from the exe, or from the ico file.
SetIcon ( main_frame_icon ( wxGetApp ( ) . get_app_mode ( ) ) ) ;
// initialize tabpanel and menubar
init_tabpanel ( ) ;
if ( wxGetApp ( ) . is_gcode_viewer ( ) )
init_menubar_as_gcodeviewer ( ) ;
else
init_menubar_as_editor ( ) ;
// BBS
#if 0
// This is needed on Windows to fake the CTRL+# of the window menu when using the numpad
wxAcceleratorEntry entries [ 6 ] ;
entries [ 0 ] . Set ( wxACCEL_CTRL , WXK_NUMPAD1 , wxID_HIGHEST + 1 ) ;
entries [ 1 ] . Set ( wxACCEL_CTRL , WXK_NUMPAD2 , wxID_HIGHEST + 2 ) ;
entries [ 2 ] . Set ( wxACCEL_CTRL , WXK_NUMPAD3 , wxID_HIGHEST + 3 ) ;
entries [ 3 ] . Set ( wxACCEL_CTRL , WXK_NUMPAD4 , wxID_HIGHEST + 4 ) ;
entries [ 4 ] . Set ( wxACCEL_CTRL , WXK_NUMPAD5 , wxID_HIGHEST + 5 ) ;
entries [ 5 ] . Set ( wxACCEL_CTRL , WXK_NUMPAD6 , wxID_HIGHEST + 6 ) ;
wxAcceleratorTable accel ( 6 , entries ) ;
SetAcceleratorTable ( accel ) ;
# endif // _WIN32
// BBS
2022-07-26 08:14:42 +00:00
//wxAcceleratorEntry entries[13];
//int index = 0;
//entries[index++].Set(wxACCEL_CTRL, (int)'N', wxID_HIGHEST + wxID_NEW);
//entries[index++].Set(wxACCEL_CTRL, (int)'O', wxID_HIGHEST + wxID_OPEN);
//entries[index++].Set(wxACCEL_CTRL, (int)'S', wxID_HIGHEST + wxID_SAVE);
//entries[index++].Set(wxACCEL_CTRL | wxACCEL_SHIFT, (int)'S', wxID_HIGHEST + wxID_SAVEAS);
//entries[index++].Set(wxACCEL_CTRL, (int)'X', wxID_HIGHEST + wxID_CUT);
////entries[index++].Set(wxACCEL_CTRL, (int)'I', wxID_HIGHEST + wxID_ADD);
//entries[index++].Set(wxACCEL_CTRL, (int)'A', wxID_HIGHEST + wxID_SELECTALL);
//entries[index++].Set(wxACCEL_NORMAL, (int)27 /* escape */, wxID_HIGHEST + wxID_CANCEL);
//entries[index++].Set(wxACCEL_CTRL, (int)'Z', wxID_HIGHEST + wxID_UNDO);
//entries[index++].Set(wxACCEL_CTRL, (int)'Y', wxID_HIGHEST + wxID_REDO);
//entries[index++].Set(wxACCEL_CTRL, (int)'C', wxID_HIGHEST + wxID_COPY);
//entries[index++].Set(wxACCEL_CTRL, (int)'V', wxID_HIGHEST + wxID_PASTE);
//entries[index++].Set(wxACCEL_CTRL, (int)'P', wxID_HIGHEST + wxID_PREFERENCES);
//entries[index++].Set(wxACCEL_CTRL, (int)'I', wxID_HIGHEST + wxID_FILE6);
//wxAcceleratorTable accel(sizeof(entries) / sizeof(entries[0]), entries);
//SetAcceleratorTable(accel);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->new_project(); }, wxID_HIGHEST + wxID_NEW);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->load_project(); }, wxID_HIGHEST + wxID_OPEN);
//// BBS: close save project
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { if (m_plater) m_plater->save_project(); }, wxID_HIGHEST + wxID_SAVE);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { if (m_plater) m_plater->save_project(true); }, wxID_HIGHEST + wxID_SAVEAS);
////Bind(wxEVT_MENU, [this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, wxID_HIGHEST + wxID_ADD);
////Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->remove_selected(); }, wxID_HIGHEST + wxID_DELETE);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) {
// if (!can_add_models())
// return;
// if (m_plater) {
// m_plater->add_model();
// }
// }, wxID_HIGHEST + wxID_FILE6);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->select_all(); }, wxID_HIGHEST + wxID_SELECTALL);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->deselect_all(); }, wxID_HIGHEST + wxID_CANCEL);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) {
// if (m_plater->is_view3D_shown())
// m_plater->undo();
// }, wxID_HIGHEST + wxID_UNDO);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) {
// if (m_plater->is_view3D_shown())
// m_plater->redo();
// }, wxID_HIGHEST + wxID_REDO);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->copy_selection_to_clipboard(); }, wxID_HIGHEST + wxID_COPY);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->paste_from_clipboard(); }, wxID_HIGHEST + wxID_PASTE);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->cut_selection_to_clipboard(); }, wxID_HIGHEST + wxID_CUT);
2022-07-15 15:37:19 +00:00
Bind ( wxEVT_SIZE , [ this ] ( wxSizeEvent & ) {
BOOST_LOG_TRIVIAL ( trace ) < < " mainframe: size changed, is maximized = " < < this - > IsMaximized ( ) ;
2022-07-27 08:24:45 +00:00
# ifdef __WINDOWS__
2022-07-15 15:37:19 +00:00
if ( this - > IsMaximized ( ) ) {
m_topbar - > SetWindowSize ( ) ;
} else {
m_topbar - > SetMaximizedSize ( ) ;
}
2022-07-27 08:24:45 +00:00
# endif
Refresh ( ) ;
Layout ( ) ;
2022-07-15 15:37:19 +00:00
} ) ;
//BBS
Bind ( EVT_SELECT_TAB , [ this ] ( wxCommandEvent & evt ) {
TabPosition pos = ( TabPosition ) evt . GetInt ( ) ;
m_tabpanel - > SetSelection ( pos ) ;
} ) ;
Bind ( EVT_SYNC_CLOUD_PRESET , & MainFrame : : on_select_default_preset , this ) ;
2022-07-26 08:14:42 +00:00
// Bind(wxEVT_MENU,
// [this](wxCommandEvent&)
// {
// PreferencesDialog dlg(this);
// dlg.ShowModal();
//#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
// if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
//#else
// if (dlg.seq_top_layer_only_changed())
//#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
// plater()->refresh_print();
// }, wxID_HIGHEST + wxID_PREFERENCES);
2022-07-15 15:37:19 +00:00
// set default tooltip timer in msec
// SetAutoPop supposedly accepts long integers but some bug doesn't allow for larger values
// (SetAutoPop is not available on GTK.)
wxToolTip : : SetAutoPop ( 32767 ) ;
m_loaded = true ;
// initialize layout
m_main_sizer = new wxBoxSizer ( wxVERTICAL ) ;
wxSizer * sizer = new wxBoxSizer ( wxVERTICAL ) ;
2022-07-22 09:46:10 +00:00
# ifdef __WINDOWS__
2022-07-15 15:37:19 +00:00
sizer - > Add ( m_topbar , 0 , wxEXPAND ) ;
2022-07-22 09:46:10 +00:00
# else
2022-07-15 15:37:19 +00:00
sizer - > Add ( panel_topbar , 0 , wxEXPAND ) ;
2022-07-22 09:46:10 +00:00
# endif // __WINDOWS__
2022-07-15 15:37:19 +00:00
sizer - > Add ( m_main_sizer , 1 , wxEXPAND ) ;
SetSizerAndFit ( sizer ) ;
// initialize layout from config
update_layout ( ) ;
sizer - > SetSizeHints ( this ) ;
// BBS: fix taskbar overlay on windows
# ifdef WIN32
auto setMaxSize = [ this ] ( ) {
2022-08-12 05:11:03 +00:00
wxDisplay display ( this ) ;
2022-07-15 15:37:19 +00:00
auto size = display . GetClientArea ( ) . GetSize ( ) ;
// 8 pixels shadow
SetMaxSize ( size + wxSize { 16 , 16 } ) ;
} ;
this - > Bind ( wxEVT_DPI_CHANGED , [ setMaxSize ] ( auto & e ) {
setMaxSize ( ) ;
e . Skip ( ) ;
} ) ;
setMaxSize ( ) ;
2022-07-25 12:07:06 +00:00
this - > Bind ( wxEVT_MAXIMIZE , [ this ] ( auto & e ) {
2022-08-12 05:11:03 +00:00
wxDisplay display ( this ) ;
2022-07-25 12:07:06 +00:00
auto pos = display . GetClientArea ( ) . GetPosition ( ) ;
Move ( pos - wxPoint { 8 , 8 } ) ;
e . Skip ( ) ;
} ) ;
2022-07-15 15:37:19 +00:00
# endif // WIN32
// BBS
Fit ( ) ;
const wxSize min_size = wxGetApp ( ) . get_min_size ( ) ; //wxSize(76*wxGetApp().em_unit(), 49*wxGetApp().em_unit());
2022-07-22 09:46:10 +00:00
2022-07-15 15:37:19 +00:00
SetMinSize ( min_size /*wxSize(760, 490)*/ ) ;
SetSize ( wxSize ( FromDIP ( 1200 ) , FromDIP ( 800 ) ) ) ;
2022-07-22 09:46:10 +00:00
2022-07-15 15:37:19 +00:00
Layout ( ) ;
update_title ( ) ;
// declare events
Bind ( wxEVT_CLOSE_WINDOW , [ this ] ( wxCloseEvent & event ) {
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " received close_widow event " ;
if ( event . CanVeto ( ) & & m_plater - > get_view3D_canvas3D ( ) - > get_gizmos_manager ( ) . is_in_editing_mode ( true ) ) {
// prevents to open the save dirty project dialog
event . Veto ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " cancelled by gizmo in editing " ;
return ;
}
//BBS:
//if (event.CanVeto() && !wxGetApp().check_and_save_current_preset_changes(_L("Application is closing"), _L("Closing Application while some presets are modified."))) {
// event.Veto();
// return;
//}
auto check = [ ] ( bool yes_or_no ) {
if ( yes_or_no )
return true ;
return wxGetApp ( ) . check_and_save_current_preset_changes ( _L ( " Application is closing " ) , _L ( " Closing Application while some presets are modified. " ) ) ;
} ;
// BBS: close save project
int result ;
if ( event . CanVeto ( ) & & ( ( result = m_plater - > close_with_confirm ( check ) ) = = wxID_CANCEL ) ) {
event . Veto ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " cancelled by close_with_confirm selection " ;
return ;
}
#if 0 // BBS
//if (m_plater != nullptr) {
// int saved_project = m_plater->save_project_if_dirty(_L("Closing Application. Current project is modified."));
// if (saved_project == wxID_CANCEL) {
// event.Veto();
// return;
// }
// // check unsaved changes only if project wasn't saved
// else if (plater()->is_project_dirty() && saved_project == wxID_NO && event.CanVeto() &&
// (plater()->is_presets_dirty() && !wxGetApp().check_and_save_current_preset_changes(_L("Application is closing"), _L("Closing Application while some presets are modified.")))) {
// event.Veto();
// return;
// }
//}
# endif
MarkdownTip : : ExitTip ( ) ;
m_plater - > reset ( ) ;
this - > shutdown ( ) ;
// propagate event
event . Skip ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " finished process close_widow event " ;
} ) ;
//FIXME it seems this method is not called on application start-up, at least not on Windows. Why?
// The same applies to wxEVT_CREATE, it is not being called on startup on Windows.
Bind ( wxEVT_ACTIVATE , [ this ] ( wxActivateEvent & event ) {
if ( m_plater ! = nullptr & & event . GetActive ( ) )
m_plater - > on_activate ( ) ;
event . Skip ( ) ;
} ) ;
// OSX specific issue:
// When we move application between Retina and non-Retina displays, The legend on a canvas doesn't redraw
// So, redraw explicitly canvas, when application is moved
//FIXME maybe this is useful for __WXGTK3__ as well?
# if __APPLE__
Bind ( wxEVT_MOVE , [ ] ( wxMoveEvent & event ) {
wxGetApp ( ) . plater ( ) - > get_current_canvas3D ( ) - > set_as_dirty ( ) ;
wxGetApp ( ) . plater ( ) - > get_current_canvas3D ( ) - > request_extra_frame ( ) ;
event . Skip ( ) ;
} ) ;
# endif
wxGetApp ( ) . persist_window_geometry ( this , true ) ;
wxGetApp ( ) . persist_window_geometry ( & m_settings_dialog , true ) ;
update_ui_from_settings ( ) ; // FIXME (?)
if ( m_plater ! = nullptr ) {
// BBS
update_slice_print_status ( eEventSliceUpdate , true , true ) ;
// BBS: backup project
std : : string backup_interval ;
if ( ! wxGetApp ( ) . app_config - > get ( " " , " backup_interval " , backup_interval ) )
backup_interval = " 10 " ;
Slic3r : : set_backup_interval ( boost : : lexical_cast < long > ( backup_interval ) ) ;
Slic3r : : set_backup_callback ( [ this ] ( int action ) {
if ( action = = 0 ) {
wxPostEvent ( this , wxCommandEvent ( EVT_BACKUP_POST ) ) ;
}
else if ( action = = 1 ) {
if ( ! m_plater - > up_to_date ( false , true ) ) {
m_plater - > export_3mf ( m_plater - > model ( ) . get_backup_path ( ) + " /.3mf " , SaveStrategy : : Backup ) ;
m_plater - > up_to_date ( true , true ) ;
}
}
} ) ;
Bind ( EVT_BACKUP_POST , [ ] ( wxCommandEvent & e ) {
Slic3r : : run_backup_ui_tasks ( ) ;
} ) ;
; }
2022-07-26 08:14:42 +00:00
this - > Bind ( wxEVT_CHAR_HOOK , [ this ] ( wxKeyEvent & evt ) {
# ifdef __APPLE__
2022-08-08 02:05:00 +00:00
if ( evt . CmdDown ( ) & & ( evt . GetKeyCode ( ) = = ' H ' ) ) {
//call parent_menu hide behavior
return ; }
if ( evt . CmdDown ( ) & & ( evt . GetKeyCode ( ) = = ' M ' ) ) {
this - > Iconize ( ) ;
return ;
}
2022-07-26 08:14:42 +00:00
if ( evt . CmdDown ( ) & & evt . GetKeyCode ( ) = = ' Q ' ) { wxPostEvent ( this , wxCloseEvent ( wxEVT_CLOSE_WINDOW ) ) ; return ; }
2022-08-08 02:05:00 +00:00
if ( evt . CmdDown ( ) & & evt . RawControlDown ( ) & & evt . GetKeyCode ( ) = = ' F ' ) {
EnableFullScreenView ( true ) ;
if ( IsFullScreen ( ) ) {
ShowFullScreen ( false ) ;
} else {
ShowFullScreen ( true ) ;
}
return ; }
2022-07-26 08:14:42 +00:00
# endif
if ( evt . CmdDown ( ) & & evt . GetKeyCode ( ) = = ' N ' ) { m_plater - > new_project ( ) ; return ; }
if ( evt . CmdDown ( ) & & evt . GetKeyCode ( ) = = ' O ' ) { m_plater - > load_project ( ) ; return ; }
if ( evt . CmdDown ( ) & & evt . ShiftDown ( ) & & evt . GetKeyCode ( ) = = ' S ' ) { if ( m_plater ) m_plater - > save_project ( true ) ; return ; }
else if ( evt . CmdDown ( ) & & evt . GetKeyCode ( ) = = ' S ' ) { if ( m_plater ) m_plater - > save_project ( ) ; return ; }
2022-08-08 02:05:00 +00:00
# ifdef __APPLE__
if ( evt . CmdDown ( ) & & evt . GetKeyCode ( ) = = ' , ' )
# else
if ( evt . CmdDown ( ) & & evt . GetKeyCode ( ) = = ' P ' )
# endif
{
2022-07-26 08:14:42 +00:00
PreferencesDialog dlg ( this ) ;
dlg . ShowModal ( ) ;
# if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
if ( dlg . seq_top_layer_only_changed ( ) | | dlg . seq_seq_top_gcode_indices_changed ( ) )
# else
if ( dlg . seq_top_layer_only_changed ( ) )
# endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
plater ( ) - > refresh_print ( ) ;
return ;
}
2022-08-08 02:05:00 +00:00
2022-07-26 08:14:42 +00:00
if ( evt . CmdDown ( ) & & evt . GetKeyCode ( ) = = ' I ' ) {
if ( ! can_add_models ( ) ) return ;
if ( m_plater ) { m_plater - > add_model ( ) ; }
return ;
}
evt . Skip ( ) ;
} ) ;
2022-07-15 15:37:19 +00:00
}
# ifdef __WIN32__
WXLRESULT MainFrame : : MSWWindowProc ( WXUINT nMsg , WXWPARAM wParam , WXLPARAM lParam )
{
/* When we have a custom titlebar in the window, we don't need the non-client area of a normal window
* to be painted . In order to achieve this , we handle the " WM_NCCALCSIZE " which is responsible for the
* size of non - client area of a window and set the return value to 0. Also we have to tell the
* application to not paint this area on activate and deactivation events so we also handle
* " WM_NCACTIVATE " message . */
switch ( nMsg ) {
case WM_NCACTIVATE : {
/* Returning 0 from this message disable the window from receiving activate events which is not
desirable . However When a visual style is not active ( ? ) for this window , " lParam " is a handle to an
optional update region for the nonclient area of the window . If this parameter is set to - 1 ,
DefWindowProc does not repaint the nonclient area to reflect the state change . */
lParam = - 1 ;
break ;
}
/* To remove the standard window frame, you must handle the WM_NCCALCSIZE message, specifically when
its wParam value is TRUE and the return value is 0 */
case WM_NCCALCSIZE :
if ( wParam ) {
HWND hWnd = GetHandle ( ) ;
/* Detect whether window is maximized or not. We don't need to change the resize border when win is
* maximized because all resize borders are gone automatically */
WINDOWPLACEMENT wPos ;
// GetWindowPlacement fail if this member is not set correctly.
wPos . length = sizeof ( wPos ) ;
GetWindowPlacement ( hWnd , & wPos ) ;
if ( wPos . showCmd ! = SW_SHOWMAXIMIZED ) {
RECT borderThickness ;
SetRectEmpty ( & borderThickness ) ;
AdjustWindowRectEx ( & borderThickness , GetWindowLongPtr ( hWnd , GWL_STYLE ) & ~ WS_CAPTION , FALSE , NULL ) ;
borderThickness . left * = - 1 ;
borderThickness . top * = - 1 ;
NCCALCSIZE_PARAMS * sz = reinterpret_cast < NCCALCSIZE_PARAMS * > ( lParam ) ;
// Add 1 pixel to the top border to make the window resizable from the top border
sz - > rgrc [ 0 ] . top + = 1 ; // borderThickness.top;
sz - > rgrc [ 0 ] . left + = borderThickness . left ;
sz - > rgrc [ 0 ] . right - = borderThickness . right ;
sz - > rgrc [ 0 ] . bottom - = borderThickness . bottom ;
return 0 ;
}
}
break ;
}
return wxFrame : : MSWWindowProc ( nMsg , wParam , lParam ) ;
}
# endif
void MainFrame : : show_log_window ( )
{
m_log_window = new wxLogWindow ( this , _L ( " Logging " ) , true , false ) ;
m_log_window - > Show ( ) ;
}
//BBS GUI refactor: remove unused layout new/dlg
void MainFrame : : update_layout ( )
{
auto restore_to_creation = [ this ] ( ) {
auto clean_sizer = [ ] ( wxSizer * sizer ) {
while ( ! sizer - > GetChildren ( ) . IsEmpty ( ) ) {
sizer - > Detach ( 0 ) ;
}
} ;
// On Linux m_plater needs to be removed from m_tabpanel before to reparent it
int plater_page_id = m_tabpanel - > FindPage ( m_plater ) ;
if ( plater_page_id ! = wxNOT_FOUND )
m_tabpanel - > RemovePage ( plater_page_id ) ;
if ( m_plater - > GetParent ( ) ! = this )
m_plater - > Reparent ( this ) ;
if ( m_tabpanel - > GetParent ( ) ! = this )
m_tabpanel - > Reparent ( this ) ;
plater_page_id = ( m_plater_page ! = nullptr ) ? m_tabpanel - > FindPage ( m_plater_page ) : wxNOT_FOUND ;
if ( plater_page_id ! = wxNOT_FOUND ) {
m_tabpanel - > DeletePage ( plater_page_id ) ;
m_plater_page = nullptr ;
}
clean_sizer ( m_main_sizer ) ;
clean_sizer ( m_settings_dialog . GetSizer ( ) ) ;
if ( m_settings_dialog . IsShown ( ) )
m_settings_dialog . Close ( ) ;
m_tabpanel - > Hide ( ) ;
m_plater - > Hide ( ) ;
Layout ( ) ;
} ;
//BBS GUI refactor: remove unused layout new/dlg
//ESettingsLayout layout = wxGetApp().is_gcode_viewer() ? ESettingsLayout::GCodeViewer : ESettingsLayout::Old;
ESettingsLayout layout = ESettingsLayout : : Old ;
if ( m_layout = = layout )
return ;
wxBusyCursor busy ;
Freeze ( ) ;
// Remove old settings
if ( m_layout ! = ESettingsLayout : : Unknown )
restore_to_creation ( ) ;
ESettingsLayout old_layout = m_layout ;
m_layout = layout ;
// From the very beginning the Print settings should be selected
//m_last_selected_tab = m_layout == ESettingsLayout::Dlg ? 0 : 1;
m_last_selected_tab = 1 ;
// Set new settings
switch ( m_layout )
{
case ESettingsLayout : : Old :
{
m_plater - > Reparent ( m_tabpanel ) ;
m_tabpanel - > InsertPage ( tp3DEditor , m_plater , _L ( " Prepare " ) , std : : string ( " tab_3d_active " ) , std : : string ( " tab_3d_active " ) ) ;
m_tabpanel - > InsertPage ( tpPreview , m_plater , _L ( " Preview " ) , std : : string ( " tab_preview_active " ) , std : : string ( " tab_preview_active " ) ) ;
m_main_sizer - > Add ( m_tabpanel , 1 , wxEXPAND | wxTOP , 0 ) ;
m_plater - > Show ( ) ;
m_tabpanel - > Show ( ) ;
break ;
}
case ESettingsLayout : : GCodeViewer :
{
m_main_sizer - > Add ( m_plater , 1 , wxEXPAND ) ;
//BBS: add bed exclude area
m_plater - > set_bed_shape ( { { 0.0 , 0.0 } , { 200.0 , 0.0 } , { 200.0 , 200.0 } , { 0.0 , 200.0 } } , { } , 0.0 , { } , { } , true ) ;
m_plater - > get_collapse_toolbar ( ) . set_enabled ( false ) ;
m_plater - > collapse_sidebar ( true ) ;
m_plater - > Show ( ) ;
break ;
}
default :
break ;
}
//BBS GUI refactor: remove unused layout new/dlg
//#ifdef __APPLE__
// // Using SetMinSize() on Mac messes up the window position in some cases
// // cf. https://groups.google.com/forum/#!topic/wx-users/yUKPBBfXWO0
// // So, if we haven't possibility to set MinSize() for the MainFrame,
// // set the MinSize() as a half of regular for the m_plater and m_tabpanel, when settings layout is in slNew mode
// // Otherwise, MainFrame will be maximized by height
// if (m_layout == ESettingsLayout::New) {
// wxSize size = wxGetApp().get_min_size();
// size.SetHeight(int(0.5 * size.GetHeight()));
// m_plater->SetMinSize(size);
// m_tabpanel->SetMinSize(size);
// }
//#endif
# ifdef __APPLE__
m_plater - > sidebar ( ) . change_top_border_for_mode_sizer ( m_layout ! = ESettingsLayout : : Old ) ;
# endif
Layout ( ) ;
Thaw ( ) ;
}
// Called when closing the application and when switching the application language.
void MainFrame : : shutdown ( )
{
// BBS: backup
Slic3r : : set_backup_callback ( nullptr ) ;
# ifdef _WIN32
if ( m_hDeviceNotify ) {
: : UnregisterDeviceNotification ( HDEVNOTIFY ( m_hDeviceNotify ) ) ;
m_hDeviceNotify = nullptr ;
}
if ( m_ulSHChangeNotifyRegister ) {
SHChangeNotifyDeregister ( m_ulSHChangeNotifyRegister ) ;
m_ulSHChangeNotifyRegister = 0 ;
}
# endif // _WIN32
if ( m_plater ! = nullptr ) {
m_plater - > stop_jobs ( ) ;
// Unbinding of wxWidgets event handling in canvases needs to be done here because on MAC,
// when closing the application using Command+Q, a mouse event is triggered after this lambda is completed,
// causing a crash
m_plater - > unbind_canvas_event_handlers ( ) ;
// Cleanup of canvases' volumes needs to be done here or a crash may happen on some Linux Debian flavours
m_plater - > reset_canvas_volumes ( ) ;
}
// Weird things happen as the Paint messages are floating around the windows being destructed.
// Avoid the Paint messages by hiding the main window.
// Also the application closes much faster without these unnecessary screen refreshes.
// In addition, there were some crashes due to the Paint events sent to already destructed windows.
this - > Show ( false ) ;
if ( m_settings_dialog . IsShown ( ) )
// call Close() to trigger call to lambda defined into GUI_App::persist_window_geometry()
m_settings_dialog . Close ( ) ;
if ( m_plater ! = nullptr ) {
// Stop the background thread (Windows and Linux).
// Disconnect from a 3DConnextion driver (OSX).
m_plater - > get_mouse3d_controller ( ) . shutdown ( ) ;
// Store the device parameter database back to appconfig.
m_plater - > get_mouse3d_controller ( ) . save_config ( * wxGetApp ( ) . app_config ) ;
}
// Stop the background thread of the removable drive manager, so that no new updates will be sent to the Plater.
//wxGetApp().removable_drive_manager()->shutdown();
//stop listening for messages from other instances
//wxGetApp().other_instance_message_handler()->shutdown(this);
// Save the slic3r.ini.Usually the ini file is saved from "on idle" callback,
// but in rare cases it may not have been called yet.
wxGetApp ( ) . app_config - > save ( ) ;
// if (m_plater)
// m_plater->print = undef;
// Slic3r::GUI::deregister_on_request_update_callback();
// set to null tabs and a plater
// to avoid any manipulations with them from App->wxEVT_IDLE after of the mainframe closing
wxGetApp ( ) . tabs_list . clear ( ) ;
wxGetApp ( ) . model_tabs_list . clear ( ) ;
2022-07-25 10:10:52 +00:00
wxGetApp ( ) . shutdown ( ) ;
2022-07-15 15:37:19 +00:00
// BBS: why clear ?
//wxGetApp().plater_ = nullptr;
}
void MainFrame : : update_title ( )
{
2022-08-04 09:16:37 +00:00
return ;
}
void MainFrame : : update_title_colour_after_set_title ( )
{
# ifdef __WXOSX__
set_title_colour_after_set_title ( ) ;
# endif
2022-07-15 15:37:19 +00:00
}
void MainFrame : : show_option ( bool show )
{
if ( ! this ) { return ; }
if ( ! show ) {
if ( m_slice_btn - > IsShown ( ) ) {
m_slice_btn - > Hide ( ) ;
m_print_btn - > Hide ( ) ;
m_print_option_btn - > Hide ( ) ;
Layout ( ) ;
}
} else {
if ( ! m_slice_btn - > IsShown ( ) ) {
m_slice_btn - > Show ( ) ;
m_print_btn - > Show ( ) ;
m_print_option_btn - > Show ( ) ;
Layout ( ) ;
}
}
}
void MainFrame : : init_tabpanel ( )
{
// wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on Windows 10
// with multiple high resolution displays connected.
// BBS
wxBoxSizer * side_tools = create_side_tools ( ) ;
m_tabpanel = new Notebook ( this , wxID_ANY , wxDefaultPosition , wxDefaultSize , side_tools , wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME ) ;
# ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
m_tabpanel - > SetFont ( Slic3r : : GUI : : wxGetApp ( ) . normal_font ( ) ) ;
# endif
m_tabpanel - > Hide ( ) ;
m_settings_dialog . set_tabpanel ( m_tabpanel ) ;
2022-07-22 09:46:10 +00:00
m_tabpanel - > Bind ( wxEVT_NOTEBOOK_PAGE_CHANGING , [ this ] ( wxBookCtrlEvent & e ) {
int old_sel = e . GetOldSelection ( ) ;
int new_sel = e . GetSelection ( ) ;
if ( new_sel = = tpMonitor ) {
if ( ! wxGetApp ( ) . getAgent ( ) ) {
e . Veto ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " skipped tab switch from %1% to %2%, lack of network plugins " ) % old_sel % new_sel ;
if ( m_plater ) {
wxCommandEvent * evt = new wxCommandEvent ( EVT_INSTALL_PLUGIN_HINT ) ;
wxQueueEvent ( m_plater , evt ) ;
}
}
}
else if ( new_sel = = tp3DEditor ) {
if ( m_plater & & ( m_plater - > only_gcode_mode ( ) | | ( m_plater - > using_exported_file ( ) ) ) ) {
e . Veto ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " skipped tab switch from %1% to %2% in preview mode " ) % old_sel % new_sel ;
wxCommandEvent * evt = new wxCommandEvent ( EVT_PREVIEW_ONLY_MODE_HINT ) ;
wxQueueEvent ( m_plater , evt ) ;
}
}
} ) ;
2022-07-15 15:37:19 +00:00
# ifdef __WXMSW__
m_tabpanel - > Bind ( wxEVT_BOOKCTRL_PAGE_CHANGED , [ this ] ( wxBookCtrlEvent & e ) {
# else
m_tabpanel - > Bind ( wxEVT_NOTEBOOK_PAGE_CHANGED , [ this ] ( wxBookCtrlEvent & e ) {
# endif
//BBS
wxWindow * panel = m_tabpanel - > GetCurrentPage ( ) ;
int sel = m_tabpanel - > GetSelection ( ) ;
//wxString page_text = m_tabpanel->GetPageText(sel);
m_last_selected_tab = m_tabpanel - > GetSelection ( ) ;
if ( panel = = m_plater ) {
2022-07-22 09:46:10 +00:00
if ( sel = = tp3DEditor ) {
2022-07-15 15:37:19 +00:00
wxPostEvent ( m_plater , SimpleEvent ( EVT_GLVIEWTOOLBAR_3D ) ) ;
m_param_panel - > OnActivate ( ) ;
}
2022-07-22 09:46:10 +00:00
else if ( sel = = tpPreview ) {
2022-07-15 15:37:19 +00:00
wxPostEvent ( m_plater , SimpleEvent ( EVT_GLVIEWTOOLBAR_PREVIEW ) ) ;
m_param_panel - > OnActivate ( ) ;
}
}
//else if (panel == m_param_panel)
// m_param_panel->OnActivate();
else if ( panel = = m_monitor ) {
//monitor
}
2022-07-27 08:24:45 +00:00
# ifdef __WINDOWS__
2022-07-22 09:46:10 +00:00
if ( sel = = tp3DEditor ) {
2022-07-15 15:37:19 +00:00
m_topbar - > EnableUndoRedoItems ( ) ;
}
else {
m_topbar - > DisableUndoRedoItems ( ) ;
}
2022-07-27 08:24:45 +00:00
# endif
2022-07-15 15:37:19 +00:00
/*switch (sel) {
case TabPosition : : tpHome :
show_option ( false ) ;
break ;
case TabPosition : : tp3DEditor :
show_option ( true ) ;
break ;
case TabPosition : : tpPreview :
show_option ( true ) ;
break ;
case TabPosition : : tpMonitor :
show_option ( false ) ;
break ;
default :
show_option ( false ) ;
break ;
} */
} ) ;
if ( wxGetApp ( ) . is_editor ( ) ) {
m_webview = new WebViewPanel ( m_tabpanel ) ;
Bind ( EVT_LOAD_URL , [ this ] ( wxCommandEvent & evt ) {
wxString url = evt . GetString ( ) ;
select_tab ( MainFrame : : tpHome ) ;
m_webview - > load_url ( url ) ;
} ) ;
m_tabpanel - > AddPage ( m_webview , " " , " tab_home_active " , " tab_home_active " ) ;
m_param_panel = new ParamsPanel ( m_tabpanel , wxID_ANY , wxDefaultPosition , wxDefaultSize , wxBK_LEFT | wxTAB_TRAVERSAL ) ;
}
m_plater = new Plater ( this , this ) ;
m_plater - > Hide ( ) ;
wxGetApp ( ) . plater_ = m_plater ;
create_preset_tabs ( ) ;
//BBS add pages
m_monitor = new MonitorPanel ( m_tabpanel , wxID_ANY , wxDefaultPosition , wxDefaultSize ) ;
m_tabpanel - > AddPage ( m_monitor , _L ( " Device " ) , std : : string ( " tab_monitor_active " ) , std : : string ( " tab_monitor_active " ) ) ;
m_auxiliary = new AuxiliaryPanel ( m_tabpanel , wxID_ANY , wxDefaultPosition , wxDefaultSize ) ;
m_tabpanel - > AddPage ( m_auxiliary , _L ( " Project " ) , std : : string ( " tab_auxiliary_avtice " ) , std : : string ( " tab_auxiliary_avtice " ) ) ;
if ( m_plater ) {
// load initial config
auto full_config = wxGetApp ( ) . preset_bundle - > full_config ( ) ;
m_plater - > on_config_change ( full_config ) ;
// Show a correct number of filament fields.
// nozzle_diameter is undefined when SLA printer is selected
// BBS
if ( full_config . has ( " filament_colour " ) ) {
m_plater - > on_filaments_change ( full_config . option < ConfigOptionStrings > ( " filament_colour " ) - > values . size ( ) ) ;
}
}
}
# ifdef WIN32
void MainFrame : : register_win32_callbacks ( )
{
//static GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED };
//static GUID GUID_DEVINTERFACE_DISK = { 0x53f56307, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b };
//static GUID GUID_DEVINTERFACE_VOLUME = { 0x71a27cdd, 0x812a, 0x11d0, 0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f };
static GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2 , 0xF16F , 0x11CF , 0x88 , 0xCB , 0x00 , 0x11 , 0x11 , 0x00 , 0x00 , 0x30 } ;
// Register USB HID (Human Interface Devices) notifications to trigger the 3DConnexion enumeration.
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter = { 0 } ;
NotificationFilter . dbcc_size = sizeof ( DEV_BROADCAST_DEVICEINTERFACE ) ;
NotificationFilter . dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE ;
NotificationFilter . dbcc_classguid = GUID_DEVINTERFACE_HID ;
m_hDeviceNotify = : : RegisterDeviceNotification ( this - > GetHWND ( ) , & NotificationFilter , DEVICE_NOTIFY_WINDOW_HANDLE ) ;
// or register for file handle change?
// DEV_BROADCAST_HANDLE NotificationFilter = { 0 };
// NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
// NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
// Using Win32 Shell API to register for media insert / removal events.
LPITEMIDLIST ppidl ;
if ( SHGetSpecialFolderLocation ( this - > GetHWND ( ) , CSIDL_DESKTOP , & ppidl ) = = NOERROR ) {
SHChangeNotifyEntry shCNE ;
shCNE . pidl = ppidl ;
shCNE . fRecursive = TRUE ;
// Returns a positive integer registration identifier (ID).
// Returns zero if out of memory or in response to invalid parameters.
m_ulSHChangeNotifyRegister = SHChangeNotifyRegister ( this - > GetHWND ( ) , // Hwnd to receive notification
SHCNE_DISKEVENTS , // Event types of interest (sources)
SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED ,
//SHCNE_UPDATEITEM, // Events of interest - use SHCNE_ALLEVENTS for all events
WM_USER_MEDIACHANGED , // Notification message to be sent upon the event
1 , // Number of entries in the pfsne array
& shCNE ) ; // Array of SHChangeNotifyEntry structures that
// contain the notifications. This array should
// always be set to one when calling SHChnageNotifyRegister
// or SHChangeNotifyDeregister will not work properly.
assert ( m_ulSHChangeNotifyRegister ! = 0 ) ; // Shell notification failed
} else {
// Failed to get desktop location
assert ( false ) ;
}
{
static constexpr int device_count = 1 ;
RAWINPUTDEVICE devices [ device_count ] = { 0 } ;
// multi-axis mouse (SpaceNavigator, etc.)
devices [ 0 ] . usUsagePage = 0x01 ;
devices [ 0 ] . usUsage = 0x08 ;
if ( ! RegisterRawInputDevices ( devices , device_count , sizeof ( RAWINPUTDEVICE ) ) )
BOOST_LOG_TRIVIAL ( error ) < < " RegisterRawInputDevices failed " ;
}
}
# endif // _WIN32
void MainFrame : : create_preset_tabs ( )
{
wxGetApp ( ) . update_label_colours_from_appconfig ( ) ;
//BBS: GUI refactor
//m_param_panel = new ParamsPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
m_param_dialog = new ParamsDialog ( m_plater ) ;
add_created_tab ( new TabPrint ( m_param_panel ) , " cog " ) ;
add_created_tab ( new TabPrintObject ( m_param_panel ) , " cog " ) ;
add_created_tab ( new TabPrintPart ( m_param_panel ) , " cog " ) ;
add_created_tab ( new TabFilament ( m_param_dialog - > panel ( ) ) , " spool " ) ;
/* BBS work around to avoid appearance bug */
//add_created_tab(new TabSLAPrint(m_param_panel));
//add_created_tab(new TabSLAMaterial(m_param_panel));
add_created_tab ( new TabPrinter ( m_param_dialog - > panel ( ) ) , " printer " ) ;
m_param_panel - > rebuild_panels ( ) ;
m_param_dialog - > panel ( ) - > rebuild_panels ( ) ;
//m_tabpanel->AddPage(m_param_panel, "Parameters", "notebook_presets_active");
//m_tabpanel->InsertPage(tpSettings, m_param_panel, _L("Parameters"), std::string("cog"));
}
void MainFrame : : add_created_tab ( Tab * panel , const std : : string & bmp_name /*= ""*/ )
{
panel - > create_preset_tab ( ) ;
// BBS: model config
if ( panel - > type ( ) = = Preset : : TYPE_MODEL ) {
wxGetApp ( ) . tabs_list . pop_back ( ) ;
wxGetApp ( ) . model_tabs_list . push_back ( panel ) ;
}
}
bool MainFrame : : is_active_and_shown_tab ( wxPanel * panel )
{
if ( panel = = m_param_panel )
panel = m_plater ;
else
return m_param_dialog - > IsShown ( ) ;
if ( m_tabpanel - > GetCurrentPage ( ) ! = panel )
return false ;
return true ;
}
bool MainFrame : : can_start_new_project ( ) const
{
/*return m_plater && (!m_plater->get_project_filename(".3mf").IsEmpty() ||
GetTitle ( ) . StartsWith ( ' * ' ) | |
wxGetApp ( ) . has_current_preset_changes ( ) | |
! m_plater - > model ( ) . objects . empty ( ) ) ; */
return ( m_plater & & ! m_plater - > is_background_process_slicing ( ) ) ;
}
bool MainFrame : : can_open_project ( ) const
{
return ( m_plater & & ! m_plater - > is_background_process_slicing ( ) ) ;
}
bool MainFrame : : can_add_models ( ) const
{
return ( m_plater & & ! m_plater - > is_background_process_slicing ( ) & & ! m_plater - > only_gcode_mode ( ) & & ! m_plater - > using_exported_file ( ) ) ;
}
bool MainFrame : : can_save ( ) const
{
return ( m_plater ! = nullptr ) & &
! m_plater - > get_view3D_canvas3D ( ) - > get_gizmos_manager ( ) . is_in_editing_mode ( false ) & &
m_plater - > is_project_dirty ( ) ;
}
bool MainFrame : : can_save_as ( ) const
{
return ( m_plater ! = nullptr ) & &
! m_plater - > get_view3D_canvas3D ( ) - > get_gizmos_manager ( ) . is_in_editing_mode ( false ) ;
}
void MainFrame : : save_project ( )
{
save_project_as ( m_plater - > get_project_filename ( " .3mf " ) ) ;
}
bool MainFrame : : save_project_as ( const wxString & filename )
{
bool ret = ( m_plater ! = nullptr ) ? m_plater - > export_3mf ( into_path ( filename ) ) : false ;
if ( ret ) {
// wxGetApp().update_saved_preset_from_current_preset();
m_plater - > reset_project_dirty_after_save ( ) ;
}
return ret ;
}
bool MainFrame : : can_upload ( ) const
{
return true ;
}
bool MainFrame : : can_export_model ( ) const
{
return ( m_plater ! = nullptr ) & & ! m_plater - > model ( ) . objects . empty ( ) ;
}
bool MainFrame : : can_export_toolpaths ( ) const
{
return ( m_plater ! = nullptr ) & & ( m_plater - > printer_technology ( ) = = ptFFF ) & & m_plater - > is_preview_shown ( ) & & m_plater - > is_preview_loaded ( ) & & m_plater - > has_toolpaths_to_export ( ) ;
}
bool MainFrame : : can_export_supports ( ) const
{
if ( ( m_plater = = nullptr ) | | ( m_plater - > printer_technology ( ) ! = ptSLA ) | | m_plater - > model ( ) . objects . empty ( ) )
return false ;
bool can_export = false ;
const PrintObjects & objects = m_plater - > sla_print ( ) . objects ( ) ;
for ( const SLAPrintObject * object : objects )
{
if ( object - > has_mesh ( slaposPad ) | | object - > has_mesh ( slaposSupportTree ) )
{
can_export = true ;
break ;
}
}
return can_export ;
}
bool MainFrame : : can_export_gcode ( ) const
{
if ( m_plater = = nullptr )
return false ;
if ( m_plater - > model ( ) . objects . empty ( ) )
return false ;
if ( m_plater - > is_export_gcode_scheduled ( ) )
return false ;
// TODO:: add other filters
PartPlateList & part_plate_list = m_plater - > get_partplate_list ( ) ;
PartPlate * current_plate = part_plate_list . get_curr_plate ( ) ;
if ( ! current_plate - > is_slice_result_ready_for_print ( ) )
return false ;
return true ;
}
/*bool MainFrame::can_export_gcode_sd() const
{
if ( m_plater = = nullptr )
return false ;
if ( m_plater - > model ( ) . objects . empty ( ) )
return false ;
if ( m_plater - > is_export_gcode_scheduled ( ) )
return false ;
// TODO:: add other filters
return wxGetApp ( ) . removable_drive_manager ( ) - > status ( ) . has_removable_drives ;
}
bool MainFrame : : can_eject ( ) const
{
return wxGetApp ( ) . removable_drive_manager ( ) - > status ( ) . has_eject ;
} */
bool MainFrame : : can_slice ( ) const
{
# ifdef SUPPORT_BACKGROUND_PROCESSING
bool bg_proc = wxGetApp ( ) . app_config - > get ( " background_processing " ) = = " 1 " ;
return ( m_plater ! = nullptr ) ? ! m_plater - > model ( ) . objects . empty ( ) & & ! bg_proc : false ;
# else
return ( m_plater ! = nullptr ) ? ! m_plater - > model ( ) . objects . empty ( ) : false ;
# endif
}
bool MainFrame : : can_change_view ( ) const
{
switch ( m_layout )
{
default : { return false ; }
//BBS GUI refactor: remove unused layout new/dlg
case ESettingsLayout : : Old : {
int page_id = m_tabpanel - > GetSelection ( ) ;
return page_id ! = wxNOT_FOUND & & dynamic_cast < const Slic3r : : GUI : : Plater * > ( m_tabpanel - > GetPage ( ( size_t ) page_id ) ) ! = nullptr ;
}
case ESettingsLayout : : GCodeViewer : { return true ; }
}
}
2022-08-08 02:05:00 +00:00
bool MainFrame : : can_clone ( ) const {
return can_select ( ) & & ! m_plater - > is_selection_empty ( ) ;
}
2022-07-15 15:37:19 +00:00
bool MainFrame : : can_select ( ) const
{
2022-08-08 02:05:00 +00:00
return ( m_plater ! = nullptr ) & & ( m_tabpanel - > GetSelection ( ) = = TabPosition : : tp3DEditor ) & & ! m_plater - > model ( ) . objects . empty ( ) ;
2022-07-15 15:37:19 +00:00
}
bool MainFrame : : can_deselect ( ) const
{
2022-08-08 02:05:00 +00:00
return ( m_plater ! = nullptr ) & & ( m_tabpanel - > GetSelection ( ) = = TabPosition : : tp3DEditor ) & & ! m_plater - > is_selection_empty ( ) ;
2022-07-15 15:37:19 +00:00
}
bool MainFrame : : can_delete ( ) const
{
2022-08-08 02:05:00 +00:00
return ( m_plater ! = nullptr ) & & ( m_tabpanel - > GetSelection ( ) = = TabPosition : : tp3DEditor ) & & ! m_plater - > is_selection_empty ( ) ;
2022-07-15 15:37:19 +00:00
}
bool MainFrame : : can_delete_all ( ) const
{
2022-08-08 02:05:00 +00:00
return ( m_plater ! = nullptr ) & & ( m_tabpanel - > GetSelection ( ) = = TabPosition : : tp3DEditor ) & & ! m_plater - > model ( ) . objects . empty ( ) ;
2022-07-15 15:37:19 +00:00
}
bool MainFrame : : can_reslice ( ) const
{
return ( m_plater ! = nullptr ) & & ! m_plater - > model ( ) . objects . empty ( ) ;
}
wxBoxSizer * MainFrame : : create_side_tools ( )
{
int em = em_unit ( ) ;
wxBoxSizer * sizer = new wxBoxSizer ( wxHORIZONTAL ) ;
m_slice_select = eSlicePlate ;
m_print_select = ePrintPlate ;
m_slice_btn = new SideButton ( this , _L ( " Slice " ) , " " ) ;
m_print_btn = new SideButton ( this , _L ( " Print " ) , " " ) ;
m_print_option_btn = new SideButton ( this , " " , " sidebutton_dropdown " , 0 , FromDIP ( 14 ) ) ;
update_side_button_style ( ) ;
m_print_option_btn - > Enable ( ) ;
sizer - > Add ( m_slice_btn , 0 , wxLEFT | wxALIGN_CENTER_VERTICAL , FromDIP ( 1 ) ) ;
sizer - > Add ( FromDIP ( 15 ) , 0 , 0 , 0 , 0 ) ;
sizer - > Add ( m_print_option_btn , 0 , wxRIGHT | wxALIGN_CENTER_VERTICAL , FromDIP ( 1 ) ) ;
sizer - > Add ( m_print_btn , 0 , wxLEFT | wxALIGN_CENTER_VERTICAL , FromDIP ( 1 ) ) ;
sizer - > Add ( FromDIP ( 19 ) , 0 , 0 , 0 , 0 ) ;
sizer - > Layout ( ) ;
m_slice_btn - > Bind ( wxEVT_BUTTON , [ this ] ( wxCommandEvent & event )
{
//this->m_plater->select_view_3D("Preview");
if ( m_slice_select = = eSliceAll )
wxPostEvent ( m_plater , SimpleEvent ( EVT_GLTOOLBAR_SLICE_ALL ) ) ;
else
wxPostEvent ( m_plater , SimpleEvent ( EVT_GLTOOLBAR_SLICE_PLATE ) ) ;
this - > m_tabpanel - > SetSelection ( tpPreview ) ;
} ) ;
m_print_btn - > Bind ( wxEVT_BUTTON , [ this ] ( wxCommandEvent & event )
{
//this->m_plater->select_view_3D("Preview");
if ( m_print_select = = ePrintAll | | m_print_select = = ePrintPlate )
{
m_plater - > apply_background_progress ( ) ;
// check valid of print
m_print_enable = get_enable_print_status ( ) ;
m_print_btn - > Enable ( m_print_enable ) ;
if ( m_print_enable ) {
if ( m_print_select = = ePrintAll )
wxPostEvent ( m_plater , SimpleEvent ( EVT_GLTOOLBAR_PRINT_ALL ) ) ;
if ( m_print_select = = ePrintPlate )
wxPostEvent ( m_plater , SimpleEvent ( EVT_GLTOOLBAR_PRINT_PLATE ) ) ;
}
}
else if ( m_print_select = = eExportGcode )
wxPostEvent ( m_plater , SimpleEvent ( EVT_GLTOOLBAR_EXPORT_GCODE ) ) ;
else if ( m_print_select = = eExportSlicedFile )
wxPostEvent ( m_plater , SimpleEvent ( EVT_GLTOOLBAR_EXPORT_SLICED_FILE ) ) ;
} ) ;
// only support single plate currently
#if 0
m_slice_option_btn - > Bind ( wxEVT_BUTTON , [ this ] ( wxCommandEvent & event )
{
SidePopup * p = new SidePopup ( this ) ;
SideButton * slice_all_btn = new SideButton ( p , _L ( " Slice all " ) , " " ) ;
slice_all_btn - > SetCornerRadius ( 0 ) ;
SideButton * slice_plate_btn = new SideButton ( p , _L ( " Slice " ) , " " ) ;
slice_plate_btn - > SetCornerRadius ( 0 ) ;
slice_all_btn - > Bind ( wxEVT_BUTTON , [ this , p ] ( wxCommandEvent & ) {
m_slice_btn - > SetLabel ( _L ( " Slice all " ) ) ;
m_slice_select = eSliceAll ;
m_slice_enable = get_enable_slice_status ( ) ;
m_slice_btn - > Enable ( m_slice_enable ) ;
this - > Layout ( ) ;
p - > Dismiss ( ) ;
} ) ;
slice_plate_btn - > Bind ( wxEVT_BUTTON , [ this , p ] ( wxCommandEvent & ) {
m_slice_btn - > SetLabel ( _L ( " Slice plate " ) ) ;
m_slice_select = eSlicePlate ;
m_slice_enable = get_enable_slice_status ( ) ;
m_slice_btn - > Enable ( m_slice_enable ) ;
this - > Layout ( ) ;
p - > Dismiss ( ) ;
} ) ;
p - > append_button ( slice_all_btn ) ;
p - > append_button ( slice_plate_btn ) ;
p - > Popup ( m_slice_btn ) ;
}
) ;
# endif
m_print_option_btn - > Bind ( wxEVT_BUTTON , [ this ] ( wxCommandEvent & event )
{
SidePopup * p = new SidePopup ( this ) ;
# if ENABEL_PRINT_ALL
SideButton * print_all_btn = new SideButton ( p , _L ( " Print all " ) , " " ) ;
print_all_btn - > SetCornerRadius ( 0 ) ;
print_all_btn - > Bind ( wxEVT_BUTTON , [ this , p ] ( wxCommandEvent & ) {
m_print_btn - > SetLabel ( _L ( " Print all " ) ) ;
m_print_select = ePrintAll ;
if ( m_print_enable ) m_print_enable = get_enable_print_status ( ) ;
m_print_btn - > Enable ( m_print_enable ) ;
this - > Layout ( ) ;
p - > Dismiss ( ) ;
} ) ;
# endif
SideButton * print_plate_btn = new SideButton ( p , _L ( " Print " ) , " " ) ;
print_plate_btn - > SetCornerRadius ( 0 ) ;
SideButton * export_sliced_file_btn = new SideButton ( p , _L ( " Export sliced file " ) , " " ) ;
export_sliced_file_btn - > SetCornerRadius ( 0 ) ;
print_plate_btn - > Bind ( wxEVT_BUTTON , [ this , p ] ( wxCommandEvent & ) {
m_print_btn - > SetLabel ( _L ( " Print " ) ) ;
m_print_select = ePrintPlate ;
m_print_enable = get_enable_print_status ( ) ;
m_print_btn - > Enable ( m_print_enable ) ;
this - > Layout ( ) ;
p - > Dismiss ( ) ;
} ) ;
export_sliced_file_btn - > Bind ( wxEVT_BUTTON , [ this , p ] ( wxCommandEvent & ) {
m_print_btn - > SetLabel ( _L ( " Export Sliced File " ) ) ;
m_print_select = eExportSlicedFile ;
if ( m_print_enable )
m_print_enable = get_enable_print_status ( ) ;
m_print_btn - > Enable ( m_print_enable ) ;
this - > Layout ( ) ;
p - > Dismiss ( ) ;
} ) ;
# if ENABEL_PRINT_ALL
p - > append_button ( print_all_btn ) ;
# endif
p - > append_button ( print_plate_btn ) ;
p - > append_button ( export_sliced_file_btn ) ;
p - > Popup ( m_print_btn ) ;
}
) ;
/*
Button * aux_btn = new Button ( this , _L ( " Auxiliary " ) ) ;
aux_btn - > SetBackgroundColour ( 0x3B4446 ) ;
aux_btn - > Bind ( wxEVT_BUTTON , [ ] ( auto e ) {
wxGetApp ( ) . sidebar ( ) . show_auxiliary_dialog ( ) ;
} ) ;
sizer - > Add ( aux_btn , 0 , wxLEFT | wxALIGN_CENTER_VERTICAL , 1 * em / 10 ) ;
*/
sizer - > Add ( FromDIP ( 19 ) , 0 , 0 , 0 , 0 ) ;
return sizer ;
}
bool MainFrame : : get_enable_slice_status ( )
{
bool enable = true ;
bool on_slicing = m_plater - > is_background_process_slicing ( ) ;
if ( on_slicing ) {
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : on slicing, return false directly! " ) ;
return false ;
}
PartPlateList & part_plate_list = m_plater - > get_partplate_list ( ) ;
PartPlate * current_plate = part_plate_list . get_curr_plate ( ) ;
if ( m_slice_select = = eSliceAll )
{
if ( part_plate_list . is_all_slice_results_valid ( ) )
{
enable = false ;
}
else if ( ! part_plate_list . is_all_plates_ready_for_slice ( ) )
{
enable = false ;
}
}
else if ( m_slice_select = = eSlicePlate )
{
if ( current_plate - > is_slice_result_valid ( ) )
{
enable = false ;
}
else if ( ! current_plate - > can_slice ( ) )
{
enable = false ;
}
}
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : m_slice_select %1%, enable= %2% " ) % m_slice_select % enable ;
return enable ;
}
bool MainFrame : : get_enable_print_status ( )
{
bool enable = true ;
PartPlateList & part_plate_list = m_plater - > get_partplate_list ( ) ;
PartPlate * current_plate = part_plate_list . get_curr_plate ( ) ;
if ( m_print_select = = ePrintAll )
{
if ( ! part_plate_list . is_all_slice_results_ready_for_print ( ) )
{
enable = false ;
}
}
else if ( m_print_select = = ePrintPlate )
{
if ( ! current_plate - > is_slice_result_ready_for_print ( ) )
{
enable = false ;
}
}
else if ( m_print_select = = eExportGcode )
{
if ( ! current_plate - > is_slice_result_valid ( ) )
{
enable = false ;
}
}
else if ( m_print_select = = eExportSlicedFile )
{
if ( ! current_plate - > is_slice_result_ready_for_print ( ) )
{
enable = false ;
}
}
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : m_print_select %1%, enable= %2% " ) % m_print_select % enable ;
return enable ;
}
void MainFrame : : update_side_button_style ( )
{
// BBS
int em = em_unit ( ) ;
m_slice_btn - > SetLayoutStyle ( 1 ) ;
m_slice_btn - > SetTextLayout ( SideButton : : EHorizontalOrientation : : HO_Center , FromDIP ( 15 ) ) ;
m_slice_btn - > SetMinSize ( wxSize ( - 1 , FromDIP ( 24 ) ) ) ;
m_slice_btn - > SetCornerRadius ( FromDIP ( 12 ) ) ;
m_slice_btn - > SetExtraSize ( wxSize ( FromDIP ( 38 ) , FromDIP ( 10 ) ) ) ;
m_slice_btn - > SetBottomColour ( wxColour ( 0x3B4446 ) ) ;
#if 0
m_slice_option_btn - > SetTextLayout ( SideButton : : EHorizontalOrientation : : HO_Center ) ;
m_slice_option_btn - > SetCornerRadius ( 12 * em / 10 ) ;
m_slice_option_btn - > SetExtraSize ( wxSize ( 10 * em / 10 , 10 * em / 10 ) ) ;
m_slice_option_btn - > SetIconOffset ( 2 * em / 10 ) ;
m_slice_option_btn - > SetMinSize ( wxSize ( 24 * em / 10 , 24 * em / 10 ) ) ;
m_slice_option_btn - > SetBottomColour ( wxColour ( 0x3B4446 ) ) ;
# endif
m_print_btn - > SetTextLayout ( SideButton : : EHorizontalOrientation : : HO_Left , FromDIP ( 15 ) ) ;
m_print_btn - > SetCornerRadius ( FromDIP ( 12 ) ) ;
m_print_btn - > SetExtraSize ( wxSize ( FromDIP ( 38 ) , FromDIP ( 10 ) ) ) ;
m_print_btn - > SetMinSize ( wxSize ( - 1 , FromDIP ( 24 ) ) ) ;
m_print_btn - > SetBottomColour ( wxColour ( 0x3B4446 ) ) ;
m_print_option_btn - > SetTextLayout ( SideButton : : EHorizontalOrientation : : HO_Center ) ;
m_print_option_btn - > SetCornerRadius ( FromDIP ( 12 ) ) ;
m_print_option_btn - > SetExtraSize ( wxSize ( FromDIP ( 10 ) , FromDIP ( 10 ) ) ) ;
m_print_option_btn - > SetIconOffset ( FromDIP ( 2 ) ) ;
m_print_option_btn - > SetMinSize ( wxSize ( FromDIP ( 24 ) , FromDIP ( 24 ) ) ) ;
m_print_option_btn - > SetBottomColour ( wxColour ( 0x3B4446 ) ) ;
}
void MainFrame : : update_slice_print_status ( SlicePrintEventType event , bool can_slice , bool can_print )
{
bool enable_print = true , enable_slice = true ;
if ( ! can_slice )
{
if ( m_slice_select = = eSlicePlate )
enable_slice = false ;
}
if ( ! can_print )
enable_print = false ;
//process print logic
if ( enable_print )
{
enable_print = get_enable_print_status ( ) ;
}
//process slice logic
if ( enable_slice )
{
enable_slice = get_enable_slice_status ( ) ;
}
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " m_slice_select %1%: can_slice= %2%, can_print %3%, enable_slice %4%, enable_print %5% " ) % m_slice_select % can_slice % can_print % enable_slice % enable_print ;
m_print_btn - > Enable ( enable_print ) ;
m_slice_btn - > Enable ( enable_slice ) ;
m_slice_enable = enable_slice ;
m_print_enable = enable_print ;
}
void MainFrame : : on_dpi_changed ( const wxRect & suggested_rect )
{
wxGetApp ( ) . update_fonts ( this ) ;
this - > SetFont ( this - > normal_font ( ) ) ;
# ifdef _MSW_DARK_MODE
// update common mode sizer
if ( ! wxGetApp ( ) . tabs_as_menu ( ) )
dynamic_cast < Notebook * > ( m_tabpanel ) - > Rescale ( ) ;
# endif
2022-07-27 08:24:45 +00:00
# ifdef __WINDOWS__
2022-07-15 15:37:19 +00:00
// BBS
m_topbar - > Rescale ( ) ;
2022-07-27 08:24:45 +00:00
# endif
2022-07-15 15:37:19 +00:00
m_tabpanel - > Rescale ( ) ;
update_side_button_style ( ) ;
m_slice_btn - > Rescale ( ) ;
//m_slice_option_btn->Rescale();
m_print_btn - > Rescale ( ) ;
m_print_option_btn - > Rescale ( ) ;
// update Plater
wxGetApp ( ) . plater ( ) - > msw_rescale ( ) ;
// update Tabs
//BBS GUI refactor: remove unused layout new/dlg
//if (m_layout != ESettingsLayout::Dlg) // Do not update tabs if the Settings are in the separated dialog
m_param_panel - > msw_rescale ( ) ;
m_auxiliary - > msw_rescale ( ) ;
m_monitor - > msw_rescale ( ) ;
// BBS
#if 0
for ( size_t id = 0 ; id < m_menubar - > GetMenuCount ( ) ; id + + )
msw_rescale_menu ( m_menubar - > GetMenu ( id ) ) ;
# endif
// Workarounds for correct Window rendering after rescale
/* Even if Window is maximized during moving,
* first of all we should imitate Window resizing . So :
* 1. cancel maximization , if it was set
* 2. imitate resizing
* 3. set maximization , if it was set
*/
const bool is_maximized = this - > IsMaximized ( ) ;
if ( is_maximized )
this - > Maximize ( false ) ;
/* To correct window rendering (especially redraw of a status bar)
* we should imitate window resizing .
*/
const wxSize & sz = this - > GetSize ( ) ;
this - > SetSize ( sz . x + 1 , sz . y + 1 ) ;
this - > SetSize ( sz ) ;
this - > Maximize ( is_maximized ) ;
}
void MainFrame : : on_sys_color_changed ( )
{
wxBusyCursor wait ;
// update label colors in respect to the system mode
wxGetApp ( ) . init_label_colours ( ) ;
# ifdef __WXMSW__
wxGetApp ( ) . UpdateDarkUI ( m_tabpanel ) ;
// m_statusbar->update_dark_ui();
# ifdef _MSW_DARK_MODE
// update common mode sizer
if ( ! wxGetApp ( ) . tabs_as_menu ( ) )
dynamic_cast < Notebook * > ( m_tabpanel ) - > Rescale ( ) ;
# endif
# endif
// BBS
m_tabpanel - > Rescale ( ) ;
// update Plater
wxGetApp ( ) . plater ( ) - > sys_color_changed ( ) ;
// update Tabs
for ( auto tab : wxGetApp ( ) . tabs_list )
tab - > sys_color_changed ( ) ;
for ( auto tab : wxGetApp ( ) . model_tabs_list )
tab - > sys_color_changed ( ) ;
MenuFactory : : sys_color_changed ( m_menubar ) ;
this - > Refresh ( ) ;
}
# ifdef _MSC_VER
// \xA0 is a non-breaking space. It is entered here to spoil the automatic accelerators,
// as the simple numeric accelerators spoil all numeric data entry.
static const wxString sep = " \t \xA0 " ;
static const wxString sep_space = " \xA0 " ;
# else
static const wxString sep = " - " ;
static const wxString sep_space = " " ;
# endif
static wxMenu * generate_help_menu ( )
{
wxMenu * helpMenu = new wxMenu ( ) ;
// shortcut key
append_menu_item ( helpMenu , wxID_ANY , _L ( " Keyboard Shortcuts " ) + sep + " &? " , _L ( " Show the list of the keyboard shortcuts " ) ,
[ ] ( wxCommandEvent & ) { wxGetApp ( ) . keyboard_shortcuts ( ) ; } ) ;
// Show Beginner's Tutorial
append_menu_item ( helpMenu , wxID_ANY , _L ( " Setup Wizard " ) , _L ( " Setup Wizard " ) , [ ] ( wxCommandEvent & ) { wxGetApp ( ) . ShowUserGuide ( ) ; } ) ;
helpMenu - > AppendSeparator ( ) ;
// Open Config Folder
append_menu_item ( helpMenu , wxID_ANY , _L ( " Show Configuration Folder " ) , _L ( " Show Configuration Folder " ) ,
[ ] ( wxCommandEvent & ) { Slic3r : : GUI : : desktop_open_datadir_folder ( ) ; } ) ;
// Report a bug
//append_menu_item(helpMenu, wxID_ANY, _L("Report Bug(TODO)"), _L("Report a bug of BambuStudio"),
// [](wxCommandEvent&) {
// //TODO
// });
// Check New Version
append_menu_item ( helpMenu , wxID_ANY , _L ( " Check for Update " ) , _L ( " Check for Update " ) ,
[ ] ( wxCommandEvent & ) {
wxGetApp ( ) . check_new_version ( true ) ;
} , " " , nullptr , [ ] ( ) {
return true ;
} ) ;
// About
2022-07-27 08:24:45 +00:00
# ifdef __WINDOWS__
2022-07-15 15:37:19 +00:00
wxString about_title = wxString : : Format ( _L ( " &About %s " ) , SLIC3R_APP_FULL_NAME ) ;
append_menu_item ( helpMenu , wxID_ANY , about_title , about_title ,
[ ] ( wxCommandEvent & ) { Slic3r : : GUI : : about ( ) ; } ) ;
2022-07-27 08:24:45 +00:00
# endif
2022-08-12 03:20:17 +00:00
append_menu_item ( helpMenu , wxID_ANY , _L ( " Open Network Test " ) , _L ( " Open Network Test " ) , [ ] ( wxCommandEvent & ) {
NetworkTestDialog dlg ( wxGetApp ( ) . mainframe ) ;
dlg . ShowModal ( ) ;
} ) ;
2022-07-15 15:37:19 +00:00
return helpMenu ;
}
static void add_common_view_menu_items ( wxMenu * view_menu , MainFrame * mainFrame , std : : function < bool ( void ) > can_change_view )
{
// The camera control accelerators are captured by GLCanvas3D::on_char().
append_menu_item ( view_menu , wxID_ANY , _L ( " Default View " ) + " \t Ctrl+0 " , _L ( " Default View " ) , [ mainFrame ] ( wxCommandEvent & ) { mainFrame - > select_view ( " topfront " ) ; } ,
" " , nullptr , [ can_change_view ] ( ) { return can_change_view ( ) ; } , mainFrame ) ;
//view_menu->AppendSeparator();
//TRN To be shown in the main menu View->Top
append_menu_item ( view_menu , wxID_ANY , _L ( " Top " ) + " \t Ctrl+1 " , _L ( " Top View " ) , [ mainFrame ] ( wxCommandEvent & ) { mainFrame - > select_view ( " top " ) ; } ,
" " , nullptr , [ can_change_view ] ( ) { return can_change_view ( ) ; } , mainFrame ) ;
//TRN To be shown in the main menu View->Bottom
append_menu_item ( view_menu , wxID_ANY , _L ( " Bottom " ) + " \t Ctrl+2 " , _L ( " Bottom View " ) , [ mainFrame ] ( wxCommandEvent & ) { mainFrame - > select_view ( " bottom " ) ; } ,
" " , nullptr , [ can_change_view ] ( ) { return can_change_view ( ) ; } , mainFrame ) ;
append_menu_item ( view_menu , wxID_ANY , _L ( " Front " ) + " \t Ctrl+3 " , _L ( " Front View " ) , [ mainFrame ] ( wxCommandEvent & ) { mainFrame - > select_view ( " front " ) ; } ,
" " , nullptr , [ can_change_view ] ( ) { return can_change_view ( ) ; } , mainFrame ) ;
append_menu_item ( view_menu , wxID_ANY , _L ( " Rear " ) + " \t Ctrl+4 " , _L ( " Rear View " ) , [ mainFrame ] ( wxCommandEvent & ) { mainFrame - > select_view ( " rear " ) ; } ,
" " , nullptr , [ can_change_view ] ( ) { return can_change_view ( ) ; } , mainFrame ) ;
append_menu_item ( view_menu , wxID_ANY , _L ( " Left " ) + " \t Ctrl+5 " , _L ( " Left View " ) , [ mainFrame ] ( wxCommandEvent & ) { mainFrame - > select_view ( " left " ) ; } ,
" " , nullptr , [ can_change_view ] ( ) { return can_change_view ( ) ; } , mainFrame ) ;
append_menu_item ( view_menu , wxID_ANY , _L ( " Right " ) + " \t Ctrl+6 " , _L ( " Right View " ) , [ mainFrame ] ( wxCommandEvent & ) { mainFrame - > select_view ( " right " ) ; } ,
" " , nullptr , [ can_change_view ] ( ) { return can_change_view ( ) ; } , mainFrame ) ;
}
void MainFrame : : init_menubar_as_editor ( )
{
# ifdef __APPLE__
wxMenuBar : : SetAutoWindowMenu ( false ) ;
2022-07-27 08:24:45 +00:00
m_menubar = new wxMenuBar ( ) ;
2022-07-15 15:37:19 +00:00
# endif
// File menu
wxMenu * fileMenu = new wxMenu ;
{
// New Project
append_menu_item ( fileMenu , wxID_ANY , _L ( " New Project " ) + " \t Ctrl+N " , _L ( " Start a new project " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ) m_plater - > new_project ( ) ; } , " " , nullptr ,
[ this ] ( ) { return can_start_new_project ( ) ; } , this ) ;
// Open Project
# ifdef __WINDOWS__
append_menu_item ( fileMenu , wxID_ANY , _L ( " Open Project " ) + dots + " \t Ctrl+O " , _L ( " Open a project file " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ) m_plater - > load_project ( ) ; } , " menu_open " , nullptr ,
[ this ] ( ) { return can_open_project ( ) ; } , this ) ;
# else
append_menu_item ( fileMenu , wxID_ANY , _L ( " Open Project " ) + dots + " \t Ctrl+O " , _L ( " Open a project file " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ) m_plater - > load_project ( ) ; } , " " , nullptr ,
[ this ] ( ) { return can_open_project ( ) ; } , this ) ;
# endif
// Recent Project
wxMenu * recent_projects_menu = new wxMenu ( ) ;
wxMenuItem * recent_projects_submenu = append_submenu ( fileMenu , recent_projects_menu , wxID_ANY , _L ( " Recent projects " ) , " " ) ;
m_recent_projects . UseMenu ( recent_projects_menu ) ;
Bind ( wxEVT_MENU , [ this ] ( wxCommandEvent & evt ) {
size_t file_id = evt . GetId ( ) - wxID_FILE1 ;
wxString filename = m_recent_projects . GetHistoryFile ( file_id ) ;
open_recent_project ( file_id , filename ) ;
} , wxID_FILE1 , wxID_FILE9 ) ;
std : : vector < std : : string > recent_projects = wxGetApp ( ) . app_config - > get_recent_projects ( ) ;
std : : reverse ( recent_projects . begin ( ) , recent_projects . end ( ) ) ;
for ( const std : : string & project : recent_projects )
{
m_recent_projects . AddFileToHistory ( from_u8 ( project ) ) ;
}
m_recent_projects . LoadThumbnails ( ) ;
Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) { evt . Enable ( can_open_project ( ) & & ( m_recent_projects . GetCount ( ) > 0 ) ) ; } , recent_projects_submenu - > GetId ( ) ) ;
// BBS: close save project
# ifdef __WINDOWS__
append_menu_item ( fileMenu , wxID_ANY , _L ( " Save Project " ) + " \t Ctrl+S " , _L ( " Save current project to file " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ) m_plater - > save_project ( ) ; } , " menu_save " , nullptr ,
[ this ] ( ) { return m_plater ! = nullptr & & can_save ( ) ; } , this ) ;
# else
append_menu_item ( fileMenu , wxID_ANY , _L ( " Save Project " ) + " \t Ctrl+S " , _L ( " Save current project to file " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ) m_plater - > save_project ( ) ; } , " " , nullptr ,
[ this ] ( ) { return m_plater ! = nullptr & & can_save ( ) ; } , this ) ;
# endif
# ifdef __WINDOWS__
append_menu_item ( fileMenu , wxID_ANY , _L ( " Save Project as " ) + dots + " \t Ctrl+Shift+S " , _L ( " Save current project as " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ) m_plater - > save_project ( true ) ; } , " menu_save " , nullptr ,
[ this ] ( ) { return m_plater ! = nullptr & & can_save_as ( ) ; } , this ) ;
# else
append_menu_item ( fileMenu , wxID_ANY , _L ( " Save Project as " ) + dots + " \t Ctrl+Shift+S " , _L ( " Save current project as " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ) m_plater - > save_project ( true ) ; } , " " , nullptr ,
[ this ] ( ) { return m_plater ! = nullptr & & can_save_as ( ) ; } , this ) ;
# endif
fileMenu - > AppendSeparator ( ) ;
//BBS
# ifdef __WINDOWS__
append_menu_item ( fileMenu , wxID_ANY , _L ( " Import 3MF/STL/STEP/OBJ/AMF " ) + dots + " \t Ctrl+I " , _L ( " Load a model " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ) {
m_plater - > add_model ( ) ;
} } , " menu_import " , nullptr ,
[ this ] ( ) { return can_add_models ( ) ; } , this ) ;
# else
append_menu_item ( fileMenu , wxID_ANY , _L ( " Import 3MF/STL/STEP/OBJ/AMF " ) + dots + " \t Ctrl+I " , _L ( " Load a model " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ) { m_plater - > add_model ( ) ; } } , " " , nullptr ,
[ this ] ( ) { return can_add_models ( ) ; } , this ) ;
# endif
wxMenu * export_menu = new wxMenu ( ) ;
// BBS export as STL
append_menu_item ( export_menu , wxID_ANY , _L ( " Export all objects as STL " ) + dots , _L ( " Export all objects as STL " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ) m_plater - > export_stl ( ) ; } , " menu_export_stl " , nullptr ,
[ this ] ( ) { return can_export_model ( ) ; } , this ) ;
2022-07-22 09:46:10 +00:00
// BBS export .gcode.3mf
append_menu_item ( export_menu , wxID_ANY , _L ( " Export Sliced File " ) + dots /* + "\tCtrl+G"*/ , _L ( " Export current Sliced file " ) ,
2022-07-15 15:37:19 +00:00
[ this ] ( wxCommandEvent & ) { if ( m_plater ) wxPostEvent ( m_plater , SimpleEvent ( EVT_GLTOOLBAR_EXPORT_SLICED_FILE ) ) ; } , " menu_export_sliced_file " , nullptr ,
[ this ] ( ) { return can_export_gcode ( ) ; } , this ) ;
2022-07-22 09:46:10 +00:00
append_menu_item ( export_menu , wxID_ANY , _L ( " Export G-code " ) + dots /* + "\tCtrl+G"*/ , _L ( " Export current plate as G-code " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ) m_plater - > export_gcode ( false ) ; } , " menu_export_gcode " , nullptr ,
[ this ] ( ) { return can_export_gcode ( ) ; } , this ) ;
2022-07-15 15:37:19 +00:00
append_submenu ( fileMenu , export_menu , wxID_ANY , _L ( " Export " ) , " " ) ;
fileMenu - > AppendSeparator ( ) ;
# ifdef __WINDOWS__
append_menu_item ( fileMenu , wxID_EXIT , _L ( " Quit " ) , wxString : : Format ( _L ( " Quit " ) ) ,
[ this ] ( wxCommandEvent & ) { Close ( false ) ; } , " menu_exit " , nullptr ) ;
# else
append_menu_item ( fileMenu , wxID_EXIT , _L ( " Quit " ) , wxString : : Format ( _L ( " Quit " ) ) ,
[ this ] ( wxCommandEvent & ) { Close ( false ) ; } , " " , nullptr ) ;
# endif
}
// Edit menu
wxMenu * editMenu = nullptr ;
if ( m_plater ! = nullptr )
{
editMenu = new wxMenu ( ) ;
# ifdef __APPLE__
// Backspace sign
wxString hotkey_delete = " \u232b " ;
# else
wxString hotkey_delete = " Del " ;
# endif
# ifdef __WINDOWS__
// BBS undo
append_menu_item ( editMenu , wxID_ANY , _L ( " Undo " ) + " \t Ctrl+Z " ,
_L ( " Undo " ) , [ this ] ( wxCommandEvent & ) { m_plater - > undo ( ) ; } ,
" menu_undo " , nullptr , [ this ] ( ) { return m_plater - > can_undo ( ) ; } , this ) ;
// BBS redo
append_menu_item ( editMenu , wxID_ANY , _L ( " Redo " ) + " \t Ctrl+Y " ,
_L ( " Redo " ) , [ this ] ( wxCommandEvent & ) { m_plater - > redo ( ) ; } ,
" menu_redo " , nullptr , [ this ] ( ) { return m_plater - > can_redo ( ) ; } , this ) ;
editMenu - > AppendSeparator ( ) ;
// BBS Cut TODO
append_menu_item ( editMenu , wxID_ANY , _L ( " Cut " ) + " \t Ctrl+X " ,
_L ( " Cut selection to clipboard " ) , [ this ] ( wxCommandEvent & ) { m_plater - > cut_selection_to_clipboard ( ) ; } ,
" menu_cut " , nullptr , [ this ] ( ) { return m_plater - > can_copy_to_clipboard ( ) ; } , this ) ;
// BBS Copy
append_menu_item ( editMenu , wxID_ANY , _L ( " Copy " ) + " \t Ctrl+C " ,
_L ( " Copy selection to clipboard " ) , [ this ] ( wxCommandEvent & ) { m_plater - > copy_selection_to_clipboard ( ) ; } ,
" menu_copy " , nullptr , [ this ] ( ) { return m_plater - > can_copy_to_clipboard ( ) ; } , this ) ;
// BBS Paste
append_menu_item ( editMenu , wxID_ANY , _L ( " Paste " ) + " \t Ctrl+V " ,
_L ( " Paste clipboard " ) , [ this ] ( wxCommandEvent & ) { m_plater - > paste_from_clipboard ( ) ; } ,
" menu_paste " , nullptr , [ this ] ( ) { return m_plater - > can_paste_from_clipboard ( ) ; } , this ) ;
// BBS Delete selected
append_menu_item ( editMenu , wxID_ANY , _L ( " Delete selected " ) + " \t Del " ,
_L ( " Deletes the current selection " ) , [ this ] ( wxCommandEvent & ) { m_plater - > remove_selected ( ) ; } ,
" menu_remove " , nullptr , [ this ] ( ) { return can_delete ( ) ; } , this ) ;
//BBS: delete all
append_menu_item ( editMenu , wxID_ANY , _L ( " Delete all " ) + " \t Ctrl+D " ,
_L ( " Deletes all objects " ) , [ this ] ( wxCommandEvent & ) { m_plater - > delete_all_objects_from_model ( ) ; } ,
" menu_remove " , nullptr , [ this ] ( ) { return can_delete_all ( ) ; } , this ) ;
editMenu - > AppendSeparator ( ) ;
// BBS Clone Selected
2022-08-16 08:12:05 +00:00
append_menu_item ( editMenu , wxID_ANY , _L ( " Clone selected " ) /*+ "\tCtrl+M"*/ ,
2022-07-15 15:37:19 +00:00
_L ( " Clone copies of selections " ) , [ this ] ( wxCommandEvent & ) {
m_plater - > clone_selection ( ) ;
} ,
2022-08-08 02:05:00 +00:00
" menu_remove " , nullptr , [ this ] ( ) { return can_clone ( ) ; } , this ) ;
2022-07-15 15:37:19 +00:00
editMenu - > AppendSeparator ( ) ;
# else
// BBS undo
append_menu_item ( editMenu , wxID_ANY , _L ( " Undo " ) + " \t Ctrl+Z " ,
_L ( " Undo " ) , [ this ] ( wxCommandEvent & ) { m_plater - > undo ( ) ; } ,
" " , nullptr , [ this ] ( ) { return m_plater - > can_undo ( ) ; } , this ) ;
// BBS redo
append_menu_item ( editMenu , wxID_ANY , _L ( " Redo " ) + " \t Ctrl+Y " ,
_L ( " Redo " ) , [ this ] ( wxCommandEvent & ) { m_plater - > redo ( ) ; } ,
" " , nullptr , [ this ] ( ) { return m_plater - > can_redo ( ) ; } , this ) ;
editMenu - > AppendSeparator ( ) ;
// BBS Cut TODO
append_menu_item ( editMenu , wxID_ANY , _L ( " Cut " ) + " \t Ctrl+X " ,
_L ( " Cut selection to clipboard " ) , [ this ] ( wxCommandEvent & ) { m_plater - > cut_selection_to_clipboard ( ) ; } ,
" " , nullptr , [ this ] ( ) { return m_plater - > can_copy_to_clipboard ( ) ; } , this ) ;
// BBS Copy
append_menu_item ( editMenu , wxID_ANY , _L ( " Copy " ) + " \t Ctrl+C " ,
_L ( " Copy selection to clipboard " ) , [ this ] ( wxCommandEvent & ) { m_plater - > copy_selection_to_clipboard ( ) ; } ,
" " , nullptr , [ this ] ( ) { return m_plater - > can_copy_to_clipboard ( ) ; } , this ) ;
// BBS Paste
append_menu_item ( editMenu , wxID_ANY , _L ( " Paste " ) + " \t Ctrl+V " ,
_L ( " Paste clipboard " ) , [ this ] ( wxCommandEvent & ) { m_plater - > paste_from_clipboard ( ) ; } ,
" " , nullptr , [ this ] ( ) { return m_plater - > can_paste_from_clipboard ( ) ; } , this ) ;
// BBS Delete selected
append_menu_item ( editMenu , wxID_ANY , _L ( " Delete selected " ) + " \t Del " ,
_L ( " Deletes the current selection " ) , [ this ] ( wxCommandEvent & ) { m_plater - > remove_selected ( ) ; } ,
" " , nullptr , [ this ] ( ) { return can_delete ( ) ; } , this ) ;
//BBS: delete all
append_menu_item ( editMenu , wxID_ANY , _L ( " Delete all " ) + " \t Ctrl+D " ,
_L ( " Deletes all objects " ) , [ this ] ( wxCommandEvent & ) { m_plater - > delete_all_objects_from_model ( ) ; } ,
" " , nullptr , [ this ] ( ) { return can_delete_all ( ) ; } , this ) ;
editMenu - > AppendSeparator ( ) ;
// BBS Clone Selected
append_menu_item ( editMenu , wxID_ANY , _L ( " Clone selected " ) + " \t Ctrl+M " ,
_L ( " Clone copies of selections " ) , [ this ] ( wxCommandEvent & ) {
m_plater - > clone_selection ( ) ;
} ,
2022-08-08 02:05:00 +00:00
" " , nullptr , [ this ] ( ) { return can_clone ( ) ; } , this ) ;
2022-07-15 15:37:19 +00:00
editMenu - > AppendSeparator ( ) ;
# endif
// BBS Select All
append_menu_item ( editMenu , wxID_ANY , _L ( " Select all " ) + " \t Ctrl+A " ,
_L ( " Selects all objects " ) , [ this ] ( wxCommandEvent & ) { m_plater - > select_all ( ) ; } ,
" " , nullptr , [ this ] ( ) { return can_select ( ) ; } , this ) ;
// BBS Deslect All
append_menu_item ( editMenu , wxID_ANY , _L ( " Deselect all " ) + " \t Esc " ,
_L ( " Deselects all objects " ) , [ this ] ( wxCommandEvent & ) { m_plater - > deselect_all ( ) ; } ,
" " , nullptr , [ this ] ( ) { return can_deselect ( ) ; } , this ) ;
2022-07-22 09:46:10 +00:00
//editMenu->AppendSeparator();
//append_menu_check_item(editMenu, wxID_ANY, _L("Show Model Mesh(TODO)"),
// _L("Display triangles of models"), [this](wxCommandEvent& evt) {
// wxGetApp().app_config->set_bool("show_model_mesh", evt.GetInt() == 1);
// }, nullptr, [this]() {return can_select(); }, [this]() { return wxGetApp().app_config->get("show_model_mesh").compare("true") == 0; }, this);
//append_menu_check_item(editMenu, wxID_ANY, _L("Show Model Shadow(TODO)"), _L("Display shadow of objects"),
// [this](wxCommandEvent& evt) {
// wxGetApp().app_config->set_bool("show_model_shadow", evt.GetInt() == 1);
// }, nullptr, [this]() {return can_select(); }, [this]() { return wxGetApp().app_config->get("show_model_shadow").compare("true") == 0; }, this);
//editMenu->AppendSeparator();
//append_menu_check_item(editMenu, wxID_ANY, _L("Show Printable Box(TODO)"), _L("Display printable box"),
// [this](wxCommandEvent& evt) {
// wxGetApp().app_config->set_bool("show_printable_box", evt.GetInt() == 1);
// }, nullptr, [this]() {return can_select(); }, [this]() { return wxGetApp().app_config->get("show_printable_box").compare("true") == 0; }, this);
2022-07-15 15:37:19 +00:00
}
// BBS
// View menu
wxMenu * viewMenu = nullptr ;
if ( m_plater ) {
viewMenu = new wxMenu ( ) ;
add_common_view_menu_items ( viewMenu , this , std : : bind ( & MainFrame : : can_change_view , this ) ) ;
viewMenu - > AppendSeparator ( ) ;
//BBS perspective view
wxWindowID camera_id_base = wxWindow : : NewControlId ( int ( wxID_CAMERA_COUNT ) ) ;
auto perspective_item = append_menu_radio_item ( viewMenu , wxID_CAMERA_PERSPECTIVE + camera_id_base , _L ( " Use Perspective View " ) , _L ( " Use Perspective View " ) ,
[ this ] ( wxCommandEvent & ) {
wxGetApp ( ) . app_config - > set_bool ( " use_perspective_camera " , true ) ;
wxGetApp ( ) . update_ui_from_settings ( ) ;
} , nullptr ) ;
//BBS orthogonal view
auto orthogonal_item = append_menu_radio_item ( viewMenu , wxID_CAMERA_ORTHOGONAL + camera_id_base , _L ( " Use Orthogonal View " ) , _L ( " Use Orthogonal View " ) ,
[ this ] ( wxCommandEvent & ) {
wxGetApp ( ) . app_config - > set_bool ( " use_perspective_camera " , false ) ;
wxGetApp ( ) . update_ui_from_settings ( ) ;
} , nullptr ) ;
if ( wxGetApp ( ) . app_config - > get ( " use_perspective_camera " ) . compare ( " true " ) = = 0 )
viewMenu - > Check ( wxID_CAMERA_PERSPECTIVE + camera_id_base , true ) ;
else
viewMenu - > Check ( wxID_CAMERA_ORTHOGONAL + camera_id_base , true ) ;
//viewMenu->AppendSeparator();
////BBS orthogonal view
//append_menu_check_item(viewMenu, wxID_ANY, _L("Show Edges(TODO)"), _L("Show Edges"),
// [this](wxCommandEvent& evt) {
// wxGetApp().app_config->set("show_build_edges", evt.GetInt() == 1 ? "true" : "false");
// }, nullptr, [this]() {return can_select(); }, [this]() {
// std::string show_build_edges = wxGetApp().app_config->get("show_build_edges");
// return show_build_edges.compare("true") == 0;
// }, this);
}
wxWindowID config_id_base = wxWindow : : NewControlId ( int ( ConfigMenuCnt ) ) ;
//TODO remove
//auto config_wizard_name = _(ConfigWizard::name(true) + "(Debug)");
//const auto config_wizard_tooltip = from_u8((boost::format(_utf8(L("Run %s"))) % config_wizard_name).str());
//auto config_item = new wxMenuItem(m_topbar->GetTopMenu(), ConfigMenuWizard + config_id_base, config_wizard_name, config_wizard_tooltip);
2022-07-27 08:24:45 +00:00
# ifdef __APPLE__
wxWindowID bambu_studio_id_base = wxWindow : : NewControlId ( int ( 2 ) ) ;
wxMenu * parent_menu = m_menubar - > OSXGetAppleMenu ( ) ;
2022-08-15 08:27:30 +00:00
//auto preference_item = new wxMenuItem(parent_menu, BambuStudioMenuPreferences + bambu_studio_id_base, _L("Preferences") + "\tCtrl+,", "");
2022-07-27 08:24:45 +00:00
# else
wxMenu * parent_menu = m_topbar - > GetTopMenu ( ) ;
auto preference_item = new wxMenuItem ( parent_menu , ConfigMenuPreferences + config_id_base , _L ( " Preferences " ) + " \t Ctrl+P " , " " ) ;
2022-08-08 02:05:00 +00:00
2022-07-27 08:24:45 +00:00
# endif
//auto printer_item = new wxMenuItem(parent_menu, ConfigMenuPrinter + config_id_base, _L("Printer"), "");
//auto language_item = new wxMenuItem(parent_menu, ConfigMenuLanguage + config_id_base, _L("Switch Language"), "");
2022-08-08 02:05:00 +00:00
// parent_menu->Bind(wxEVT_MENU, [this, config_id_base](wxEvent& event) {
// switch (event.GetId() - config_id_base) {
// //case ConfigMenuLanguage:
// //{
// // /* Before change application language, let's check unsaved changes on 3D-Scene
// // * and draw user's attention to the application restarting after a language change
// // */
// // {
// // // 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
// // wxString title = _L("Language selection");
// // wxMessageDialog dialog(nullptr,
// // _L("Switching the language requires application restart.\n") + "\n\n" +
// // _L("Do you want to continue?"),
// // title,
// // wxICON_QUESTION | wxOK | wxCANCEL);
// // if (dialog.ShowModal() == wxID_CANCEL)
// // return;
// // }
//
// // wxGetApp().switch_language();
// // break;
// //}
// //case ConfigMenuWizard:
// //{
// // wxGetApp().run_wizard(ConfigWizard::RR_USER);
// // break;
// //}
// case ConfigMenuPrinter:
// {
// wxGetApp().params_dialog()->Popup();
// wxGetApp().get_tab(Preset::TYPE_PRINTER)->restore_last_select_item();
// break;
// }
// case ConfigMenuPreferences:
// {
// wxGetApp().CallAfter([this] {
// PreferencesDialog dlg(this);
// dlg.ShowModal();
//#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
// if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
//#else
// if (dlg.seq_top_layer_only_changed())
//#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
// plater()->refresh_print();
//#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
//#ifdef _WIN32
// /*
// if (wxGetApp().app_config()->get("associate_3mf") == "true")
// wxGetApp().associate_3mf_files();
// if (wxGetApp().app_config()->get("associate_stl") == "true")
// wxGetApp().associate_stl_files();
// /*if (wxGetApp().app_config()->get("associate_step") == "true")
// wxGetApp().associate_step_files();*/
//#endif // _WIN32
//#endif
// });
// break;
// }
// default:
// break;
// }
// });
2022-07-15 15:37:19 +00:00
2022-07-27 08:24:45 +00:00
# ifdef __APPLE__
wxString about_title = wxString : : Format ( _L ( " &About %s " ) , SLIC3R_APP_FULL_NAME ) ;
2022-08-15 08:27:30 +00:00
//auto about_item = new wxMenuItem(parent_menu, BambuStudioMenuAbout + bambu_studio_id_base, about_title, "");
2022-08-08 02:05:00 +00:00
//parent_menu->Bind(wxEVT_MENU, [this, bambu_studio_id_base](wxEvent& event) {
// switch (event.GetId() - bambu_studio_id_base) {
// case BambuStudioMenuAbout:
// Slic3r::GUI::about();
// break;
// case BambuStudioMenuPreferences:
// wxGetApp().CallAfter([this] {
// PreferencesDialog dlg(this);
// dlg.ShowModal();
//#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
// if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
//#else
// if (dlg.seq_top_layer_only_changed())
//#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
// plater()->refresh_print();
// });
// break;
// default:
// break;
// }
//});
//parent_menu->Insert(0, about_item);
append_menu_item (
2022-08-15 08:27:30 +00:00
parent_menu , wxID_ANY , _L ( about_title ) , _L ( " " ) ,
2022-08-08 02:05:00 +00:00
[ this ] ( wxCommandEvent & ) { Slic3r : : GUI : : about ( ) ; } ,
" " , nullptr , [ ] ( ) { return true ; } , this , 0 ) ;
append_menu_item (
2022-08-15 08:27:30 +00:00
parent_menu , wxID_ANY , _L ( " Preferences " ) + " \t Ctrl+, " , _L ( " " ) ,
2022-08-08 02:05:00 +00:00
[ this ] ( wxCommandEvent & ) {
PreferencesDialog dlg ( this ) ;
dlg . ShowModal ( ) ;
# if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
if ( dlg . seq_top_layer_only_changed ( ) | | dlg . seq_seq_top_gcode_indices_changed ( ) )
# else
if ( dlg . seq_top_layer_only_changed ( ) )
# endif
plater ( ) - > refresh_print ( ) ;
} ,
" " , nullptr , [ ] ( ) { return true ; } , this , 1 ) ;
//parent_menu->Insert(1, preference_item);
2022-07-27 08:24:45 +00:00
# endif
2022-07-15 15:37:19 +00:00
// Help menu
auto helpMenu = generate_help_menu ( ) ;
2022-07-27 08:24:45 +00:00
# ifdef __WINDOWS__
2022-07-15 15:37:19 +00:00
m_topbar - > SetFileMenu ( fileMenu ) ;
if ( editMenu )
m_topbar - > AddDropDownSubMenu ( editMenu , _L ( " Edit " ) ) ;
if ( viewMenu )
m_topbar - > AddDropDownSubMenu ( viewMenu , _L ( " View " ) ) ;
//BBS add Preference
2022-08-08 02:05:00 +00:00
append_menu_item (
m_topbar - > GetTopMenu ( ) , wxID_ANY , _L ( " Preferences " ) + " \t Ctrl+P " , _L ( " " ) ,
[ this ] ( wxCommandEvent & ) {
PreferencesDialog dlg ( this ) ;
dlg . ShowModal ( ) ;
# if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
if ( dlg . seq_top_layer_only_changed ( ) | | dlg . seq_seq_top_gcode_indices_changed ( ) )
# else
if ( dlg . seq_top_layer_only_changed ( ) )
# endif
plater ( ) - > refresh_print ( ) ;
} ,
" " , nullptr , [ ] ( ) { return true ; } , this ) ;
//m_topbar->AddDropDownMenuItem(preference_item);
2022-07-15 15:37:19 +00:00
//m_topbar->AddDropDownMenuItem(printer_item);
//m_topbar->AddDropDownMenuItem(language_item);
//m_topbar->AddDropDownMenuItem(config_item);
m_topbar - > AddDropDownSubMenu ( helpMenu , _L ( " Help " ) ) ;
2022-07-27 08:24:45 +00:00
# else
m_menubar - > Append ( fileMenu , _L ( " &File " ) ) ;
if ( editMenu )
m_menubar - > Append ( editMenu , _L ( " &Edit " ) ) ;
if ( viewMenu )
m_menubar - > Append ( viewMenu , _L ( " &View " ) ) ;
if ( helpMenu )
m_menubar - > Append ( helpMenu , _L ( " &Help " ) ) ;
SetMenuBar ( m_menubar ) ;
# endif
2022-07-15 15:37:19 +00:00
# ifdef _MSW_DARK_MODE
if ( wxGetApp ( ) . tabs_as_menu ( ) )
m_menubar - > EnableTop ( 6 , false ) ;
# endif
# ifdef __APPLE__
// This fixes a bug on Mac OS where the quit command doesn't emit window close events
// wx bug: https://trac.wxwidgets.org/ticket/18328
2022-07-27 08:24:45 +00:00
wxMenu * apple_menu = m_menubar - > OSXGetAppleMenu ( ) ;
2022-07-15 15:37:19 +00:00
if ( apple_menu ! = nullptr ) {
apple_menu - > Bind ( wxEVT_MENU , [ this ] ( wxCommandEvent & ) {
Close ( ) ;
} , wxID_EXIT ) ;
2022-07-27 08:24:45 +00:00
}
2022-07-15 15:37:19 +00:00
# endif // __APPLE__
}
void MainFrame : : open_menubar_item ( const wxString & menu_name , const wxString & item_name )
{
if ( m_menubar = = nullptr )
return ;
// Get menu object from menubar
int menu_index = m_menubar - > FindMenu ( menu_name ) ;
wxMenu * menu = m_menubar - > GetMenu ( menu_index ) ;
if ( menu = = nullptr ) {
BOOST_LOG_TRIVIAL ( error ) < < " Mainframe open_menubar_item function couldn't find menu: " < < menu_name ;
return ;
}
// Get item id from menu
int item_id = menu - > FindItem ( item_name ) ;
if ( item_id = = wxNOT_FOUND )
{
// try adding three dots char
item_id = menu - > FindItem ( item_name + dots ) ;
}
if ( item_id = = wxNOT_FOUND )
{
BOOST_LOG_TRIVIAL ( error ) < < " Mainframe open_menubar_item function couldn't find item: " < < item_name ;
return ;
}
// wxEVT_MENU will trigger item
wxPostEvent ( ( wxEvtHandler * ) menu , wxCommandEvent ( wxEVT_MENU , item_id ) ) ;
}
void MainFrame : : init_menubar_as_gcodeviewer ( )
{
//BBS do not show gcode viewer mebu
#if 0
wxMenu * fileMenu = new wxMenu ;
{
append_menu_item ( fileMenu , wxID_ANY , _L ( " &Open G-code " ) + dots + " \t Ctrl+O " , _L ( " Open a G-code file " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ! = nullptr ) m_plater - > load_gcode ( ) ; } , " open " , nullptr ,
[ this ] ( ) { return m_plater ! = nullptr ; } , this ) ;
# ifdef __APPLE__
append_menu_item ( fileMenu , wxID_ANY , _L ( " Re&load from Disk " ) + dots + " \t Ctrl+Shift+R " ,
_L ( " Reload the plater from disk " ) , [ this ] ( wxCommandEvent & ) { m_plater - > reload_gcode_from_disk ( ) ; } ,
" " , nullptr , [ this ] ( ) { return ! m_plater - > get_last_loaded_gcode ( ) . empty ( ) ; } , this ) ;
# else
append_menu_item ( fileMenu , wxID_ANY , _L ( " Re&load from Disk " ) + sep + " F5 " ,
_L ( " Reload the plater from disk " ) , [ this ] ( wxCommandEvent & ) { m_plater - > reload_gcode_from_disk ( ) ; } ,
" " , nullptr , [ this ] ( ) { return ! m_plater - > get_last_loaded_gcode ( ) . empty ( ) ; } , this ) ;
# endif // __APPLE__
fileMenu - > AppendSeparator ( ) ;
append_menu_item ( fileMenu , wxID_ANY , _L ( " Export &Toolpaths as OBJ " ) + dots , _L ( " Export toolpaths as OBJ " ) ,
[ this ] ( wxCommandEvent & ) { if ( m_plater ! = nullptr ) m_plater - > export_toolpaths_to_obj ( ) ; } , " export_plater " , nullptr ,
[ this ] ( ) { return can_export_toolpaths ( ) ; } , this ) ;
append_menu_item ( fileMenu , wxID_ANY , _L ( " Open &PrusaSlicer " ) + dots , _L ( " Open PrusaSlicer " ) ,
[ ] ( wxCommandEvent & ) { start_new_slicer ( ) ; } , " " , nullptr ,
[ ] ( ) { return true ; } , this ) ;
fileMenu - > AppendSeparator ( ) ;
append_menu_item ( fileMenu , wxID_EXIT , _L ( " &Quit " ) , wxString : : Format ( _L ( " Quit %s " ) , SLIC3R_APP_NAME ) ,
[ this ] ( wxCommandEvent & ) { Close ( false ) ; } ) ;
}
// View menu
wxMenu * viewMenu = nullptr ;
if ( m_plater ! = nullptr ) {
viewMenu = new wxMenu ( ) ;
add_common_view_menu_items ( viewMenu , this , std : : bind ( & MainFrame : : can_change_view , this ) ) ;
}
// helpmenu
auto helpMenu = generate_help_menu ( ) ;
m_menubar = new wxMenuBar ( ) ;
m_menubar - > Append ( fileMenu , _L ( " &File " ) ) ;
if ( viewMenu ! = nullptr ) m_menubar - > Append ( viewMenu , _L ( " &View " ) ) ;
// Add additional menus from C++
wxGetApp ( ) . add_config_menu ( m_menubar ) ;
m_menubar - > Append ( helpMenu , _L ( " &Help " ) ) ;
SetMenuBar ( m_menubar ) ;
# ifdef __APPLE__
// This fixes a bug on Mac OS where the quit command doesn't emit window close events
// wx bug: https://trac.wxwidgets.org/ticket/18328
wxMenu * apple_menu = m_menubar - > OSXGetAppleMenu ( ) ;
if ( apple_menu ! = nullptr ) {
apple_menu - > Bind ( wxEVT_MENU , [ this ] ( wxCommandEvent & ) {
Close ( ) ;
} , wxID_EXIT ) ;
}
# endif // __APPLE__
# endif
}
void MainFrame : : update_menubar ( )
{
if ( wxGetApp ( ) . is_gcode_viewer ( ) )
return ;
const bool is_fff = plater ( ) - > printer_technology ( ) = = ptFFF ;
}
void MainFrame : : reslice_now ( )
{
if ( m_plater )
m_plater - > reslice ( ) ;
}
void MainFrame : : export_config ( )
{
// Generate a cummulative configuration for the selected print, filaments and printer.
auto config = wxGetApp ( ) . preset_bundle - > full_config ( ) ;
// Validate the cummulative configuration.
auto valid = config . validate ( ) ;
if ( ! valid . empty ( ) ) {
show_error ( this , valid ) ;
return ;
}
// Ask user for the file name for the config file.
wxFileDialog dlg ( this , _L ( " Save configuration as: " ) ,
! m_last_config . IsEmpty ( ) ? get_dir_name ( m_last_config ) : wxGetApp ( ) . app_config - > get_last_dir ( ) ,
! m_last_config . IsEmpty ( ) ? get_base_name ( m_last_config ) : " config.ini " ,
file_wildcards ( FT_INI ) , wxFD_SAVE | wxFD_OVERWRITE_PROMPT ) ;
wxString file ;
if ( dlg . ShowModal ( ) = = wxID_OK )
file = dlg . GetPath ( ) ;
if ( ! file . IsEmpty ( ) ) {
wxGetApp ( ) . app_config - > update_config_dir ( get_dir_name ( file ) ) ;
m_last_config = file ;
config . save ( file . ToUTF8 ( ) . data ( ) ) ;
}
}
// Load a config file containing a Print, Filament & Printer preset.
void MainFrame : : load_config_file ( )
{
//BBS do not load config file
// if (!wxGetApp().check_and_save_current_preset_changes(_L("Loading profile file"), "", false))
// return;
// wxFileDialog dlg(this, _L("Select profile to load:"),
// !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(),
// "config.json", "INI files (*.ini, *.gcode)|*.json;;*.gcode;*.g", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
// wxString file;
// if (dlg.ShowModal() == wxID_OK)
// file = dlg.GetPath();
// if (! file.IsEmpty() && this->load_config_file(file.ToUTF8().data())) {
// wxGetApp().app_config->update_config_dir(get_dir_name(file));
// m_last_config = file;
// }
}
// Load a config file containing a Print, Filament & Printer preset from command line.
bool MainFrame : : load_config_file ( const std : : string & path )
{
try {
ConfigSubstitutions config_substitutions = wxGetApp ( ) . preset_bundle - > load_config_file ( path , ForwardCompatibilitySubstitutionRule : : Enable ) ;
if ( ! config_substitutions . empty ( ) )
show_substitutions_info ( config_substitutions , path ) ;
} catch ( const std : : exception & ex ) {
show_error ( this , ex . what ( ) ) ;
return false ;
}
wxGetApp ( ) . load_current_presets ( ) ;
return true ;
}
//BBS: export current config bundle as BBL default reference
//void MainFrame::export_current_configbundle()
//{
// BBS do not export profile
// if (!wxGetApp().check_and_save_current_preset_changes(_L("Exporting current profile bundle"),
// _L("Some presets are modified and the unsaved changes will not be exported into profile bundle."), false, true))
// return;
// // validate current configuration in case it's dirty
// auto err = wxGetApp().preset_bundle->full_config().validate();
// if (! err.empty()) {
// show_error(this, err);
// return;
// }
// // Ask user for a file name.
// wxFileDialog dlg(this, _L("Save BBL Default bundle as:"),
// !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(),
// "BBL_config_bundle.ini",
// file_wildcards(FT_INI), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
// wxString file;
// if (dlg.ShowModal() == wxID_OK)
// file = dlg.GetPath();
// if (!file.IsEmpty()) {
// // Export the config bundle.
// wxGetApp().app_config->update_config_dir(get_dir_name(file));
// try {
// wxGetApp().preset_bundle->export_current_configbundle(file.ToUTF8().data());
// } catch (const std::exception &ex) {
//show_error(this, ex.what());
// }
// }
//}
//BBS: export all the system preset configs to seperate files
/*void MainFrame::export_system_configs()
{
// Ask user for a file name.
wxDirDialog dlg ( this , _L ( " choose a directory " ) ,
! m_last_config . IsEmpty ( ) ? get_dir_name ( m_last_config ) : wxGetApp ( ) . app_config - > get_last_dir ( ) , wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST ) ;
wxString path ;
if ( dlg . ShowModal ( ) = = wxID_OK )
path = dlg . GetPath ( ) ;
if ( ! path . IsEmpty ( ) ) {
// Export the config bundle.
wxGetApp ( ) . app_config - > update_config_dir ( path . ToStdString ( ) ) ;
try {
wxGetApp ( ) . preset_bundle - > export_system_configs ( path . ToUTF8 ( ) . data ( ) ) ;
} catch ( const std : : exception & ex ) {
show_error ( this , ex . what ( ) ) ;
}
}
} */
//void MainFrame::export_configbundle(bool export_physical_printers /*= false*/)
//{
//// ; //BBS do not export config bundle
//}
// Loading a config bundle with an external file name used to be used
// to auto - install a config bundle on a fresh user account,
// but that behavior was not documented and likely buggy.
//void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool reset_user_profile*/)
//{
// ; //BBS do not import config bundle
//}
// Load a provied DynamicConfig into the Print / Filament / Printer tabs, thus modifying the active preset.
// Also update the plater with the new presets.
void MainFrame : : load_config ( const DynamicPrintConfig & config )
{
PrinterTechnology printer_technology = wxGetApp ( ) . preset_bundle - > printers . get_edited_preset ( ) . printer_technology ( ) ;
const auto * opt_printer_technology = config . option < ConfigOptionEnum < PrinterTechnology > > ( " printer_technology " ) ;
if ( opt_printer_technology ! = nullptr & & opt_printer_technology - > value ! = printer_technology ) {
printer_technology = opt_printer_technology - > value ;
this - > plater ( ) - > set_printer_technology ( printer_technology ) ;
}
#if 0
for ( auto tab : wxGetApp ( ) . tabs_list )
if ( tab - > supports_printer_technology ( printer_technology ) ) {
if ( tab - > type ( ) = = Slic3r : : Preset : : TYPE_PRINTER )
static_cast < TabPrinter * > ( tab ) - > update_pages ( ) ;
tab - > load_config ( config ) ;
}
if ( m_plater )
m_plater - > on_config_change ( config ) ;
# else
// Load the currently selected preset into the GUI, update the preset selection box.
//FIXME this is not quite safe for multi-extruder printers,
// as the number of extruders is not adjusted for the vector values.
// (see PresetBundle::update_multi_material_filament_presets())
// Better to call PresetBundle::load_config() instead?
for ( auto tab : wxGetApp ( ) . tabs_list )
if ( tab - > supports_printer_technology ( printer_technology ) ) {
// Only apply keys, which are present in the tab's config. Ignore the other keys.
for ( const std : : string & opt_key : tab - > get_config ( ) - > diff ( config ) )
// Ignore print_settings_id, printer_settings_id, filament_settings_id etc.
if ( ! boost : : algorithm : : ends_with ( opt_key , " _settings_id " ) )
tab - > get_config ( ) - > option ( opt_key ) - > set ( config . option ( opt_key ) ) ;
}
wxGetApp ( ) . load_current_presets ( ) ;
# endif
}
//BBS: GUI refactor
void MainFrame : : select_tab ( wxPanel * panel )
{
if ( ! panel )
return ;
if ( panel = = m_param_panel ) {
panel = m_plater ;
} else if ( dynamic_cast < ParamsPanel * > ( panel ) ) {
wxGetApp ( ) . params_dialog ( ) - > Popup ( ) ;
return ;
}
int page_idx = m_tabpanel - > FindPage ( panel ) ;
if ( page_idx = = tp3DEditor & & m_tabpanel - > GetSelection ( ) = = tpPreview )
return ;
//BBS GUI refactor: remove unused layout new/dlg
/*if (page_idx != wxNOT_FOUND && m_layout == ESettingsLayout::Dlg)
page_idx + + ; */
select_tab ( size_t ( page_idx ) ) ;
}
//BBS
void MainFrame : : jump_to_monitor ( std : : string dev_id )
{
2022-07-22 09:46:10 +00:00
m_tabpanel - > SetSelection ( tpMonitor ) ;
2022-07-15 15:37:19 +00:00
( ( MonitorPanel * ) m_monitor ) - > select_machine ( dev_id ) ;
}
//BBS GUI refactor: remove unused layout new/dlg
void MainFrame : : select_tab ( size_t tab /* = size_t(-1)*/ )
{
//bool tabpanel_was_hidden = false;
// Controls on page are created on active page of active tab now.
// We should select/activate tab before its showing to avoid an UI-flickering
auto select = [ this , tab ] ( bool was_hidden ) {
// when tab == -1, it means we should show the last selected tab
//BBS GUI refactor: remove unused layout new/dlg
//size_t new_selection = tab == (size_t)(-1) ? m_last_selected_tab : (m_layout == ESettingsLayout::Dlg && tab != 0) ? tab - 1 : tab;
size_t new_selection = tab = = ( size_t ) ( - 1 ) ? m_last_selected_tab : tab ;
if ( m_tabpanel - > GetSelection ( ) ! = ( int ) new_selection )
m_tabpanel - > SetSelection ( new_selection ) ;
# ifdef _MSW_DARK_MODE
if ( wxGetApp ( ) . tabs_as_menu ( ) ) {
if ( Tab * cur_tab = dynamic_cast < Tab * > ( m_tabpanel - > GetPage ( new_selection ) ) )
update_marker_for_tabs_menu ( ( m_layout = = ESettingsLayout : : Old ? m_menubar : m_settings_dialog . menubar ( ) ) , cur_tab - > title ( ) , m_layout = = ESettingsLayout : : Old ) ;
else if ( tab = = 0 & & m_layout = = ESettingsLayout : : Old )
m_plater - > get_current_canvas3D ( ) - > render ( ) ;
}
# endif
if ( tab = = MainFrame : : tp3DEditor & & m_layout = = ESettingsLayout : : Old )
m_plater - > canvas3D ( ) - > render ( ) ;
else if ( was_hidden ) {
Tab * cur_tab = dynamic_cast < Tab * > ( m_tabpanel - > GetPage ( new_selection ) ) ;
if ( cur_tab )
cur_tab - > OnActivate ( ) ;
}
} ;
select ( false ) ;
}
void MainFrame : : request_select_tab ( TabPosition pos )
{
wxCommandEvent * evt = new wxCommandEvent ( EVT_SELECT_TAB ) ;
2022-07-22 09:46:10 +00:00
evt - > SetInt ( pos ) ;
2022-07-15 15:37:19 +00:00
wxQueueEvent ( this , evt ) ;
}
// Set a camera direction, zoom to all objects.
void MainFrame : : select_view ( const std : : string & direction )
{
if ( m_plater )
m_plater - > select_view ( direction ) ;
}
// #ys_FIXME_to_delete
void MainFrame : : on_presets_changed ( SimpleEvent & event )
{
auto * tab = dynamic_cast < Tab * > ( event . GetEventObject ( ) ) ;
wxASSERT ( tab ! = nullptr ) ;
if ( tab = = nullptr ) {
return ;
}
// Update preset combo boxes(Print settings, Filament, Material, Printer) from their respective tabs.
auto presets = tab - > get_presets ( ) ;
if ( m_plater ! = nullptr & & presets ! = nullptr ) {
// FIXME: The preset type really should be a property of Tab instead
Slic3r : : Preset : : Type preset_type = tab - > type ( ) ;
if ( preset_type = = Slic3r : : Preset : : TYPE_INVALID ) {
wxASSERT ( false ) ;
return ;
}
m_plater - > on_config_change ( * tab - > get_config ( ) ) ;
m_plater - > sidebar ( ) . update_presets ( preset_type ) ;
}
}
// #ys_FIXME_to_delete
void MainFrame : : on_value_changed ( wxCommandEvent & event )
{
auto * tab = dynamic_cast < Tab * > ( event . GetEventObject ( ) ) ;
wxASSERT ( tab ! = nullptr ) ;
if ( tab = = nullptr )
return ;
auto opt_key = event . GetString ( ) ;
if ( m_plater ) {
m_plater - > on_config_change ( * tab - > get_config ( ) ) ; // propagate config change events to the plater
if ( opt_key = = " extruders_count " ) {
auto value = event . GetInt ( ) ;
m_plater - > on_filaments_change ( value ) ;
}
}
}
void MainFrame : : on_config_changed ( DynamicPrintConfig * config ) const
{
if ( m_plater )
m_plater - > on_config_change ( * config ) ; // propagate config change events to the plater
}
void MainFrame : : add_to_recent_projects ( const wxString & filename )
{
if ( wxFileExists ( filename ) )
{
m_recent_projects . AddFileToHistory ( filename ) ;
std : : vector < std : : string > recent_projects ;
size_t count = m_recent_projects . GetCount ( ) ;
for ( size_t i = 0 ; i < count ; + + i )
{
recent_projects . push_back ( into_u8 ( m_recent_projects . GetHistoryFile ( i ) ) ) ;
}
wxGetApp ( ) . app_config - > set_recent_projects ( recent_projects ) ;
wxGetApp ( ) . app_config - > save ( ) ;
m_webview - > SendRecentList ( " " ) ;
}
}
std : : wstring MainFrame : : FileHistory : : GetThumbnailUrl ( int index ) const
{
if ( m_thumbnails [ index ] . empty ( ) ) return L " " ;
std : : wstringstream wss ;
wss < < L " data:image/png;base64, " ;
wss < < wxBase64Encode ( m_thumbnails [ index ] . data ( ) , m_thumbnails [ index ] . size ( ) ) ;
return wss . str ( ) ;
}
void MainFrame : : FileHistory : : AddFileToHistory ( const wxString & file )
{
wxFileHistory : : AddFileToHistory ( file ) ;
if ( m_load_called )
m_thumbnails . push_front ( bbs_3mf_get_thumbnail ( into_u8 ( file ) . c_str ( ) ) ) ;
else
m_thumbnails . push_front ( " " ) ;
}
void MainFrame : : FileHistory : : RemoveFileFromHistory ( size_t i )
{
wxFileHistory : : RemoveFileFromHistory ( i ) ;
m_thumbnails . erase ( m_thumbnails . begin ( ) + i ) ;
}
size_t MainFrame : : FileHistory : : FindFileInHistory ( const wxString & file )
{
return m_fileHistory . Index ( file ) ;
}
void MainFrame : : FileHistory : : LoadThumbnails ( )
{
tbb : : parallel_for ( tbb : : blocked_range < size_t > ( 0 , GetCount ( ) ) , [ this ] ( tbb : : blocked_range < size_t > range ) {
for ( size_t i = range . begin ( ) ; i < range . end ( ) ; + + i ) {
auto thumbnail = bbs_3mf_get_thumbnail ( into_u8 ( GetHistoryFile ( i ) ) . c_str ( ) ) ;
if ( ! thumbnail . empty ( ) ) {
m_thumbnails [ i ] = thumbnail ;
}
}
} ) ;
m_load_called = true ;
}
void MainFrame : : get_recent_projects ( boost : : property_tree : : wptree & tree )
{
for ( size_t i = 0 ; i < m_recent_projects . GetCount ( ) ; + + i ) {
boost : : property_tree : : wptree item ;
std : : wstring proj = m_recent_projects . GetHistoryFile ( i ) . ToStdWstring ( ) ;
item . put ( L " project_name " , proj . substr ( proj . find_last_of ( L " / \\ " ) + 1 ) ) ;
item . put ( L " path " , proj ) ;
boost : : system : : error_code ec ;
std : : time_t t = boost : : filesystem : : last_write_time ( proj , ec ) ;
if ( ! ec ) {
std : : wstring time = wxDateTime ( t ) . FormatISOCombined ( ' ' ) . ToStdWstring ( ) ;
item . put ( L " time " , time ) ;
auto thumbnail = m_recent_projects . GetThumbnailUrl ( i ) ;
if ( ! thumbnail . empty ( ) ) item . put ( L " image " , thumbnail ) ;
} else {
item . put ( L " time " , _L ( " File is missing " ) ) ;
}
tree . push_back ( { L " " , item } ) ;
}
}
void MainFrame : : open_recent_project ( size_t file_id , wxString const & filename )
{
if ( file_id = = size_t ( - 1 ) ) {
file_id = m_recent_projects . FindFileInHistory ( filename ) ;
}
if ( wxFileExists ( filename ) ) {
wxGetApp ( ) . CallAfter ( [ this , filename ] {
if ( wxGetApp ( ) . can_load_project ( ) )
m_plater - > load_project ( filename ) ;
} ) ;
}
else
{
MessageDialog msg ( this , _L ( " The project is no longer available. " ) , _L ( " Error " ) , wxYES | wxYES_DEFAULT ) ;
if ( msg . ShowModal ( ) = = wxID_YES )
{
m_recent_projects . RemoveFileFromHistory ( file_id ) ;
std : : vector < std : : string > recent_projects ;
size_t count = m_recent_projects . GetCount ( ) ;
for ( size_t i = 0 ; i < count ; + + i )
{
recent_projects . push_back ( into_u8 ( m_recent_projects . GetHistoryFile ( i ) ) ) ;
}
wxGetApp ( ) . app_config - > set_recent_projects ( recent_projects ) ;
wxGetApp ( ) . app_config - > save ( ) ;
m_webview - > SendRecentList ( " " ) ;
}
}
}
void MainFrame : : load_url ( wxString url )
{
BOOST_LOG_TRIVIAL ( trace ) < < " load_url: " < < url ;
auto evt = new wxCommandEvent ( EVT_LOAD_URL , this - > GetId ( ) ) ;
evt - > SetString ( url ) ;
wxQueueEvent ( this , evt ) ;
}
2022-07-22 09:46:10 +00:00
void MainFrame : : refresh_plugin_tips ( )
{
if ( m_webview ! = nullptr )
m_webview - > ShowNetpluginTip ( ) ;
}
2022-07-15 15:37:19 +00:00
void MainFrame : : RunScript ( wxString js )
{
if ( m_webview ! = nullptr )
m_webview - > RunScript ( js ) ;
}
void MainFrame : : technology_changed ( )
{
// upadte DiffDlg
diff_dialog . update_presets ( ) ;
// update menu titles
PrinterTechnology pt = plater ( ) - > printer_technology ( ) ;
if ( int id = m_menubar - > FindMenu ( pt = = ptFFF ? _omitL ( " Material Settings " ) : _L ( " Filament Settings " ) ) ; id ! = wxNOT_FOUND )
m_menubar - > SetMenuLabel ( id , pt = = ptSLA ? _omitL ( " Material Settings " ) : _L ( " Filament Settings " ) ) ;
}
//
// Called after the Preferences dialog is closed and the program settings are saved.
// Update the UI based on the current preferences.
void MainFrame : : update_ui_from_settings ( )
{
if ( m_plater )
m_plater - > update_ui_from_settings ( ) ;
for ( auto tab : wxGetApp ( ) . tabs_list )
tab - > update_ui_from_settings ( ) ;
}
void MainFrame : : show_sync_dialog ( )
{
SimpleEvent * evt = new SimpleEvent ( EVT_SYNC_CLOUD_PRESET ) ;
wxQueueEvent ( this , evt ) ;
}
void MainFrame : : update_side_preset_ui ( )
{
// select last preset
for ( auto tab : wxGetApp ( ) . tabs_list ) {
tab - > update_tab_ui ( ) ;
}
//BBS: update the preset
m_plater - > sidebar ( ) . update_presets ( Preset : : TYPE_PRINTER ) ;
m_plater - > sidebar ( ) . update_presets ( Preset : : TYPE_FILAMENT ) ;
}
void MainFrame : : on_select_default_preset ( SimpleEvent & evt )
{
MessageDialog dialog ( this ,
_L ( " Do you want to synchronize your personal data from Bambu Cloud? \n "
2022-07-22 09:46:10 +00:00
" It contains the following information: \n "
2022-07-15 15:37:19 +00:00
" 1. The Process presets \n "
" 2. The Filament presets \n "
" 3. The Printer presets \n " ) ,
_L ( " Synchronization " ) ,
wxCENTER |
wxYES_DEFAULT | wxYES_NO |
wxICON_INFORMATION ) ;
/* get setting list */
NetworkAgent * agent = wxGetApp ( ) . getAgent ( ) ;
switch ( dialog . ShowModal ( ) )
{
case wxID_YES : {
wxGetApp ( ) . app_config - > set_bool ( " sync_user_preset " , true ) ;
wxGetApp ( ) . start_sync_user_preset ( true ) ;
break ;
}
case wxID_NO :
wxGetApp ( ) . app_config - > set_bool ( " sync_user_preset " , false ) ;
wxGetApp ( ) . stop_sync_user_preset ( ) ;
break ;
default :
break ;
}
update_side_preset_ui ( ) ;
}
std : : string MainFrame : : get_base_name ( const wxString & full_name , const char * extension ) const
{
boost : : filesystem : : path filename = boost : : filesystem : : path ( full_name . wx_str ( ) ) . filename ( ) ;
if ( extension ! = nullptr )
filename = filename . replace_extension ( extension ) ;
return filename . string ( ) ;
}
std : : string MainFrame : : get_dir_name ( const wxString & full_name ) const
{
return boost : : filesystem : : path ( full_name . wx_str ( ) ) . parent_path ( ) . string ( ) ;
}
// ----------------------------------------------------------------------------
// SettingsDialog
// ----------------------------------------------------------------------------
SettingsDialog : : SettingsDialog ( MainFrame * mainframe )
: DPIFrame ( NULL , wxID_ANY , wxString ( SLIC3R_APP_NAME ) + " - " + _L ( " Settings " ) , wxDefaultPosition , wxDefaultSize , wxDEFAULT_FRAME_STYLE , " settings_dialog " ) ,
//: DPIDialog(mainframe, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Settings"), wxDefaultPosition, wxDefaultSize,
// wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX, "settings_dialog"),
m_main_frame ( mainframe )
{
if ( wxGetApp ( ) . is_gcode_viewer ( ) )
return ;
# if defined(__WXMSW__)
// ys_FIXME! temporary workaround for correct font scaling
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
this - > SetFont ( wxSystemSettings : : GetFont ( wxSYS_DEFAULT_GUI_FONT ) ) ;
# else
this - > SetFont ( wxGetApp ( ) . normal_font ( ) ) ;
this - > SetBackgroundColour ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_WINDOW ) ) ;
# endif // __WXMSW__
// Load the icon either from the exe, or from the ico file.
# if _WIN32
{
TCHAR szExeFileName [ MAX_PATH ] ;
GetModuleFileName ( nullptr , szExeFileName , MAX_PATH ) ;
SetIcon ( wxIcon ( szExeFileName , wxBITMAP_TYPE_ICO ) ) ;
}
# else
SetIcon ( wxIcon ( var ( " BambuStudio_128px.png " ) , wxBITMAP_TYPE_PNG ) ) ;
# endif // _WIN32
//just hide the Frame on closing
this - > Bind ( wxEVT_CLOSE_WINDOW , [ this ] ( wxCloseEvent & evt ) { this - > Hide ( ) ; } ) ;
# ifdef _MSW_DARK_MODE
if ( wxGetApp ( ) . tabs_as_menu ( ) ) {
// menubar
m_menubar = new wxMenuBar ( ) ;
add_tabs_as_menu ( m_menubar , mainframe , this ) ;
this - > SetMenuBar ( m_menubar ) ;
}
# endif
// initialize layout
auto sizer = new wxBoxSizer ( wxVERTICAL ) ;
sizer - > SetSizeHints ( this ) ;
SetSizer ( sizer ) ;
Fit ( ) ;
const wxSize min_size = wxSize ( 85 * em_unit ( ) , 50 * em_unit ( ) ) ;
# ifdef __APPLE__
// Using SetMinSize() on Mac messes up the window position in some cases
// cf. https://groups.google.com/forum/#!topic/wx-users/yUKPBBfXWO0
SetSize ( min_size ) ;
# else
SetMinSize ( min_size ) ;
SetSize ( GetMinSize ( ) ) ;
# endif
Layout ( ) ;
}
void SettingsDialog : : on_dpi_changed ( const wxRect & suggested_rect )
{
if ( wxGetApp ( ) . is_gcode_viewer ( ) )
return ;
const int & em = em_unit ( ) ;
const wxSize & size = wxSize ( 85 * em , 50 * em ) ;
// BBS
m_tabpanel - > Rescale ( ) ;
// update Tabs
for ( auto tab : wxGetApp ( ) . tabs_list )
tab - > msw_rescale ( ) ;
SetMinSize ( size ) ;
Fit ( ) ;
Refresh ( ) ;
}
} // GUI
} // Slic3r