From b9e8fbacb719c445ae3273faa9ec5f0fd97b609f Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Thu, 19 Jun 2014 20:07:16 +0200 Subject: [PATCH] Put the Default Extruder option in a less confusing position --- lib/Slic3r/GUI/OptionsGroup.pm | 83 +++++++++++++++---- lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm | 28 +++++-- .../GUI/Plater/OverrideSettingsPanel.pm | 27 ++++-- xs/src/Config.hpp | 2 + xs/src/PrintConfig.cpp | 12 ++- xs/src/PrintConfig.hpp | 18 ++-- xs/xsp/Config.xsp | 2 + 7 files changed, 132 insertions(+), 40 deletions(-) diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index 9d2c8f5c8..53ef59fcf 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -196,7 +196,8 @@ sub _build_field { my $field; my $tooltip = $opt->{tooltip}; - if ($opt->{type} =~ /^(i|f|s|s@|percent|slider)$/) { + my $type = $opt->{gui_type} || $opt->{type}; + if ($type =~ /^(i|i_enum_open|i_enum_closed|f|s|s@|percent|slider)$/) { my $style = 0; $style = wxTE_MULTILINE if $opt->{multiline}; # default width on Windows is too large @@ -204,30 +205,82 @@ sub _build_field { my $on_change = sub { my $value = $field->GetValue; - $value ||= 0 if $opt->{type} =~ /^(i|f|percent)$/; # prevent crash trying to pass empty strings to Config + $value ||= 0 if $type =~ /^(i|i_enum_open|i_enum_closed|f|percent)$/; # prevent crash trying to pass empty strings to Config $self->_on_change($opt_key, $value); }; - if ($opt->{type} eq 'i') { + if ($type eq 'i') { $field = Wx::SpinCtrl->new($self->parent, -1, $opt->{default}, wxDefaultPosition, $size, $style, $opt->{min} || 0, $opt->{max} || 2147483647, $opt->{default}); $self->_setters->{$opt_key} = sub { $field->SetValue($_[0]) }; EVT_SPINCTRL ($self->parent, $field, $on_change); EVT_TEXT ($self->parent, $field, $on_change); EVT_KILL_FOCUS($field, $on_kill_focus); - } elsif ($opt->{values}) { + } elsif ($type eq 'i_enum_open' || $type eq 'i_enum_closed') { $field = Wx::ComboBox->new($self->parent, -1, $opt->{default}, wxDefaultPosition, $size, $opt->{labels} || $opt->{values}); $self->_setters->{$opt_key} = sub { - $field->SetValue($_[0]); + my ($value) = @_; + + if ($opt->{gui_flags} =~ /\bshow_value\b/) { + $field->SetValue($value); + return; + } + + if ($opt->{values}) { + # check whether we have a value index + my $value_idx = first { $opt->{values}[$_] eq $value } 0..$#{$opt->{values}}; + if (defined $value_idx) { + $field->SetSelection($value_idx); + return; + } + } + if ($opt->{labels} && $value <= $#{$opt->{labels}}) { + $field->SetValue($opt->{labels}[$value]); + return; + } + $field->SetValue($value); }; + $self->_setters->{$opt_key}->($opt->{default}); # use label if any EVT_COMBOBOX($self->parent, $field, sub { # Without CallAfter, the field text is not populated on Windows. wxTheApp->CallAfter(sub { - $field->SetValue($opt->{values}[ $field->GetSelection ]); # set the text field to the selected value - $self->_on_change($opt_key, $on_change); + my $value = $field->GetSelection; + my $label; + + if ($opt->{values}) { + $label = $value = $opt->{values}[$value]; + } elsif ($value <= $#{$opt->{labels}}) { + $label = $opt->{labels}[$value]; + } else { + $label = $value; + } + + $field->SetValue($label); + $self->_on_change($opt_key, $value); }); }); - EVT_TEXT($self->parent, $field, $on_change); - EVT_KILL_FOCUS($field, $on_kill_focus); - } elsif ($opt->{type} eq 'slider') { + EVT_TEXT($self->parent, $field, sub { + my ($s, $event) = @_; + $event->Skip; + wxTheApp->CallAfter(sub { + my $label = $field->GetValue; + if (defined (my $value = first { $opt->{labels}[$_] eq $label } 0..$#{$opt->{labels}})) { + if ($opt->{values}) { + $value = $opt->{values}[$value]; + } + $self->_on_change($opt_key, $value); + } elsif ($label !~ /^[0-9]+$/) { + # if typed text is not numeric, select the default value + my $default = 0; + if ($opt->{values}) { + $default = $opt->{values}[0]; + } + $self->_setters->{$opt_key}->($default); + $self->_on_change($opt_key, $default); + } else { + $self->_on_change($opt_key, $label); + } + }); + }); + } elsif ($type eq 'slider') { my $scale = 10; $field = Wx::BoxSizer->new(wxHORIZONTAL); my $slider = Wx::Slider->new($self->parent, -1, ($opt->{default} // $opt->{min})*$scale, ($opt->{min} // 0)*$scale, ($opt->{max} // 100)*$scale, wxDefaultPosition, $size); @@ -251,14 +304,14 @@ sub _build_field { } $field->Disable if $opt->{readonly}; $tooltip .= " (default: " . $opt->{default} . ")" if ($opt->{default}); - } elsif ($opt->{type} eq 'bool') { + } elsif ($type eq 'bool') { $field = Wx::CheckBox->new($self->parent, -1, ""); $field->SetValue($opt->{default}); $field->Disable if $opt->{readonly}; EVT_CHECKBOX($self->parent, $field, sub { $self->_on_change($opt_key, $field->GetValue); }); $self->_setters->{$opt_key} = sub { $field->SetValue($_[0]) }; $tooltip .= " (default: " . ($opt->{default} ? 'yes' : 'no') . ")" if defined($opt->{default}); - } elsif ($opt->{type} eq 'point') { + } elsif ($type eq 'point') { $field = Wx::BoxSizer->new(wxHORIZONTAL); my $field_size = Wx::Size->new(40, -1); my @items = ( @@ -281,7 +334,7 @@ sub _build_field { $x_field->SetValue($_[0][0]); $y_field->SetValue($_[0][1]); }; - } elsif ($opt->{type} eq 'select') { + } elsif ($type eq 'select') { $field = Wx::ComboBox->new($self->parent, -1, "", wxDefaultPosition, wxDefaultSize, $opt->{labels} || $opt->{values}, wxCB_READONLY); EVT_COMBOBOX($self->parent, $field, sub { $self->_on_change($opt_key, $opt->{values}[$field->GetSelection]); @@ -295,7 +348,7 @@ sub _build_field { . $opt->{labels}[ first { $opt->{values}[$_] eq $opt->{default} } 0..$#{$opt->{values}} ] . ")" if ($opt->{default}); } else { - die "Unsupported option type: " . $opt->{type}; + die "Unsupported option type: " . $type; } if ($tooltip && $field->can('SetToolTipString')) { $field->SetToolTipString($tooltip); @@ -387,7 +440,7 @@ sub _trigger_options { opt_key => $full_key, config => 1, label => ($self->full_labels && defined $config_opt->{full_label}) ? $config_opt->{full_label} : $config_opt->{label}, - (map { $_ => $config_opt->{$_} } qw(type tooltip sidetext width height full_width min max labels values multiline readonly)), + (map { $_ => $config_opt->{$_} } qw(type gui_type gui_flags tooltip sidetext width height full_width min max labels values multiline readonly)), default => $self->_get_config($opt_key, $index), on_change => sub { return $self->_set_config($opt_key, $index, $_[0]) }, }; diff --git a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm index 9a6f3cc00..097f86d12 100644 --- a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm +++ b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm @@ -150,6 +150,7 @@ sub selection_changed { $self->{settings_panel}->set_config(undef); if (my $itemData = $self->get_selection) { + my ($config, @opt_keys); if ($itemData->{type} eq 'volume') { # select volume in 3D preview if ($self->{canvas}) { @@ -162,9 +163,11 @@ sub selection_changed { my $material = $self->{model_object}->model->get_material($volume->material_id // '_'); $material //= $volume->assign_unique_material; $self->{staticbox}->SetLabel('Part Settings'); - $self->{settings_panel}->enable; - $self->{settings_panel}->set_opt_keys([ 'extruder', @{Slic3r::Config::PrintRegion->new->get_keys} ]); - $self->{settings_panel}->set_config($material->config); + + # get default values + @opt_keys = @{Slic3r::Config::PrintRegion->new->get_keys}; + + $config = $material->config; } elsif ($itemData->{type} eq 'object') { # select all object volumes in 3D preview if ($self->{canvas}) { @@ -173,12 +176,21 @@ sub selection_changed { # attach object config to settings panel $self->{staticbox}->SetLabel('Object Settings'); - $self->{settings_panel}->enable; - $self->{settings_panel}->set_opt_keys( - [ 'extruder', map @{$_->get_keys}, Slic3r::Config::PrintObject->new, Slic3r::Config::PrintRegion->new ] - ); - $self->{settings_panel}->set_config($self->{model_object}->config); + @opt_keys = (map @{$_->get_keys}, Slic3r::Config::PrintObject->new, Slic3r::Config::PrintRegion->new); + $config = $self->{model_object}->config; } + # get default values + my $default_config = Slic3r::Config->new_from_defaults(@opt_keys); + + # append default extruder + push @opt_keys, 'extruder'; + $default_config->set('extruder', 0); + $config->set_ifndef('extruder', 0); + $self->{settings_panel}->set_default_config($default_config); + $self->{settings_panel}->set_config($config); + $self->{settings_panel}->set_opt_keys(\@opt_keys); + $self->{settings_panel}->set_fixed_options([qw(extruder)]); + $self->{settings_panel}->enable; } $self->{canvas}->Render if $self->{canvas}; diff --git a/lib/Slic3r/GUI/Plater/OverrideSettingsPanel.pm b/lib/Slic3r/GUI/Plater/OverrideSettingsPanel.pm index 175f006cd..a6b59bf84 100644 --- a/lib/Slic3r/GUI/Plater/OverrideSettingsPanel.pm +++ b/lib/Slic3r/GUI/Plater/OverrideSettingsPanel.pm @@ -17,8 +17,10 @@ sub new { my $class = shift; my ($parent, %params) = @_; my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); - $self->{config} = $params{config}; # may be passed as undef + $self->{default_config} = Slic3r::Config->new; + $self->{config} = Slic3r::Config->new; $self->{on_change} = $params{on_change}; + $self->{fixed_options} = {}; $self->{sizer} = Wx::BoxSizer->new(wxVERTICAL); @@ -36,7 +38,7 @@ sub new { my $id = &Wx::NewId(); $menu->Append($id, $self->{option_labels}{$opt_key}); EVT_MENU($menu, $id, sub { - $self->{config}->apply(Slic3r::Config->new_from_defaults($opt_key)); + $self->{config}->apply($self->{default_config}->get($opt_key)); $self->update_optgroup; $self->{on_change}->() if $self->{on_change}; }); @@ -59,6 +61,17 @@ sub new { return $self; } +sub set_default_config { + my ($self, $config) = @_; + $self->{default_config} = $config; +} + +sub set_config { + my ($self, $config) = @_; + $self->{config} = $config; + $self->update_optgroup; +} + sub set_opt_keys { my ($self, $opt_keys) = @_; @@ -69,9 +82,9 @@ sub set_opt_keys { $self->{options} = [ sort { $self->{option_labels}{$a} cmp $self->{option_labels}{$b} } @$opt_keys ]; } -sub set_config { - my ($self, $config) = @_; - $self->{config} = $config; +sub set_fixed_options { + my ($self, $opt_keys) = @_; + $self->{fixed_options} = { map {$_ => 1} @$opt_keys }; $self->update_optgroup; } @@ -102,8 +115,8 @@ sub update_optgroup { my ($line) = @_; my ($opt_key) = @{$line->{options}}; # we assume that we have one option per line - # if this option is not listed in the ones the user can add, disallow deleting it - return undef if !first { $_ eq $opt_key } @{$self->{options}}; + # disallow deleting fixed options + return undef if $self->{fixed_options}{$opt_key}; my $btn = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/delete.png", wxBITMAP_TYPE_PNG), wxDefaultPosition, wxDefaultSize, Wx::wxBORDER_NONE); diff --git a/xs/src/Config.hpp b/xs/src/Config.hpp index df678131b..42d19c830 100644 --- a/xs/src/Config.hpp +++ b/xs/src/Config.hpp @@ -432,6 +432,8 @@ class ConfigOptionDef { public: ConfigOptionType type; + std::string gui_type; + std::string gui_flags; std::string label; std::string full_label; std::string category; diff --git a/xs/src/PrintConfig.cpp b/xs/src/PrintConfig.cpp index c56c662de..b114837f0 100644 --- a/xs/src/PrintConfig.cpp +++ b/xs/src/PrintConfig.cpp @@ -144,11 +144,17 @@ PrintConfigDef::build_def() { Options["extra_perimeters"].cli = "extra-perimeters!"; Options["extruder"].type = coInt; - Options["extruder"].label = "Default extruder"; + Options["extruder"].gui_type = "i_enum_open"; + Options["extruder"].label = "Extruder"; Options["extruder"].category = "Extruders"; Options["extruder"].tooltip = "The extruder to use (unless more specific extruder settings are specified)."; Options["extruder"].cli = "extruder=i"; - Options["extruder"].min = 1; + Options["extruder"].min = 0; // 0 = inherit defaults + Options["extruder"].enum_labels.push_back("default"); // override label for item 0 + Options["extruder"].enum_labels.push_back("1"); + Options["extruder"].enum_labels.push_back("2"); + Options["extruder"].enum_labels.push_back("3"); + Options["extruder"].enum_labels.push_back("4"); Options["extruder_clearance_height"].type = coFloat; Options["extruder_clearance_height"].label = "Height"; @@ -218,6 +224,8 @@ PrintConfigDef::build_def() { Options["fill_angle"].max = 359; Options["fill_density"].type = coPercent; + Options["fill_density"].gui_type = "i_enum_open"; + Options["fill_density"].gui_flags = "show_value"; Options["fill_density"].label = "Fill density"; Options["fill_density"].category = "Infill"; Options["fill_density"].tooltip = "Density of internal infill, expressed in the range 0% - 100%."; diff --git a/xs/src/PrintConfig.hpp b/xs/src/PrintConfig.hpp index 5bcc3a32d..368c8deb8 100644 --- a/xs/src/PrintConfig.hpp +++ b/xs/src/PrintConfig.hpp @@ -81,14 +81,16 @@ class DynamicPrintConfig : public DynamicConfig if (this->has("extruder")) { int extruder = this->option("extruder")->getInt(); this->erase("extruder"); - if (!this->has("infill_extruder")) - this->option("infill_extruder", true)->setInt(extruder); - if (!this->has("perimeter_extruder")) - this->option("perimeter_extruder", true)->setInt(extruder); - if (!this->has("support_material_extruder")) - this->option("support_material_extruder", true)->setInt(extruder); - if (!this->has("support_material_interface_extruder")) - this->option("support_material_interface_extruder", true)->setInt(extruder); + if (extruder != 0) { + if (!this->has("infill_extruder")) + this->option("infill_extruder", true)->setInt(extruder); + if (!this->has("perimeter_extruder")) + this->option("perimeter_extruder", true)->setInt(extruder); + if (!this->has("support_material_extruder")) + this->option("support_material_extruder", true)->setInt(extruder); + if (!this->has("support_material_interface_extruder")) + this->option("support_material_interface_extruder", true)->setInt(extruder); + } } if (this->has("spiral_vase") && this->opt("spiral_vase", true)->value) { { diff --git a/xs/xsp/Config.xsp b/xs/xsp/Config.xsp index 7fe554e4f..f96f45b8a 100644 --- a/xs/xsp/Config.xsp +++ b/xs/xsp/Config.xsp @@ -154,6 +154,8 @@ print_config_def() throw "Unknown option type"; } (void)hv_stores( hv, "type", newSVpv(opt_type, 0) ); + (void)hv_stores( hv, "gui_type", newSVpvn(optdef->gui_type.c_str(), optdef->gui_type.length()) ); + (void)hv_stores( hv, "gui_flags", newSVpvn(optdef->gui_flags.c_str(), optdef->gui_flags.length()) ); (void)hv_stores( hv, "label", newSVpvn_utf8(optdef->label.c_str(), optdef->label.length(), true) ); if (!optdef->full_label.empty()) (void)hv_stores( hv, "full_label", newSVpvn_utf8(optdef->full_label.c_str(), optdef->full_label.length(), true) );