1 #ifndef slic3r_GUI_App_hpp_ 2 #define slic3r_GUI_App_hpp_ 3 4 #include <memory> 5 #include <string> 6 #include "ImGuiWrapper.hpp" 7 #include "ConfigWizard.hpp" 8 #include "OpenGLManager.hpp" 9 #include "libslic3r/Preset.hpp" 10 11 #include <wx/app.h> 12 #include <wx/colour.h> 13 #include <wx/font.h> 14 #include <wx/string.h> 15 #include <wx/snglinst.h> 16 17 #include <mutex> 18 #include <stack> 19 20 class wxMenuItem; 21 class wxMenuBar; 22 class wxTopLevelWindow; 23 class wxNotebook; 24 struct wxLanguageInfo; 25 26 namespace Slic3r { 27 28 class AppConfig; 29 class PresetBundle; 30 class PresetUpdater; 31 class ModelObject; 32 class PrintHostJobQueue; 33 class Model; 34 35 namespace GUI{ 36 37 class RemovableDriveManager; 38 class OtherInstanceMessageHandler; 39 class MainFrame; 40 class Sidebar; 41 class ObjectManipulation; 42 class ObjectSettings; 43 class ObjectList; 44 class ObjectLayers; 45 class Plater; 46 struct GUI_InitParams; 47 48 49 50 enum FileType 51 { 52 FT_STL, 53 FT_OBJ, 54 FT_AMF, 55 FT_3MF, 56 FT_PRUSA, 57 FT_GCODE, 58 FT_MODEL, 59 FT_PROJECT, 60 61 FT_INI, 62 FT_SVG, 63 64 FT_TEX, 65 66 FT_SL1, 67 // Workaround for OSX file picker, for some reason it always saves with the 1st extension. 68 FT_SL1S, 69 70 FT_SIZE, 71 }; 72 73 extern wxString file_wildcards(FileType file_type, const std::string &custom_extension = std::string()); 74 75 enum ConfigMenuIDs { 76 ConfigMenuWizard, 77 ConfigMenuSnapshots, 78 ConfigMenuTakeSnapshot, 79 ConfigMenuUpdate, 80 ConfigMenuPreferences, 81 ConfigMenuModeSimple, 82 ConfigMenuModeAdvanced, 83 ConfigMenuModeExpert, 84 ConfigMenuLanguage, 85 ConfigMenuFlashFirmware, 86 ConfigMenuCnt, 87 }; 88 89 class Tab; 90 class ConfigWizard; 91 92 static wxString dots("…", wxConvUTF8); 93 94 // Does our wxWidgets version support markup? 95 // https://github.com/prusa3d/PrusaSlicer/issues/4282#issuecomment-634676371 96 #if wxUSE_MARKUP && wxCHECK_VERSION(3, 1, 1) 97 #define SUPPORTS_MARKUP 98 #endif 99 100 class GUI_App : public wxApp 101 { 102 public: 103 enum class EAppMode : unsigned char 104 { 105 Editor, 106 GCodeViewer 107 }; 108 109 private: 110 bool m_initialized { false }; 111 bool m_app_conf_exists{ false }; 112 EAppMode m_app_mode{ EAppMode::Editor }; 113 bool m_is_recreating_gui{ false }; 114 #ifdef __linux__ 115 bool m_opengl_initialized{ false }; 116 #endif 117 118 wxColour m_color_label_modified; 119 wxColour m_color_label_sys; 120 wxColour m_color_label_default; 121 122 wxFont m_small_font; 123 wxFont m_bold_font; 124 wxFont m_normal_font; 125 wxFont m_code_font; 126 127 int m_em_unit; // width of a "m"-symbol in pixels for current system font 128 // Note: for 100% Scale m_em_unit = 10 -> it's a good enough coefficient for a size setting of controls 129 130 std::unique_ptr<wxLocale> m_wxLocale; 131 // System language, from locales, owned by wxWidgets. 132 const wxLanguageInfo *m_language_info_system = nullptr; 133 // Best translation language, provided by Windows or OSX, owned by wxWidgets. 134 const wxLanguageInfo *m_language_info_best = nullptr; 135 136 OpenGLManager m_opengl_mgr; 137 138 std::unique_ptr<RemovableDriveManager> m_removable_drive_manager; 139 140 std::unique_ptr<ImGuiWrapper> m_imgui; 141 std::unique_ptr<PrintHostJobQueue> m_printhost_job_queue; 142 ConfigWizard* m_wizard; // Managed by wxWindow tree 143 std::unique_ptr <OtherInstanceMessageHandler> m_other_instance_message_handler; 144 std::unique_ptr <wxSingleInstanceChecker> m_single_instance_checker; 145 std::string m_instance_hash_string; 146 size_t m_instance_hash_int; 147 148 public: 149 bool OnInit() override; initialized() const150 bool initialized() const { return m_initialized; } 151 152 explicit GUI_App(EAppMode mode = EAppMode::Editor); 153 ~GUI_App() override; 154 get_app_mode() const155 EAppMode get_app_mode() const { return m_app_mode; } is_editor() const156 bool is_editor() const { return m_app_mode == EAppMode::Editor; } is_gcode_viewer() const157 bool is_gcode_viewer() const { return m_app_mode == EAppMode::GCodeViewer; } is_recreating_gui() const158 bool is_recreating_gui() const { return m_is_recreating_gui; } 159 160 // To be called after the GUI is fully built up. 161 // Process command line parameters cached in this->init_params, 162 // load configs, STLs etc. 163 void post_init(); 164 static std::string get_gl_info(bool format_as_html, bool extensions); 165 wxGLContext* init_glcontext(wxGLCanvas& canvas); 166 bool init_opengl(); 167 168 static unsigned get_colour_approx_luma(const wxColour &colour); 169 static bool dark_mode(); 170 void init_label_colours(); 171 void update_label_colours_from_appconfig(); 172 void init_fonts(); 173 void update_fonts(const MainFrame *main_frame = nullptr); 174 void set_label_clr_modified(const wxColour& clr); 175 void set_label_clr_sys(const wxColour& clr); 176 get_label_clr_modified()177 const wxColour& get_label_clr_modified(){ return m_color_label_modified; } get_label_clr_sys()178 const wxColour& get_label_clr_sys() { return m_color_label_sys; } get_label_clr_default()179 const wxColour& get_label_clr_default() { return m_color_label_default; } 180 small_font()181 const wxFont& small_font() { return m_small_font; } bold_font()182 const wxFont& bold_font() { return m_bold_font; } normal_font()183 const wxFont& normal_font() { return m_normal_font; } code_font()184 const wxFont& code_font() { return m_code_font; } em_unit() const185 int em_unit() const { return m_em_unit; } 186 wxSize get_min_size() const; 187 float toolbar_icon_scale(const bool is_limited = false) const; 188 void set_auto_toolbar_icon_scale(float scale) const; 189 void check_printer_presets(); 190 191 void recreate_GUI(const wxString& message); 192 void system_info(); 193 void keyboard_shortcuts(); 194 void load_project(wxWindow *parent, wxString& input_file) const; 195 void import_model(wxWindow *parent, wxArrayString& input_files) const; 196 void load_gcode(wxWindow* parent, wxString& input_file) const; 197 198 static bool catch_error(std::function<void()> cb, const std::string& err); 199 200 void persist_window_geometry(wxTopLevelWindow *window, bool default_maximized = false); 201 void update_ui_from_settings(bool apply_free_camera_correction = true); 202 203 bool switch_language(); 204 bool load_language(wxString language, bool initial); 205 206 Tab* get_tab(Preset::Type type); 207 ConfigOptionMode get_mode(); 208 void save_mode(const /*ConfigOptionMode*/int mode) ; 209 void update_mode(); 210 211 void add_config_menu(wxMenuBar *menu); 212 bool check_unsaved_changes(const wxString &header = wxString()); 213 bool check_print_host_queue(); 214 bool checked_tab(Tab* tab); 215 void load_current_presets(bool check_printer_presets = true); 216 void update_wizard_from_config(); 217 current_language_code() const218 wxString current_language_code() const { return m_wxLocale->GetCanonicalName(); } 219 // Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US". 220 wxString current_language_code_safe() const; is_localized() const221 bool is_localized() const { return m_wxLocale->GetLocale() != "English"; } 222 223 virtual bool OnExceptionInMainLoop() override; 224 225 #ifdef __APPLE__ 226 void OSXStoreOpenFiles(const wxArrayString &files) override; 227 // wxWidgets override to get an event on open files. 228 void MacOpenFiles(const wxArrayString &fileNames) override; 229 #endif /* __APPLE */ 230 231 Sidebar& sidebar(); 232 ObjectManipulation* obj_manipul(); 233 ObjectSettings* obj_settings(); 234 ObjectList* obj_list(); 235 ObjectLayers* obj_layers(); 236 Plater* plater(); 237 Model& model(); 238 239 240 // Parameters extracted from the command line to be passed to GUI after initialization. 241 GUI_InitParams* init_params { nullptr }; 242 243 AppConfig* app_config{ nullptr }; 244 PresetBundle* preset_bundle{ nullptr }; 245 PresetUpdater* preset_updater{ nullptr }; 246 MainFrame* mainframe{ nullptr }; 247 Plater* plater_{ nullptr }; 248 get_preset_updater()249 PresetUpdater* get_preset_updater() { return preset_updater; } 250 251 wxNotebook* tab_panel() const ; 252 int extruders_cnt() const; 253 int extruders_edited_cnt() const; 254 255 std::vector<Tab *> tabs_list; 256 removable_drive_manager()257 RemovableDriveManager* removable_drive_manager() { return m_removable_drive_manager.get(); } other_instance_message_handler()258 OtherInstanceMessageHandler* other_instance_message_handler() { return m_other_instance_message_handler.get(); } single_instance_checker()259 wxSingleInstanceChecker* single_instance_checker() {return m_single_instance_checker.get();} 260 261 void init_single_instance_checker(const std::string &name, const std::string &path); set_instance_hash(const size_t hash)262 void set_instance_hash (const size_t hash) { m_instance_hash_int = hash; m_instance_hash_string = std::to_string(hash); } get_instance_hash_string()263 std::string get_instance_hash_string () { return m_instance_hash_string; } get_instance_hash_int()264 size_t get_instance_hash_int () { return m_instance_hash_int; } 265 imgui()266 ImGuiWrapper* imgui() { return m_imgui.get(); } 267 printhost_job_queue()268 PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); } 269 270 void open_web_page_localized(const std::string &http_address); 271 bool run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page = ConfigWizard::SP_WELCOME); 272 273 #if ENABLE_THUMBNAIL_GENERATOR_DEBUG 274 // temporary and debug only -> extract thumbnails from selected gcode and save them as png files 275 void gcode_thumbnails_debug(); 276 #endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG 277 get_shader(const std::string & shader_name)278 GLShaderProgram* get_shader(const std::string& shader_name) { return m_opengl_mgr.get_shader(shader_name); } get_current_shader()279 GLShaderProgram* get_current_shader() { return m_opengl_mgr.get_current_shader(); } 280 is_gl_version_greater_or_equal_to(unsigned int major,unsigned int minor) const281 bool is_gl_version_greater_or_equal_to(unsigned int major, unsigned int minor) const { return m_opengl_mgr.get_gl_info().is_version_greater_or_equal_to(major, minor); } is_glsl_version_greater_or_equal_to(unsigned int major,unsigned int minor) const282 bool is_glsl_version_greater_or_equal_to(unsigned int major, unsigned int minor) const { return m_opengl_mgr.get_gl_info().is_glsl_version_greater_or_equal_to(major, minor); } 283 284 #if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN 285 #ifdef __WXMSW__ 286 void associate_3mf_files(); 287 void associate_stl_files(); 288 void associate_gcode_files(); 289 #endif // __WXMSW__ 290 #endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN 291 292 private: 293 bool on_init_inner(); 294 void init_app_config(); 295 void window_pos_save(wxTopLevelWindow* window, const std::string &name); 296 void window_pos_restore(wxTopLevelWindow* window, const std::string &name, bool default_maximized = false); 297 void window_pos_sanitize(wxTopLevelWindow* window); 298 bool select_language(); 299 300 bool config_wizard_startup(); 301 void check_updates(const bool verbose); 302 303 #if !ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN 304 #ifdef __WXMSW__ 305 void associate_3mf_files(); 306 void associate_gcode_files(); 307 #endif // __WXMSW__ 308 #endif // !ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN 309 }; 310 311 DECLARE_APP(GUI_App) 312 313 } // GUI 314 } // Slic3r 315 316 #endif // slic3r_GUI_App_hpp_ 317