1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
|
#ifndef slic3r_Tab_hpp_
#define slic3r_Tab_hpp_
// The "Expert" tab at the right of the main tabbed window.
//
// This file implements following packages:
// Slic3r::GUI::Tab;
// Slic3r::GUI::Tab::Print;
// Slic3r::GUI::Tab::Filament;
// Slic3r::GUI::Tab::Printer;
// Slic3r::GUI::Tab::Page
// - Option page: For example, the Slic3r::GUI::Tab::Print has option pages "Layers and perimeters", "Infill", "Skirt and brim" ...
// Slic3r::GUI::SavePresetWindow
// - Dialog to select a new preset name to store the configuration.
// Slic3r::GUI::Tab::Preset;
// - Single preset item: name, file is default or external.
#include <wx/panel.h>
#include <wx/notebook.h>
#include <wx/listbook.h>
#include <wx/scrolwin.h>
#include <wx/sizer.h>
#include <wx/bmpcbox.h>
#include <wx/bmpbuttn.h>
#include <wx/treectrl.h>
#include <wx/imaglist.h>
#include <map>
#include <vector>
#include <memory>
#include "BedShapeDialog.hpp"
#include "ButtonsDescription.hpp"
#include "Event.hpp"
#include "wxExtensions.hpp"
#include "GUI_Tags.hpp"
#include "ConfigManipulation.hpp"
#include "OptionsGroup.hpp"
#include "ScriptExecutor.hpp"
#include "libslic3r/Preset.hpp"
namespace Slic3r {
namespace GUI {
class TabPresetComboBox;
class OG_CustomCtrl;
// G-code substitutions
// Substitution Manager - helper for manipuation of the substitutions
class SubstitutionManager
{
DynamicPrintConfig* m_config{ nullptr };
wxWindow* m_parent{ nullptr };
wxFlexGridSizer* m_grid_sizer{ nullptr };
int m_em{10};
std::function<void()> m_cb_edited_substitution{ nullptr };
std::function<void()> m_cb_hide_delete_all_btn{ nullptr };
void validate_lenth();
bool is_compatibile_with_ui();
bool is_valid_id(int substitution_id, const wxString& message);
public:
SubstitutionManager() = default;
~SubstitutionManager() = default;
void init(DynamicPrintConfig* config, wxWindow* parent, wxFlexGridSizer* grid_sizer);
void create_legend();
void delete_substitution(int substitution_id);
void add_substitution( int substitution_id = -1,
const std::string& plain_pattern = std::string(),
const std::string& format = std::string(),
const std::string& params = std::string(),
const std::string& notes = std::string());
void update_from_config();
void delete_all();
void edit_substitution(int substitution_id,
int opt_pos, // option position insubstitution [0, 2]
const std::string& value);
void set_cb_edited_substitution(std::function<void()> cb_edited_substitution) {
m_cb_edited_substitution = cb_edited_substitution;
}
void call_ui_update() {
if (m_cb_edited_substitution)
m_cb_edited_substitution();
}
void set_cb_hide_delete_all_btn(std::function<void()> cb_hide_delete_all_btn) {
m_cb_hide_delete_all_btn = cb_hide_delete_all_btn;
}
void hide_delete_all_btn() {
if (m_cb_hide_delete_all_btn)
m_cb_hide_delete_all_btn();
}
bool is_empty_substitutions();
};
// Single Tab page containing a{ vsizer } of{ optgroups }
// package Slic3r::GUI::Tab::Page;
using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>;
class Page// : public wxScrolledWindow
{
wxWindow* m_parent;
wxString m_title;
size_t m_iconID;
wxBoxSizer* m_vsizer;
bool m_show = true;
public:
Page(wxWindow* parent, const wxString& title, int iconID);
~Page() {}
bool m_is_modified_values{ false };
bool m_is_nonsys_values{ true };
std::vector<std::string> descriptions;
public:
std::vector <ConfigOptionsGroupShp> m_optgroups;
DynamicPrintConfig* m_config;
wxBoxSizer* vsizer() const { return m_vsizer; }
wxWindow* parent() const { return m_parent; }
const wxString& title() const { return m_title; }
size_t iconID() const { return m_iconID; }
void set_config(DynamicPrintConfig* config_in) { m_config = config_in; }
void reload_config();
void update_script_presets();
void update_visibility(ConfigOptionMode mode, bool update_contolls_visibility);
void activate(ConfigOptionMode mode, std::function<void()> throw_if_canceled);
void clear();
void msw_rescale();
void sys_color_changed();
void refresh();
Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const;
bool set_value(const t_config_option_key& opt_key, const boost::any& value);
ConfigOptionsGroupShp new_optgroup(const wxString& title, bool no_title = false);
const ConfigOptionsGroupShp get_optgroup(const wxString& title) const;
bool set_item_colour(const wxColour *clr) {
if (m_item_color != clr) {
m_item_color = clr;
return true;
}
return false;
}
const wxColour get_item_colour() {
return *m_item_color;
}
bool get_show() const { return m_show; }
protected:
// Color of TreeCtrlItem. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
const wxColour* m_item_color;
};
using PageShp = std::shared_ptr<Page>;
class Tab: public wxPanel
{
wxBookCtrlBase* m_parent;
#ifdef __WXOSX__
wxPanel* m_tmp_panel;
int m_size_move = -1;
#endif // __WXOSX__
protected:
Preset::Type m_type;
std::string m_name;
const wxString m_title;
TabPresetComboBox* m_presets_choice;
ScalableButton* m_search_btn;
ScalableButton* m_btn_compare_preset;
ScalableButton* m_btn_save_preset;
ScalableButton* m_btn_delete_preset;
ScalableButton* m_btn_edit_ph_printer {nullptr};
ScalableButton* m_btn_hide_incompatible_presets;
wxBoxSizer* m_hsizer;
wxBoxSizer* m_left_sizer;
wxTreeCtrl* m_treectrl;
wxImageList* m_icons;
wxScrolledWindow* m_page_view {nullptr};
wxBoxSizer* m_page_sizer {nullptr};
ModeSizer* m_mode_sizer {nullptr};
struct PresetDependencies {
Preset::Type type = Preset::TYPE_INVALID;
wxCheckBox *checkbox = nullptr;
ScalableButton *btn = nullptr;
std::string key_list; // "compatible_printers"
std::string key_condition;
wxString dialog_title;
wxString dialog_label;
};
PresetDependencies m_compatible_printers;
PresetDependencies m_compatible_prints;
/* Indicates, that default preset or preset inherited from default is selected
* This value is used for a options color updating
* (use green color only for options, which values are equal to system values)
*/
bool m_is_default_preset {false};
ScalableButton* m_undo_btn;
ScalableButton* m_undo_to_sys_btn;
ScalableButton* m_question_btn;
// Cached bitmaps.
// A "flag" icon to be displayned next to the preset name in the Tab's combo box.
ScalableBitmap m_bmp_show_incompatible_presets;
ScalableBitmap m_bmp_hide_incompatible_presets;
// Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
ScalableBitmap m_bmp_value_lock;
ScalableBitmap m_bmp_value_unlock;
ScalableBitmap m_bmp_white_bullet;
// The following bitmap points to either m_bmp_value_unlock or m_bmp_white_bullet, depending on whether the current preset has a parent preset.
ScalableBitmap *m_bmp_non_system;
// Bitmaps to be shown on the "Undo user changes" button next to each input field.
ScalableBitmap m_bmp_value_revert;
std::vector<ScalableButton*> m_scaled_buttons = {};
std::vector<ScalableBitmap*> m_scaled_bitmaps = {};
std::vector<ScalableBitmap> m_scaled_icons_list = {};
// Colors for ui "decoration"
wxColour m_sys_label_clr;
wxColour m_modified_label_clr;
wxColour m_default_label_clr;
wxColour m_phony_label_clr;
// Tooltip text for reset buttons (for whole options group)
wxString m_ttg_value_lock;
wxString m_ttg_value_unlock;
wxString m_ttg_white_bullet_ns;
// The following text points to either m_ttg_value_unlock or m_ttg_white_bullet_ns, depending on whether the current preset has a parent preset.
wxString *m_ttg_non_system;
// Tooltip text to be shown on the "Undo user changes" button next to each input field.
wxString m_ttg_white_bullet;
wxString m_ttg_value_revert;
// Tooltip text for reset buttons (for each option in group)
wxString m_tt_value_lock;
wxString m_tt_value_unlock;
// The following text points to either m_tt_value_unlock or m_ttg_white_bullet_ns, depending on whether the current preset has a parent preset.
wxString *m_tt_non_system;
// Tooltip text to be shown on the "Undo user changes" button next to each input field.
wxString m_tt_white_bullet;
wxString m_tt_value_revert;
// Tooltip for script reset icon/button
wxString m_tt_value_lock_script;
wxString m_tt_value_unlock_script;
wxString m_tt_white_bullet_script;
wxString m_tt_value_revert_script;
wxString *m_tt_non_system_script;
int m_icon_count;
std::map<std::string, size_t> m_icon_index; // Map from an icon file name to its index
std::map<wxString, std::string> m_category_icon; // Map from a category name to an icon file name
std::vector<PageShp> m_pages;
Page* m_active_page {nullptr};
bool m_disable_tree_sel_changed_event {false};
bool m_show_incompatible_presets;
ScriptContainer m_script_exec;
std::unordered_map<std::string, std::vector<std::string>> deps_id_2_script_ids;
std::vector<Preset::Type> m_dependent_tabs;
enum OptStatus {
osSystemValue = 1,
osInitValue = 2,
osSystemPhony = 4,
osInitPhony = 8,
osCurrentPhony = 16,
};
std::map<std::string, int> m_options_list;
std::map<std::string, int> m_options_script;
std::vector<std::string> m_options_dirty;
int m_opt_status_value = 0;
std::vector<ButtonsDescription::Entry> m_icon_descriptions = {};
bool m_is_modified_values{ false };
bool m_is_nonsys_values{ true };
bool m_postpone_update_ui {false};
void set_type();
int m_em_unit;
// To avoid actions with no-completed Tab
bool m_completed { false };
ConfigOptionMode m_mode = comExpert; // to correct first Tab update_visibility() set mode to Expert
struct Highlighter
{
void set_timer_owner(wxEvtHandler* owner, int timerid = wxID_ANY);
void init(std::pair<OG_CustomCtrl*, bool*>);
void blink();
void invalidate();
private:
OG_CustomCtrl* m_custom_ctrl {nullptr};
bool* m_show_blink_ptr{nullptr};
int m_blink_counter {0};
wxTimer m_timer;
}
m_highlighter;
DynamicPrintConfig m_cache_config;
bool m_page_switch_running = false;
bool m_page_switch_planned = false;
public:
PresetBundle* m_preset_bundle;
bool m_show_btn_incompatible_presets = false;
PresetCollection* m_presets = nullptr;
DynamicPrintConfig* m_config;
ogStaticText* m_parent_preset_description_line = nullptr;
ScalableButton* m_detach_preset_btn = nullptr;
// map of option name -> wxColour (color of the colored label, associated with option)
// Used for options which don't have corresponded field
std::map<std::string, wxColour> m_colored_Label_colors;
// Counter for the updating (because of an update() function can have a recursive behavior):
// 1. increase value from the very beginning of an update() function
// 2. decrease value at the end of an update() function
// 3. propagate changed configuration to the Plater when (m_update_cnt == 0) only
int m_update_cnt = 0;
public:
Tab(wxBookCtrlBase* parent, const wxString& title, Preset::Type type);
~Tab() {}
wxWindow* parent() const { return m_parent; }
wxString title() const { return m_title; }
std::string name() const { return m_presets->name(); }
Preset::Type type() const { return m_type; }
// The tab is already constructed.
bool completed() const { return m_completed; }
virtual bool supports_printer_technology(const PrinterTechnology tech) const = 0;
void create_preset_tab();
void add_scaled_button(wxWindow* parent, ScalableButton** btn, const std::string& icon_name,
const wxString& label = wxEmptyString,
long style = wxBU_EXACTFIT | wxNO_BORDER);
void add_scaled_bitmap(wxWindow* parent, ScalableBitmap& btn, const std::string& icon_name);
void update_ui_items_related_on_parent_preset(const Preset* selected_preset_parent);
void load_current_preset();
void rebuild_page_tree();
void update_btns_enabling();
void update_preset_choice();
// Select a new preset, possibly delete the current one.
void select_preset(std::string preset_name = "", bool delete_current = false, const std::string& last_selected_ph_printer_name = "");
bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = "");
virtual void clear_pages();
virtual void update_description_lines();
virtual void activate_selected_page(std::function<void()> throw_if_canceled);
void OnTreeSelChange(wxTreeEvent& event);
void OnKeyDown(wxKeyEvent& event);
void compare_preset();
void save_preset(std::string name = std::string(), bool detach = false);
void delete_preset();
void toggle_show_hide_incompatible();
void update_show_hide_incompatible_button();
void update_ui_from_settings();
void update_label_colours();
void decorate();
void update_changed_ui();
void get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page);
void update_changed_tree_ui();
void update_undo_buttons();
void on_roll_back_value(const bool to_sys = false);
PageShp add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages = false);
static wxString translate_category(const wxString& title, Preset::Type preset_type);
virtual void OnActivate();
virtual void on_preset_loaded() {}
virtual void build() = 0;
virtual void update() = 0;
virtual void toggle_options() = 0;
virtual void init_options_list();
void load_initial_data();
void add_dirty_setting(const std::string& opt_key);
void update_dirty();
void update_tab_ui();
void load_config(const DynamicPrintConfig& config);
virtual void reload_config();
void update_mode();
void update_visibility();
virtual void msw_rescale();
virtual void sys_color_changed();
size_t get_page_count() { return m_pages.size(); }
PageShp get_page(size_t idx) { return m_pages[idx]; }
Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const;
std::pair<OG_CustomCtrl*, bool*> get_custom_ctrl_with_blinking_ptr(const t_config_option_key& opt_key, int opt_index = -1);
Field* get_field(Page*& selected_page, const t_config_option_key &opt_key, int opt_index = -1);
void toggle_option(const std::string& opt_key, bool toggle, int opt_index = -1);
wxSizer* description_line_widget(wxWindow* parent, ogStaticText** StaticText, wxString text = wxEmptyString);
bool current_preset_is_dirty() const;
bool saved_preset_is_dirty() const;
void update_saved_preset_from_current_preset();
DynamicPrintConfig* get_config() { return m_config; }
PresetCollection* get_presets() { return m_presets; }
const PresetCollection* get_presets() const { return m_presets; }
bool set_value(const t_config_option_key& opt_key, const boost::any& value);
void on_value_change(const std::string& opt_key, const boost::any& value);
void update_wiping_button_visibility();
void activate_option(const std::string& opt_key, const wxString& category);
void apply_searcher();
void cache_config_diff(const std::vector<std::string>& selected_options);
void apply_config_from_cache();
const std::map<wxString, std::string>& get_category_icon_map() { return m_category_icon; }
static bool validate_custom_gcode(const wxString& title, const std::string& gcode);
bool validate_custom_gcodes_was_shown{ false };
protected:
void create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, const std::string& path, widget_t widget);
wxSizer* compatible_widget_create(wxWindow* parent, PresetDependencies &deps);
void compatible_widget_reload(PresetDependencies &deps);
void load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value = false);
// return true if cancelled
bool tree_sel_change_delayed();
void on_presets_changed();
void build_preset_description_line(ConfigOptionsGroup* optgroup);
void update_preset_description_line();
void update_frequently_changed_parameters();
void update_script_presets();
void fill_icon_descriptions();
void set_tooltips_text();
bool create_pages(std::string setting_type_name, int idx = -1);
ConfigManipulation m_config_manipulation;
ConfigManipulation get_config_manipulation();
};
class TabPrint : public Tab
{
public:
TabPrint(wxBookCtrlBase* parent) :
Tab(parent, _(L("Print Settings")), Slic3r::Preset::TYPE_FFF_PRINT) {}
~TabPrint() {}
void build() override;
void reload_config() override;
void update_description_lines() override;
void toggle_options() override;
void update() override;
void clear_pages() override;
bool supports_printer_technology(const PrinterTechnology tech) const override { return tech == ptFFF; }
wxSizer* create_manage_substitution_widget(wxWindow* parent);
wxSizer* create_substitutions_widget(wxWindow* parent);
ogStaticText* m_recommended_thin_wall_thickness_description_line = nullptr;
ogStaticText* m_recommended_extrusion_width_description_line = nullptr;
ogStaticText* m_top_bottom_shell_thickness_explanation = nullptr;
ogStaticText* m_post_process_explanation = nullptr;
ScalableButton* m_del_all_substitutions_btn{nullptr};
SubstitutionManager m_subst_manager;
};
class TabFilament : public Tab
{
public:
ogStaticText* m_volumetric_speed_description_line {nullptr};
ogStaticText* m_cooling_description_line {nullptr};
ogStaticText* m_machine_limits_descr {nullptr};
void add_filament_overrides_page();
protected:
void update_filament_overrides_page();
void update_volumetric_flow_preset_hints();
std::map<std::string, wxCheckBox*> m_overrides_options;
public:
TabFilament(wxBookCtrlBase* parent) :
Tab(parent, _(L("Filament Settings")), Slic3r::Preset::TYPE_FFF_FILAMENT) {}
~TabFilament() {}
void build() override;
void reload_config() override;
void update_description_lines() override;
void toggle_options() override;
void update() override;
void clear_pages() override;
bool supports_printer_technology(const PrinterTechnology tech) const override { return tech == ptFFF; }
};
class TabPrinter : public Tab
{
ogStaticText* m_machine_limits_description_line {nullptr};
void update_machine_limits_description(const MachineLimitsUsage usage);
std::vector<PageShp> m_pages_fff;
std::vector<PageShp> m_pages_sla;
public:
ogStaticText* m_fff_print_host_upload_description_line{ nullptr };
ogStaticText* m_sla_print_host_upload_description_line{ nullptr };
// void build_printhost(ConfigOptionsGroup *optgroup);
bool m_has_single_extruder_MM_page = false;
uint8_t m_last_gcode_flavor = uint8_t(255);
bool m_use_silent_mode = false;
bool m_supports_travel_acceleration = false;
bool m_supports_min_feedrates = false;
void append_option_line_kinematics(ConfigOptionsGroupShp optgroup, const std::string opt_key, const std::string override_units = "");
bool m_rebuild_kinematics_page = false;
ScalableButton* m_reset_to_filament_color = nullptr;
size_t m_extruders_count = 0;
size_t m_extruders_count_old = 0;
size_t m_initial_extruders_count = 0;
size_t m_sys_extruders_count = 0;
size_t m_cache_extruder_count = 0;
size_t m_milling_count = 0;
size_t m_milling_count_old = 0;
size_t m_initial_milling_count;
size_t m_sys_milling_count = 0;
size_t m_cache_milling_count = 0;
PrinterTechnology m_printer_technology = ptFFF;
TabPrinter(wxBookCtrlBase* parent) :
Tab(parent, _L("Printer Settings"), Slic3r::Preset::TYPE_PRINTER) {}
~TabPrinter() {}
void build() override;
void build_fff();
void build_sla();
void reload_config() override;
void activate_selected_page(std::function<void()> throw_if_canceled) override;
void clear_pages() override;
void toggle_options() override;
void update() override;
void update_fff();
void update_sla();
void update_pages(); // update m_pages according to printer technology
void update_printers();
void extruders_count_changed(size_t extruders_count);
void milling_count_changed(size_t extruders_count);
PageShp build_kinematics_page();
void build_unregular_pages(bool from_initial_build = false);
void on_preset_loaded() override;
void init_options_list() override;
void msw_rescale() override;
bool supports_printer_technology(const PrinterTechnology /* tech */) const override { return true; }
wxSizer* create_bed_shape_widget(wxWindow* parent);
void cache_extruder_cnt();
bool apply_extruder_cnt_from_cache();
};
class TabSLAMaterial : public Tab
{
public:
TabSLAMaterial(wxBookCtrlBase* parent) :
Tab(parent, _(L("Material Settings")), Slic3r::Preset::TYPE_SLA_MATERIAL) {}
~TabSLAMaterial() {}
void build() override;
void reload_config() override;
void toggle_options() override;
void update() override;
void init_options_list() override;
bool supports_printer_technology(const PrinterTechnology tech) const override { return tech == ptSLA; }
};
class TabSLAPrint : public Tab
{
public:
TabSLAPrint(wxBookCtrlBase* parent) :
Tab(parent, _(L("Print Settings")), Slic3r::Preset::TYPE_SLA_PRINT) {}
~TabSLAPrint() {}
ogStaticText* m_support_object_elevation_description_line = nullptr;
void build() override;
void reload_config() override;
void update_description_lines() override;
void toggle_options() override;
void update() override;
void clear_pages() override;
bool supports_printer_technology(const PrinterTechnology tech) const override { return tech == ptSLA; }
};
} // GUI
} // Slic3r
#endif /* slic3r_Tab_hpp_ */
|