"on_change" function call correctly work now. Start adding of Tab::update().

It's need to think about config->set_key_value(...): at cpp side it's non-trivial.
This commit is contained in:
YuSanka 2018-01-05 15:11:33 +01:00
parent f8a48f5c13
commit e62c17bddf
9 changed files with 617 additions and 262 deletions

View file

@ -158,7 +158,9 @@ sub _build_field {
my $opt_id = $opt->opt_id;
my $on_change = sub {
#! This function will be called from Field.
my ($opt_id, $value) = @_;
#! Call OptionGroup._on_change(...)
$self->_on_change($opt_id, $value)
unless $self->_disabled;
};
@ -213,6 +215,7 @@ sub _build_field {
}
return undef if !$field;
#! setting up a function that will be triggered when the field changes
$field->on_change($on_change);
$field->on_kill_focus($on_kill_focus);
$self->_fields->{$opt_id} = $field;

View file

@ -15,13 +15,13 @@ namespace Slic3r { namespace GUI {
event.Skip(1);
// call the registered function if it is available
//! if (on_kill_focus)
//! on_kill_focus(opt_id);
if (on_kill_focus)
on_kill_focus(m_opt_id);
}
void Field::_on_change(wxCommandEvent& event) {
std::cerr << "calling Field::_on_change \n";
//! if (on_change != nullptr && !disable_change_event)
//! on_change(opt_id, "A");
void Field::on_change_field(wxCommandEvent& event) {
// std::cerr << "calling Field::_on_change \n";
if (m_on_change != nullptr && !m_disable_change_event)
m_on_change(m_opt_id, get_value());
}
@ -33,32 +33,32 @@ namespace Slic3r { namespace GUI {
void TextCtrl::BUILD() {
auto size = wxSize(wxDefaultSize);
if (opt.height >= 0) size.SetHeight(opt.height);
if (opt.width >= 0) size.SetWidth(opt.width);
if (m_opt.height >= 0) size.SetHeight(m_opt.height);
if (m_opt.width >= 0) size.SetWidth(m_opt.width);
wxString text_value = wxString("");
switch (opt.type) {
switch (m_opt.type) {
case coFloatOrPercent:
{
if (static_cast<const ConfigOptionFloatOrPercent*>(opt.default_value)->percent)
if (static_cast<const ConfigOptionFloatOrPercent*>(m_opt.default_value)->percent)
{
text_value = wxString::Format(_T("%i"), int(opt.default_value->getFloat()));
text_value = wxString::Format(_T("%i"), int(m_opt.default_value->getFloat()));
text_value += "%";
}
else
wxNumberFormatter::ToString(opt.default_value->getFloat(), 2);
wxNumberFormatter::ToString(m_opt.default_value->getFloat(), 2);
break;
}
case coPercent:
{
text_value = wxString::Format(_T("%i"), int(opt.default_value->getFloat()));
text_value = wxString::Format(_T("%i"), int(m_opt.default_value->getFloat()));
text_value += "%";
break;
}
case coPercents:
{
const ConfigOptionPercents *vec = static_cast<const ConfigOptionPercents*>(opt.default_value);
const ConfigOptionPercents *vec = static_cast<const ConfigOptionPercents*>(m_opt.default_value);
if (vec == nullptr || vec->empty()) break;
if (vec->size() > 1)
break;
@ -68,13 +68,13 @@ namespace Slic3r { namespace GUI {
}
case coFloat:
{
double val = opt.default_value->getFloat();
double val = m_opt.default_value->getFloat();
text_value = (val - int(val)) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2);
break;
}
case coFloats:
{
const ConfigOptionFloats *vec = static_cast<const ConfigOptionFloats*>(opt.default_value);
const ConfigOptionFloats *vec = static_cast<const ConfigOptionFloats*>(m_opt.default_value);
if (vec == nullptr || vec->empty()) break;
if (vec->size() > 1)
break;
@ -83,11 +83,11 @@ namespace Slic3r { namespace GUI {
break;
}
case coString:
text_value = static_cast<const ConfigOptionString*>(opt.default_value)->value;
text_value = static_cast<const ConfigOptionString*>(m_opt.default_value)->value;
break;
case coStrings:
{
const ConfigOptionStrings *vec = static_cast<const ConfigOptionStrings*>(opt.default_value);
const ConfigOptionStrings *vec = static_cast<const ConfigOptionStrings*>(m_opt.default_value);
if (vec == nullptr || vec->empty()) break;
if (vec->size() > 1)
break;
@ -98,11 +98,11 @@ namespace Slic3r { namespace GUI {
break;
}
auto temp = new wxTextCtrl(parent, wxID_ANY, text_value, wxDefaultPosition, size, (opt.multiline ? wxTE_MULTILINE : 0));
auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, (m_opt.multiline ? wxTE_MULTILINE : 0));
if (opt.tooltip.length() > 0) { temp->SetToolTip(opt.tooltip); }
if (m_opt.tooltip.length() > 0) { temp->SetToolTip(m_opt.tooltip); }
temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e); }), temp->GetId());
temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e); }), temp->GetId());
temp->Bind(wxEVT_KILL_FOCUS, ([this](wxFocusEvent e) { _on_kill_focus(e); }), temp->GetId());
// recast as a wxWindow to fit the calling convention
@ -116,21 +116,21 @@ namespace Slic3r { namespace GUI {
void CheckBox::BUILD() {
auto size = wxSize(wxDefaultSize);
if (opt.height >= 0) size.SetHeight(opt.height);
if (opt.width >= 0) size.SetWidth(opt.width);
if (m_opt.height >= 0) size.SetHeight(m_opt.height);
if (m_opt.width >= 0) size.SetWidth(m_opt.width);
bool check_value = opt.type == coBool ?
opt.default_value->getBool() : opt.type == coBools ?
static_cast<ConfigOptionBools*>(opt.default_value)->values.at(0) :
bool check_value = m_opt.type == coBool ?
m_opt.default_value->getBool() : m_opt.type == coBools ?
static_cast<ConfigOptionBools*>(m_opt.default_value)->values.at(0) :
false;
auto temp = new wxCheckBox(parent, wxID_ANY, wxString(""), wxDefaultPosition, size);
auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size);
temp->SetValue(check_value);
if (opt.readonly) temp->Disable();
if (m_opt.readonly) temp->Disable();
temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { _on_change(e); }), temp->GetId());
temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { on_change_field(e); }), temp->GetId());
if (opt.tooltip.length() > 0) { temp->SetToolTip(opt.tooltip); }
if (m_opt.tooltip.length() > 0) { temp->SetToolTip(m_opt.tooltip); }
// recast as a wxWindow to fit the calling convention
window = dynamic_cast<wxWindow*>(temp);
@ -140,20 +140,20 @@ int undef_spin_val = -9999; //! Probably, It's not necessary
void SpinCtrl::BUILD() {
auto size = wxSize(wxDefaultSize);
if (opt.height >= 0) size.SetHeight(opt.height);
if (opt.width >= 0) size.SetWidth(opt.width);
if (m_opt.height >= 0) size.SetHeight(m_opt.height);
if (m_opt.width >= 0) size.SetWidth(m_opt.width);
wxString text_value = wxString("");
int default_value = 0;
switch (opt.type) {
switch (m_opt.type) {
case coInt:
default_value = opt.default_value->getInt();
default_value = m_opt.default_value->getInt();
text_value = wxString::Format(_T("%i"), default_value);
break;
case coInts:
{
const ConfigOptionInts *vec = static_cast<const ConfigOptionInts*>(opt.default_value);
const ConfigOptionInts *vec = static_cast<const ConfigOptionInts*>(m_opt.default_value);
if (vec == nullptr || vec->empty()) break;
for (size_t id = 0; id < vec->size(); ++id)
{
@ -166,10 +166,10 @@ void SpinCtrl::BUILD() {
break;
}
auto temp = new wxSpinCtrl(parent, wxID_ANY, text_value, wxDefaultPosition, size,
0, opt.min >0 ? opt.min : 0, opt.max < 2147483647 ? opt.max : 2147483647, default_value);
auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size,
0, m_opt.min >0 ? m_opt.min : 0, m_opt.max < 2147483647 ? m_opt.max : 2147483647, default_value);
temp->Bind(wxEVT_SPINCTRL, ([=](wxCommandEvent e) { tmp_value = undef_spin_val; _on_change(e); }), temp->GetId());
temp->Bind(wxEVT_SPINCTRL, ([=](wxCommandEvent e) { tmp_value = undef_spin_val; on_change_field(e); }), temp->GetId());
temp->Bind(wxEVT_KILL_FOCUS, ([this](wxFocusEvent e) { tmp_value = undef_spin_val; _on_kill_focus(e); }), temp->GetId());
temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e)
{
@ -181,14 +181,14 @@ void SpinCtrl::BUILD() {
std::string value = e.GetString();
if (is_matched(value, "^\d+$"))
tmp_value = std::stoi(value);
_on_change(e);
on_change_field(e);
// # We don't reset tmp_value here because _on_change might put callbacks
// # in the CallAfter queue, and we want the tmp value to be available from
// # them as well.
}), temp->GetId());
if (opt.tooltip.length() > 0) { temp->SetToolTip(opt.tooltip); }
if (m_opt.tooltip.length() > 0) { temp->SetToolTip(m_opt.tooltip); }
// recast as a wxWindow to fit the calling convention
window = dynamic_cast<wxWindow*>(temp);
@ -196,66 +196,66 @@ void SpinCtrl::BUILD() {
void Choice::BUILD() {
auto size = wxSize(wxDefaultSize);
if (opt.height >= 0) size.SetHeight(opt.height);
if (opt.width >= 0) size.SetWidth(opt.width);
if (m_opt.height >= 0) size.SetHeight(m_opt.height);
if (m_opt.width >= 0) size.SetWidth(m_opt.width);
auto temp = new wxComboBox(parent, wxID_ANY, wxString(""), wxDefaultPosition, size);
if (opt.gui_type.compare("select_open") != 0)
auto temp = new wxComboBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size);
if (m_opt.gui_type.compare("select_open") != 0)
temp->SetExtraStyle(wxCB_READONLY);
// recast as a wxWindow to fit the calling convention
window = dynamic_cast<wxWindow*>(temp);
if (opt.enum_labels.empty() && opt.enum_values.empty()){
if (m_opt.enum_labels.empty() && m_opt.enum_values.empty()){
}
else{
for (auto el : opt.enum_labels.empty() ? opt.enum_values : opt.enum_labels)
for (auto el : m_opt.enum_labels.empty() ? m_opt.enum_values : m_opt.enum_labels)
temp->Append(wxString(el));
set_selection();
}
temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e); }), temp->GetId());
temp->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e) { _on_change(e); }), temp->GetId());
temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e); }), temp->GetId());
temp->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e) { on_change_field(e); }), temp->GetId());
if (opt.tooltip.length() > 0) temp->SetToolTip(opt.tooltip);
if (m_opt.tooltip.length() > 0) temp->SetToolTip(m_opt.tooltip);
}
void Choice::set_selection()
{
wxString text_value = wxString("");
switch (opt.type){
switch (m_opt.type){
case coFloat:
case coPercent: {
double val = opt.default_value->getFloat();
double val = m_opt.default_value->getFloat();
text_value = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 1);
auto idx = 0;
for (auto el : opt.enum_values)
for (auto el : m_opt.enum_values)
{
if (el.compare(text_value) == 0)
break;
++idx;
}
if (opt.type == coPercent) text_value += "%";
idx == opt.enum_values.size() ?
if (m_opt.type == coPercent) text_value += "%";
idx == m_opt.enum_values.size() ?
dynamic_cast<wxComboBox*>(window)->SetValue(text_value) :
dynamic_cast<wxComboBox*>(window)->SetSelection(idx);
break;
}
case coEnum:{
int id_value = static_cast<const ConfigOptionEnum<SeamPosition>*>(opt.default_value)->value; //!!
int id_value = static_cast<const ConfigOptionEnum<SeamPosition>*>(m_opt.default_value)->value; //!!
dynamic_cast<wxComboBox*>(window)->SetSelection(id_value);
break;
}
case coInt:{
int val = opt.default_value->getInt(); //!!
int val = m_opt.default_value->getInt(); //!!
text_value = wxString::Format(_T("%i"), int(val));
auto idx = 0;
for (auto el : opt.enum_values)
for (auto el : m_opt.enum_values)
{
if (el.compare(text_value) == 0)
break;
++idx;
}
idx == opt.enum_values.size() ?
idx == m_opt.enum_values.size() ?
dynamic_cast<wxComboBox*>(window)->SetValue(text_value) :
dynamic_cast<wxComboBox*>(window)->SetSelection(idx);
break;
@ -276,16 +276,16 @@ void Choice::set_selection()
// break;
// }
case coStrings:{
text_value = static_cast<const ConfigOptionStrings*>(opt.default_value)->values.at(0);
text_value = static_cast<const ConfigOptionStrings*>(m_opt.default_value)->values.at(0);
auto idx = 0;
for (auto el : opt.enum_values)
for (auto el : m_opt.enum_values)
{
if (el.compare(text_value) == 0)
break;
++idx;
}
idx == opt.enum_values.size() ?
idx == m_opt.enum_values.size() ?
dynamic_cast<wxComboBox*>(window)->SetValue(text_value) :
dynamic_cast<wxComboBox*>(window)->SetSelection(idx);
break;
@ -295,27 +295,29 @@ void Choice::set_selection()
void Choice::set_value(const std::string value) //! Redundant?
{
disable_change_event = true;
m_disable_change_event = true;
auto idx=0;
for (auto el : opt.enum_values)
for (auto el : m_opt.enum_values)
{
if (el.compare(value) == 0)
break;
++idx;
}
idx == opt.enum_values.size() ?
idx == m_opt.enum_values.size() ?
dynamic_cast<wxComboBox*>(window)->SetValue(value) :
dynamic_cast<wxComboBox*>(window)->SetSelection(idx);
disable_change_event = false;
m_disable_change_event = false;
}
//! it's needed for _update_serial_ports()
void Choice::set_values(const std::vector<std::string> values)
{
disable_change_event = true;
if (values.empty())
return;
m_disable_change_event = true;
// # it looks that Clear() also clears the text field in recent wxWidgets versions,
// # but we want to preserve it
@ -326,75 +328,75 @@ void Choice::set_values(const std::vector<std::string> values)
ww->Append(wxString(el));
ww->SetValue(value);
disable_change_event = false;
m_disable_change_event = false;
}
void ColourPicker::BUILD()
{
auto size = wxSize(wxDefaultSize);
if (opt.height >= 0) size.SetHeight(opt.height);
if (opt.width >= 0) size.SetWidth(opt.width);
if (m_opt.height >= 0) size.SetHeight(m_opt.height);
if (m_opt.width >= 0) size.SetWidth(m_opt.width);
wxString clr(static_cast<ConfigOptionStrings*>(opt.default_value)->values.at(0));
auto temp = new wxColourPickerCtrl(parent, wxID_ANY, clr, wxDefaultPosition, size);
wxString clr(static_cast<ConfigOptionStrings*>(m_opt.default_value)->values.at(0));
auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size);
// // recast as a wxWindow to fit the calling convention
window = dynamic_cast<wxWindow*>(temp);
temp->Bind(wxEVT_COLOURPICKER_CHANGED, ([=](wxCommandEvent e) { _on_change(e); }), temp->GetId());
temp->Bind(wxEVT_COLOURPICKER_CHANGED, ([=](wxCommandEvent e) { on_change_field(e); }), temp->GetId());
if (opt.tooltip.length() > 0) temp->SetToolTip(opt.tooltip);
if (m_opt.tooltip.length() > 0) temp->SetToolTip(m_opt.tooltip);
}
void Point::BUILD()
{
auto size = wxSize(wxDefaultSize);
if (opt.height >= 0) size.SetHeight(opt.height);
if (opt.width >= 0) size.SetWidth(opt.width);
if (m_opt.height >= 0) size.SetHeight(m_opt.height);
if (m_opt.width >= 0) size.SetWidth(m_opt.width);
auto temp = new wxBoxSizer(wxHORIZONTAL);
// $self->wxSizer($sizer);
//
wxSize field_size(40, -1);
auto default_pt = static_cast<ConfigOptionPoints*>(opt.default_value)->values.at(0);
auto default_pt = static_cast<ConfigOptionPoints*>(m_opt.default_value)->values.at(0);
double val = default_pt.x;
wxString X = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2);
val = default_pt.y;
wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2);
x_textctrl = new wxTextCtrl(parent, wxID_ANY, X, wxDefaultPosition, field_size);
y_textctrl = new wxTextCtrl(parent, wxID_ANY, Y, wxDefaultPosition, field_size);
x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size);
y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size);
temp->Add(new wxStaticText(parent, wxID_ANY, "x:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/);
temp->Add(new wxStaticText(m_parent, wxID_ANY, "x:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/);
temp->Add(x_textctrl);
temp->Add(new wxStaticText(parent, wxID_ANY, "y:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/);
temp->Add(new wxStaticText(m_parent, wxID_ANY, "y:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/);
temp->Add(y_textctrl);
x_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e/*$self->option->opt_id*/); }), x_textctrl->GetId());
y_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e/*$self->option->opt_id*/); }), x_textctrl->GetId());
x_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e/*$self->option->opt_id*/); }), x_textctrl->GetId());
y_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e/*$self->option->opt_id*/); }), x_textctrl->GetId());
// // recast as a wxWindow to fit the calling convention
sizer = dynamic_cast<wxSizer*>(temp);
if (opt.tooltip.length() > 0)
if (m_opt.tooltip.length() > 0)
{
x_textctrl->SetToolTip(opt.tooltip);
y_textctrl->SetToolTip(opt.tooltip);
x_textctrl->SetToolTip(m_opt.tooltip);
y_textctrl->SetToolTip(m_opt.tooltip);
}
}
void Point::set_value(const Pointf value)
{
disable_change_event = true;
m_disable_change_event = true;
double val = value.x;
x_textctrl->SetValue(val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2));
val = value.y;
y_textctrl->SetValue(val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2));
disable_change_event = false;
m_disable_change_event = false;
}
boost::any Point::get_value()

View file

@ -23,6 +23,8 @@ namespace Slic3r { namespace GUI {
class Field;
using t_field = std::unique_ptr<Field>;
using t_kill_focus = std::function<void(t_config_option_key)>;
using t_change = std::function<void(t_config_option_key, boost::any)>;
class Field {
protected:
@ -35,47 +37,47 @@ protected:
/// Call the attached on_kill_focus method.
void _on_kill_focus(wxFocusEvent& event);
/// Call the attached on_change method.
void _on_change(wxCommandEvent& event);
void on_change_field(wxCommandEvent& event);
public:
/// parent wx item, opportunity to refactor (probably not necessary - data duplication)
wxWindow* parent {nullptr};
wxWindow* m_parent {nullptr};
/// Function object to store callback passed in from owning object.
//! t_kill_focus on_kill_focus {nullptr};
t_kill_focus on_kill_focus {nullptr};
/// Function object to store callback passed in from owning object.
//! t_change on_change {nullptr};
t_change m_on_change {nullptr};
bool disable_change_event {false};
bool m_disable_change_event {false};
/// Copy of ConfigOption for deduction purposes
const ConfigOptionDef opt {ConfigOptionDef()};
const t_config_option_key opt_id;//! {""};
const ConfigOptionDef m_opt {ConfigOptionDef()};
const t_config_option_key m_opt_id;//! {""};
/// Sets a value for this control.
/// subclasses should overload with a specific version
/// Postcondition: Method does not fire the on_change event.
virtual void set_value(boost::any value) = 0;
virtual void set_value(boost::any value) = 0;
/// Gets a boost::any representing this control.
/// 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 disable() = 0;
virtual void enable() = 0;
virtual void disable() = 0;
/// 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 void set_tooltip(const wxString& tip) = 0;
virtual void set_tooltip(const wxString& tip) = 0;
Field(const ConfigOptionDef& opt, const t_config_option_key& id) : opt(opt), opt_id(id) {};
Field(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : parent(parent), opt(opt), 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) {};
/// If you don't know what you are getting back, check both methods for nullptr.
virtual wxSizer* getSizer() { return nullptr; }
virtual wxWindow* getWindow() { return nullptr; }
virtual wxSizer* getSizer() { return nullptr; }
virtual wxWindow* getWindow() { return nullptr; }
bool is_matched(std::string string, std::string pattern);
@ -210,14 +212,14 @@ public:
wxWindow* window{ nullptr };
void BUILD() override;
void set_selection();
// void set_selection();
void set_value(const std::string value) {
dynamic_cast<wxColourPickerCtrl*>(window)->SetColour(value);
}
void set_value(boost::any value) {
dynamic_cast<wxColourPickerCtrl*>(window)->SetColour(boost::any_cast<std::string>(value));
}
void set_values(const std::vector<std::string> values);
// void set_values(const std::vector<std::string> values);
boost::any get_value() override {
return boost::any(dynamic_cast<wxColourPickerCtrl*>(window)->GetColour());
}

View file

@ -32,11 +32,7 @@
#include <wx/window.h>
#include "Tab.h"
//#include <wx/bmpcbox.h>
//#include <wx/bmpbuttn.h>
//#include <wx/treectrl.h>
//#include <wx/imaglist.h>
#include "AppConfig.hpp"
namespace Slic3r { namespace GUI {
@ -189,15 +185,53 @@ void add_debug_menu(wxMenuBar *menu)
}
void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config)
{
add_created_tab(new CTabPrint (g_wxTabPanel, "Print"), preset_bundle, app_config);
add_created_tab(new CTabFilament(g_wxTabPanel, "Filament"), preset_bundle, app_config);
add_created_tab(new CTabPrinter (g_wxTabPanel, "Printer"), preset_bundle, app_config);
{
add_created_tab(new TabPrint (g_wxTabPanel, "Print"), preset_bundle, app_config);
add_created_tab(new TabFilament(g_wxTabPanel, "Filament"), preset_bundle, app_config);
add_created_tab(new TabPrinter (g_wxTabPanel, "Printer"), preset_bundle, app_config);
}
void add_created_tab(CTab* panel, PresetBundle *preset_bundle, AppConfig *app_config)
void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_config)
{
panel->create_preset_tab(preset_bundle, app_config);
panel->m_no_controller = app_config->get("no_controller").empty();
panel->create_preset_tab(preset_bundle);
// Callback to be executed after any of the configuration fields(Perl class Slic3r::GUI::OptionsGroup::Field) change their value.
panel->m_on_value_change = [/*this*/](std::string opt_key, boost::any value){
//! plater & loaded - variables of MainFrame
// if (plater) {
// plater->on_config_change(m_config); //# propagate config change events to the plater
// if (opt_key.compare("extruders_count") plater->on_extruders_change(value);
// }
// don't save while loading for the first time
// if (loaded && Slic3r::GUI::autosave) m_config->save(Slic3r::GUI::autosave) ;
};
// # Install a callback for the tab to update the platter and print controller presets, when
// # a preset changes at Slic3r::GUI::Tab.
// $tab->on_presets_changed(sub{
// if ($self->{plater}) {
// # Update preset combo boxes(Print settings, Filament, Printer) from their respective tabs.
// $self->{plater}->update_presets($tab_name, @_);
// if ($tab_name eq 'printer') {
// # Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors.
// my($presets, $reload_dependent_tabs) = @_;
// for my $tab_name_other(qw(print filament)) {
// # If the printer tells us that the print or filament preset has been switched or invalidated,
// # refresh the print or filament tab page.Otherwise just refresh the combo box.
// my $update_action = ($reload_dependent_tabs && (first{ $_ eq $tab_name_other } (@{$reload_dependent_tabs})))
// ? 'load_current_preset' : 'update_tab_ui';
// $self->{options_tabs}{$tab_name_other}->$update_action;
// }
// # Update the controller printers.
// $self->{controller}->update_presets(@_) if $self->{controller};
// }
// $self->{plater}->on_config_change($tab->{presets}->get_current_preset->config);
// }
// });
//# Load the currently selected preset into the GUI, update the preset selection box.
// panel->load_current_preset;
g_wxTabPanel->AddPage(panel, panel->title());
}

View file

@ -13,11 +13,12 @@ class wxNotebook;
namespace Slic3r {
class PresetBundle;
class PresetCollection;
class AppConfig;
namespace GUI {
class CTab;
class Tab;
void disable_screensaver();
void enable_screensaver();
@ -34,7 +35,7 @@ void add_debug_menu(wxMenuBar *menu);
// Create a new preset tab (print, filament and printer),
void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config);
// add it at the end of the tab panel.
void add_created_tab(CTab* panel, PresetBundle *preset_bundle, AppConfig *app_config);
void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_config);
void show_error(wxWindow* parent, std::string message);
void show_info(wxWindow* parent, std::string message, std::string title);

View file

@ -10,7 +10,7 @@ const t_field& OptionsGroup::build_field(const Option& opt) {
return build_field(opt.opt_id, opt.opt);
}
const t_field& OptionsGroup::build_field(const t_config_option_key& id) {
const ConfigOptionDef& opt = options.at(id);
const ConfigOptionDef& opt = m_options_map.at(id);
return build_field(id, opt);
}
@ -19,13 +19,13 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
// is the normal type.
if (opt.gui_type.compare("select") == 0) {
} else if (opt.gui_type.compare("select_open") == 0) {
fields.emplace(id, STDMOVE(Choice::Create<Choice>(_parent, opt, id)));
m_fields.emplace(id, STDMOVE(Choice::Create<Choice>(m_parent, opt, id)));
} else if (opt.gui_type.compare("color") == 0) {
fields.emplace(id, STDMOVE(ColourPicker::Create<ColourPicker>(_parent, opt, id)));
m_fields.emplace(id, STDMOVE(ColourPicker::Create<ColourPicker>(m_parent, opt, id)));
} else if (opt.gui_type.compare("f_enum_open") == 0 ||
opt.gui_type.compare("i_enum_open") == 0 ||
opt.gui_type.compare("i_enum_closed") == 0) {
fields.emplace(id, STDMOVE(Choice::Create<Choice>(_parent, opt, id)));
m_fields.emplace(id, STDMOVE(Choice::Create<Choice>(m_parent, opt, id)));
} else if (opt.gui_type.compare("slider") == 0) {
} else if (opt.gui_type.compare("i_spin") == 0) { // Spinctrl
} else {
@ -37,21 +37,21 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
case coPercents:
case coString:
case coStrings:
fields.emplace(id, STDMOVE(TextCtrl::Create<TextCtrl>(_parent, opt, id)));
m_fields.emplace(id, STDMOVE(TextCtrl::Create<TextCtrl>(m_parent, opt, id)));
break;
case coBool:
case coBools:
fields.emplace(id, STDMOVE(CheckBox::Create<CheckBox>(_parent, opt, id)));
m_fields.emplace(id, STDMOVE(CheckBox::Create<CheckBox>(m_parent, opt, id)));
break;
case coInt:
case coInts:
fields.emplace(id, STDMOVE(SpinCtrl::Create<SpinCtrl>(_parent, opt, id)));
m_fields.emplace(id, STDMOVE(SpinCtrl::Create<SpinCtrl>(m_parent, opt, id)));
break;
case coEnum:
fields.emplace(id, STDMOVE(Choice::Create<Choice>(_parent, opt, id)));
m_fields.emplace(id, STDMOVE(Choice::Create<Choice>(m_parent, opt, id)));
break;
case coPoints:
fields.emplace(id, STDMOVE(Point::Create<Point>(_parent, opt, id)));
m_fields.emplace(id, STDMOVE(Point::Create<Point>(m_parent, opt, id)));
break;
case coNone: break;
default:
@ -59,9 +59,14 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
}
}
// Grab a reference to fields for convenience
const t_field& field = fields[id];
//! field->on_change = [this](std::string id, boost::any val) { };
field->parent = parent();
const t_field& field = m_fields[id];
field->m_on_change = [this](std::string opt_id, boost::any value){
//! This function will be called from Field.
//! Call OptionGroup._on_change(...)
if (!this->m_disabled)
this->on_change_OG(opt_id, value);
};
field->m_parent = parent();
// assign function objects for callbacks, etc.
return field;
}
@ -74,7 +79,7 @@ void OptionsGroup::append_line(const Line& line) {
return;
}
if (line.widget != nullptr) {
sizer->Add(line.widget(_parent), 0, wxEXPAND | wxALL, wxOSX ? 0 : 15);
sizer->Add(line.widget(m_parent), 0, wxEXPAND | wxALL, wxOSX ? 0 : 15);
return;
}
}
@ -95,7 +100,7 @@ void OptionsGroup::append_line(const Line& line) {
return;
}
auto grid_sizer = _grid_sizer;
auto grid_sizer = m_grid_sizer;
// Build a label if we have it
if (label_width != 0) {
@ -146,8 +151,6 @@ void OptionsGroup::append_line(const Line& line) {
// add field
const Option& opt_ref = opt;
//! auto field = build_field(opt_ref)->getWindow();
//! sizer->Add(field, 0, wxALIGN_CENTER_VERTICAL, 0);
auto& field = build_field(opt_ref);
is_sizer_field(field) ?
sizer->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) :
@ -184,14 +187,45 @@ Line OptionsGroup::create_single_option_line(const Option& option) const {
return retval;
}
//! void OptionsGroup::_on_change(t_config_option_key id, config_value value) {
//! if (on_change != nullptr)
//! on_change(id, value);
//! }
void OptionsGroup::on_change_OG(t_config_option_key id, /*config_value*/boost::any value) {
if (m_on_change != nullptr)
m_on_change(id, value);
}
void OptionsGroup::_on_kill_focus (t_config_option_key id) {
// do nothing.
}
void ConfigOptionsGroup::on_change_OG(t_config_option_key opt_id, boost::any value)
{
// if (m_options_map.at(opt_id)/*exists $self->_opt_map->{$opt_id}*/) {
// my($opt_key, $opt_index) = @{ $self->_opt_map->{$opt_id} };
// auto option = m_options->{$opt_id};
}}
// get value
auto field_value = get_value(opt_id);
// if ($option->gui_flags = ~/ \bserialized\b / ) {
// die "Can't set serialized option indexed value" if $opt_index != -1;
// # Split a string to multiple strings by a semi - colon.This is the old way of storing multi - string values.
// # Currently used for the post_process config value only.
// my @values = split / ; / , $field_value;
// $self->config->set($opt_key, \@values);
// }
// else {
// if ($opt_index == -1) {
// $self->config->set($opt_key, $field_value);
//! m_config->set_key_value(opt_id, new ConfigOption(value));
// }
// else {
// my $value = $self->config->get($opt_key);
// $value->[$opt_index] = $field_value;
// $self->config->set($opt_key, $value);
// }
// }
// }
OptionsGroup::on_change_OG(opt_id, value);
}
} // GUI
} // Slic3r

View file

@ -33,118 +33,119 @@ class StaticText;
/// Wraps a ConfigOptionDef and adds function object for creating a side_widget.
struct Option {
ConfigOptionDef opt { ConfigOptionDef() };
t_config_option_key opt_id;//! {""};
widget_t side_widget {nullptr};
bool readonly {false};
ConfigOptionDef opt { ConfigOptionDef() };
t_config_option_key opt_id;//! {""};
widget_t side_widget {nullptr};
bool readonly {false};
Option(const ConfigOptionDef& _opt, t_config_option_key id) : opt(_opt), opt_id(id) {};
Option(const ConfigOptionDef& _opt, t_config_option_key id) :
opt(_opt), opt_id(id) {}
};
using t_option = std::unique_ptr<Option>; //!
/// Represents option lines
class Line {
public:
wxString label {wxString("")};
wxString label_tooltip {wxString("")};
size_t full_width {0};
wxSizer* sizer {nullptr};
widget_t widget {nullptr};
wxString label {wxString("")};
wxString label_tooltip {wxString("")};
size_t full_width {0};
wxSizer* sizer {nullptr};
widget_t widget {nullptr};
void append_option(const Option& option) {
_options.push_back(option);
m_options.push_back(option);
}
void append_widget(const widget_t widget) {
_extra_widgets.push_back(widget);
m_extra_widgets.push_back(widget);
}
Line(std::string label, std::string tooltip) : label(wxString(label)), label_tooltip(wxString(tooltip)) {} ;
Line(std::string label, std::string tooltip) :
label(wxString(label)), label_tooltip(wxString(tooltip)) {}
const std::vector<widget_t>& get_extra_widgets() const {return _extra_widgets;}
const std::vector<Option>& get_options() const { return _options; }
const std::vector<widget_t>& get_extra_widgets() const {return m_extra_widgets;}
const std::vector<Option>& get_options() const { return m_options; }
private:
std::vector<Option> _options;//! {std::vector<Option>()};
std::vector<widget_t> _extra_widgets;//! {std::vector<widget_t>()};
std::vector<Option> m_options;//! {std::vector<Option>()};
std::vector<widget_t> m_extra_widgets;//! {std::vector<widget_t>()};
};
using t_optionfield_map = std::map<t_config_option_key, t_field>;
class OptionsGroup {
public:
const bool staticbox {true};
const wxString title {wxString("")};
size_t label_width {200};
wxSizer* sizer {nullptr};
column_t extra_column {nullptr};
t_change m_on_change {nullptr};
const bool staticbox {true};
const wxString title {wxString("")};
size_t label_width {200};
wxSizer* sizer {nullptr};
column_t extra_column {nullptr};
// t_change on_change {nullptr};
wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
/// Returns a copy of the pointer of the parent wxWindow.
/// Accessor function is because users are not allowed to change the parent
/// but defining it as const means a lot of const_casts to deal with wx functions.
inline wxWindow* parent() const { return _parent; }
inline wxWindow* parent() const { return m_parent; }
wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
void append_line(const Line& line);
/*virtual*/ Line create_single_option_line(const Option& option) const;
inline void append_single_option_line(const Option& option) { append_line(create_single_option_line(option)); }
void append_line(const Line& line);
Line create_single_option_line(const Option& option) const;
inline void append_single_option_line(const Option& option) { append_line(create_single_option_line(option)); }
// return a non-owning pointer reference
inline const Field* get_field(t_config_option_key id) const { try { return fields.at(id).get(); } catch (std::out_of_range e) { return nullptr; } }
inline /*const*/ Field* get_field(t_config_option_key id) const { try { return m_fields.at(id).get(); } catch (std::out_of_range e) { return nullptr; } }
//! inline const Option& get_option(t_config_option_key id) const { try { return options.at(id).get(); } catch (std::out_of_range e) { return nullptr; } }
// }
//! inline void set_value(t_config_option_key id, boost::any value) { try { fields.at(id).set_value(value); } catch (std::out_of_range e) {;} }
inline void set_value(t_config_option_key id, boost::any value) { try { m_fields.at(id)->set_value(value); } catch (std::out_of_range e) {;} }
boost::any get_value(t_config_option_key id) { try { return m_fields.at(id)->get_value(); } catch (std::out_of_range e) { ; } }
inline void enable() { for (auto& field : fields) field.second->enable(); }
inline void disable() { for (auto& field : fields) field.second->disable(); }
inline void enable() { for (auto& field : m_fields) field.second->enable(); }
inline void disable() { for (auto& field : m_fields) field.second->disable(); }
OptionsGroup(wxWindow* _parent, std::string title, const ConfigDef& configs) : options(configs.options), _parent(_parent), title(wxString(title)) {
OptionsGroup(wxWindow* _parent, std::string title, const ConfigDef& configs) :
m_options_map(configs.options), m_parent(_parent), title(wxString(title)) {
sizer = (staticbox ? new wxStaticBoxSizer(new wxStaticBox(_parent, wxID_ANY, title), wxVERTICAL) : new wxBoxSizer(wxVERTICAL));
auto num_columns = 1U;
if (label_width != 0) num_columns++;
if (extra_column != nullptr) num_columns++;
_grid_sizer = new wxFlexGridSizer(0, num_columns, 0,0);
static_cast<wxFlexGridSizer*>(_grid_sizer)->SetFlexibleDirection(wxHORIZONTAL);
static_cast<wxFlexGridSizer*>(_grid_sizer)->AddGrowableCol(label_width != 0);
m_grid_sizer = new wxFlexGridSizer(0, num_columns, 0,0);
static_cast<wxFlexGridSizer*>(m_grid_sizer)->SetFlexibleDirection(wxHORIZONTAL);
static_cast<wxFlexGridSizer*>(m_grid_sizer)->AddGrowableCol(label_width != 0);
sizer->Add(_grid_sizer, 0, wxEXPAND | wxALL, wxOSX ? 0: 5);
};
sizer->Add(m_grid_sizer, 0, wxEXPAND | wxALL, wxOSX ? 0: 5);
}
protected:
const t_optiondef_map& options;
wxWindow* _parent {nullptr};
const t_optiondef_map& m_options_map;
wxWindow* m_parent {nullptr};
/// Field list, contains unique_ptrs of the derived type.
/// using types that need to know what it is beyond the public interface
/// need to cast based on the related ConfigOptionDef.
t_optionfield_map fields;
bool _disabled {false};
wxGridSizer* _grid_sizer {nullptr};
t_optionfield_map m_fields;
bool m_disabled {false};
wxGridSizer* m_grid_sizer {nullptr};
/// Generate a wxSizer or wxWindow from a configuration option
/// Precondition: opt resolves to a known ConfigOption
/// Postcondition: fields contains a wx gui object.
const t_field& build_field(const t_config_option_key& id, const ConfigOptionDef& opt);
const t_field& build_field(const t_config_option_key& id);
const t_field& build_field(const Option& opt);
virtual void _on_kill_focus (t_config_option_key id);
//! virtual void _on_change(t_config_option_key id, config_value value);
const t_field& build_field(const t_config_option_key& id, const ConfigOptionDef& opt);
const t_field& build_field(const t_config_option_key& id);
const t_field& build_field(const Option& opt);
virtual void _on_kill_focus (t_config_option_key id);
virtual void on_change_OG(t_config_option_key opt_id, boost::any value);
};
class ConfigOptionsGroup: public OptionsGroup {
public:
/// reference to libslic3r config, non-owning pointer (?).
const DynamicPrintConfig* config {nullptr};
bool full_labels {0};
ConfigOptionsGroup(wxWindow* parent, std::string title, DynamicPrintConfig* _config) : OptionsGroup(parent, title, *(_config->def())), config(_config) {}
const DynamicPrintConfig* m_config {nullptr};
bool m_full_labels {0};
ConfigOptionsGroup(wxWindow* parent, std::string title, DynamicPrintConfig* _config) :
OptionsGroup(parent, title, *(_config->def())), m_config(_config) {}
void on_change_OG(t_config_option_key opt_id, boost::any value) override;
};
}}

View file

@ -21,12 +21,12 @@ namespace Slic3r {
namespace GUI {
// sub new
void CTab::create_preset_tab(PresetBundle *preset_bundle, AppConfig *app_config)
void Tab::create_preset_tab(PresetBundle *preset_bundle)
{
m_preset_bundle = preset_bundle;
m_app_config = app_config;
// Vertical sizer to hold the choice menu and the rest of the page.
CTab *panel = this;
Tab *panel = this;
auto *sizer = new wxBoxSizer(wxVERTICAL);
sizer->SetSizeHints(panel);
panel->SetSizer(sizer);
@ -93,13 +93,13 @@ void CTab::create_preset_tab(PresetBundle *preset_bundle, AppConfig *app_config)
m_treectrl->SetIndent(0);
m_disable_tree_sel_changed_event = 0;
m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, &CTab::OnTreeSelChange, this);
m_treectrl->Bind(wxEVT_KEY_DOWN, &CTab::OnKeyDown, this);
m_treectrl->Bind(wxEVT_COMBOBOX, &CTab::OnComboBox, this);
m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, &Tab::OnTreeSelChange, this);
m_treectrl->Bind(wxEVT_KEY_DOWN, &Tab::OnKeyDown, this);
m_treectrl->Bind(wxEVT_COMBOBOX, &Tab::OnComboBox, this);
m_btn_save_preset->Bind(wxEVT_BUTTON, &CTab::save_preset, this);
m_btn_delete_preset->Bind(wxEVT_BUTTON, &CTab::delete_preset, this);
m_btn_hide_incompatible_presets->Bind(wxEVT_BUTTON, &CTab::toggle_show_hide_incompatible, this);
m_btn_save_preset->Bind(wxEVT_BUTTON, &Tab::save_preset, this);
m_btn_delete_preset->Bind(wxEVT_BUTTON, &Tab::delete_preset, this);
m_btn_hide_incompatible_presets->Bind(wxEVT_BUTTON, &Tab::toggle_show_hide_incompatible, this);
// Initialize the DynamicPrintConfig by default keys/values.
// Possible %params keys: no_controller
@ -108,7 +108,7 @@ void CTab::create_preset_tab(PresetBundle *preset_bundle, AppConfig *app_config)
// _update();
}
CPageShp CTab::add_options_page(wxString title, std::string icon, bool is_extruder_pages/* = false*/)
PageShp Tab::add_options_page(wxString title, std::string icon, bool is_extruder_pages/* = false*/)
{
// Index of icon in an icon list $self->{icons}.
auto icon_idx = 0;
@ -124,7 +124,7 @@ CPageShp CTab::add_options_page(wxString title, std::string icon, bool is_extrud
}
}
// Initialize the page.
CPageShp page(new CPage(this, title, icon_idx));
PageShp page(new Page(this, title, icon_idx));
page->SetScrollbars(1, 1, 1, 1);
page->Hide();
m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5);
@ -135,7 +135,64 @@ CPageShp CTab::add_options_page(wxString title, std::string icon, bool is_extrud
return page;
}
void CTab::load_key_value(std::string opt_key, std::vector<std::string> value)
// Update the combo box label of the selected preset based on its "dirty" state,
// comparing the selected preset config with $self->{config}.
void Tab::update_dirty(){
m_presets->update_dirty_ui(m_presets_choice);
// _on_presets_changed;
}
// Load a provied DynamicConfig into the tab, modifying the active preset.
// This could be used for example by setting a Wipe Tower position by interactive manipulation in the 3D view.
void Tab::load_config(DynamicPrintConfig config)
{
bool modified = 0;
for(auto opt_key : m_config.diff(config)) {
ConfigOption* opt;
switch ( config.def()->get(opt_key)->type ){
// case coFloatOrPercent:
case coPercent:
// case coPercents:
case coFloat:
opt = new ConfigOptionFloat(config.opt_float(opt_key));
break;
// case coFloats:
case coString:
opt = new ConfigOptionString(config.opt_string(opt_key));
break;
case coStrings:
break;
case coBool:
opt = new ConfigOptionBool(config.opt_bool(opt_key));
break;
case coBools:
// opt = new ConfigOptionBools(0, config.opt_bool(opt_key)); //! 0?
break;
case coInt:
opt = new ConfigOptionInt(config.opt_int(opt_key));
break;
case coInts:
break;
case coEnum:
break;
case coPoints:
break;
case coNone: break;
default:
break;
}
m_config.set_key_value(opt_key, opt);
modified = 1;
}
if (modified) {
// update_dirty();
//# Initialize UI components with the config values.
// _reload_config();
update();
}
}
void Tab::load_key_value(std::string opt_key, std::vector<std::string> value)
{
// # To be called by custom widgets, load a value into a config,
// # update the preset selection boxes (the dirty flags)
@ -151,9 +208,10 @@ void CTab::load_key_value(std::string opt_key, std::vector<std::string> value)
// $self->_update;
}
void CTabPrint::build()
void TabPrint::build()
{
m_config = m_preset_bundle->prints.get_edited_preset().config;
m_presets = &m_preset_bundle->prints;
m_config = m_presets->get_edited_preset().config;
m_config_def = m_config.def();
auto page = add_options_page("Layers and perimeters", "layers.png");
@ -352,7 +410,211 @@ void CTabPrint::build()
optgroup->append_line(line);
}
void CTabFilament::build()
void TabPrint::update()
{
Freeze();
if ( m_config.opt_bool("spiral_vase") &&
!(m_config.opt_int("perimeters") == 1 && m_config.opt_int("top_solid_layers") == 0 && m_config.opt_float("fill_density") == 0)) {
std::string msg_text = "The Spiral Vase mode requires:\n"
"- one perimeter\n"
"- no top solid layers\n"
"- 0% fill density\n"
"- no support material\n"
"- no ensure_vertical_shell_thickness\n"
"\nShall I adjust those settings in order to enable Spiral Vase?";
auto dialog = new wxMessageDialog(parent(), msg_text, wxT("Spiral Vase"), wxICON_WARNING | wxYES | wxNO);
DynamicPrintConfig new_conf = m_config;//new DynamicPrintConfig;
if (dialog->ShowModal() == wxID_YES) {
new_conf.set_key_value("perimeters", new ConfigOptionInt(1));
new_conf.set_key_value("top_solid_layers", new ConfigOptionInt(0));
new_conf.set_key_value("fill_density", new ConfigOptionPercent(0));
new_conf.set_key_value("support_material", new ConfigOptionBool(false));
new_conf.set_key_value("ensure_vertical_shell_thickness", new ConfigOptionBool(false));
}
else {
new_conf.set_key_value("spiral_vase", new ConfigOptionBool(false));
}
load_config(new_conf);
}
// if ($config->wipe_tower &&
// ($config->first_layer_height != 0.2 || $config->layer_height < 0.15 || $config->layer_height > 0.35)) {
// my $dialog = Wx::MessageDialog->new($self,
// "The Wipe Tower currently supports only:\n"
// . "- first layer height 0.2mm\n"
// . "- layer height from 0.15mm to 0.35mm\n"
// . "\nShall I adjust those settings in order to enable the Wipe Tower?",
// 'Wipe Tower', wxICON_WARNING | wxYES | wxNO);
// my $new_conf = Slic3r::Config->new;
// if ($dialog->ShowModal() == wxID_YES) {
// $new_conf->set("first_layer_height", 0.2);
// $new_conf->set("layer_height", 0.15) if $config->layer_height < 0.15;
// $new_conf->set("layer_height", 0.35) if $config->layer_height > 0.35;
// }
// else {
// $new_conf->set("wipe_tower", 0);
// }
// $self->load_config($new_conf);
// }
//
// if ($config->wipe_tower && $config->support_material && $config->support_material_contact_distance > 0. &&
// ($config->support_material_extruder != 0 || $config->support_material_interface_extruder != 0)) {
// my $dialog = Wx::MessageDialog->new($self,
// "The Wipe Tower currently supports the non-soluble supports only\n"
// . "if they are printed with the current extruder without triggering a tool change.\n"
// . "(both support_material_extruder and support_material_interface_extruder need to be set to 0).\n"
// . "\nShall I adjust those settings in order to enable the Wipe Tower?",
// 'Wipe Tower', wxICON_WARNING | wxYES | wxNO);
// my $new_conf = Slic3r::Config->new;
// if ($dialog->ShowModal() == wxID_YES) {
// $new_conf->set("support_material_extruder", 0);
// $new_conf->set("support_material_interface_extruder", 0);
// }
// else {
// $new_conf->set("wipe_tower", 0);
// }
// $self->load_config($new_conf);
// }
//
// if ($config->wipe_tower && $config->support_material && $config->support_material_contact_distance == 0 &&
// !$config->support_material_synchronize_layers) {
// my $dialog = Wx::MessageDialog->new($self,
// "For the Wipe Tower to work with the soluble supports, the support layers\n"
// . "need to be synchronized with the object layers.\n"
// . "\nShall I synchronize support layers in order to enable the Wipe Tower?",
// 'Wipe Tower', wxICON_WARNING | wxYES | wxNO);
// my $new_conf = Slic3r::Config->new;
// if ($dialog->ShowModal() == wxID_YES) {
// $new_conf->set("support_material_synchronize_layers", 1);
// }
// else {
// $new_conf->set("wipe_tower", 0);
// }
// $self->load_config($new_conf);
// }
//
// if ($config->support_material) {
// # Ask only once.
// if (!$self->{support_material_overhangs_queried}) {
// $self->{support_material_overhangs_queried} = 1;
// if ($config->overhangs != 1) {
// my $dialog = Wx::MessageDialog->new($self,
// "Supports work better, if the following feature is enabled:\n"
// . "- Detect bridging perimeters\n"
// . "\nShall I adjust those settings for supports?",
// 'Support Generator', wxICON_WARNING | wxYES | wxNO | wxCANCEL);
// my $answer = $dialog->ShowModal();
// my $new_conf = Slic3r::Config->new;
// if ($answer == wxID_YES) {
// # Enable "detect bridging perimeters".
// $new_conf->set("overhangs", 1);
// } elsif($answer == wxID_NO) {
// # Do nothing, leave supports on and "detect bridging perimeters" off.
// } elsif($answer == wxID_CANCEL) {
// # Disable supports.
// $new_conf->set("support_material", 0);
// $self->{support_material_overhangs_queried} = 0;
// }
// $self->load_config($new_conf);
// }
// }
// }
// else {
// $self->{support_material_overhangs_queried} = 0;
// }
//
// if ($config->fill_density == 100
// && !first{ $_ eq $config->fill_pattern } @{$Slic3r::Config::Options->{external_fill_pattern}{values}}) {
// my $dialog = Wx::MessageDialog->new($self,
// "The ".$config->fill_pattern . " infill pattern is not supposed to work at 100% density.\n"
// . "\nShall I switch to rectilinear fill pattern?",
// 'Infill', wxICON_WARNING | wxYES | wxNO);
//
// my $new_conf = Slic3r::Config->new;
// if ($dialog->ShowModal() == wxID_YES) {
// $new_conf->set("fill_pattern", 'rectilinear');
// $new_conf->set("fill_density", 100);
// }
// else {
// $new_conf->set("fill_density", 40);
// }
// $self->load_config($new_conf);
// }
//
// my $have_perimeters = $config->perimeters > 0;
// $self->get_field($_)->toggle($have_perimeters)
// for qw(extra_perimeters ensure_vertical_shell_thickness thin_walls overhangs seam_position external_perimeters_first
// external_perimeter_extrusion_width
// perimeter_speed small_perimeter_speed external_perimeter_speed);
//
// my $have_infill = $config->fill_density > 0;
// # infill_extruder uses the same logic as in Print::extruders()
// $self->get_field($_)->toggle($have_infill)
// for qw(fill_pattern infill_every_layers infill_only_where_needed solid_infill_every_layers
// solid_infill_below_area infill_extruder);
//
// my $have_solid_infill = ($config->top_solid_layers > 0) || ($config->bottom_solid_layers > 0);
// # solid_infill_extruder uses the same logic as in Print::extruders()
// $self->get_field($_)->toggle($have_solid_infill)
// for qw(external_fill_pattern infill_first solid_infill_extruder solid_infill_extrusion_width
// solid_infill_speed);
//
// $self->get_field($_)->toggle($have_infill || $have_solid_infill)
// for qw(fill_angle bridge_angle infill_extrusion_width infill_speed bridge_speed);
//
// $self->get_field('gap_fill_speed')->toggle($have_perimeters && $have_infill);
//
// my $have_top_solid_infill = $config->top_solid_layers > 0;
// $self->get_field($_)->toggle($have_top_solid_infill)
// for qw(top_infill_extrusion_width top_solid_infill_speed);
//
// my $have_default_acceleration = $config->default_acceleration > 0;
// $self->get_field($_)->toggle($have_default_acceleration)
// for qw(perimeter_acceleration infill_acceleration bridge_acceleration first_layer_acceleration);
//
// my $have_skirt = $config->skirts > 0 || $config->min_skirt_length > 0;
// $self->get_field($_)->toggle($have_skirt)
// for qw(skirt_distance skirt_height);
//
// my $have_brim = $config->brim_width > 0;
// # perimeter_extruder uses the same logic as in Print::extruders()
// $self->get_field('perimeter_extruder')->toggle($have_perimeters || $have_brim);
//
// my $have_raft = $config->raft_layers > 0;
// my $have_support_material = $config->support_material || $have_raft;
// my $have_support_interface = $config->support_material_interface_layers > 0;
// my $have_support_soluble = $have_support_material && $config->support_material_contact_distance == 0;
// $self->get_field($_)->toggle($have_support_material)
// for qw(support_material_threshold support_material_pattern support_material_with_sheath
// support_material_spacing support_material_angle
// support_material_interface_layers dont_support_bridges
// support_material_extrusion_width support_material_contact_distance support_material_xy_spacing);
// $self->get_field($_)->toggle($have_support_material && $have_support_interface)
// for qw(support_material_interface_spacing support_material_interface_extruder
// support_material_interface_speed support_material_interface_contact_loops);
// $self->get_field('support_material_synchronize_layers')->toggle($have_support_soluble);
//
// $self->get_field('perimeter_extrusion_width')->toggle($have_perimeters || $have_skirt || $have_brim);
// $self->get_field('support_material_extruder')->toggle($have_support_material || $have_skirt);
// $self->get_field('support_material_speed')->toggle($have_support_material || $have_brim || $have_skirt);
//
// my $have_sequential_printing = $config->complete_objects;
// $self->get_field($_)->toggle($have_sequential_printing)
// for qw(extruder_clearance_radius extruder_clearance_height);
//
// my $have_ooze_prevention = $config->ooze_prevention;
// $self->get_field($_)->toggle($have_ooze_prevention)
// for qw(standby_temperature_delta);
//
// my $have_wipe_tower = $config->wipe_tower;
// $self->get_field($_)->toggle($have_wipe_tower)
// for qw(wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_per_color_wipe);
Thaw();
}
void TabFilament::build()
{
m_config = m_preset_bundle->filaments.get_edited_preset().config;
m_config_def = m_config.def();
@ -447,7 +709,7 @@ void CTabFilament::build()
optgroup->append_line(line);
}
wxSizer* CTabFilament::description_line_widget(wxWindow* parent, wxStaticText* StaticText)
wxSizer* TabFilament::description_line_widget(wxWindow* parent, wxStaticText* StaticText)
{
StaticText = new wxStaticText(parent, wxID_ANY, "gfghjkkl;\n fgdsufhsreotklg\n iesrftorsikgyfkh\nauiwrhfidj", wxDefaultPosition, wxDefaultSize);
auto font = (new wxSystemSettings)->GetFont(wxSYS_DEFAULT_GUI_FONT);
@ -460,7 +722,7 @@ wxSizer* CTabFilament::description_line_widget(wxWindow* parent, wxStaticText* S
return sizer;
}
void CTabPrinter::build()
void TabPrinter::build()
{
m_config = m_preset_bundle->printers.get_edited_preset().config;
m_config_def = m_config.def(); // It will be used in get_option_(const std::string title)
@ -520,7 +782,7 @@ void CTabPrinter::build()
// });
//if (!$params{ no_controller })
if (m_app_config->get("no_controller").empty())
if (!m_no_controller/*m_app_config->get("no_controller").empty()*/)
{
optgroup = page->new_optgroup("USB/Serial connection");
line = {"Serial port", ""};
@ -692,17 +954,17 @@ void CTabPrinter::build()
build_extruder_pages();
// $self->_update_serial_ports if (!$params{ no_controller });
if (m_app_config->get("no_controller").empty()){
if (!m_no_controller/*m_app_config->get("no_controller").empty()*/){
Field *field = optgroup->get_field("serial_port");
Choice *choice = static_cast<Choice *>(field);
choice->set_values(scan_serial_ports());
}
}
void CTabPrinter::build_extruder_pages(){
void TabPrinter::build_extruder_pages(){
// auto default_config = m_preset_bundle->full_config();
std::vector<CPageShp> extruder_pages;
std::vector<PageShp> extruder_pages;
for (auto extruder_idx = 0; extruder_idx < m_extruders_count; ++extruder_idx){
//# build page
@ -750,7 +1012,7 @@ void CTabPrinter::build_extruder_pages(){
}
// # rebuild page list
CPageShp page_note = m_pages.back();
PageShp page_note = m_pages.back();
m_pages.pop_back();
for (auto page_extruder : extruder_pages)
m_pages.push_back(page_extruder);
@ -759,8 +1021,13 @@ void CTabPrinter::build_extruder_pages(){
rebuild_page_tree();
}
void Tab::load_current_preset()
{
;
}
//Regerenerate content of the page tree.
void CTab::rebuild_page_tree()
void Tab::rebuild_page_tree()
{
Freeze();
// get label of the currently selected item
@ -786,10 +1053,10 @@ void CTab::rebuild_page_tree()
Thaw();
}
void CTab::OnTreeSelChange(wxTreeEvent& event)
void Tab::OnTreeSelChange(wxTreeEvent& event)
{
if (m_disable_tree_sel_changed_event) return;
CPage* page = nullptr;
Page* page = nullptr;
auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
for (auto p : m_pages)
if (p->title() == selection)
@ -806,19 +1073,19 @@ void CTab::OnTreeSelChange(wxTreeEvent& event)
Refresh();
}
void CTab::OnKeyDown(wxKeyEvent& event)
void Tab::OnKeyDown(wxKeyEvent& event)
{
event.GetKeyCode() == WXK_TAB ?
m_treectrl->Navigate(event.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward) :
event.Skip();
};
void CTab::save_preset(wxCommandEvent &event){};
void CTab::delete_preset(wxCommandEvent &event){};
void CTab::toggle_show_hide_incompatible(wxCommandEvent &event){};
void Tab::save_preset(wxCommandEvent &event){};
void Tab::delete_preset(wxCommandEvent &event){};
void Tab::toggle_show_hide_incompatible(wxCommandEvent &event){};
// # Return a callback to create a Tab widget to mark the preferences as compatible / incompatible to the current printer.
wxSizer* CTab::compatible_printers_widget(wxWindow* parent, wxCheckBox* checkbox, wxButton* btn)
wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox* checkbox, wxButton* btn)
{
checkbox = new wxCheckBox(parent, wxID_ANY, "All");
@ -890,20 +1157,20 @@ wxSizer* CTab::compatible_printers_widget(wxWindow* parent, wxCheckBox* checkbox
}
// package Slic3r::GUI::Tab::Page;
ConfigOptionsGroupShp CPage::new_optgroup(std::string title, int noncommon_label_width /*= -1*/)
ConfigOptionsGroupShp Page::new_optgroup(std::string title, int noncommon_label_width /*= -1*/)
{
//! config_ have to be "right"
ConfigOptionsGroupShp optgroup = std::make_shared<ConfigOptionsGroup>(this, title, m_config);
if (noncommon_label_width >= 0)
optgroup->label_width = noncommon_label_width;
// on_change => sub {
// my ($opt_key, $value) = @_;
// wxTheApp->CallAfter(sub {
// $self->GetParent->update_dirty;
// $self->GetParent->_on_value_change($opt_key, $value);
// });
// },
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
//! This function will be called from OptionGroup.
wxTheApp->CallAfter([this, opt_key, value]() {
static_cast<Tab*>(GetParent())->update_dirty();
static_cast<Tab*>(GetParent())->on_value_change(opt_key, value);
});
},
vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10);
m_optgroups.push_back(optgroup);

View file

@ -36,14 +36,14 @@ namespace GUI {
// Single Tab page containing a{ vsizer } of{ optgroups }
// package Slic3r::GUI::Tab::Page;
using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>;
class CPage : public wxScrolledWindow
class Page : public wxScrolledWindow
{
wxWindow* m_parent;
wxString m_title;
size_t m_iconID;
wxBoxSizer* m_vsizer;
public:
CPage(wxWindow* parent, const wxString title, const int iconID) :
Page(wxWindow* parent, const wxString title, const int iconID) :
m_parent(parent),
m_title(title),
m_iconID(iconID)
@ -52,7 +52,7 @@ public:
m_vsizer = new wxBoxSizer(wxVERTICAL);
SetSizer(m_vsizer);
}
~CPage(){}
~Page(){}
public:
std::vector <ConfigOptionsGroupShp> m_optgroups; // $self->{optgroups} = [];
@ -69,8 +69,8 @@ public:
// Slic3r::GUI::Tab;
using CPageShp = std::shared_ptr<CPage>;
class CTab: public wxPanel
using PageShp = std::shared_ptr<Page>;
class Tab: public wxPanel
{
wxNotebook* m_parent;
protected:
@ -90,26 +90,35 @@ protected:
int m_icon_count;
std::map<std::string, size_t> m_icon_index; // Map from an icon file name to its index in $self->{icons}.
std::vector<CPageShp> m_pages; // $self->{pages} = [];
std::vector<PageShp> m_pages; // $self->{pages} = [];
bool m_disable_tree_sel_changed_event;
public:
PresetBundle* m_preset_bundle;
AppConfig* m_app_config;
bool m_no_controller;
PresetCollection* m_presets;
DynamicPrintConfig m_config; //! tmp_val
const ConfigDef* m_config_def; // It will be used in get_option_(const std::string title)
t_change m_on_value_change{ nullptr };
public:
CTab() {}
CTab(wxNotebook* parent, const char *title) : m_parent(parent), m_title(title) {
Tab() {}
Tab(wxNotebook* parent, const char *title) : m_parent(parent), m_title(title) {
Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
}
~CTab(){}
~Tab(){}
wxWindow* parent() const { return m_parent; }
wxString title() const { return m_title; }
void create_preset_tab(PresetBundle *preset_bundle, AppConfig *app_config);
void create_preset_tab(PresetBundle *preset_bundle);
void on_value_change(std::string opt_key, boost::any value){
if (m_on_value_change != nullptr)
m_on_value_change(opt_key, value);
update();
};
void on_presets_changed(){};
void load_current_preset();
void rebuild_page_tree();
void select_preset(wxString preset_name){};
@ -124,37 +133,39 @@ public:
void delete_preset(wxCommandEvent &event);
void toggle_show_hide_incompatible(wxCommandEvent &event);
CPageShp add_options_page(wxString title, std::string icon, bool is_extruder_pages = false);
PageShp add_options_page(wxString title, std::string icon, bool is_extruder_pages = false);
virtual void build() = 0;
virtual void update() = 0;
void update_dirty();
void load_config(DynamicPrintConfig config);
Option get_option(const std::string title, int idx = -1){
Option get_option(const std::string title, int idx = -1){
return Option(*m_config_def->get(title), idx == -1 ? title : title + std::to_string(idx));
}
};
//Slic3r::GUI::Tab::Print;
class CTabPrint : public CTab
class TabPrint : public Tab
{
public:
CTabPrint() {}
CTabPrint(wxNotebook* parent, const char *title) : CTab(parent, title) {}
~CTabPrint(){}
TabPrint() {}
TabPrint(wxNotebook* parent, const char *title) : Tab(parent, title) {}
~TabPrint(){}
void build() override;
void update() override{};
void update() override;
};
//Slic3r::GUI::Tab::Filament;
class CTabFilament : public CTab
class TabFilament : public Tab
{
wxStaticText* m_cooling_description_line;
wxStaticText* m_volumetric_speed_description_line;
public:
CTabFilament() {}
CTabFilament(wxNotebook* parent, const char *title) : CTab(parent, title) {}
~CTabFilament(){}
TabFilament() {}
TabFilament(wxNotebook* parent, const char *title) : Tab(parent, title) {}
~TabFilament(){}
wxSizer* description_line_widget(wxWindow* parent, wxStaticText* StaticText);
@ -163,7 +174,7 @@ public:
};
//Slic3r::GUI::Tab::Printer;
class CTabPrinter : public CTab
class TabPrinter : public Tab
{
public:
wxButton* serial_test_btn;
@ -172,9 +183,9 @@ public:
size_t m_extruders_count;
public:
CTabPrinter() {}
CTabPrinter(wxNotebook* parent, const char *title) : CTab(parent, title) {}
~CTabPrinter(){}
TabPrinter() {}
TabPrinter(wxNotebook* parent, const char *title) : Tab(parent, title) {}
~TabPrinter(){}
void build() override;
void update() override{};