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