Merge branch 'profile_changes_reset' into updating

This commit is contained in:
Vojtech Kral 2018-04-24 18:15:23 +02:00
commit 62d67d35ec
28 changed files with 803 additions and 394 deletions

View file

@ -149,6 +149,7 @@ sub _init_tabpanel {
if (defined $presets){ if (defined $presets){
my $reload_dependent_tabs = $tab->get_dependent_tabs; my $reload_dependent_tabs = $tab->get_dependent_tabs;
$self->{plater}->update_presets($tab_name, $reload_dependent_tabs, $presets); $self->{plater}->update_presets($tab_name, $reload_dependent_tabs, $presets);
$self->{plater}->{"selected_item_$tab_name"} = $tab->get_selected_preset_item;
if ($tab_name eq 'printer') { if ($tab_name eq 'printer') {
# Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. # Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors.
for my $tab_name_other (qw(print filament)) { for my $tab_name_other (qw(print filament)) {

View file

@ -514,6 +514,13 @@ sub new {
$self->SetSizer($sizer); $self->SetSizer($sizer);
} }
# Last correct selected item for each preset
{
$self->{selected_item_print} = 0;
$self->{selected_item_filament} = 0;
$self->{selected_item_printer} = 0;
}
$self->update_ui_from_settings(); $self->update_ui_from_settings();
return $self; return $self;
@ -538,9 +545,21 @@ sub _on_select_preset {
# Only update the platter UI for the 2nd and other filaments. # Only update the platter UI for the 2nd and other filaments.
wxTheApp->{preset_bundle}->update_platter_filament_ui($idx, $choice); wxTheApp->{preset_bundle}->update_platter_filament_ui($idx, $choice);
} else { } else {
my $selected_item = $choice->GetSelection();
return if ($selected_item == $self->{"selected_item_$group"});
my $selected_string = $choice->GetString($selected_item);
if ($selected_string eq "------- System presets -------" ||
$selected_string eq "------- User presets -------"){
$choice->SetSelection($self->{"selected_item_$group"});
return;
}
# call GetSelection() in scalar context as it's context-aware # call GetSelection() in scalar context as it's context-aware
$self->{on_select_preset}->($group, $choice->GetStringSelection) # $self->{on_select_preset}->($group, $choice->GetStringSelection)
if $self->{on_select_preset}; $self->{on_select_preset}->($group, $selected_string)
if $self->{on_select_preset};
$self->{"selected_item_$group"} = $selected_item;
} }
# Synchronize config.ini with the current selections. # Synchronize config.ini with the current selections.
wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config}); wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 491 B

After

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

View file

@ -212,6 +212,8 @@ add_library(libslic3r_gui STATIC
${LIBDIR}/slic3r/GUI/RammingChart.hpp ${LIBDIR}/slic3r/GUI/RammingChart.hpp
${LIBDIR}/slic3r/GUI/BonjourDialog.cpp ${LIBDIR}/slic3r/GUI/BonjourDialog.cpp
${LIBDIR}/slic3r/GUI/BonjourDialog.hpp ${LIBDIR}/slic3r/GUI/BonjourDialog.hpp
${LIBDIR}/slic3r/GUI/ButtonsDescription.cpp
${LIBDIR}/slic3r/GUI/ButtonsDescription.hpp
${LIBDIR}/slic3r/Config/Snapshot.cpp ${LIBDIR}/slic3r/Config/Snapshot.cpp
${LIBDIR}/slic3r/Config/Snapshot.hpp ${LIBDIR}/slic3r/Config/Snapshot.hpp
${LIBDIR}/slic3r/Config/Version.cpp ${LIBDIR}/slic3r/Config/Version.cpp

View file

@ -206,6 +206,44 @@ t_config_option_keys ConfigBase::diff(const ConfigBase &other) const
return diff; return diff;
} }
template<class T>
void add_correct_opts_to_diff(const std::string &opt_key, t_config_option_keys& vec, const ConfigBase &other, const ConfigBase *this_c)
{
const T* opt_init = static_cast<const T*>(other.option(opt_key));
const T* opt_cur = static_cast<const T*>(this_c->option(opt_key));
int opt_init_max_id = opt_init->values.size() - 1;
for (int i = 0; i < opt_cur->values.size(); i++)
{
int init_id = i <= opt_init_max_id ? i : 0;
if (opt_cur->values[i] != opt_init->values[init_id])
vec.emplace_back(opt_key + "#" + std::to_string(i));
}
}
t_config_option_keys ConfigBase::deep_diff(const ConfigBase &other) const
{
t_config_option_keys diff;
for (const t_config_option_key &opt_key : this->keys()) {
const ConfigOption *this_opt = this->option(opt_key);
const ConfigOption *other_opt = other.option(opt_key);
if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt)
{
if (opt_key == "bed_shape"){ diff.emplace_back(opt_key); continue; }
switch (other_opt->type())
{
case coInts: add_correct_opts_to_diff<ConfigOptionInts >(opt_key, diff, other, this); break;
case coBools: add_correct_opts_to_diff<ConfigOptionBools >(opt_key, diff, other, this); break;
case coFloats: add_correct_opts_to_diff<ConfigOptionFloats >(opt_key, diff, other, this); break;
case coStrings: add_correct_opts_to_diff<ConfigOptionStrings >(opt_key, diff, other, this); break;
case coPercents:add_correct_opts_to_diff<ConfigOptionPercents >(opt_key, diff, other, this); break;
case coPoints: add_correct_opts_to_diff<ConfigOptionPoints >(opt_key, diff, other, this); break;
default: diff.emplace_back(opt_key); break;
}
}
}
return diff;
}
t_config_option_keys ConfigBase::equal(const ConfigBase &other) const t_config_option_keys ConfigBase::equal(const ConfigBase &other) const
{ {
t_config_option_keys equal; t_config_option_keys equal;

View file

@ -1047,6 +1047,9 @@ public:
void apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false); void apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false);
bool equals(const ConfigBase &other) const { return this->diff(other).empty(); } bool equals(const ConfigBase &other) const { return this->diff(other).empty(); }
t_config_option_keys diff(const ConfigBase &other) const; t_config_option_keys diff(const ConfigBase &other) const;
// Use deep_diff to correct return of changed options,
// considering individual options for each extruder
t_config_option_keys deep_diff(const ConfigBase &other) const;
t_config_option_keys equal(const ConfigBase &other) const; t_config_option_keys equal(const ConfigBase &other) const;
std::string serialize(const t_config_option_key &opt_key) const; std::string serialize(const t_config_option_key &opt_key) const;
// Set a configuration value from a string, it will call an overridable handle_legacy() // Set a configuration value from a string, it will call an overridable handle_legacy()

View file

@ -1,3 +1,6 @@
#ifndef slic3r_2DBed_hpp_
#define slic3r_2DBed_hpp_
#include <wx/wx.h> #include <wx/wx.h>
#include "Config.hpp" #include "Config.hpp"
@ -45,3 +48,5 @@ public:
} // GUI } // GUI
} // Slic3r } // Slic3r
#endif /* slic3r_2DBed_hpp_ */

View file

@ -1,3 +1,5 @@
#ifndef slic3r_BedShapeDialog_hpp_
#define slic3r_BedShapeDialog_hpp_
// The bed shape dialog. // The bed shape dialog.
// The dialog opens from Print Settins tab->Bed Shape : Set... // The dialog opens from Print Settins tab->Bed Shape : Set...
@ -49,3 +51,6 @@ public:
} // GUI } // GUI
} // Slic3r } // Slic3r
#endif /* slic3r_BedShapeDialog_hpp_ */

View file

@ -0,0 +1,44 @@
#include "ButtonsDescription.hpp"
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/statbmp.h>
#include "GUI.hpp"
namespace Slic3r {
namespace GUI {
ButtonsDescription::ButtonsDescription(wxWindow* parent, t_icon_descriptions* icon_descriptions) :
wxDialog(parent, wxID_ANY, "Buttons Description", wxDefaultPosition, wxDefaultSize),
m_icon_descriptions(icon_descriptions)
{
auto grid_sizer = new wxFlexGridSizer(3, 20, 20);
auto main_sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->Add(grid_sizer, 0, wxEXPAND | wxALL, 20);
for (auto pair : *m_icon_descriptions)
{
auto icon = new wxStaticBitmap(this, wxID_ANY, *pair.first);
grid_sizer->Add(icon, -1, wxALIGN_CENTRE_VERTICAL);
std::istringstream f(pair.second);
std::string s;
getline(f, s, ';');
auto description = new wxStaticText(this, wxID_ANY, _(s));
grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL);
getline(f, s, ';');
description = new wxStaticText(this, wxID_ANY, _(s));
grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
}
auto button = CreateStdDialogButtonSizer(wxOK);
main_sizer->Add(button, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10);
SetSizer(main_sizer);
main_sizer->SetSizeHints(this);
}
} // GUI
} // Slic3r

View file

@ -0,0 +1,27 @@
#ifndef slic3r_ButtonsDescription_hpp
#define slic3r_ButtonsDescription_hpp
#include <wx/dialog.h>
#include <vector>
namespace Slic3r {
namespace GUI {
using t_icon_descriptions = std::vector<std::pair<wxBitmap*, std::string>>;
class ButtonsDescription : public wxDialog
{
t_icon_descriptions* m_icon_descriptions;
public:
ButtonsDescription(wxWindow* parent, t_icon_descriptions* icon_descriptions);
~ButtonsDescription(){}
};
} // GUI
} // Slic3r
#endif

View file

@ -20,23 +20,22 @@ namespace Slic3r { namespace GUI {
void Field::PostInitialize(){ void Field::PostInitialize(){
auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
m_Undo_btn = new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); auto sz = 16;
m_Undo_to_sys_btn = new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); #ifdef __WXGTK__
sz = 28;
#endif // __WXGTK__
m_Undo_btn = new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxSize(sz,sz), wxNO_BORDER);
m_Undo_to_sys_btn = new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxSize(sz,sz), wxNO_BORDER);
if (wxMSW) { if (wxMSW) {
m_Undo_btn->SetBackgroundColour(color); m_Undo_btn->SetBackgroundColour(color);
m_Undo_to_sys_btn->SetBackgroundColour(color); m_Undo_to_sys_btn->SetBackgroundColour(color);
} }
m_Undo_btn->SetBitmap(wxBitmap(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG));
m_Undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_initial_value(); })); m_Undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_initial_value(); }));
m_Undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_sys_value(); })); m_Undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_sys_value(); }));
BUILD(); BUILD();
} }
void Field::set_nonsys_btn_icon(const std::string& icon){
m_Undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(icon)), wxBITMAP_TYPE_PNG));
}
void Field::on_kill_focus(wxEvent& event) { void Field::on_kill_focus(wxEvent& event) {
// Without this, there will be nasty focus bugs on Windows. // Without this, there will be nasty focus bugs on Windows.
// Also, docs for wxEvent::Skip() say "In general, it is recommended to skip all // Also, docs for wxEvent::Skip() say "In general, it is recommended to skip all
@ -81,12 +80,13 @@ namespace Slic3r { namespace GUI {
return std::regex_match(string, regex_pattern); return std::regex_match(string, regex_pattern);
} }
boost::any Field::get_value_by_opt_type(wxString& str) // boost::any Field::get_value_by_opt_type(wxString& str)
void Field::get_value_by_opt_type(wxString& str)
{ {
boost::any ret_val; // boost::any m_value;
switch (m_opt.type){ switch (m_opt.type){
case coInt: case coInt:
ret_val = wxAtoi(str); m_value = wxAtoi(str);
break; break;
case coPercent: case coPercent:
case coPercents: case coPercents:
@ -96,18 +96,18 @@ namespace Slic3r { namespace GUI {
str.RemoveLast(); str.RemoveLast();
double val; double val;
str.ToCDouble(&val); str.ToCDouble(&val);
ret_val = val; m_value = val;
break; } break; }
case coString: case coString:
case coStrings: case coStrings:
case coFloatOrPercent: case coFloatOrPercent:
ret_val = str.ToStdString(); m_value = str.ToStdString();
break; break;
default: default:
break; break;
} }
return ret_val; // return m_value;
} }
void TextCtrl::BUILD() { void TextCtrl::BUILD() {
@ -183,12 +183,12 @@ namespace Slic3r { namespace GUI {
window = dynamic_cast<wxWindow*>(temp); window = dynamic_cast<wxWindow*>(temp);
} }
boost::any TextCtrl::get_value() boost::any& TextCtrl::get_value()
{ {
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue(); wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
boost::any ret_val = get_value_by_opt_type(ret_str); /*boost::any ret_val*/get_value_by_opt_type(ret_str);
return ret_val; return m_value;//ret_val;
} }
void TextCtrl::enable() { dynamic_cast<wxTextCtrl*>(window)->Enable(); dynamic_cast<wxTextCtrl*>(window)->SetEditable(true); } void TextCtrl::enable() { dynamic_cast<wxTextCtrl*>(window)->Enable(); dynamic_cast<wxTextCtrl*>(window)->SetEditable(true); }
@ -216,15 +216,15 @@ void CheckBox::BUILD() {
window = dynamic_cast<wxWindow*>(temp); window = dynamic_cast<wxWindow*>(temp);
} }
boost::any CheckBox::get_value() boost::any& CheckBox::get_value()
{ {
boost::any ret_val; // boost::any m_value;
bool value = dynamic_cast<wxCheckBox*>(window)->GetValue(); bool value = dynamic_cast<wxCheckBox*>(window)->GetValue();
if (m_opt.type == coBool) if (m_opt.type == coBool)
ret_val = static_cast<bool>(value); m_value = static_cast<bool>(value);
else else
ret_val = static_cast<unsigned char>(value); m_value = static_cast<unsigned char>(value);
return ret_val; return m_value;
} }
int undef_spin_val = -9999; //! Probably, It's not necessary int undef_spin_val = -9999; //! Probably, It's not necessary
@ -424,7 +424,33 @@ void Choice::set_value(const boost::any& value, bool change_event)
break; break;
} }
case coEnum:{ case coEnum:{
dynamic_cast<wxComboBox*>(window)->SetSelection(boost::any_cast<int>(value)); int val = boost::any_cast<int>(value);
if (m_opt_id.compare("external_fill_pattern") == 0)
{
if (!m_opt.enum_values.empty()){
std::string key;
t_config_enum_values map_names = ConfigOptionEnum<InfillPattern>::get_enum_values();
for (auto it : map_names) {
if (val == it.second) {
key = it.first;
break;
}
}
size_t idx = 0;
for (auto el : m_opt.enum_values)
{
if (el.compare(key) == 0)
break;
++idx;
}
val = idx == m_opt.enum_values.size() ? 0 : idx;
}
else
val = 0;
}
dynamic_cast<wxComboBox*>(window)->SetSelection(val);
break; break;
} }
default: default:
@ -454,16 +480,16 @@ void Choice::set_values(const std::vector<std::string>& values)
m_disable_change_event = false; m_disable_change_event = false;
} }
boost::any Choice::get_value() boost::any& Choice::get_value()
{ {
boost::any ret_val; // boost::any m_value;
wxString ret_str = static_cast<wxComboBox*>(window)->GetValue(); wxString ret_str = static_cast<wxComboBox*>(window)->GetValue();
if (m_opt_id == "support") if (m_opt_id == "support")
return ret_str; return m_value = boost::any(ret_str);//ret_str;
if (m_opt.type != coEnum) if (m_opt.type != coEnum)
ret_val = get_value_by_opt_type(ret_str); /*m_value = */get_value_by_opt_type(ret_str);
else else
{ {
int ret_enum = static_cast<wxComboBox*>(window)->GetSelection(); int ret_enum = static_cast<wxComboBox*>(window)->GetSelection();
@ -474,22 +500,22 @@ boost::any Choice::get_value()
t_config_enum_values map_names = ConfigOptionEnum<InfillPattern>::get_enum_values(); t_config_enum_values map_names = ConfigOptionEnum<InfillPattern>::get_enum_values();
int value = map_names.at(key); int value = map_names.at(key);
ret_val = static_cast<InfillPattern>(value); m_value = static_cast<InfillPattern>(value);
} }
else else
ret_val = static_cast<InfillPattern>(0); m_value = static_cast<InfillPattern>(0);
} }
if (m_opt_id.compare("fill_pattern") == 0) if (m_opt_id.compare("fill_pattern") == 0)
ret_val = static_cast<InfillPattern>(ret_enum); m_value = static_cast<InfillPattern>(ret_enum);
else if (m_opt_id.compare("gcode_flavor") == 0) else if (m_opt_id.compare("gcode_flavor") == 0)
ret_val = static_cast<GCodeFlavor>(ret_enum); m_value = static_cast<GCodeFlavor>(ret_enum);
else if (m_opt_id.compare("support_material_pattern") == 0) else if (m_opt_id.compare("support_material_pattern") == 0)
ret_val = static_cast<SupportMaterialPattern>(ret_enum); m_value = static_cast<SupportMaterialPattern>(ret_enum);
else if (m_opt_id.compare("seam_position") == 0) else if (m_opt_id.compare("seam_position") == 0)
ret_val = static_cast<SeamPosition>(ret_enum); m_value = static_cast<SeamPosition>(ret_enum);
} }
return ret_val; return m_value;
} }
void ColourPicker::BUILD() void ColourPicker::BUILD()
@ -509,14 +535,14 @@ void ColourPicker::BUILD()
temp->SetToolTip(get_tooltip_text(clr)); temp->SetToolTip(get_tooltip_text(clr));
} }
boost::any ColourPicker::get_value(){ boost::any& ColourPicker::get_value(){
boost::any ret_val; // boost::any m_value;
auto colour = static_cast<wxColourPickerCtrl*>(window)->GetColour(); auto colour = static_cast<wxColourPickerCtrl*>(window)->GetColour();
auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue()); auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue());
ret_val = clr_str.ToStdString(); m_value = clr_str.ToStdString();
return ret_val; return m_value;
} }
void PointCtrl::BUILD() void PointCtrl::BUILD()
@ -580,7 +606,7 @@ void PointCtrl::set_value(const boost::any& value, bool change_event)
set_value(pt, change_event); set_value(pt, change_event);
} }
boost::any PointCtrl::get_value() boost::any& PointCtrl::get_value()
{ {
Pointf ret_point; Pointf ret_point;
double val; double val;
@ -588,7 +614,7 @@ boost::any PointCtrl::get_value()
ret_point.x = val; ret_point.x = val;
y_textctrl->GetValue().ToDouble(&val); y_textctrl->GetValue().ToDouble(&val);
ret_point.y = val; ret_point.y = val;
return ret_point; return m_value = ret_point;
} }
} // GUI } // GUI

View file

@ -85,22 +85,18 @@ public:
/// Gets a boost::any representing this control. /// Gets a boost::any representing this control.
/// subclasses should overload with a specific version /// subclasses should overload with a specific version
virtual boost::any get_value() = 0; virtual boost::any& get_value() = 0;
virtual void enable() = 0; virtual void enable() = 0;
virtual void disable() = 0; virtual void disable() = 0;
wxStaticText* m_Label = nullptr; /// Fires the enable or disable function, based on the input.
wxButton* m_Undo_btn = nullptr;
wxButton* m_Undo_to_sys_btn = nullptr;
/// Fires the enable or disable function, based on the input.
inline void toggle(bool en) { en ? enable() : disable(); } inline void toggle(bool en) { en ? enable() : disable(); }
virtual wxString get_tooltip_text(const wxString& default_string); virtual wxString get_tooltip_text(const wxString& default_string);
// set icon to "UndoToSystemValue" button according to an inheritance of preset // set icon to "UndoToSystemValue" button according to an inheritance of preset
void set_nonsys_btn_icon(const std::string& icon); // void set_nonsys_btn_icon(const wxBitmap& icon);
Field(const ConfigOptionDef& opt, const t_config_option_key& id) : m_opt(opt), m_opt_id(id) {}; Field(const ConfigOptionDef& opt, const t_config_option_key& id) : m_opt(opt), m_opt_id(id) {};
Field(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : m_parent(parent), m_opt(opt), m_opt_id(id) {}; Field(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : m_parent(parent), m_opt(opt), m_opt_id(id) {};
@ -110,7 +106,8 @@ public:
virtual wxWindow* getWindow() { return nullptr; } virtual wxWindow* getWindow() { return nullptr; }
bool is_matched(const std::string& string, const std::string& pattern); bool is_matched(const std::string& string, const std::string& pattern);
boost::any get_value_by_opt_type(wxString& str); // boost::any get_value_by_opt_type(wxString& str);
void get_value_by_opt_type(wxString& str);
/// Factory method for generating new derived classes. /// Factory method for generating new derived classes.
template<class T> template<class T>
@ -120,6 +117,71 @@ public:
p->PostInitialize(); p->PostInitialize();
return std::move(p); //!p; return std::move(p); //!p;
} }
bool set_undo_bitmap(const wxBitmap *bmp) {
if (m_undo_bitmap != bmp) {
m_undo_bitmap = bmp;
m_Undo_btn->SetBitmap(*bmp);
return true;
}
return false;
}
bool set_undo_to_sys_bitmap(const wxBitmap *bmp) {
if (m_undo_to_sys_bitmap != bmp) {
m_undo_to_sys_bitmap = bmp;
m_Undo_to_sys_btn->SetBitmap(*bmp);
return true;
}
return false;
}
bool set_label_colour(const wxColour *clr) {
if (m_Label == nullptr) return false;
if (m_label_color != clr) {
m_label_color = clr;
m_Label->SetForegroundColour(*clr);
m_Label->Refresh(true);
}
return false;
}
bool set_undo_tooltip(const wxString *tip) {
if (m_undo_tooltip != tip) {
m_undo_tooltip = tip;
m_Undo_btn->SetToolTip(*tip);
return true;
}
return false;
}
bool set_undo_to_sys_tooltip(const wxString *tip) {
if (m_undo_to_sys_tooltip != tip) {
m_undo_to_sys_tooltip = tip;
m_Undo_to_sys_btn->SetToolTip(*tip);
return true;
}
return false;
}
protected:
wxButton* m_Undo_btn = nullptr;
// Bitmap and Tooltip text for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
const wxBitmap* m_undo_bitmap = nullptr;
const wxString* m_undo_tooltip = nullptr;
wxButton* m_Undo_to_sys_btn = nullptr;
// Bitmap and Tooltip text for m_Undo_to_sys_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
const wxBitmap* m_undo_to_sys_bitmap = nullptr;
const wxString* m_undo_to_sys_tooltip = nullptr;
wxStaticText* m_Label = nullptr;
// Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
const wxColour* m_label_color;
// current value
boost::any m_value;
friend class OptionsGroup;
}; };
/// Convenience function, accepts a const reference to t_field and checks to see whether /// Convenience function, accepts a const reference to t_field and checks to see whether
@ -153,7 +215,7 @@ public:
m_disable_change_event = false; m_disable_change_event = false;
} }
boost::any get_value() override; boost::any& get_value() override;
virtual void enable(); virtual void enable();
virtual void disable(); virtual void disable();
@ -180,7 +242,7 @@ public:
dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<bool>(value)); dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<bool>(value));
m_disable_change_event = false; m_disable_change_event = false;
} }
boost::any get_value() override; boost::any& get_value() override;
void enable() override { dynamic_cast<wxCheckBox*>(window)->Enable(); } void enable() override { dynamic_cast<wxCheckBox*>(window)->Enable(); }
void disable() override { dynamic_cast<wxCheckBox*>(window)->Disable(); } void disable() override { dynamic_cast<wxCheckBox*>(window)->Disable(); }
@ -210,8 +272,9 @@ public:
dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value); dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value);
m_disable_change_event = false; m_disable_change_event = false;
} }
boost::any get_value() override { boost::any& get_value() override {
return boost::any(tmp_value); // return boost::any(tmp_value);
return m_value = tmp_value;
} }
void enable() override { dynamic_cast<wxSpinCtrl*>(window)->Enable(); } void enable() override { dynamic_cast<wxSpinCtrl*>(window)->Enable(); }
@ -233,7 +296,7 @@ public:
void set_value(const std::string& value, bool change_event = false); void set_value(const std::string& value, bool change_event = false);
void set_value(const boost::any& value, bool change_event = false); void set_value(const boost::any& value, bool change_event = false);
void set_values(const std::vector<std::string> &values); void set_values(const std::vector<std::string> &values);
boost::any get_value() override; boost::any& get_value() override;
void enable() override { dynamic_cast<wxComboBox*>(window)->Enable(); }; void enable() override { dynamic_cast<wxComboBox*>(window)->Enable(); };
void disable() override{ dynamic_cast<wxComboBox*>(window)->Disable(); }; void disable() override{ dynamic_cast<wxComboBox*>(window)->Disable(); };
@ -261,7 +324,7 @@ public:
m_disable_change_event = false; m_disable_change_event = false;
} }
boost::any get_value() override; boost::any& get_value() override;
void enable() override { dynamic_cast<wxColourPickerCtrl*>(window)->Enable(); }; void enable() override { dynamic_cast<wxColourPickerCtrl*>(window)->Enable(); };
void disable() override{ dynamic_cast<wxColourPickerCtrl*>(window)->Disable(); }; void disable() override{ dynamic_cast<wxColourPickerCtrl*>(window)->Disable(); };
@ -283,7 +346,7 @@ public:
void set_value(const Pointf& value, bool change_event = false); void set_value(const Pointf& value, bool change_event = false);
void set_value(const boost::any& value, bool change_event = false); void set_value(const boost::any& value, bool change_event = false);
boost::any get_value() override; boost::any& get_value() override;
void enable() override { void enable() override {
x_textctrl->Enable(); x_textctrl->Enable();

View file

@ -187,6 +187,7 @@ PresetBundle *g_PresetBundle= nullptr;
PresetUpdater *g_PresetUpdater = nullptr; PresetUpdater *g_PresetUpdater = nullptr;
wxColour g_color_label_modified; wxColour g_color_label_modified;
wxColour g_color_label_sys; wxColour g_color_label_sys;
wxColour g_color_label_default;
std::vector<Tab *> g_tabs_list; std::vector<Tab *> g_tabs_list;
@ -206,6 +207,7 @@ static void init_label_colours()
g_color_label_modified = wxColour(253, 111, 40); g_color_label_modified = wxColour(253, 111, 40);
g_color_label_sys = wxColour(115, 220, 103); g_color_label_sys = wxColour(115, 220, 103);
} }
g_color_label_default = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
} }
void set_wxapp(wxApp *app) void set_wxapp(wxApp *app)
@ -699,6 +701,10 @@ const wxColour& get_sys_label_clr() {
return g_color_label_sys; return g_color_label_sys;
} }
const wxColour& get_default_label_clr() {
return g_color_label_default;
}
unsigned get_colour_approx_luma(const wxColour &colour) unsigned get_colour_approx_luma(const wxColour &colour)
{ {
double r = colour.Red(); double r = colour.Red();

View file

@ -86,6 +86,7 @@ PresetBundle* get_preset_bundle();
const wxColour& get_modified_label_clr(); const wxColour& get_modified_label_clr();
const wxColour& get_sys_label_clr(); const wxColour& get_sys_label_clr();
const wxColour& get_default_label_clr();
unsigned get_colour_approx_luma(const wxColour &colour); unsigned get_colour_approx_luma(const wxColour &colour);
extern void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_language_change); extern void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_language_change);

View file

@ -90,8 +90,8 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
field->m_Undo_btn->Hide(); field->m_Undo_btn->Hide();
field->m_Undo_to_sys_btn->Hide(); field->m_Undo_to_sys_btn->Hide();
} }
if (nonsys_btn_icon != nullptr) // if (nonsys_btn_icon != nullptr)
field->set_nonsys_btn_icon(nonsys_btn_icon()); // field->set_nonsys_btn_icon(*nonsys_btn_icon);
// assign function objects for callbacks, etc. // assign function objects for callbacks, etc.
return field; return field;
@ -149,7 +149,8 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
// If there's a widget, build it and add the result to the sizer. // If there's a widget, build it and add the result to the sizer.
if (line.widget != nullptr) { if (line.widget != nullptr) {
auto wgt = line.widget(parent()); auto wgt = line.widget(parent());
grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, wxOSX ? 0 : 5); // If widget doesn't have label, don't use border
grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, (wxOSX || line.label.IsEmpty()) ? 0 : 5);
if (colored_Label != nullptr) *colored_Label = label; if (colored_Label != nullptr) *colored_Label = label;
return; return;
} }

View file

@ -1,3 +1,6 @@
#ifndef slic3r_OptionsGroup_hpp_
#define slic3r_OptionsGroup_hpp_
#include <wx/wx.h> #include <wx/wx.h>
#include <wx/stattext.h> #include <wx/stattext.h>
#include <wx/settings.h> #include <wx/settings.h>
@ -86,7 +89,7 @@ public:
wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
std::function<std::string()> nonsys_btn_icon{ nullptr }; // std::function<const wxBitmap&()> nonsys_btn_icon{ nullptr };
/// Returns a copy of the pointer of the parent wxWindow. /// Returns a copy of the pointer of the parent wxWindow.
/// Accessor function is because users are not allowed to change the parent /// Accessor function is because users are not allowed to change the parent
@ -204,3 +207,5 @@ public:
}; };
}} }}
#endif /* slic3r_OptionsGroup_hpp_ */

View file

@ -1,3 +1,6 @@
#ifndef slic3r_Preferences_hpp_
#define slic3r_Preferences_hpp_
#include "GUI.hpp" #include "GUI.hpp"
#include <wx/dialog.h> #include <wx/dialog.h>
@ -25,3 +28,5 @@ public:
} // GUI } // GUI
} // Slic3r } // Slic3r
#endif /* slic3r_Preferences_hpp_ */

View file

@ -3,6 +3,7 @@
#include "Preset.hpp" #include "Preset.hpp"
#include "AppConfig.hpp" #include "AppConfig.hpp"
#include "BitmapCache.hpp"
#include <fstream> #include <fstream>
#include <stdexcept> #include <stdexcept>
@ -340,7 +341,8 @@ PresetCollection::PresetCollection(Preset::Type type, const std::vector<std::str
m_type(type), m_type(type),
m_edited_preset(type, "", false), m_edited_preset(type, "", false),
m_idx_selected(0), m_idx_selected(0),
m_bitmap_main_frame(new wxBitmap) m_bitmap_main_frame(new wxBitmap),
m_bitmap_cache(new GUI::BitmapCache)
{ {
// Insert just the default preset. // Insert just the default preset.
m_presets.emplace_back(Preset(type, "- default -", true)); m_presets.emplace_back(Preset(type, "- default -", true));
@ -352,6 +354,8 @@ PresetCollection::~PresetCollection()
{ {
delete m_bitmap_main_frame; delete m_bitmap_main_frame;
m_bitmap_main_frame = nullptr; m_bitmap_main_frame = nullptr;
delete m_bitmap_cache;
m_bitmap_cache = nullptr;
} }
void PresetCollection::reset(bool delete_files) void PresetCollection::reset(bool delete_files)
@ -585,17 +589,41 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui)
// Otherwise fill in the list from scratch. // Otherwise fill in the list from scratch.
ui->Freeze(); ui->Freeze();
ui->Clear(); ui->Clear();
std::map<wxString, bool> nonsys_presets;
const Preset &selected_preset = this->get_selected_preset();
// Show wide icons if the currently selected preset is not compatible with the current printer,
// and draw a red flag in front of the selected preset.
bool wide_icons = !selected_preset.is_compatible && m_bitmap_incompatible != nullptr;
std::map<wxString, wxBitmap*> nonsys_presets;
wxString selected = ""; wxString selected = "";
for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++ i) { if (!this->m_presets.front().is_visible)
ui->Append("------- System presets -------", wxNullBitmap);
for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++i) {
const Preset &preset = this->m_presets[i]; const Preset &preset = this->m_presets[i];
if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected)) if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected))
continue; continue;
const wxBitmap *bmp = (i == 0 || preset.is_compatible) ? m_bitmap_main_frame : m_bitmap_incompatible; std::string bitmap_key = "";
// ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), // If the filament preset is not compatible and there is a "red flag" icon loaded, show it left
// (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); // to the filament color image.
// if (i == m_idx_selected) if (wide_icons)
// ui->SetSelection(ui->GetCount() - 1); bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt";
bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst";
wxBitmap *bmp = m_bitmap_cache->find(bitmap_key);
if (bmp == nullptr) {
// Create the bitmap with color bars.
std::vector<wxBitmap> bmps;
if (wide_icons)
// Paint a red flag for incompatible presets.
bmps.emplace_back(preset.is_compatible ? m_bitmap_cache->mkclear(16, 16) : *m_bitmap_incompatible);
// Paint the color bars.
bmps.emplace_back(m_bitmap_cache->mkclear(4, 16));
bmps.emplace_back(*m_bitmap_main_frame);
// Paint a lock at the system presets.
bmps.emplace_back(m_bitmap_cache->mkclear(6, 16));
bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(16, 16));
bmp = m_bitmap_cache->insert(bitmap_key, bmps);
}
if (preset.is_default || preset.is_system){ if (preset.is_default || preset.is_system){
ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()),
@ -605,20 +633,18 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui)
} }
else else
{ {
nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), preset.is_compatible); nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bmp/*preset.is_compatible*/);
if (i == m_idx_selected) if (i == m_idx_selected)
selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str());
} }
if (preset.is_default) if (preset.is_default)
ui->Append("------------------------------------", wxNullBitmap); ui->Append("------- System presets -------", wxNullBitmap);
} }
if (!nonsys_presets.empty()) if (!nonsys_presets.empty())
{ {
ui->Append("------------------------------------", wxNullBitmap); ui->Append("------- User presets -------", wxNullBitmap);
for (std::map<wxString, bool>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
const wxBitmap *bmp = it->second ? m_bitmap_compatible : m_bitmap_incompatible; ui->Append(it->first, *it->second);
ui->Append(it->first,
(bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp);
if (it->first == selected) if (it->first == selected)
ui->SetSelection(ui->GetCount() - 1); ui->SetSelection(ui->GetCount() - 1);
} }
@ -626,51 +652,63 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui)
ui->Thaw(); ui->Thaw();
} }
void PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible) size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible)
{ {
if (ui == nullptr) if (ui == nullptr)
return; return 0;
ui->Freeze(); ui->Freeze();
ui->Clear(); ui->Clear();
std::map<wxString, bool> nonsys_presets; size_t selected_preset_item = 0;
std::map<wxString, wxBitmap*> nonsys_presets;
wxString selected = ""; wxString selected = "";
for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++ i) { if (!this->m_presets.front().is_visible)
ui->Append("------- System presets -------", wxNullBitmap);
for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++i) {
const Preset &preset = this->m_presets[i]; const Preset &preset = this->m_presets[i];
if (! preset.is_visible || (! show_incompatible && ! preset.is_compatible && i != m_idx_selected)) if (! preset.is_visible || (! show_incompatible && ! preset.is_compatible && i != m_idx_selected))
continue; continue;
const wxBitmap *bmp = preset.is_compatible ? m_bitmap_compatible : m_bitmap_incompatible; std::string bitmap_key = "tab";
// ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt";
// (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst";
// if (i == m_idx_selected) wxBitmap *bmp = m_bitmap_cache->find(bitmap_key);
// ui->SetSelection(ui->GetCount() - 1); if (bmp == nullptr) {
// Create the bitmap with color bars.
std::vector<wxBitmap> bmps;
const wxBitmap* tmp_bmp = preset.is_compatible ? m_bitmap_compatible : m_bitmap_incompatible;
bmps.emplace_back((tmp_bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *tmp_bmp);
// Paint a lock at the system presets.
bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(16, 16));
bmp = m_bitmap_cache->insert(bitmap_key, bmps);
}
if (preset.is_default || preset.is_system){ if (preset.is_default || preset.is_system){
ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()),
(bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp);
if (i == m_idx_selected) if (i == m_idx_selected)
ui->SetSelection(ui->GetCount() - 1); selected_preset_item = ui->GetCount() - 1;
} }
else else
{ {
nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), preset.is_compatible); nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bmp/*preset.is_compatible*/);
if (i == m_idx_selected) if (i == m_idx_selected)
selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str());
} }
if (preset.is_default) if (preset.is_default)
ui->Append("------------------------------------", wxNullBitmap); ui->Append("------- System presets -------", wxNullBitmap);
} }
if (!nonsys_presets.empty()) if (!nonsys_presets.empty())
{ {
ui->Append("------------------------------------", wxNullBitmap); ui->Append("------- User presets -------", wxNullBitmap);
for (std::map<wxString, bool>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
const wxBitmap *bmp = it->second ? m_bitmap_compatible : m_bitmap_incompatible; ui->Append(it->first, *it->second);
ui->Append(it->first,
(bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp);
if (it->first == selected) if (it->first == selected)
ui->SetSelection(ui->GetCount() - 1); selected_preset_item = ui->GetCount() - 1;
} }
} }
ui->SetSelection(selected_preset_item);
ui->Thaw(); ui->Thaw();
return selected_preset_item;
} }
// Update a dirty floag of the current preset, update the labels of the UI component accordingly. // Update a dirty floag of the current preset, update the labels of the UI component accordingly.
@ -703,11 +741,13 @@ bool PresetCollection::update_dirty_ui(wxBitmapComboBox *ui)
return was_dirty != is_dirty; return was_dirty != is_dirty;
} }
std::vector<std::string> PresetCollection::dirty_options(const Preset *edited, const Preset *reference) std::vector<std::string> PresetCollection::dirty_options(const Preset *edited, const Preset *reference, const bool is_printer_type /*= false*/)
{ {
std::vector<std::string> changed; std::vector<std::string> changed;
if (edited != nullptr && reference != nullptr) { if (edited != nullptr && reference != nullptr) {
changed = reference->config.diff(edited->config); changed = is_printer_type ?
reference->config.deep_diff(edited->config) :
reference->config.diff(edited->config);
// The "compatible_printers" option key is handled differently from the others: // The "compatible_printers" option key is handled differently from the others:
// It is not mandatory. If the key is missing, it means it is compatible with any printer. // It is not mandatory. If the key is missing, it means it is compatible with any printer.
// If the key exists and it is empty, it means it is compatible with no printer. // If the key exists and it is empty, it means it is compatible with no printer.
@ -764,6 +804,11 @@ bool PresetCollection::select_preset_by_name(const std::string &name_w_suffix, b
// If the first visible preset was not found, return the 0th element, which is the default preset. // If the first visible preset was not found, return the 0th element, which is the default preset.
} }
// Temporary decision
if (name_w_suffix == "------- System presets -------" ||
name_w_suffix == "------- User presets -------")
return true;
// 2) Select the new preset. // 2) Select the new preset.
if (m_idx_selected != idx || force) { if (m_idx_selected != idx || force) {
this->select_preset(idx); this->select_preset(idx);

View file

@ -20,6 +20,10 @@ namespace Slic3r {
class AppConfig; class AppConfig;
class PresetBundle; class PresetBundle;
namespace GUI {
class BitmapCache;
}
enum ConfigFileType enum ConfigFileType
{ {
CONFIG_FILE_TYPE_UNKNOWN, CONFIG_FILE_TYPE_UNKNOWN,
@ -302,18 +306,18 @@ public:
// Compare the content of get_selected_preset() with get_edited_preset() configs, return true if they differ. // Compare the content of get_selected_preset() with get_edited_preset() configs, return true if they differ.
bool current_is_dirty() const { return ! this->current_dirty_options().empty(); } bool current_is_dirty() const { return ! this->current_dirty_options().empty(); }
// Compare the content of get_selected_preset() with get_edited_preset() configs, return the list of keys where they differ. // Compare the content of get_selected_preset() with get_edited_preset() configs, return the list of keys where they differ.
std::vector<std::string> current_dirty_options() const std::vector<std::string> current_dirty_options(const bool is_printer_type = false) const
{ return dirty_options(&this->get_edited_preset(), &this->get_selected_preset()); } { return dirty_options(&this->get_edited_preset(), &this->get_selected_preset(), is_printer_type); }
// Compare the content of get_selected_preset() with get_edited_preset() configs, return the list of keys where they differ. // Compare the content of get_selected_preset() with get_edited_preset() configs, return the list of keys where they differ.
std::vector<std::string> current_different_from_parent_options() const std::vector<std::string> current_different_from_parent_options(const bool is_printer_type = false) const
{ return dirty_options(&this->get_edited_preset(), this->get_selected_preset_parent()); } { return dirty_options(&this->get_edited_preset(), this->get_selected_preset_parent(), is_printer_type); }
// Compare the content of get_selected_preset() with get_selected_preset_parent() configs, return the list of keys where they equal. // Compare the content of get_selected_preset() with get_selected_preset_parent() configs, return the list of keys where they equal.
std::vector<std::string> system_equal_options() const; std::vector<std::string> system_equal_options() const;
// Update the choice UI from the list of presets. // Update the choice UI from the list of presets.
// If show_incompatible, all presets are shown, otherwise only the compatible presets are shown. // If show_incompatible, all presets are shown, otherwise only the compatible presets are shown.
// If an incompatible preset is selected, it is shown as well. // If an incompatible preset is selected, it is shown as well.
void update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible); size_t update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible);
// Update the choice UI from the list of presets. // Update the choice UI from the list of presets.
// Only the compatible presets are shown. // Only the compatible presets are shown.
// If an incompatible preset is selected, it is shown as well. // If an incompatible preset is selected, it is shown as well.
@ -358,7 +362,7 @@ private:
size_t update_compatible_with_printer_internal(const Preset &active_printer, bool unselect_if_incompatible); size_t update_compatible_with_printer_internal(const Preset &active_printer, bool unselect_if_incompatible);
static std::vector<std::string> dirty_options(const Preset *edited, const Preset *reference); static std::vector<std::string> dirty_options(const Preset *edited, const Preset *reference, const bool is_printer_type = false);
// Type of this PresetCollection: TYPE_PRINT, TYPE_FILAMENT or TYPE_PRINTER. // Type of this PresetCollection: TYPE_PRINT, TYPE_FILAMENT or TYPE_PRINTER.
Preset::Type m_type; Preset::Type m_type;
@ -384,6 +388,9 @@ private:
// Path to the directory to store the config files into. // Path to the directory to store the config files into.
std::string m_dir_path; std::string m_dir_path;
// Caching color bitmaps for the filament combo box.
GUI::BitmapCache *m_bitmap_cache = nullptr;
// to access select_preset_by_name_strict() // to access select_preset_by_name_strict()
friend class PresetBundle; friend class PresetBundle;
}; };

View file

@ -1011,6 +1011,10 @@ void PresetBundle::export_configbundle(const std::string &path) //, const Dynami
// an optional "(modified)" suffix will be removed from the filament name. // an optional "(modified)" suffix will be removed from the filament name.
void PresetBundle::set_filament_preset(size_t idx, const std::string &name) void PresetBundle::set_filament_preset(size_t idx, const std::string &name)
{ {
if (name == "------- System presets -------" ||
name == "------- User presets -------")
return;
if (idx >= filament_presets.size()) if (idx >= filament_presets.size())
filament_presets.resize(idx + 1, filaments.default_preset().name); filament_presets.resize(idx + 1, filaments.default_preset().name);
filament_presets[idx] = Preset::remove_suffix_modified(name); filament_presets[idx] = Preset::remove_suffix_modified(name);
@ -1059,9 +1063,11 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma
// and draw a red flag in front of the selected preset. // and draw a red flag in front of the selected preset.
bool wide_icons = selected_preset != nullptr && ! selected_preset->is_compatible && m_bitmapIncompatible != nullptr; bool wide_icons = selected_preset != nullptr && ! selected_preset->is_compatible && m_bitmapIncompatible != nullptr;
assert(selected_preset != nullptr); assert(selected_preset != nullptr);
std::map<wxString, wxBitmap> nonsys_presets; std::map<wxString, wxBitmap*> nonsys_presets;
wxString selected_str = ""; wxString selected_str = "";
for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++ i) { if (!this->filaments().front().is_visible)
ui->Append("------- System presets -------", wxNullBitmap);
for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++i) {
const Preset &preset = this->filaments.preset(i); const Preset &preset = this->filaments.preset(i);
bool selected = this->filament_presets[idx_extruder] == preset.name; bool selected = this->filament_presets[idx_extruder] == preset.name;
if (! preset.is_visible || (! preset.is_compatible && ! selected)) if (! preset.is_visible || (! preset.is_compatible && ! selected))
@ -1093,14 +1099,11 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma
bmps.emplace_back(m_bitmapCache->mksolid(8, 16, rgb)); bmps.emplace_back(m_bitmapCache->mksolid(8, 16, rgb));
} }
// Paint a lock at the system presets. // Paint a lock at the system presets.
bmps.emplace_back(m_bitmapCache->mkclear(4, 16)); bmps.emplace_back(m_bitmapCache->mkclear(2, 16));
bmps.emplace_back((preset.is_system || preset.is_default) ? bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmapLock : m_bitmapCache->mkclear(16, 16));
(preset.is_dirty ? *m_bitmapLockOpen : *m_bitmapLock) : m_bitmapCache->mkclear(16, 16)); // (preset.is_dirty ? *m_bitmapLockOpen : *m_bitmapLock) : m_bitmapCache->mkclear(16, 16));
bitmap = m_bitmapCache->insert(bitmap_key, bmps); bitmap = m_bitmapCache->insert(bitmap_key, bmps);
} }
// ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), (bitmap == 0) ? wxNullBitmap : *bitmap);
// if (selected)
// ui->SetSelection(ui->GetCount() - 1);
if (preset.is_default || preset.is_system){ if (preset.is_default || preset.is_system){
ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()),
@ -1111,19 +1114,19 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma
else else
{ {
nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()),
(bitmap == 0) ? wxNullBitmap : *bitmap); (bitmap == 0) ? &wxNullBitmap : bitmap);
if (selected) if (selected)
selected_str = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()); selected_str = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str());
} }
if (preset.is_default) if (preset.is_default)
ui->Append("------------------------------------", wxNullBitmap); ui->Append("------- System presets -------", wxNullBitmap);
} }
if (!nonsys_presets.empty()) if (!nonsys_presets.empty())
{ {
ui->Append("------------------------------------", wxNullBitmap); ui->Append("------- User presets -------", wxNullBitmap);
for (std::map<wxString, wxBitmap>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
ui->Append(it->first, it->second); ui->Append(it->first, *it->second);
if (it->first == selected_str) if (it->first == selected_str)
ui->SetSelection(ui->GetCount() - 1); ui->SetSelection(ui->GetCount() - 1);
} }

View file

@ -8,6 +8,7 @@
#include "slic3r/Utils/OctoPrint.hpp" #include "slic3r/Utils/OctoPrint.hpp"
#include "BonjourDialog.hpp" #include "BonjourDialog.hpp"
#include "WipeTowerDialog.hpp" #include "WipeTowerDialog.hpp"
#include "ButtonsDescription.hpp"
#include <wx/app.h> #include <wx/app.h>
#include <wx/button.h> #include <wx/button.h>
@ -23,6 +24,9 @@
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include "wxExtensions.hpp" #include "wxExtensions.hpp"
#include <wx/wupdlock.h>
#include <chrono>
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
@ -88,9 +92,9 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
if (wxMSW) m_btn_delete_preset->SetBackgroundColour(color); if (wxMSW) m_btn_delete_preset->SetBackgroundColour(color);
m_show_incompatible_presets = false; m_show_incompatible_presets = false;
m_bmp_show_incompatible_presets = new wxBitmap(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG); m_bmp_show_incompatible_presets.LoadFile(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG);
m_bmp_hide_incompatible_presets = new wxBitmap(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG); m_bmp_hide_incompatible_presets.LoadFile(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG);
m_btn_hide_incompatible_presets = new wxBitmapButton(panel, wxID_ANY, *m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); m_btn_hide_incompatible_presets = new wxBitmapButton(panel, wxID_ANY, m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
if (wxMSW) m_btn_hide_incompatible_presets->SetBackgroundColour(color); if (wxMSW) m_btn_hide_incompatible_presets->SetBackgroundColour(color);
m_btn_save_preset->SetToolTip(_(L("Save current ")) + m_title); m_btn_save_preset->SetToolTip(_(L("Save current ")) + m_title);
@ -99,14 +103,44 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
m_undo_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); m_undo_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
m_undo_to_sys_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); m_undo_to_sys_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
m_question_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
if (wxMSW) { if (wxMSW) {
m_undo_btn->SetBackgroundColour(color); m_undo_btn->SetBackgroundColour(color);
m_undo_to_sys_btn->SetBackgroundColour(color); m_undo_to_sys_btn->SetBackgroundColour(color);
m_question_btn->SetBackgroundColour(color);
} }
m_undo_btn->SetBitmap(wxBitmap(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG));
m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_initial_value(); })); m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information.")));
m_undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG));
m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_sys_value(); })); // Determine the theme color of OS (dark or light)
auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
// Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
m_bmp_value_lock .LoadFile(from_u8(var("sys_lock.png")), wxBITMAP_TYPE_PNG);
m_bmp_value_unlock .LoadFile(from_u8(var(luma >= 128 ? "sys_unlock.png" : "sys_unlock_grey.png")), wxBITMAP_TYPE_PNG);
m_bmp_non_system = &m_bmp_white_bullet;
// Bitmaps to be shown on the "Undo user changes" button next to each input field.
m_bmp_value_revert .LoadFile(from_u8(var(luma >= 128 ? "action_undo.png" : "action_undo_grey.png")), wxBITMAP_TYPE_PNG);
m_bmp_white_bullet .LoadFile(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG);
m_bmp_question .LoadFile(from_u8(var("question_mark_01.png")), wxBITMAP_TYPE_PNG);
fill_icon_descriptions();
set_tooltips_text();
m_undo_btn->SetBitmap(m_bmp_white_bullet);
m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_roll_back_value(); }));
m_undo_to_sys_btn->SetBitmap(m_bmp_white_bullet);
m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_roll_back_value(true); }));
m_question_btn->SetBitmap(m_bmp_question);
m_question_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent)
{
auto dlg = new ButtonsDescription(this, &m_icon_descriptions);
dlg->ShowModal();
}));
// Colors for ui "decoration"
m_sys_label_clr = get_sys_label_clr();
m_modified_label_clr = get_modified_label_clr();
m_default_text_clr = get_default_label_clr();
m_hsizer = new wxBoxSizer(wxHORIZONTAL); m_hsizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(m_hsizer, 0, wxBOTTOM, 3); sizer->Add(m_hsizer, 0, wxBOTTOM, 3);
@ -120,7 +154,8 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
m_hsizer->AddSpacer(64); m_hsizer->AddSpacer(64);
m_hsizer->Add(m_undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->Add(m_undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL);
m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL);
// m_hsizer->AddSpacer(64); m_hsizer->AddSpacer(32);
m_hsizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL);
// m_hsizer->Add(m_cc_presets_choice, 1, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3); // m_hsizer->Add(m_cc_presets_choice, 1, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3);
//Horizontal sizer to hold the tree and the selected page. //Horizontal sizer to hold the tree and the selected page.
@ -183,8 +218,16 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
//! select_preset(m_presets_choice->GetStringSelection().ToStdString()); //! select_preset(m_presets_choice->GetStringSelection().ToStdString());
//! we doing next: //! we doing next:
int selected_item = m_presets_choice->GetSelection(); int selected_item = m_presets_choice->GetSelection();
if (m_selected_preset_item == selected_item)
return;
if (selected_item >= 0){ if (selected_item >= 0){
std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data(); std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data();
if (selected_string == "------- System presets -------" ||
selected_string == "------- User presets -------"){
m_presets_choice->SetSelection(m_selected_preset_item);
return;
}
m_selected_preset_item = selected_item;
select_preset(selected_string); select_preset(selected_string);
} }
})); }));
@ -204,8 +247,9 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
void Tab::load_initial_data() void Tab::load_initial_data()
{ {
m_config = &m_presets->get_edited_preset().config; m_config = &m_presets->get_edited_preset().config;
m_nonsys_btn_icon = m_presets->get_selected_preset_parent() == nullptr ? m_bmp_non_system = m_presets->get_selected_preset_parent() ? &m_bmp_value_unlock : &m_bmp_white_bullet;
"bullet_white.png" : "sys_unlock.png"; m_ttg_non_system = m_presets->get_selected_preset_parent() ? &m_ttg_value_unlock : &m_ttg_white_bullet_ns;
m_tt_non_system = m_presets->get_selected_preset_parent() ? &m_tt_value_unlock : &m_ttg_white_bullet_ns;
} }
PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages/* = false*/) PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages/* = false*/)
@ -234,140 +278,78 @@ PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bo
return page; return page;
} }
template<class T>
void add_correct_opts_to_dirty_options(const std::string &opt_key, std::vector<std::string> *vec, TabPrinter *tab)
{
auto opt_init = static_cast<T*>(tab->m_presets->get_selected_preset().config.option(opt_key));
auto opt_cur = static_cast<T*>(tab->m_config->option(opt_key));
int opt_init_max_id = opt_init->values.size()-1;
for (int i = 0; i < opt_cur->values.size(); i++)
{
int init_id = i <= opt_init_max_id ? i : 0;
if (opt_cur->values[i] != opt_init->values[init_id])
vec->emplace_back(opt_key + "#" + std::to_string(i));
}
}
template<class T>
void add_correct_opts_to_sys_options(const std::string &opt_key, std::vector<std::string> *vec, TabPrinter *tab)
{
const Preset* sys_preset = tab->m_presets->get_selected_preset_parent();
if (sys_preset == nullptr)
return;
T *opt_cur = static_cast<T*>(tab->m_config->option(opt_key));
const T *opt_sys = static_cast<const T*>(sys_preset->config.option(opt_key));
int opt_max_id = opt_sys->values.size()-1;
for (int i = 0; i < opt_cur->values.size(); i++)
{
int init_id = i <= opt_max_id ? i : 0;
if (opt_cur->values[i] == opt_sys->values[init_id])
vec->emplace_back(opt_key + "#" + std::to_string(i));
}
}
// Update UI according to changes // Update UI according to changes
void Tab::update_changed_ui() void Tab::update_changed_ui()
{ {
auto dirty_options = m_presets->current_dirty_options(); if (m_postpone_update_ui)
return;
if (name() == "printer"){ const bool is_printer_type = (name() == "printer");
// Update dirty_options in case changes of Extruder's options auto dirty_options = m_presets->current_dirty_options(is_printer_type);
auto nonsys_options = m_presets->current_different_from_parent_options(is_printer_type);
if (is_printer_type){
TabPrinter* tab = static_cast<TabPrinter*>(this); TabPrinter* tab = static_cast<TabPrinter*>(this);
m_dirty_options.resize(0);
for (auto opt_key : dirty_options)
{
if (opt_key == "bed_shape"){ m_dirty_options.emplace_back(opt_key); continue; }
switch (m_config->option(opt_key)->type())
{
case coInts: add_correct_opts_to_dirty_options<ConfigOptionInts >(opt_key, &m_dirty_options, tab); break;
case coBools: add_correct_opts_to_dirty_options<ConfigOptionBools >(opt_key, &m_dirty_options, tab); break;
case coFloats: add_correct_opts_to_dirty_options<ConfigOptionFloats >(opt_key, &m_dirty_options, tab); break;
case coStrings: add_correct_opts_to_dirty_options<ConfigOptionStrings >(opt_key, &m_dirty_options, tab); break;
case coPercents:add_correct_opts_to_dirty_options<ConfigOptionPercents >(opt_key, &m_dirty_options, tab); break;
case coPoints: add_correct_opts_to_dirty_options<ConfigOptionPoints >(opt_key, &m_dirty_options, tab); break;
default: m_dirty_options.emplace_back(opt_key); break;
}
}
if (tab->m_initial_extruders_count != tab->m_extruders_count) if (tab->m_initial_extruders_count != tab->m_extruders_count)
m_dirty_options.emplace_back("extruders_count"); dirty_options.emplace_back("extruders_count");
if (tab->m_sys_extruders_count != tab->m_extruders_count)
m_sys_options.resize(0); nonsys_options.emplace_back("extruders_count");
const auto sys_preset = m_presets->get_selected_preset_parent();
if (sys_preset){
for (auto opt_key : m_config->keys())
{
if (opt_key == "bed_shape"){
if (*tab->m_config->option(opt_key) == *sys_preset->config.option(opt_key))
m_sys_options.emplace_back(opt_key);
continue;
}
switch (m_config->option(opt_key)->type())
{
case coInts: add_correct_opts_to_sys_options<ConfigOptionInts >(opt_key, &m_sys_options, tab); break;
case coBools: add_correct_opts_to_sys_options<ConfigOptionBools >(opt_key, &m_sys_options, tab); break;
case coFloats: add_correct_opts_to_sys_options<ConfigOptionFloats >(opt_key, &m_sys_options, tab); break;
case coStrings: add_correct_opts_to_sys_options<ConfigOptionStrings >(opt_key, &m_sys_options, tab); break;
case coPercents:add_correct_opts_to_sys_options<ConfigOptionPercents>(opt_key, &m_sys_options, tab); break;
case coPoints: add_correct_opts_to_sys_options<ConfigOptionPoints >(opt_key, &m_sys_options, tab); break;
default:{
const ConfigOption *opt_cur = tab->m_config->option(opt_key);
const ConfigOption *opt_sys = sys_preset->config.option(opt_key);
if (opt_cur != nullptr && opt_sys != nullptr && *opt_cur == *opt_sys)
m_sys_options.emplace_back(opt_key);
break;
}
}
}
if (tab->m_sys_extruders_count == tab->m_extruders_count)
m_sys_options.emplace_back("extruders_count");
}
}
else{
m_sys_options = m_presets->system_equal_options();
m_dirty_options = dirty_options;
} }
for (auto& it : m_options_list)
it.second = m_opt_status_value;
for (auto opt_key : dirty_options) m_options_list[opt_key] &= ~osInitValue;
for (auto opt_key : nonsys_options) m_options_list[opt_key] &= ~osSystemValue;
Freeze(); Freeze();
//update options "decoration" //update options "decoration"
for (const auto opt_key : m_full_options_list) for (const auto opt : m_options_list)
{ {
bool is_nonsys_value = false; bool is_nonsys_value = false;
bool is_modified_value = true; bool is_modified_value = true;
std::string sys_icon = "sys_lock.png"; const wxBitmap *sys_icon = &m_bmp_value_lock;
std::string icon = "action_undo.png"; const wxBitmap *icon = &m_bmp_value_revert;
wxColour color = get_sys_label_clr();
if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) { const wxColour *color = &m_sys_label_clr;
const wxString *sys_tt = &m_tt_value_lock;
const wxString *tt = &m_tt_value_revert;
// value isn't equal to system value
if ((opt.second & osSystemValue) == 0){
is_nonsys_value = true; is_nonsys_value = true;
sys_icon = m_nonsys_btn_icon; sys_icon = m_bmp_non_system;
if(find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end()) sys_tt = m_tt_non_system;
color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); // value is equal to last saved
if ((opt.second & osInitValue) != 0)
color = &m_default_text_clr;
// value is modified
else else
color = get_modified_label_clr(); color = &m_modified_label_clr;
} }
if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end()) if ((opt.second & osInitValue) != 0)
{ {
is_modified_value = false; is_modified_value = false;
icon = "bullet_white.png"; icon = &m_bmp_white_bullet;
tt = &m_tt_white_bullet;
} }
if (opt_key == "bed_shape" || opt_key == "compatible_printers") { if (opt.first == "bed_shape" || opt.first == "compatible_printers") {
if (m_colored_Label != nullptr) { if (m_colored_Label != nullptr) {
m_colored_Label->SetForegroundColour(color); m_colored_Label->SetForegroundColour(*color);
m_colored_Label->Refresh(true); m_colored_Label->Refresh(true);
} }
continue; continue;
} }
Field* field = get_field(opt_key); Field* field = get_field(opt.first);
if (field == nullptr) continue; if (field == nullptr) continue;
field->m_is_nonsys_value = is_nonsys_value; field->m_is_nonsys_value = is_nonsys_value;
field->m_is_modified_value = is_modified_value; field->m_is_modified_value = is_modified_value;
field->m_Undo_btn->SetBitmap(wxBitmap(from_u8(var(icon)), wxBITMAP_TYPE_PNG)); field->set_undo_bitmap(icon);
field->m_Undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(sys_icon)), wxBITMAP_TYPE_PNG)); field->set_undo_to_sys_bitmap(sys_icon);
if (field->m_Label != nullptr){ field->set_undo_tooltip(tt);
field->m_Label->SetForegroundColour(color); field->set_undo_to_sys_tooltip(sys_tt);
field->m_Label->Refresh(true); field->set_label_colour(color);
}
} }
Thaw(); Thaw();
@ -376,67 +358,53 @@ void Tab::update_changed_ui()
}); });
} }
void Tab::init_options_list()
{
if (!m_options_list.empty())
m_options_list.clear();
for (const auto opt_key : m_config->keys())
m_options_list.emplace(opt_key, m_opt_status_value);
}
template<class T> template<class T>
void add_correct_opts_to_full_options_list(const std::string &opt_key, std::vector<std::string> *vec, TabPrinter *tab) void add_correct_opts_to_options_list(const std::string &opt_key, std::map<std::string, int>& map, TabPrinter *tab, const int& value)
{ {
T *opt_cur = static_cast<T*>(tab->m_config->option(opt_key)); T *opt_cur = static_cast<T*>(tab->m_config->option(opt_key));
for (int i = 0; i < opt_cur->values.size(); i++) for (int i = 0; i < opt_cur->values.size(); i++)
vec->emplace_back(opt_key + "#" + std::to_string(i)); map.emplace(opt_key + "#" + std::to_string(i), value);
} }
void Tab::update_full_options_list() void TabPrinter::init_options_list()
{ {
if (!m_full_options_list.empty()) if (!m_options_list.empty())
m_full_options_list.resize(0); m_options_list.clear();
if (m_name != "printer"){
m_full_options_list = m_config->keys();
return;
}
TabPrinter* tab = static_cast<TabPrinter*>(this);
for (const auto opt_key : m_config->keys()) for (const auto opt_key : m_config->keys())
{ {
if (opt_key == "bed_shape"){ if (opt_key == "bed_shape"){
m_full_options_list.emplace_back(opt_key); m_options_list.emplace(opt_key, m_opt_status_value);
continue; continue;
} }
switch (m_config->option(opt_key)->type()) switch (m_config->option(opt_key)->type())
{ {
case coInts: add_correct_opts_to_full_options_list<ConfigOptionInts >(opt_key, &m_full_options_list, tab); break; case coInts: add_correct_opts_to_options_list<ConfigOptionInts >(opt_key, m_options_list, this, m_opt_status_value); break;
case coBools: add_correct_opts_to_full_options_list<ConfigOptionBools >(opt_key, &m_full_options_list, tab); break; case coBools: add_correct_opts_to_options_list<ConfigOptionBools >(opt_key, m_options_list, this, m_opt_status_value); break;
case coFloats: add_correct_opts_to_full_options_list<ConfigOptionFloats >(opt_key, &m_full_options_list, tab); break; case coFloats: add_correct_opts_to_options_list<ConfigOptionFloats >(opt_key, m_options_list, this, m_opt_status_value); break;
case coStrings: add_correct_opts_to_full_options_list<ConfigOptionStrings >(opt_key, &m_full_options_list, tab); break; case coStrings: add_correct_opts_to_options_list<ConfigOptionStrings >(opt_key, m_options_list, this, m_opt_status_value); break;
case coPercents:add_correct_opts_to_full_options_list<ConfigOptionPercents >(opt_key, &m_full_options_list, tab); break; case coPercents:add_correct_opts_to_options_list<ConfigOptionPercents >(opt_key, m_options_list, this, m_opt_status_value); break;
case coPoints: add_correct_opts_to_full_options_list<ConfigOptionPoints >(opt_key, &m_full_options_list, tab); break; case coPoints: add_correct_opts_to_options_list<ConfigOptionPoints >(opt_key, m_options_list, this, m_opt_status_value); break;
default: m_full_options_list.emplace_back(opt_key); break; default: m_options_list.emplace(opt_key, m_opt_status_value); break;
} }
} }
m_full_options_list.emplace_back("extruders_count"); m_options_list.emplace("extruders_count", m_opt_status_value);
}
void Tab::update_sys_ui_after_sel_preset()
{
for (const auto opt_key : m_full_options_list){
Field* field = get_field(opt_key);
if (field != nullptr){
field->m_Undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(m_nonsys_btn_icon)), wxBITMAP_TYPE_PNG));
field->m_is_nonsys_value = true;
if (field->m_Label != nullptr){
field->m_Label->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
field->m_Label->Refresh(true);
}
}
}
m_sys_options.resize(0);
} }
void Tab::get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page) void Tab::get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page)
{ {
if (sys_page && find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) auto opt = m_options_list.find(opt_key);
sys_page = false; if (sys_page) sys_page = (opt->second & osSystemValue) != 0;
if (!modified_page && find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) != m_dirty_options.end()) if (!modified_page) modified_page = (opt->second & osInitValue) == 0;
modified_page = true;
} }
void Tab::update_changed_tree_ui() void Tab::update_changed_tree_ui()
@ -457,7 +425,7 @@ void Tab::update_changed_tree_ui()
get_sys_and_mod_flags(opt_key, sys_page, modified_page); get_sys_and_mod_flags(opt_key, sys_page, modified_page);
} }
} }
if (title == _("Dependencies")){ if (title == _("Dependencies") && name() != "printer"){
get_sys_and_mod_flags("compatible_printers", sys_page, modified_page); get_sys_and_mod_flags("compatible_printers", sys_page, modified_page);
} }
for (auto group : page->m_optgroups) for (auto group : page->m_optgroups)
@ -469,12 +437,13 @@ void Tab::update_changed_tree_ui()
get_sys_and_mod_flags(opt_key, sys_page, modified_page); get_sys_and_mod_flags(opt_key, sys_page, modified_page);
} }
} }
if (sys_page)
m_treectrl->SetItemTextColour(cur_item, get_sys_label_clr()); const wxColor *clr = sys_page ? &m_sys_label_clr :
else if (modified_page) modified_page ? &m_modified_label_clr :
m_treectrl->SetItemTextColour(cur_item, get_modified_label_clr()); &m_default_text_clr;
else
m_treectrl->SetItemTextColour(cur_item, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); if (page->set_item_colour(clr))
m_treectrl->SetItemTextColour(cur_item, *clr);
page->m_is_nonsys_values = !sys_page; page->m_is_nonsys_values = !sys_page;
page->m_is_modified_values = modified_page; page->m_is_modified_values = modified_page;
@ -493,80 +462,62 @@ void Tab::update_changed_tree_ui()
void Tab::update_undo_buttons() void Tab::update_undo_buttons()
{ {
const std::string& undo_icon = !m_is_modified_values ? "bullet_white.png" : "action_undo.png"; m_undo_btn->SetBitmap(m_is_modified_values ? m_bmp_value_revert : m_bmp_white_bullet);
const std::string& undo_to_sys_icon = m_is_nonsys_values ? m_nonsys_btn_icon : "sys_lock.png"; m_undo_to_sys_btn->SetBitmap(m_is_nonsys_values ? *m_bmp_non_system : m_bmp_value_lock);
m_undo_btn->SetBitmap(wxBitmap(from_u8(var(undo_icon)), wxBITMAP_TYPE_PNG)); m_undo_btn->SetToolTip(m_is_modified_values ? m_ttg_value_revert : m_ttg_white_bullet);
m_undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(undo_to_sys_icon)), wxBITMAP_TYPE_PNG)); m_undo_to_sys_btn->SetToolTip(m_is_nonsys_values ? *m_ttg_non_system : m_ttg_value_lock);
} }
void Tab::on_back_to_initial_value() void Tab::on_roll_back_value(const bool to_sys /*= true*/)
{ {
if (!m_is_modified_values) return; int os;
if (to_sys) {
if (!m_is_nonsys_values) return;
os = osSystemValue;
}
else {
if (!m_is_modified_values) return;
os = osInitValue;
}
m_postpone_update_ui = true;
auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
for (auto page : m_pages) for (auto page : m_pages)
if (page->title() == selection) { if (page->title() == selection) {
for (auto group : page->m_optgroups){ for (auto group : page->m_optgroups){
if (group->title == _("Capabilities")){ if (group->title == _("Capabilities")){
if (find(m_dirty_options.begin(), m_dirty_options.end(), "extruders_count") != m_dirty_options.end()) if ((m_options_list["extruders_count"] & os) == 0)
group->back_to_initial_value("extruders_count"); to_sys ? group->back_to_sys_value("extruders_count") : group->back_to_initial_value("extruders_count");
} }
if (group->title == _("Size and coordinates")){ if (group->title == _("Size and coordinates")){
if (find(m_dirty_options.begin(), m_dirty_options.end(), "bed_shape") != m_dirty_options.end()) if ((m_options_list["bed_shape"] & os) == 0){
group->back_to_initial_value("bed_shape"); to_sys ? group->back_to_sys_value("bed_shape") : group->back_to_initial_value("bed_shape");
} load_key_value("bed_shape", true/*some value*/, true);
if (group->title == _("Profile dependencies")){ }
if (find(m_dirty_options.begin(), m_dirty_options.end(), "compatible_printers") != m_dirty_options.end())
group->back_to_initial_value("compatible_printers");
bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty(); }
m_compatible_printers_checkbox->SetValue(is_empty); if (group->title == _("Profile dependencies") && name() != "printer"){
is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable(); if ((m_options_list["compatible_printers"] & os) == 0){
to_sys ? group->back_to_sys_value("compatible_printers") : group->back_to_initial_value("compatible_printers");
load_key_value("compatible_printers", true/*some value*/, true);
bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
m_compatible_printers_checkbox->SetValue(is_empty);
is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable();
}
} }
for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) { for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) {
const std::string& opt_key = it->first; const std::string& opt_key = it->first;
if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) != m_dirty_options.end()) if ((m_options_list[opt_key] & os) == 0)
group->back_to_initial_value(opt_key); to_sys ? group->back_to_sys_value(opt_key) : group->back_to_initial_value(opt_key);
} }
} }
break; break;
} }
update_changed_ui();
}
void Tab::on_back_to_sys_value() m_postpone_update_ui = false;
{
if (!m_is_nonsys_values) return;
auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
for (auto page : m_pages)
if (page->title() == selection) {
for (auto group : page->m_optgroups) {
if (group->title == _("Capabilities")){
if (find(m_sys_options.begin(), m_sys_options.end(), "extruders_count") == m_sys_options.end())
group->back_to_sys_value("extruders_count");
}
if (group->title == _("Size and coordinates")){
if (find(m_sys_options.begin(), m_sys_options.end(), "bed_shape") == m_sys_options.end())
group->back_to_sys_value("bed_shape");
}
if (group->title == _("Profile dependencies")){
if (find(m_sys_options.begin(), m_sys_options.end(), "compatible_printers") == m_sys_options.end())
group->back_to_sys_value("compatible_printers");
bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
m_compatible_printers_checkbox->SetValue(is_empty);
is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable();
}
for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) {
const std::string& opt_key = it->first;
if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end())
group->back_to_sys_value(opt_key);
}
}
break;
}
update_changed_ui(); update_changed_ui();
} }
@ -581,7 +532,7 @@ void Tab::update_dirty(){
void Tab::update_tab_ui() void Tab::update_tab_ui()
{ {
m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets); m_selected_preset_item = m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets);
// update_tab_presets(m_cc_presets_choice, m_show_incompatible_presets); // update_tab_presets(m_cc_presets_choice, m_show_incompatible_presets);
// update_presetsctrl(m_presetctrl, m_show_incompatible_presets); // update_presetsctrl(m_presetctrl, m_show_incompatible_presets);
} }
@ -636,9 +587,11 @@ bool Tab::set_value(const t_config_option_key& opt_key, const boost::any& value)
// To be called by custom widgets, load a value into a config, // To be called by custom widgets, load a value into a config,
// update the preset selection boxes (the dirty flags) // update the preset selection boxes (the dirty flags)
void Tab::load_key_value(const std::string& opt_key, const boost::any& value) // If value is saved before calling this function, put saved_value = true,
// and value can be some random value because in this case it will not been used
void Tab::load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value /*= false*/)
{ {
change_opt_value(*m_config, opt_key, value); if (!saved_value) change_opt_value(*m_config, opt_key, value);
// Mark the print & filament enabled if they are compatible with the currently selected preset. // Mark the print & filament enabled if they are compatible with the currently selected preset.
if (opt_key.compare("compatible_printers") == 0) { if (opt_key.compare("compatible_printers") == 0) {
// Don't select another profile if this profile happens to become incompatible. // Don't select another profile if this profile happens to become incompatible.
@ -1354,6 +1307,7 @@ void TabFilament::reload_config(){
void TabFilament::update() void TabFilament::update()
{ {
Freeze();
wxString text = from_u8(PresetHints::cooling_description(m_presets->get_edited_preset())); wxString text = from_u8(PresetHints::cooling_description(m_presets->get_edited_preset()));
m_cooling_description_line->SetText(text); m_cooling_description_line->SetText(text);
text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle)); text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle));
@ -1367,6 +1321,7 @@ void TabFilament::update()
for (auto el : { "min_fan_speed", "disable_fan_first_layers" }) for (auto el : { "min_fan_speed", "disable_fan_first_layers" })
get_field(el)->toggle(fan_always_on); get_field(el)->toggle(fan_always_on);
Thaw();
} }
void TabFilament::OnActivate() void TabFilament::OnActivate()
@ -1396,6 +1351,9 @@ void TabPrinter::build()
m_presets = &m_preset_bundle->printers; m_presets = &m_preset_bundle->printers;
load_initial_data(); load_initial_data();
// to avoid redundant memory allocation / deallocation during extruders count changing
m_pages.reserve(30);
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter")); auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter"));
m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size(); m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size();
const Preset* parent_preset = m_presets->get_selected_preset_parent(); const Preset* parent_preset = m_presets->get_selected_preset_parent();
@ -1673,12 +1631,34 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){
} }
void TabPrinter::build_extruder_pages(){ void TabPrinter::build_extruder_pages(){
for (auto extruder_idx = m_extruder_pages.size(); extruder_idx < m_extruders_count; ++extruder_idx){ size_t n_before_extruders = 2; // Count of pages before Extruder pages
size_t n_after_single_extruder_MM = 2; // Count of pages after single_extruder_multi_material page
if (m_extruders_count_old == m_extruders_count || m_extruders_count <= 2)
{
// if we have a single extruder MM setup, add a page with configuration options:
for (int i = 0; i < m_pages.size(); ++i) // first make sure it's not there already
if (m_pages[i]->title().find(_(L("Single extruder MM setup"))) != std::string::npos) {
m_pages.erase(m_pages.begin() + i);
break;
}
if (m_extruders_count > 1 && m_config->opt_bool("single_extruder_multi_material")) {
// create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves
auto page = add_options_page(_(L("Single extruder MM setup")), "printer_empty.png", true);
auto optgroup = page->new_optgroup(_(L("Single extruder multimaterial parameters")));
optgroup->append_single_option_line("cooling_tube_retraction");
optgroup->append_single_option_line("cooling_tube_length");
optgroup->append_single_option_line("parking_pos_retraction");
m_pages.insert(m_pages.end() - n_after_single_extruder_MM, page);
}
}
for (auto extruder_idx = m_extruders_count_old; extruder_idx < m_extruders_count; ++extruder_idx){
//# build page //# build page
char buf[MIN_BUF_LENGTH_FOR_L]; char buf[MIN_BUF_LENGTH_FOR_L];
sprintf(buf, _CHB(L("Extruder %d")), extruder_idx + 1); sprintf(buf, _CHB(L("Extruder %d")), extruder_idx + 1);
auto page = add_options_page(from_u8(buf), "funnel.png", true); auto page = add_options_page(from_u8(buf), "funnel.png", true);
m_extruder_pages.push_back(page); m_pages.insert(m_pages.begin() + n_before_extruders + extruder_idx, page);
auto optgroup = page->new_optgroup(_(L("Size"))); auto optgroup = page->new_optgroup(_(L("Size")));
optgroup->append_single_option_line("nozzle_diameter", extruder_idx); optgroup->append_single_option_line("nozzle_diameter", extruder_idx);
@ -1716,36 +1696,11 @@ void TabPrinter::build_extruder_pages(){
} }
// # remove extra pages // # remove extra pages
if (m_extruders_count <= m_extruder_pages.size()) { if (m_extruders_count < m_extruders_count_old)
m_extruder_pages.resize(m_extruders_count); m_pages.erase( m_pages.begin() + n_before_extruders + m_extruders_count,
} m_pages.begin() + n_before_extruders + m_extruders_count_old);
// # rebuild page list m_extruders_count_old = m_extruders_count;
PageShp page_note = m_pages.back();
m_pages.pop_back();
while (m_pages.back()->title().find(_(L("Extruder"))) != std::string::npos)
m_pages.pop_back();
for (auto page_extruder : m_extruder_pages)
m_pages.push_back(page_extruder);
m_pages.push_back(page_note);
{
// if we have a single extruder MM setup, add a page with configuration options:
for (int i=0;i<m_pages.size();++i) // first make sure it's not there already
if (m_pages[i]->title().find(_(L("Single extruder MM setup"))) != std::string::npos) {
m_pages.erase(m_pages.begin()+i);
break;
}
if ( m_extruder_pages.size()>1 && m_config->opt_bool("single_extruder_multi_material")) {
// create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves
auto page = add_options_page(_(L("Single extruder MM setup")), "printer_empty.png",true);
auto optgroup = page->new_optgroup(_(L("Single extruder multimaterial parameters")));
optgroup->append_single_option_line("cooling_tube_retraction");
optgroup->append_single_option_line("cooling_tube_length");
optgroup->append_single_option_line("parking_pos_retraction");
m_pages.insert(m_pages.begin()+1,page);
}
}
rebuild_page_tree(); rebuild_page_tree();
} }
@ -1853,8 +1808,9 @@ void Tab::load_current_preset()
on_preset_loaded(); on_preset_loaded();
// Reload preset pages with the new configuration values. // Reload preset pages with the new configuration values.
reload_config(); reload_config();
const Preset* parent = m_presets->get_selected_preset_parent(); m_bmp_non_system = m_presets->get_selected_preset_parent() ? &m_bmp_value_unlock : &m_bmp_white_bullet;
m_nonsys_btn_icon = parent == nullptr ? "bullet_white.png" : "sys_unlock.png"; m_ttg_non_system = m_presets->get_selected_preset_parent() ? &m_ttg_value_unlock : &m_ttg_white_bullet_ns;
m_tt_non_system = m_presets->get_selected_preset_parent() ? &m_tt_value_unlock : &m_ttg_white_bullet_ns;
// use CallAfter because some field triggers schedule on_change calls using CallAfter, // use CallAfter because some field triggers schedule on_change calls using CallAfter,
// and we don't want them to be called after this update_dirty() as they would mark the // and we don't want them to be called after this update_dirty() as they would mark the
@ -1875,8 +1831,8 @@ void Tab::load_current_preset()
static_cast<TabPrinter*>(this)->m_sys_extruders_count = parent_preset == nullptr ? 0 : static_cast<TabPrinter*>(this)->m_sys_extruders_count = parent_preset == nullptr ? 0 :
static_cast<const ConfigOptionFloats*>(parent_preset->config.option("nozzle_diameter"))->values.size(); static_cast<const ConfigOptionFloats*>(parent_preset->config.option("nozzle_diameter"))->values.size();
} }
update_sys_ui_after_sel_preset(); m_opt_status_value = (m_presets->get_selected_preset_parent() ? osSystemValue : 0) | osInitValue;
update_full_options_list(); init_options_list();
update_changed_ui(); update_changed_ui();
}); });
} }
@ -1888,11 +1844,13 @@ void Tab::rebuild_page_tree()
// get label of the currently selected item // get label of the currently selected item
auto selected = m_treectrl->GetItemText(m_treectrl->GetSelection()); auto selected = m_treectrl->GetItemText(m_treectrl->GetSelection());
auto rootItem = m_treectrl->GetRootItem(); auto rootItem = m_treectrl->GetRootItem();
m_treectrl->DeleteChildren(rootItem);
auto have_selection = 0; auto have_selection = 0;
m_treectrl->DeleteChildren(rootItem);
for (auto p : m_pages) for (auto p : m_pages)
{ {
auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID()); auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID());
m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
if (p->title() == selected) { if (p->title() == selected) {
m_disable_tree_sel_changed_event = 1; m_disable_tree_sel_changed_event = 1;
m_treectrl->SelectItem(itemId); m_treectrl->SelectItem(itemId);
@ -1900,7 +1858,7 @@ void Tab::rebuild_page_tree()
have_selection = 1; have_selection = 1;
} }
} }
if (!have_selection) { if (!have_selection) {
// this is triggered on first load, so we don't disable the sel change event // this is triggered on first load, so we don't disable the sel change event
m_treectrl->SelectItem(m_treectrl->GetFirstVisibleItem());//! (treectrl->GetFirstChild(rootItem)); m_treectrl->SelectItem(m_treectrl->GetFirstVisibleItem());//! (treectrl->GetFirstChild(rootItem));
@ -2016,6 +1974,8 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr
void Tab::OnTreeSelChange(wxTreeEvent& event) void Tab::OnTreeSelChange(wxTreeEvent& event)
{ {
if (m_disable_tree_sel_changed_event) return; if (m_disable_tree_sel_changed_event) return;
wxWindowUpdateLocker noUpdates(this);
Page* page = nullptr; Page* page = nullptr;
auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
for (auto p : m_pages) for (auto p : m_pages)
@ -2142,7 +2102,7 @@ void Tab::toggle_show_hide_incompatible()
void Tab::update_show_hide_incompatible_button() void Tab::update_show_hide_incompatible_button()
{ {
m_btn_hide_incompatible_presets->SetBitmap(m_show_incompatible_presets ? m_btn_hide_incompatible_presets->SetBitmap(m_show_incompatible_presets ?
*m_bmp_show_incompatible_presets : *m_bmp_hide_incompatible_presets); m_bmp_show_incompatible_presets : m_bmp_hide_incompatible_presets);
m_btn_hide_incompatible_presets->SetToolTip(m_show_incompatible_presets ? m_btn_hide_incompatible_presets->SetToolTip(m_show_incompatible_presets ?
"Both compatible an incompatible presets are shown. Click to hide presets not compatible with the current printer." : "Both compatible an incompatible presets are shown. Click to hide presets not compatible with the current printer." :
"Only compatible presets are shown. Click to show both the presets compatible and not compatible with the current printer."); "Only compatible presets are shown. Click to show both the presets compatible and not compatible with the current printer.");
@ -2402,6 +2362,75 @@ void Tab::update_tab_presets(wxComboCtrl* ui, bool show_incompatible)
ui->Thaw(); ui->Thaw();
} }
void Tab::fill_icon_descriptions()
{
m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_lock, L("LOCKED LOCK;"
"indicates that the settings are the same as the system values for the current option group")));
m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_unlock, L("UNLOCKED LOCK;"
"indicates that some settings were changed and are not equal to the system values for "
"the current option group.\n"
"Click the UNLOCKED LOCK icon to reset all settings for current option group to "
"the system values.")));
m_icon_descriptions.push_back(t_icon_description(&m_bmp_white_bullet, L("WHITE BULLET;"
"for the left button: \tindicates a non-system preset,\n"
"for the right button: \tindicates that the settings hasn't been modified.")));
m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_revert, L("BACK ARROW;"
"indicates that the settings were changed and are not equal to the last saved preset for "
"the current option group.\n"
"Click the BACK ARROW icon to reset all settings for the current option group to "
"the last saved preset.")));
}
void Tab::set_tooltips_text()
{
// m_undo_to_sys_btn->SetToolTip(_(L( "LOCKED LOCK icon indicates that the settings are the same as the system values "
// "for the current option group.\n"
// "UNLOCKED LOCK icon indicates that some settings were changed and are not equal "
// "to the system values for the current option group.\n"
// "WHITE BULLET icon indicates a non system preset.\n\n"
// "Click the UNLOCKED LOCK icon to reset all settings for current option group to "
// "the system values.")));
//
// m_undo_btn->SetToolTip(_(L( "WHITE BULLET icon indicates that the settings are the same as in the last saved"
// "preset for the current option group.\n"
// "BACK ARROW icon indicates that the settings were changed and are not equal to "
// "the last saved preset for the current option group.\n\n"
// "Click the BACK ARROW icon to reset all settings for the current option group to "
// "the last saved preset.")));
// --- Tooltip text for reset buttons (for whole options group)
// Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
m_ttg_value_lock = _(L("LOCKED LOCK icon indicates that the settings are the same as the system values "
"for the current option group"));
m_ttg_value_unlock = _(L("UNLOCKED LOCK icon indicates that some settings were changed and are not equal "
"to the system values for the current option group.\n"
"Click to reset all settings for current option group to the system values."));
m_ttg_white_bullet_ns = _(L("WHITE BULLET icon indicates a non system preset."));
m_ttg_non_system = &m_ttg_white_bullet_ns;
// Text to be shown on the "Undo user changes" button next to each input field.
m_ttg_white_bullet = _(L("WHITE BULLET icon indicates that the settings are the same as in the last saved "
"preset for the current option group."));
m_ttg_value_revert = _(L("BACK ARROW icon indicates that the settings were changed and are not equal to "
"the last saved preset for the current option group.\n"
"Click to reset all settings for the current option group to the last saved preset."));
// --- Tooltip text for reset buttons (for each option in group)
// Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
m_tt_value_lock = _(L("LOCKED LOCK icon indicates that the value is the same as the system value."));
m_tt_value_unlock = _(L("UNLOCKED LOCK icon indicates that the value was changed and is not equal "
"to the system value.\n"
"Click to reset current value to the system value."));
// m_tt_white_bullet_ns= _(L("WHITE BULLET icon indicates a non system preset."));
m_tt_non_system = &m_ttg_white_bullet_ns;
// Text to be shown on the "Undo user changes" button next to each input field.
m_tt_white_bullet = _(L("WHITE BULLET icon indicates that the value is the same as in the last saved preset."));
m_tt_value_revert = _(L("BACK ARROW icon indicates that the value was changed and is not equal to the last saved preset.\n"
"Click to reset current value to the last saved preset."));
}
void Page::reload_config() void Page::reload_config()
{ {
for (auto group : m_optgroups) for (auto group : m_optgroups)
@ -2460,10 +2489,6 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la
return static_cast<Tab*>(GetParent())->m_presets->get_selected_preset_parent() != nullptr; return static_cast<Tab*>(GetParent())->m_presets->get_selected_preset_parent() != nullptr;
}; };
optgroup->nonsys_btn_icon = [this](){
return static_cast<Tab*>(GetParent())->m_nonsys_btn_icon;
};
vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10);
m_optgroups.push_back(optgroup); m_optgroups.push_back(optgroup);

View file

@ -1,3 +1,6 @@
#ifndef slic3r_Tab_hpp_
#define slic3r_Tab_hpp_
// The "Expert" tab at the right of the main tabbed window. // The "Expert" tab at the right of the main tabbed window.
// //
// This file implements following packages: // This file implements following packages:
@ -34,6 +37,9 @@
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
typedef std::pair<wxBitmap*, std::string> t_icon_description;
typedef std::vector<std::pair<wxBitmap*, std::string>> t_icon_descriptions;
// Single Tab page containing a{ vsizer } of{ optgroups } // Single Tab page containing a{ vsizer } of{ optgroups }
// package Slic3r::GUI::Tab::Page; // package Slic3r::GUI::Tab::Page;
using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>; using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>;
@ -51,6 +57,7 @@ public:
{ {
Create(m_parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); Create(m_parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
m_vsizer = new wxBoxSizer(wxVERTICAL); m_vsizer = new wxBoxSizer(wxVERTICAL);
m_item_color = &get_default_label_clr();
SetSizer(m_vsizer); SetSizer(m_vsizer);
} }
~Page(){} ~Page(){}
@ -71,6 +78,22 @@ public:
Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const; 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); bool set_value(const t_config_option_key& opt_key, const boost::any& value);
ConfigOptionsGroupShp new_optgroup(const wxString& title, int noncommon_label_width = -1); ConfigOptionsGroupShp new_optgroup(const wxString& title, int noncommon_label_width = -1);
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;
}
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;
}; };
// Slic3r::GUI::Tab; // Slic3r::GUI::Tab;
@ -85,8 +108,6 @@ protected:
wxBitmapComboBox* m_presets_choice; wxBitmapComboBox* m_presets_choice;
wxBitmapButton* m_btn_save_preset; wxBitmapButton* m_btn_save_preset;
wxBitmapButton* m_btn_delete_preset; wxBitmapButton* m_btn_delete_preset;
wxBitmap* m_bmp_show_incompatible_presets;
wxBitmap* m_bmp_hide_incompatible_presets;
wxBitmapButton* m_btn_hide_incompatible_presets; wxBitmapButton* m_btn_hide_incompatible_presets;
wxBoxSizer* m_hsizer; wxBoxSizer* m_hsizer;
wxBoxSizer* m_left_sizer; wxBoxSizer* m_left_sizer;
@ -96,10 +117,51 @@ protected:
wxButton* m_compatible_printers_btn; wxButton* m_compatible_printers_btn;
wxButton* m_undo_btn; wxButton* m_undo_btn;
wxButton* m_undo_to_sys_btn; wxButton* m_undo_to_sys_btn;
wxButton* m_question_btn;
wxComboCtrl* m_cc_presets_choice; wxComboCtrl* m_cc_presets_choice;
wxDataViewTreeCtrl* m_presetctrl; wxDataViewTreeCtrl* m_presetctrl;
wxImageList* m_preset_icons; wxImageList* m_preset_icons;
// Cached bitmaps.
// A "flag" icon to be displayned next to the preset name in the Tab's combo box.
wxBitmap m_bmp_show_incompatible_presets;
wxBitmap m_bmp_hide_incompatible_presets;
// Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
wxBitmap m_bmp_value_lock;
wxBitmap m_bmp_value_unlock;
wxBitmap 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.
wxBitmap *m_bmp_non_system;
// Bitmaps to be shown on the "Undo user changes" button next to each input field.
wxBitmap m_bmp_value_revert;
// wxBitmap m_bmp_value_unmodified;
wxBitmap m_bmp_question;
// Colors for ui "decoration"
wxColour m_sys_label_clr;
wxColour m_modified_label_clr;
wxColour m_default_text_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;
int m_icon_count; int m_icon_count;
std::map<std::string, size_t> m_icon_index; // Map from an icon file name to its index std::map<std::string, size_t> m_icon_index; // Map from an icon file name to its index
std::vector<PageShp> m_pages; std::vector<PageShp> m_pages;
@ -108,9 +170,11 @@ protected:
bool m_no_controller; bool m_no_controller;
std::vector<std::string> m_reload_dependent_tabs = {}; std::vector<std::string> m_reload_dependent_tabs = {};
std::vector<std::string> m_dirty_options = {}; enum OptStatus { osSystemValue = 1, osInitValue = 2 };
std::vector<std::string> m_sys_options = {}; std::map<std::string, int> m_options_list;
std::vector<std::string> m_full_options_list = {}; int m_opt_status_value;
t_icon_descriptions m_icon_descriptions = {};
// The two following two event IDs are generated at Plater.pm by calling Wx::NewEventType. // The two following two event IDs are generated at Plater.pm by calling Wx::NewEventType.
wxEventType m_event_value_change = 0; wxEventType m_event_value_change = 0;
@ -118,13 +182,15 @@ protected:
bool m_is_modified_values{ false }; bool m_is_modified_values{ false };
bool m_is_nonsys_values{ true }; bool m_is_nonsys_values{ true };
bool m_postpone_update_ui {false};
size_t m_selected_preset_item{ 0 };
public: public:
PresetBundle* m_preset_bundle; PresetBundle* m_preset_bundle;
bool m_show_btn_incompatible_presets = false; bool m_show_btn_incompatible_presets = false;
PresetCollection* m_presets; PresetCollection* m_presets;
DynamicPrintConfig* m_config; DynamicPrintConfig* m_config;
std::string m_nonsys_btn_icon;
ogStaticText* m_parent_preset_description_line; ogStaticText* m_parent_preset_description_line;
wxStaticText* m_colored_Label = nullptr; wxStaticText* m_colored_Label = nullptr;
@ -135,7 +201,9 @@ public:
Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
get_tabs_list().push_back(this); get_tabs_list().push_back(this);
} }
~Tab() { delete_tab_from_list(this); } ~Tab(){
delete_tab_from_list(this);
}
wxWindow* parent() const { return m_parent; } wxWindow* parent() const { return m_parent; }
wxString title() const { return m_title; } wxString title() const { return m_title; }
@ -153,7 +221,7 @@ public:
wxSizer* compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn); wxSizer* compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn);
void update_presetsctrl(wxDataViewTreeCtrl* ui, bool show_incompatible); void update_presetsctrl(wxDataViewTreeCtrl* ui, bool show_incompatible);
void load_key_value(const std::string& opt_key, const boost::any& value); void load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value = false);
void reload_compatible_printers_widget(); void reload_compatible_printers_widget();
void OnTreeSelChange(wxTreeEvent& event); void OnTreeSelChange(wxTreeEvent& event);
@ -165,14 +233,11 @@ public:
void update_show_hide_incompatible_button(); void update_show_hide_incompatible_button();
void update_ui_from_settings(); void update_ui_from_settings();
void update_changed_ui(); void update_changed_ui();
void update_full_options_list();
void update_sys_ui_after_sel_preset();
void get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page); void get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page);
void update_changed_tree_ui(); void update_changed_tree_ui();
void update_undo_buttons(); void update_undo_buttons();
void on_back_to_initial_value(); void on_roll_back_value(const bool to_sys = false);
void on_back_to_sys_value();
PageShp add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages = false); PageShp add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages = false);
@ -180,6 +245,7 @@ public:
virtual void on_preset_loaded(){} virtual void on_preset_loaded(){}
virtual void build() = 0; virtual void build() = 0;
virtual void update() = 0; virtual void update() = 0;
virtual void init_options_list();
void load_initial_data(); void load_initial_data();
void update_dirty(); void update_dirty();
void update_tab_ui(); void update_tab_ui();
@ -189,12 +255,11 @@ public:
bool set_value(const t_config_option_key& opt_key, const boost::any& value); bool set_value(const t_config_option_key& opt_key, const boost::any& value);
wxSizer* description_line_widget(wxWindow* parent, ogStaticText** StaticText); wxSizer* description_line_widget(wxWindow* parent, ogStaticText** StaticText);
bool current_preset_is_dirty(); bool current_preset_is_dirty();
DynamicPrintConfig* get_config() { return m_config; } DynamicPrintConfig* get_config() { return m_config; }
PresetCollection* get_presets() PresetCollection* get_presets() { return m_presets; }
{
return m_presets;
}
std::vector<std::string> get_dependent_tabs() { return m_reload_dependent_tabs; } std::vector<std::string> get_dependent_tabs() { return m_reload_dependent_tabs; }
size_t get_selected_preset_item() { return m_selected_preset_item; }
void on_value_change(const std::string& opt_key, const boost::any& value); void on_value_change(const std::string& opt_key, const boost::any& value);
@ -203,6 +268,8 @@ protected:
void update_frequently_changed_parameters(); void update_frequently_changed_parameters();
void update_wiping_button_visibility(); void update_wiping_button_visibility();
void update_tab_presets(wxComboCtrl* ui, bool show_incompatible); void update_tab_presets(wxComboCtrl* ui, bool show_incompatible);
void fill_icon_descriptions();
void set_tooltips_text();
}; };
//Slic3r::GUI::Tab::Print; //Slic3r::GUI::Tab::Print;
@ -248,9 +315,9 @@ public:
wxButton* m_octoprint_host_test_btn; wxButton* m_octoprint_host_test_btn;
size_t m_extruders_count; size_t m_extruders_count;
size_t m_extruders_count_old = 0;
size_t m_initial_extruders_count; size_t m_initial_extruders_count;
size_t m_sys_extruders_count; size_t m_sys_extruders_count;
std::vector<PageShp> m_extruder_pages;
TabPrinter() {} TabPrinter() {}
TabPrinter(wxNotebook* parent, bool no_controller) : Tab(parent, _(L("Printer Settings")), "printer", no_controller) {} TabPrinter(wxNotebook* parent, bool no_controller) : Tab(parent, _(L("Printer Settings")), "printer", no_controller) {}
@ -262,6 +329,7 @@ public:
void extruders_count_changed(size_t extruders_count); void extruders_count_changed(size_t extruders_count);
void build_extruder_pages(); void build_extruder_pages();
void on_preset_loaded() override; void on_preset_loaded() override;
void init_options_list() override;
}; };
class SavePresetWindow :public wxDialog class SavePresetWindow :public wxDialog
@ -280,3 +348,5 @@ public:
} // GUI } // GUI
} // Slic3r } // Slic3r
#endif /* slic3r_Tab_hpp_ */

View file

@ -11,6 +11,7 @@ void TabIface::load_config(DynamicPrintConfig* config) { m_tab->load_config(*con
void TabIface::load_key_value(char* opt_key, char* value){ m_tab->load_key_value(opt_key, static_cast<std::string>(value)); } void TabIface::load_key_value(char* opt_key, char* value){ m_tab->load_key_value(opt_key, static_cast<std::string>(value)); }
bool TabIface::current_preset_is_dirty() { return m_tab->current_preset_is_dirty();} bool TabIface::current_preset_is_dirty() { return m_tab->current_preset_is_dirty();}
void TabIface::OnActivate() { return m_tab->OnActivate();} void TabIface::OnActivate() { return m_tab->OnActivate();}
size_t TabIface::get_selected_preset_item() { return m_tab->get_selected_preset_item(); }
std::string TabIface::title() { return m_tab->title().ToUTF8().data(); } std::string TabIface::title() { return m_tab->title().ToUTF8().data(); }
DynamicPrintConfig* TabIface::get_config() { return m_tab->get_config(); } DynamicPrintConfig* TabIface::get_config() { return m_tab->get_config(); }
PresetCollection* TabIface::get_presets() { return m_tab!=nullptr ? m_tab->get_presets() : nullptr; } PresetCollection* TabIface::get_presets() { return m_tab!=nullptr ? m_tab->get_presets() : nullptr; }

View file

@ -1,3 +1,6 @@
#ifndef slic3r_TabIface_hpp_
#define slic3r_TabIface_hpp_
#include <vector> #include <vector>
#include <string> #include <string>
@ -27,9 +30,12 @@ public:
DynamicPrintConfig* get_config(); DynamicPrintConfig* get_config();
PresetCollection* get_presets(); PresetCollection* get_presets();
std::vector<std::string> get_dependent_tabs(); std::vector<std::string> get_dependent_tabs();
size_t get_selected_preset_item();
protected: protected:
GUI::Tab *m_tab; GUI::Tab *m_tab;
}; }; // namespace GUI
}; // namespace Slic3r }; // namespace Slic3r
#endif /* slic3r_TabIface_hpp_ */

View file

@ -16,6 +16,7 @@
bool current_preset_is_dirty(); bool current_preset_is_dirty();
void load_key_value(char* opt_key, char* value); void load_key_value(char* opt_key, char* value);
void OnActivate(); void OnActivate();
size_t get_selected_preset_item();
std::string title(); std::string title();
Ref<DynamicPrintConfig> get_config(); Ref<DynamicPrintConfig> get_config();
Ref<PresetCollection> get_presets(); Ref<PresetCollection> get_presets();