From 741a85187ce6ef6de224a7ea20443d20cea9fe90 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 24 Oct 2016 16:07:36 +0200 Subject: [PATCH] Suppress the '- default -' selection of Print/Filament/Printer settings if there is any valid option available. This feature has been asked for by the Prusa3D customers as the '- default -' option has nothing to do with the actual printer and when selected accidentally, it could even lead to a printer damage. --- lib/Slic3r/Config.pm | 1 + lib/Slic3r/GUI.pm | 6 ++- lib/Slic3r/GUI/Controller.pm | 7 ++- lib/Slic3r/GUI/MainFrame.pm | 4 +- lib/Slic3r/GUI/Plater.pm | 55 +++++++++++++++----- lib/Slic3r/GUI/Preferences.pm | 7 +++ lib/Slic3r/GUI/Tab.pm | 94 +++++++++++++++++++++++++++-------- 7 files changed, 136 insertions(+), 38 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index b4cfaa5d9..c315f9b4e 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -36,6 +36,7 @@ sub new_from_defaults { my (@opt_keys) = @_; my $self = $class->new; + # Instantiating the C++ class Slic3r::FullPrintConfig. my $defaults = Slic3r::Config::Full->new; if (@opt_keys) { $self->set($_, $defaults->get($_)) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index b91930870..614f74f61 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -69,10 +69,12 @@ our $Settings = { # If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden. # By default, Prusa has the controller hidden. no_controller => 1, + # If set, the "- default -" selections of print/filament/printer are suppressed, if there is a valid preset available. + no_defaults => 1, }, }; -our $have_button_icons = &Wx::wxVERSION_STRING =~ / (?:2\.9\.[1-9]|3\.)/; +our $have_button_icons = &Wx::wxVERSION_STRING =~ m" (?:2\.9\.[1-9]|3\.)"; our $small_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); $small_font->SetPointSize(11) if !&Wx::wxMSW; our $small_bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); @@ -126,6 +128,8 @@ sub OnInit { $Settings->{_}{background_processing} //= 1; # If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden. $Settings->{_}{no_controller} //= 1; + # If set, the "- default -" selections of print/filament/printer are suppressed, if there is a valid preset available. + $Settings->{_}{no_defaults} //= 1; } $Settings->{_}{version} = $Slic3r::VERSION; $self->save_settings; diff --git a/lib/Slic3r/GUI/Controller.pm b/lib/Slic3r/GUI/Controller.pm index c6a568f82..8c4dcbec7 100644 --- a/lib/Slic3r/GUI/Controller.pm +++ b/lib/Slic3r/GUI/Controller.pm @@ -177,9 +177,14 @@ sub print_panels { map $_->GetWindow, $self->{sizer}->GetChildren; } +# Called by +# Slic3r::GUI::Tab::Print::_on_presets_changed +# Slic3r::GUI::Tab::Filament::_on_presets_changed +# Slic3r::GUI::Tab::Printer::_on_presets_changed +# when the presets are loaded or the user select another preset. sub update_presets { my $self = shift; - my ($group, $presets, $selected, $is_dirty) = @_; + my ($group, $presets, $default_suppressed, $selected, $is_dirty) = @_; # update configs of currently loaded print panels foreach my $panel ($self->print_panels) { diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 3b7d7ef46..1969d8bea 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -140,6 +140,8 @@ sub _init_tabpanel { $self->config->save($Slic3r::GUI::autosave) if $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}) { $self->{plater}->update_presets($tab_name, @_); @@ -393,7 +395,7 @@ sub quick_slice { print_center => $print_center, status_cb => sub { my ($percent, $message) = @_; - return if &Wx::wxVERSION_STRING !~ / 2\.(8\.|9\.[2-9])/; + return if &Wx::wxVERSION_STRING !~ m" 2\.(8\.|9\.[2-9])"; $progress_dialog->Update($percent, "$message…"); }, ); diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index dcc26c5e7..79cc8f994 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -330,12 +330,19 @@ sub new { filament => 'Filament', printer => 'Printer', ); + # UI Combo boxes for a print, multiple filaments, and a printer. + # Initially a single filament combo box is created, but the number of combo boxes for the filament selection may increase, + # once a printer preset with multiple extruders is activated. + # $self->{preset_choosers}{$group}[$idx] $self->{preset_choosers} = {}; + # Boolean indicating whether the '- default -' preset is shown by the combo box. + $self->{preset_choosers_default_suppressed} = {}; for my $group (qw(print filament printer)) { my $text = Wx::StaticText->new($self, -1, "$group_labels{$group}:", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); $text->SetFont($Slic3r::GUI::small_font); my $choice = Wx::BitmapComboBox->new($self, -1, "", wxDefaultPosition, wxDefaultSize, [], wxCB_READONLY); $self->{preset_choosers}{$group} = [$choice]; + $self->{preset_choosers_default_suppressed}{$group} = 0; # setup the listener EVT_COMBOBOX($choice, $choice, sub { my ($choice) = @_; @@ -427,18 +434,22 @@ sub _on_select_preset { my $self = shift; my ($group, $choice) = @_; - # if user changed filament preset, don't propagate this to the tabs + # If user changed a filament preset and the selected machine is equipped with multiple extruders, + # there are multiple filament selection combo boxes shown at the platter. In that case + # don't propagate the filament selection changes to the tab. + my $default_suppressed = $self->{preset_choosers_default_suppressed}{$group}; if ($group eq 'filament' && @{$self->{preset_choosers}{filament}} > 1) { + # Indices of the filaments selected. my @filament_presets = $self->filament_presets; - $Slic3r::GUI::Settings->{presets}{filament} = $choice->GetString($filament_presets[0]) . ".ini"; - $Slic3r::GUI::Settings->{presets}{"filament_${_}"} = $choice->GetString($filament_presets[$_]) + $Slic3r::GUI::Settings->{presets}{filament} = $choice->GetString($filament_presets[0] - $default_suppressed) . ".ini"; + $Slic3r::GUI::Settings->{presets}{"filament_${_}"} = $choice->GetString($filament_presets[$_] - $default_suppressed) for 1 .. $#filament_presets; wxTheApp->save_settings; return; } # call GetSelection() in scalar context as it's context-aware - $self->{on_select_preset}->($group, scalar $choice->GetSelection) + $self->{on_select_preset}->($group, scalar($choice->GetSelection) + $default_suppressed) if $self->{on_select_preset}; # get new config and generate on_config_change() event for updating plater and other things @@ -450,20 +461,32 @@ sub GetFrame { return &Wx::GetTopLevelParent($self); } +# Update presets (Print settings, Filament, Printer) from their respective tabs. +# Called by +# Slic3r::GUI::Tab::Print::_on_presets_changed +# Slic3r::GUI::Tab::Filament::_on_presets_changed +# Slic3r::GUI::Tab::Printer::_on_presets_changed +# when the presets are loaded or the user selects another preset. +# For Print settings and Printer, synchronize the selection index with their tabs. +# For Filament, synchronize the selection index for a single extruder printer only, otherwise keep the selection. sub update_presets { my $self = shift; - my ($group, $presets, $selected, $is_dirty) = @_; + # $presets: one of qw(print filament printer) + # $selected: index of the selected preset in the array. This may not correspond + # with the index of selection in the UI element, where not all items are displayed. + my ($group, $presets, $default_suppressed, $selected, $is_dirty) = @_; my @choosers = @{ $self->{preset_choosers}{$group} }; foreach my $choice (@choosers) { if ($group eq 'filament' && @choosers > 1) { # if we have more than one filament chooser, keep our selection # instead of importing the one from the tab - $selected = $choice->GetSelection; + $selected = $choice->GetSelection + $self->{preset_choosers_default_suppressed}{$group}; $is_dirty = 0; } $choice->Clear; foreach my $preset (@$presets) { + next if ($preset->default && $default_suppressed); my $bitmap; if ($group eq 'filament') { my $config = $preset->config(['filament_colour']); @@ -486,21 +509,26 @@ sub update_presets { } if ($selected <= $#$presets) { - if ($is_dirty) { - $choice->SetString($selected, $choice->GetString($selected) . " (modified)"); + my $idx = $selected - $default_suppressed; + if ($idx >= 0) { + if ($is_dirty) { + $choice->SetString($idx, $choice->GetString($idx) . " (modified)"); + } + # call SetSelection() only after SetString() otherwise the new string + # won't be picked up as the visible string + $choice->SetSelection($idx); } - # call SetSelection() only after SetString() otherwise the new string - # won't be picked up as the visible string - $choice->SetSelection($selected); } } + + $self->{preset_choosers_default_suppressed}{$group} = $default_suppressed; } +# Return a vector of indices of filaments selected by the $self->{preset_choosers}{filament} combo boxes. sub filament_presets { my $self = shift; - # force scalar context for GetSelection() as it's context-aware - return map scalar($_->GetSelection), @{ $self->{preset_choosers}{filament} }; + return map scalar($_->GetSelection) + $self->{preset_choosers_default_suppressed}{filament}, @{ $self->{preset_choosers}{filament} }; } sub add { @@ -1436,6 +1464,7 @@ sub update { $self->refresh_canvases; } +# When a number of extruders changes, the UI needs to be updated to show a single filament selection combo box per extruder. sub on_extruders_change { my ($self, $num_extruders) = @_; diff --git a/lib/Slic3r/GUI/Preferences.pm b/lib/Slic3r/GUI/Preferences.pm index 431f642d6..9c36d3098 100644 --- a/lib/Slic3r/GUI/Preferences.pm +++ b/lib/Slic3r/GUI/Preferences.pm @@ -67,6 +67,13 @@ sub new { tooltip => 'Disable communication with the printer over a serial / USB cable. This simplifies the user interface in case the printer is never attached to the computer.', default => $Slic3r::GUI::Settings->{_}{no_controller}, )); + $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( + opt_id => 'no_defaults', + type => 'bool', + label => 'Suppress "- default -" presets', + tooltip => 'Suppress "- default -" presets in the Print / Filament / Printer selections once there are any other valid presets available.', + default => $Slic3r::GUI::Settings->{_}{no_defaults}, + )); my $sizer = Wx::BoxSizer->new(wxVERTICAL); $sizer->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10); diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index c05465664..d30e31abc 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -1,6 +1,18 @@ # The "Expert" tab at the right of the main tabbed window. # The "Expert" is enabled by File->Preferences dialog. +# This file implements following packages: +# Slic3r::GUI::Tab; +# Slic3r::GUI::Tab::Print; +# Slic3r::GUI::Tab::Filament; +# Slic3r::GUI::Tab::Printer; +# Slic3r::GUI::Tab::Page +# - Option page: For example, the Slic3r::GUI::Tab::Print has option pages "Layers and perimeters", "Infill", "Skirt and brim" ... +# Slic3r::GUI::SavePresetWindow +# - Dialog to select a new preset name to store the configuration. +# Slic3r::GUI::Tab::Preset; +# - Single preset item: name, file is default or external. + package Slic3r::GUI::Tab; use strict; use warnings; @@ -13,6 +25,7 @@ use Wx qw(:bookctrl :dialog :keycode :icon :id :misc :panel :sizer :treectrl :wi use Wx::Event qw(EVT_BUTTON EVT_CHOICE EVT_KEY_DOWN EVT_TREE_SEL_CHANGED); use base qw(Wx::Panel Class::Accessor); +# Index of the currently active preset. __PACKAGE__->mk_accessors(qw(current_preset)); sub new { @@ -30,7 +43,7 @@ sub new { $self->{sizer}->Add($left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3); my $left_col_width = 150; - + # preset chooser { @@ -96,16 +109,32 @@ sub new { EVT_BUTTON($self, $self->{btn_delete_preset}, sub { my $i = $self->current_preset; - return if $i == 0; # this shouldn't happen but let's trap it anyway + # Don't let the user delete the '- default -' configuration. + # This shall not happen as the 'delete' button is disabled for the '- default -' entry, + # but better be safe than sorry. + return if ($i == 0 && $self->get_current_preset->{default}); my $res = Wx::MessageDialog->new($self, "Are you sure you want to delete the selected preset?", 'Delete Preset', wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION)->ShowModal; return unless $res == wxID_YES; - if (-e $self->{presets}[$i]->file) { - unlink $self->{presets}[$i]->file; + # Delete the file. + my $path = Slic3r::encode_path($self->{presets}[$i]->file); + if (-e $path && ! unlink $path) { + # Cannot delete the file, therefore the item will not be removed from the selection. + Slic3r::GUI::show_error($self, "Cannot delete file $path : $!"); + return; } + # Delete the preset. splice @{$self->{presets}}, $i, 1; - $self->{presets_choice}->Delete($i); + # Delete the item from the UI component. + $self->{presets_choice}->Delete($i - $self->{default_suppressed}); $self->current_preset(undef); - $self->select_preset(0); + if ($self->{default_suppressed} && scalar(@{$self->{presets}}) == 1) { + # Empty selection. Add the '- default -' item into the drop down selection. + $self->{presets_choice}->Append($self->{presets}->[0]->name); + # and remember that the '- default -' is shown. + $self->{default_suppressed} = 0; + } + # Select the 0th item. If default is suppressed, select the first valid. + $self->select_preset($self->{default_suppressed}); $self->_on_presets_changed; }); @@ -120,11 +149,18 @@ sub new { return $self; } +# Are the '- default -' selections suppressed by the Slic3r GUI preferences? +sub no_defaults { + return $Slic3r::GUI::Settings->{_}{no_defaults} ? 1 : 0; +} + +# Get a currently active preset (Perl class Slic3r::GUI::Tab::Preset). sub get_current_preset { my $self = shift; return $self->get_preset($self->current_preset); } +# Get a preset (Perl class Slic3r::GUI::Tab::Preset) with an index $i. sub get_preset { my ($self, $i) = @_; return $self->{presets}[$i]; @@ -185,7 +221,8 @@ sub _on_presets_changed { $self->{on_presets_changed}->( $self->{presets}, - scalar($self->{presets_choice}->GetSelection), + $self->{default_suppressed}, + scalar($self->{presets_choice}->GetSelection) + $self->{default_suppressed}, $self->is_dirty, ) if $self->{on_presets_changed}; } @@ -200,8 +237,18 @@ sub select_default_preset { } sub select_preset { - my $self = shift; - $self->{presets_choice}->SetSelection($_[0]); + my ($self, $i) = @_; + if ($self->{default_suppressed} && $i == 0) { + # Selecting the '- default -'. Add it to the combo box. + $self->{default_suppressed} = 0; + $self->{presets_choice}->Insert($self->{presets}->[0]->name, 0); + } elsif ($self->no_defaults && ! $self->{default_suppressed} && $i > 0) { + # The user wants to hide the '- default -' items and a non-default item has been added to the presets. + # Hide the '- default -' item. + $self->{presets_choice}->Delete(0); + $self->{default_suppressed} = 1; + } + $self->{presets_choice}->SetSelection($i - $self->{default_suppressed}); $self->on_select_preset; } @@ -216,6 +263,7 @@ sub on_select_preset { my $self = shift; if ($self->is_dirty) { + # Display a dialog showing the dirty options in a human readable form. my $old_preset = $self->get_current_preset; my $name = $old_preset->default ? 'Default preset' : "Preset \"" . $old_preset->name . "\""; @@ -233,7 +281,7 @@ sub on_select_preset { my $confirm = Wx::MessageDialog->new($self, "$name has unsaved changes:\n$changes\n\nDiscard changes and continue anyway?", 'Unsaved Changes', wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); if ($confirm->ShowModal == wxID_NO) { - $self->{presets_choice}->SetSelection($self->current_preset); + $self->{presets_choice}->SetSelection($self->current_preset - $self->{default_suppressed}); # trigger the on_presets_changed event so that we also restore the previous value # in the plater selector @@ -242,7 +290,7 @@ sub on_select_preset { } } - $self->current_preset($self->{presets_choice}->GetSelection); + $self->current_preset($self->{presets_choice}->GetSelection + $self->{default_suppressed}); my $preset = $self->get_current_preset; my $preset_config = $self->get_preset_config($preset); eval { @@ -333,15 +381,13 @@ sub update_tree { sub update_dirty { my $self = shift; - foreach my $i (0..$#{$self->{presets}}) { + foreach my $i ($self->{default_suppressed}..$#{$self->{presets}}) { my $preset = $self->get_preset($i); - if ($i == $self->current_preset && $self->is_dirty) { - $self->{presets_choice}->SetString($i, $preset->name . " (modified)"); - } else { - $self->{presets_choice}->SetString($i, $preset->name); - } + $self->{presets_choice}->SetString( + $i - $self->{default_suppressed}, + ($i == $self->current_preset && $self->is_dirty) ? $preset->name . " (modified)" : $preset->name); } - $self->{presets_choice}->SetSelection($self->current_preset); # http://trac.wxwidgets.org/ticket/13769 + $self->{presets_choice}->SetSelection($self->current_preset - $self->{default_suppressed}); # http://trac.wxwidgets.org/ticket/13769 $self->_on_presets_changed; } @@ -374,14 +420,17 @@ sub load_presets { file => $presets{$preset_name}, ); } - $self->current_preset(undef); + $self->{default_suppressed} = Slic3r::GUI::Tab->no_defaults && scalar(@{$self->{presets}}) > 1; $self->{presets_choice}->Clear; - $self->{presets_choice}->Append($_->name) for @{$self->{presets}}; + foreach my $preset (@{$self->{presets}}) { + next if ($preset->default && $self->{default_suppressed}); + $self->{presets_choice}->Append($preset->name); + } { # load last used preset my $i = first { basename($self->{presets}[$_]->file) eq ($Slic3r::GUI::Settings->{presets}{$self->name} || '') } 1 .. $#{$self->{presets}}; - $self->select_preset($i || 0); + $self->select_preset($i || $self->{default_suppressed}); } $self->_on_presets_changed; } @@ -402,7 +451,7 @@ sub load_config_file { $self->{presets_choice}->Append($preset_name); $i = $#{$self->{presets}}; } - $self->{presets_choice}->SetSelection($i); + $self->{presets_choice}->SetSelection($i - $self->{default_suppressed}); $self->on_select_preset; $self->_on_presets_changed; } @@ -1584,6 +1633,7 @@ sub config { my ($self, $keys) = @_; if ($self->default) { + # Perl class Slic3r::Config extends the C++ class Slic3r::DynamicPrintConfig return Slic3r::Config->new_from_defaults(@$keys); } else { if (!-e Slic3r::encode_path($self->file)) {