Merge branch 'gui3-shortcuts'

This commit is contained in:
Alessandro Ranellucci 2017-05-29 18:51:57 +02:00
commit b2a6dce75b
10 changed files with 253 additions and 106 deletions

View File

@ -88,6 +88,7 @@ our $Settings = {
no_controller => 0, no_controller => 0,
threads => $Slic3r::Config::Options->{threads}{default}, threads => $Slic3r::Config::Options->{threads}{default},
color_toolpaths_by => 'role', color_toolpaths_by => 'role',
tabbed_preset_editors => 1,
}, },
}; };

View File

@ -47,13 +47,13 @@ sub new {
delete $presets{$_} for map $_->printer_name, @panels; delete $presets{$_} for map $_->printer_name, @panels;
foreach my $preset_name (sort keys %presets) { foreach my $preset_name (sort keys %presets) {
my $config = $presets{$preset_name}->dirty_config; my $preset = $presets{$preset_name};
next if !$config->serial_port; next if !$preset->dirty_config->serial_port;
my $id = &Wx::NewId(); my $id = &Wx::NewId();
$menu->Append($id, $preset_name); $menu->Append($id, $preset_name);
EVT_MENU($menu, $id, sub { EVT_MENU($menu, $id, sub {
$self->add_printer($preset_name, $config); $self->add_printer($preset);
}); });
} }
$self->PopupMenu($menu, $btn->GetPosition); $self->PopupMenu($menu, $btn->GetPosition);
@ -100,10 +100,10 @@ sub OnActivate {
# get all available presets # get all available presets
my %presets = (); my %presets = ();
{ foreach my $preset (@{wxTheApp->presets->{printer}}) {
my %all = map { $_->name => $_ } @{wxTheApp->presets->{printer}}; $preset->load_config;
my %configs = map { my $name = $_; $name => $all{$name}->load_config } keys %all; next if !$preset->dirty_config->serial_port;
%presets = map { $_ => $configs{$_} } grep $configs{$_}->serial_port, keys %all; $presets{$preset->name} = $preset;
} }
# decide which ones we want to keep # decide which ones we want to keep
@ -124,7 +124,7 @@ sub OnActivate {
# enable printers whose port is available # enable printers whose port is available
my %ports = map { $_ => 1 } wxTheApp->scan_serial_ports; my %ports = map { $_ => 1 } wxTheApp->scan_serial_ports;
$active{$_} = 1 $active{$_} = 1
for grep exists $ports{$presets{$_}->serial_port}, keys %presets; for grep exists $ports{$presets{$_}->dirty_config->serial_port}, keys %presets;
} }
if (!%active && $self->_selected_printer_preset) { if (!%active && $self->_selected_printer_preset) {
# enable currently selected printer if it is configured # enable currently selected printer if it is configured
@ -140,7 +140,7 @@ sub OnActivate {
$self->{sizer}->DetachWindow($panel); $self->{sizer}->DetachWindow($panel);
$panel->Destroy; $panel->Destroy;
} }
$self->add_printer($_, $presets{$_}) for sort keys %active; $self->add_printer($presets{$_}) for sort keys %active;
# show/hide the warning about no printers # show/hide the warning about no printers
$self->{text_no_printers}->Show(!%presets); $self->{text_no_printers}->Show(!%presets);
@ -156,16 +156,16 @@ sub OnActivate {
} }
sub add_printer { sub add_printer {
my ($self, $printer_name, $config) = @_; my ($self, $preset) = @_;
# check that printer doesn't exist already # check that printer doesn't exist already
foreach my $panel ($self->print_panels) { foreach my $panel ($self->print_panels) {
if ($panel->printer_name eq $printer_name) { if ($panel->printer_name eq $preset->name) {
return $panel; return $panel;
} }
} }
my $printer_panel = Slic3r::GUI::Controller::PrinterPanel->new($self, $printer_name, $config); my $printer_panel = Slic3r::GUI::Controller::PrinterPanel->new($self, $preset->name, $preset);
$self->{sizer}->Prepend($printer_panel, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 10); $self->{sizer}->Prepend($printer_panel, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 10);
$self->Layout; $self->Layout;

View File

@ -16,11 +16,11 @@ use constant STATUS_TIMER_INTERVAL => 1000; # milliseconds
use constant TEMP_TIMER_INTERVAL => 5000; # milliseconds use constant TEMP_TIMER_INTERVAL => 5000; # milliseconds
sub new { sub new {
my ($class, $parent, $printer_name, $config) = @_; my ($class, $parent, $printer_name, $preset) = @_;
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, [500, 250]); my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, [500, 250]);
$self->printer_name($printer_name || 'Printer'); $self->printer_name($printer_name || 'Printer');
$self->config($config); $self->config($preset->dirty_config);
$self->manual_control_config({ $self->manual_control_config({
xy_travel_speed => 130, xy_travel_speed => 130,
z_travel_speed => 10, z_travel_speed => 10,
@ -103,7 +103,7 @@ sub new {
} }
my $serial_port_sizer = Wx::BoxSizer->new(wxHORIZONTAL); my $serial_port_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
{ {
$self->{serial_port_combobox} = Wx::ComboBox->new($self, -1, $config->serial_port, wxDefaultPosition, wxDefaultSize, []); $self->{serial_port_combobox} = Wx::ComboBox->new($self, -1, $self->config->serial_port, wxDefaultPosition, wxDefaultSize, []);
$self->{serial_port_combobox}->SetFont($Slic3r::GUI::small_font); $self->{serial_port_combobox}->SetFont($Slic3r::GUI::small_font);
$self->update_serial_ports; $self->update_serial_ports;
$serial_port_sizer->Add($self->{serial_port_combobox}, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 1); $serial_port_sizer->Add($self->{serial_port_combobox}, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 1);
@ -125,7 +125,7 @@ sub new {
} }
my $serial_speed_sizer = Wx::BoxSizer->new(wxHORIZONTAL); my $serial_speed_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
{ {
$self->{serial_speed_combobox} = Wx::ComboBox->new($self, -1, $config->serial_speed, wxDefaultPosition, wxDefaultSize, $self->{serial_speed_combobox} = Wx::ComboBox->new($self, -1, $self->config->serial_speed, wxDefaultPosition, wxDefaultSize,
["57600", "115200", "250000"]); ["57600", "115200", "250000"]);
$self->{serial_speed_combobox}->SetFont($Slic3r::GUI::small_font); $self->{serial_speed_combobox}->SetFont($Slic3r::GUI::small_font);
$serial_speed_sizer->Add($self->{serial_speed_combobox}, 0, wxALIGN_CENTER_VERTICAL, 0); $serial_speed_sizer->Add($self->{serial_speed_combobox}, 0, wxALIGN_CENTER_VERTICAL, 0);

View File

@ -8,9 +8,10 @@ use utf8;
use File::Basename qw(basename dirname); use File::Basename qw(basename dirname);
use List::Util qw(min); use List::Util qw(min);
use Slic3r::Geometry qw(X Y Z); use Slic3r::Geometry qw(X Y Z);
use Wx qw(:frame :bitmap :id :misc :notebook :panel :sizer :menu :dialog :filedialog use Wx qw(:frame :bitmap :id :misc :panel :sizer :menu :dialog :filedialog
:font :icon wxTheApp); :font :icon :aui wxTheApp);
use Wx::Event qw(EVT_CLOSE EVT_NOTEBOOK_PAGE_CHANGED); use Wx::AUI;
use Wx::Event qw(EVT_CLOSE EVT_AUINOTEBOOK_PAGE_CHANGED EVT_AUINOTEBOOK_PAGE_CLOSE);
use base 'Wx::Frame'; use base 'Wx::Frame';
our $qs_last_input_file; our $qs_last_input_file;
@ -28,6 +29,7 @@ sub new {
} }
$self->{loaded} = 0; $self->{loaded} = 0;
$self->{preset_editor_tabs} = {}; # group => panel
# initialize tabpanel and menubar # initialize tabpanel and menubar
$self->_init_tabpanel; $self->_init_tabpanel;
@ -92,10 +94,24 @@ sub new {
sub _init_tabpanel { sub _init_tabpanel {
my ($self) = @_; my ($self) = @_;
$self->{tabpanel} = my $panel = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL); $self->{tabpanel} = my $panel = Wx::AuiNotebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP);
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{tabpanel}, sub { EVT_AUINOTEBOOK_PAGE_CHANGED($self, $self->{tabpanel}, sub {
my $panel = $self->{tabpanel}->GetCurrentPage; my $panel = $self->{tabpanel}->GetPage($self->{tabpanel}->GetSelection);
$panel->OnActivate if $panel->can('OnActivate'); $panel->OnActivate if $panel->can('OnActivate');
if ($self->{tabpanel}->GetSelection > 1) {
$self->{tabpanel}->SetWindowStyle($self->{tabpanel}->GetWindowStyleFlag | wxAUI_NB_CLOSE_ON_ACTIVE_TAB);
} else {
$self->{tabpanel}->SetWindowStyle($self->{tabpanel}->GetWindowStyleFlag & ~wxAUI_NB_CLOSE_ON_ACTIVE_TAB);
}
});
EVT_AUINOTEBOOK_PAGE_CLOSE($self, $self->{tabpanel}, sub {
my $panel = $self->{tabpanel}->GetPage($self->{tabpanel}->GetSelection);
if ($panel->isa('Slic3r::GUI::PresetEditor')) {
delete $self->{preset_editor_tabs}{$panel->name};
}
wxTheApp->CallAfter(sub {
$self->{tabpanel}->SetSelection(0);
});
}); });
$panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), "Plater"); $panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), "Plater");

View File

@ -49,7 +49,7 @@ sub new {
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
$self->{config} = Slic3r::Config->new_from_defaults(qw( $self->{config} = Slic3r::Config->new_from_defaults(qw(
bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width
serial_port serial_speed octoprint_host octoprint_apikey overridable filament_colour serial_port serial_speed octoprint_host octoprint_apikey shortcuts filament_colour
)); ));
$self->{model} = Slic3r::Model->new; $self->{model} = Slic3r::Model->new;
$self->{print} = Slic3r::Print->new; $self->{print} = Slic3r::Print->new;
@ -366,9 +366,37 @@ sub new {
{ {
my $o = $self->{settings_override_panel} = Slic3r::GUI::Plater::OverrideSettingsPanel->new($self, my $o = $self->{settings_override_panel} = Slic3r::GUI::Plater::OverrideSettingsPanel->new($self,
on_change => sub { on_change => sub {
my ($opt_key) = @_;
my ($preset) = $self->selected_presets('print');
$preset->load_config;
# If this option is not in the override panel it means it was manually deleted,
# so let's restore the profile value.
if (!$self->{settings_override_config}->has($opt_key)) {
$preset->_dirty_config->set($opt_key, $preset->_config->get($opt_key));
} else {
# Apply the overrides to the current Print preset, potentially making it dirty
$preset->_dirty_config->apply($self->{settings_override_config});
# If this is a configured shortcut (and not just a dirty option),
# save it now.
if (any { $_ eq $opt_key } @{$preset->dirty_config->shortcuts}) {
$preset->save([$opt_key]);
}
}
$self->load_presets;
$self->config_changed; $self->config_changed;
# Reload the open tab if any
if (my $print_tab = $self->GetFrame->{preset_editor_tabs}{print}) {
$print_tab->load_presets;
$print_tab->reload_preset;
}
}); });
$o->set_editable(1); $o->can_add(0);
$o->can_delete(1);
$o->set_opt_keys([ Slic3r::GUI::PresetEditor::Print->options ]); $o->set_opt_keys([ Slic3r::GUI::PresetEditor::Print->options ]);
$self->{settings_override_config} = Slic3r::Config->new; $self->{settings_override_config} = Slic3r::Config->new;
$o->set_default_config($self->{settings_override_config}); $o->set_default_config($self->{settings_override_config});
@ -534,6 +562,14 @@ sub _on_change_combobox {
return 0 if !$self->prompt_unsaved_changes; return 0 if !$self->prompt_unsaved_changes;
} }
wxTheApp->CallAfter(sub { wxTheApp->CallAfter(sub {
# Close the preset editor tab if any
if (exists $self->GetFrame->{preset_editor_tabs}{$group}) {
my $tabpanel = $self->GetFrame->{tabpanel};
$tabpanel->DeletePage($tabpanel->GetPageIndex($self->GetFrame->{preset_editor_tabs}{$group}));
delete $self->GetFrame->{preset_editor_tabs}{$group};
$tabpanel->SetSelection(0); # without this, a newly created tab will not be selected by wx
}
$self->_on_select_preset($group); $self->_on_select_preset($group);
# This will remove the "(modified)" mark from any dirty preset handled here. # This will remove the "(modified)" mark from any dirty preset handled here.
@ -562,31 +598,19 @@ sub _on_select_preset {
my $o_config = $self->{settings_override_config}; my $o_config = $self->{settings_override_config};
my $o_panel = $self->{settings_override_panel}; my $o_panel = $self->{settings_override_panel};
if ($changed) { my $shortcuts = $config->get('shortcuts');
# Preserve current options if re-selecting the same preset
$o_config->clear;
}
my $overridable = $config->get('overridable'); # Re-populate the override panel with the configured shortcuts
# and the dirty options.
# Add/remove options (we do it this way for preserving current options) $o_config->clear;
foreach my $opt_key (@$overridable) { foreach my $opt_key (@$shortcuts, $presets[0]->dirty_options) {
# Populate option with the default value taken from configuration # Don't add shortcut for shortcuts!
# (re-set the override always, because if we here it means user next if $opt_key eq 'shortcuts';
# switched to this preset or opened/closed the editor, so he expects
# the new values set in the editor to be used).
$o_config->set($opt_key, $config->get($opt_key)); $o_config->set($opt_key, $config->get($opt_key));
} }
foreach my $opt_key (@{$o_config->get_keys}) {
# Keep options listed among overridable and options added on the fly
if ((none { $_ eq $opt_key } @$overridable)
&& (any { $_ eq $opt_key } $o_panel->fixed_options)) {
$o_config->erase($opt_key);
}
}
$o_panel->set_default_config($config); $o_panel->set_default_config($config);
$o_panel->set_fixed_options(\@$overridable); $o_panel->set_fixed_options(\@$shortcuts);
$o_panel->update_optgroup; $o_panel->update_optgroup;
} elsif ($group eq 'printer') { } elsif ($group eq 'printer') {
# reload print and filament settings to honor their compatible_printer options # reload print and filament settings to honor their compatible_printer options
@ -699,7 +723,7 @@ sub load_presets {
} }
} }
$self->{print}->placeholder_parser->set("${group}_preset", [ @preset_names ]); $self->{print}->placeholder_parser->set_multiple("${group}_preset", [ @preset_names ]);
} }
} }
@ -742,19 +766,54 @@ sub selected_presets {
sub show_preset_editor { sub show_preset_editor {
my ($self, $group, $i) = @_; my ($self, $group, $i) = @_;
my $class = "Slic3r::GUI::PresetEditorDialog::" . ucfirst($group); wxTheApp->CallAfter(sub {
my $dlg = $class->new($self); my @presets = $self->selected_presets($group);
my @presets = $self->selected_presets($group); my $preset_editor;
$dlg->preset_editor->select_preset_by_name($presets[$i // 0]->name); my $dlg;
$dlg->ShowModal; my $mainframe = $self->GetFrame;
my $tabpanel = $mainframe->{tabpanel};
if (exists $mainframe->{preset_editor_tabs}{$group}) {
# we already have an open editor
$tabpanel->SetSelection($tabpanel->GetPageIndex($mainframe->{preset_editor_tabs}{$group}));
return;
} elsif ($Slic3r::GUI::Settings->{_}{tabbed_preset_editors}) {
my $class = "Slic3r::GUI::PresetEditor::" . ucfirst($group);
$mainframe->{preset_editor_tabs}{$group} = $preset_editor = $class->new($self->GetFrame);
$tabpanel->AddPage($preset_editor, ucfirst($group) . " Settings", 1);
} else {
my $class = "Slic3r::GUI::PresetEditorDialog::" . ucfirst($group);
$dlg = $class->new($self);
$preset_editor = $dlg->preset_editor;
}
# Re-load the presets as they might have changed. $preset_editor->select_preset_by_name($presets[$i // 0]->name);
$self->load_presets; $preset_editor->on_value_change(sub {
# Re-load the presets in order to toggle the (modified) suffix
$self->load_presets;
# Update shortcuts
$self->_on_select_preset($group);
# Use the new config wherever we actually use its contents
$self->config_changed;
});
my $cb = sub {
my ($group, $preset) = @_;
# Re-load the presets as they might have changed.
$self->load_presets;
# Select the preset in plater too
$self->select_preset_by_name($preset->name, $group, $i, 1);
};
$preset_editor->on_select_preset($cb);
$preset_editor->on_save_preset($cb);
# Select the preset that was last selected in the editor. if ($dlg) {
$self->select_preset_by_name $dlg->ShowModal;
($dlg->preset_editor->current_preset->name, $group, $i, 1); }
});
} }
# Returns the current config by merging the selected presets and the overrides. # Returns the current config by merging the selected presets and the overrides.
@ -765,7 +824,7 @@ sub config {
my $config = Slic3r::Config->new_from_defaults; my $config = Slic3r::Config->new_from_defaults;
# get defaults also for the values tracked by the Plater's config # get defaults also for the values tracked by the Plater's config
# (for example 'overridable') # (for example 'shortcuts')
$config->apply(Slic3r::Config->new_from_defaults(@{$self->{config}->get_keys})); $config->apply(Slic3r::Config->new_from_defaults(@{$self->{config}->get_keys}));
my %classes = map { $_ => "Slic3r::GUI::PresetEditor::".ucfirst($_) } my %classes = map { $_ => "Slic3r::GUI::PresetEditor::".ucfirst($_) }

View File

@ -34,7 +34,8 @@ sub new {
$self->{default_config} = Slic3r::Config->new; $self->{default_config} = Slic3r::Config->new;
$self->{config} = Slic3r::Config->new; $self->{config} = Slic3r::Config->new;
$self->{on_change} = $params{on_change}; $self->{on_change} = $params{on_change};
$self->{editable} = 1; $self->{can_add} = 1;
$self->{can_delete} = 1;
$self->{fixed_options} = {}; $self->{fixed_options} = {};
$self->{sizer} = Wx::BoxSizer->new(wxVERTICAL); $self->{sizer} = Wx::BoxSizer->new(wxVERTICAL);
@ -144,7 +145,7 @@ sub update_optgroup {
$self->{options_sizer}->Clear(1); $self->{options_sizer}->Clear(1);
return if !defined $self->{config}; return if !defined $self->{config};
$self->{btn_add}->Show($self->{editable}); $self->{btn_add}->Show($self->{can_add});
my %categories = (); my %categories = ();
foreach my $opt_key (@{$self->{config}->get_keys}) { foreach my $opt_key (@{$self->{config}->get_keys}) {
@ -173,7 +174,7 @@ sub update_optgroup {
my ($opt_key, $opt_index) = @{ $optgroup->_opt_map->{$opt_id} }; my ($opt_key, $opt_index) = @{ $optgroup->_opt_map->{$opt_id} };
# disallow deleting fixed options # disallow deleting fixed options
return undef if $self->{fixed_options}{$opt_key} || !$self->{editable}; return undef if $self->{fixed_options}{$opt_key} || !$self->{can_delete};
my $btn = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new($Slic3r::var->("delete.png"), wxBITMAP_TYPE_PNG), my $btn = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new($Slic3r::var->("delete.png"), wxBITMAP_TYPE_PNG),
wxDefaultPosition, wxDefaultSize, Wx::wxBORDER_NONE); wxDefaultPosition, wxDefaultSize, Wx::wxBORDER_NONE);
@ -210,11 +211,27 @@ sub disable {
$self->Disable; $self->Disable;
} }
# Shows or hides the Add button. # Shows or hides the Add/Delete buttons.
sub set_editable { sub set_editable {
my ($self, $editable) = @_; my ($self, $editable) = @_;
$self->{editable} = $editable; $self->{can_add} = $self->{can_delete} = $editable;
}
# Shows or hides the Add button.
sub can_add {
my ($self, $can) = @_;
$self->{can_add} = $can if defined $can;
return $can;
}
# Shows or hides the Delete button.
sub can_delete {
my ($self, $can) = @_;
$self->{can_delete} = $can if defined $can;
return $can;
} }
1; 1;

View File

@ -71,6 +71,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.', 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}, default => $Slic3r::GUI::Settings->{_}{no_controller},
)); ));
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
opt_id => 'tabbed_preset_editors',
type => 'bool',
label => 'Display profile editors as tabs',
tooltip => 'When opening a profile editor, it will be shown in a dialog or in a tab according to this option.',
default => $Slic3r::GUI::Settings->{_}{tabbed_preset_editors},
));
my $sizer = Wx::BoxSizer->new(wxVERTICAL); my $sizer = Wx::BoxSizer->new(wxVERTICAL);
$sizer->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10); $sizer->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);

View File

@ -94,7 +94,7 @@ sub prompt_unsaved_changes {
if ($res == wxID_CANCEL) { if ($res == wxID_CANCEL) {
return 0; return 0;
} elsif ($res == wxID_YES) { } elsif ($res == wxID_YES) {
return $self->save($self->default ? undef : $self->name); return $self->default ? $self->save_prompt($parent) : $self->save;
} elsif ($res == wxID_NO) { } elsif ($res == wxID_NO) {
$self->dismiss_changes; $self->dismiss_changes;
return 1; return 1;
@ -104,20 +104,29 @@ sub prompt_unsaved_changes {
return 1; return 1;
} }
sub save_prompt {
my ($self, $parent) = @_;
my $default_name = $self->default ? 'Untitled' : $self->name;
$default_name =~ s/\.ini$//i;
my $dlg = Slic3r::GUI::SavePresetWindow->new($parent,
default => $default_name,
values => [ map $_->name, grep !$_->default && !$_->external, @{wxTheApp->presets->{$self->name}} ],
);
return 0 unless $dlg->ShowModal == wxID_OK;
$self->save_as($dlg->get_name);
}
sub save { sub save {
my ($self, $name, $parent) = @_; my ($self, $opt_keys) = @_;
if (!$name) { return $self->save_as($self->name, $opt_keys);
my $default_name = $self->default ? 'Untitled' : $self->name; }
$default_name =~ s/\.ini$//i;
sub save_as {
my $dlg = Slic3r::GUI::SavePresetWindow->new($parent, my ($self, $name, $opt_keys) = @_;
default => $default_name,
values => [ map $_->name, grep !$_->default && !$_->external, @{wxTheApp->presets->{$self->name}} ],
);
return 0 unless $dlg->ShowModal == wxID_OK;
$name = $dlg->get_name;
}
$self->rename($name); $self->rename($name);
@ -125,8 +134,15 @@ sub save {
die "Calling save() without setting filename"; die "Calling save() without setting filename";
} }
$self->_config->clear; if ($opt_keys) {
$self->_config->apply($self->_dirty_config); $self->_config->apply_only($self->_dirty_config, $opt_keys);
} else {
$self->_config->clear;
$self->_config->apply($self->_dirty_config);
}
# unlink the file first to avoid problems on case-insensitive file systems
unlink Slic3r::encode_path($self->file);
$self->_config->save($self->file); $self->_config->save($self->file);
wxTheApp->load_presets; wxTheApp->load_presets;
@ -167,6 +183,8 @@ sub dirty_config {
sub load_config { sub load_config {
my ($self) = @_; my ($self) = @_;
return if $self->_loaded;
my @keys = $self->_group_class->options; my @keys = $self->_group_class->options;
my @extra_keys = $self->_group_class->overriding_options; my @extra_keys = $self->_group_class->overriding_options;

View File

@ -87,7 +87,7 @@ sub new {
}); });
EVT_CHOICE($parent, $self->{presets_choice}, sub { EVT_CHOICE($parent, $self->{presets_choice}, sub {
$self->on_select_preset; $self->_on_select_preset;
}); });
EVT_BUTTON($self, $self->{btn_save_preset}, sub { $self->save_preset }); EVT_BUTTON($self, $self->{btn_save_preset}, sub { $self->save_preset });
@ -123,13 +123,20 @@ sub save_preset {
$self->{treectrl}->SetFocus; $self->{treectrl}->SetFocus;
my $preset = $self->current_preset; my $preset = $self->current_preset;
$preset->save(undef, $self); $preset->save_prompt($self);
$self->load_presets; $self->load_presets;
$self->select_preset_by_name($preset->name); $self->select_preset_by_name($preset->name);
$self->{on_save_preset}->($self->name, $preset) if $self->{on_save_preset};
return 1; return 1;
} }
sub on_save_preset {
my ($self, $cb) = @_;
$self->{on_save_preset} = $cb;
}
sub on_value_change { sub on_value_change {
my ($self, $cb) = @_; my ($self, $cb) = @_;
$self->{on_value_change} = $cb; $self->{on_value_change} = $cb;
@ -141,10 +148,12 @@ sub on_value_change {
sub _on_value_change { sub _on_value_change {
my ($self, $opt_key) = @_; my ($self, $opt_key) = @_;
$self->current_preset->_dirty_config->apply($self->config); wxTheApp->CallAfter(sub {
$self->{on_value_change}->($opt_key) if $self->{on_value_change}; $self->current_preset->_dirty_config->apply($self->config);
$self->load_presets; $self->{on_value_change}->($opt_key) if $self->{on_value_change};
$self->_update; $self->load_presets;
$self->_update;
});
} }
sub _update {} sub _update {}
@ -155,7 +164,7 @@ sub select_preset {
my ($self, $i, $force) = @_; my ($self, $i, $force) = @_;
$self->{presets_choice}->SetSelection($i); $self->{presets_choice}->SetSelection($i);
$self->on_select_preset($force); $self->_on_select_preset($force);
} }
sub select_preset_by_name { sub select_preset_by_name {
@ -163,8 +172,12 @@ sub select_preset_by_name {
my $presets = wxTheApp->presets->{$self->name}; my $presets = wxTheApp->presets->{$self->name};
my $i = first { $presets->[$_]->name eq $name } 0..$#$presets; my $i = first { $presets->[$_]->name eq $name } 0..$#$presets;
if (!defined $i) {
warn "No preset named $name";
return 0;
}
$self->{presets_choice}->SetSelection($i); $self->{presets_choice}->SetSelection($i);
$self->on_select_preset($force); $self->_on_select_preset($force);
} }
sub prompt_unsaved_changes { sub prompt_unsaved_changes {
@ -175,6 +188,11 @@ sub prompt_unsaved_changes {
} }
sub on_select_preset { sub on_select_preset {
my ($self, $cb) = @_;
$self->{on_select_preset} = $cb;
}
sub _on_select_preset {
my ($self, $force) = @_; my ($self, $force) = @_;
# This method is called: # This method is called:
@ -185,9 +203,6 @@ sub on_select_preset {
# Get the selected name. # Get the selected name.
my $preset = wxTheApp->presets->{$self->name}->[$self->{presets_choice}->GetSelection]; my $preset = wxTheApp->presets->{$self->name}->[$self->{presets_choice}->GetSelection];
# If selection didn't change, do nothing.
return if defined $self->current_preset && $preset->name eq $self->current_preset->name;
# If we have unsaved changes, prompt user. # If we have unsaved changes, prompt user.
if (!$force && !$self->prompt_unsaved_changes) { if (!$force && !$self->prompt_unsaved_changes) {
# User decided not to save the current changes, so we restore the previous selection. # User decided not to save the current changes, so we restore the previous selection.
@ -199,13 +214,16 @@ sub on_select_preset {
$self->current_preset($preset); $self->current_preset($preset);
# If selection didn't change, do nothing.
# Only after resetting current_preset because it might contain an older object of the
# current preset.
return if defined $self->current_preset && $preset->name eq $self->current_preset->name;
# We reload presets in order to remove the "(modified)" suffix in case user was # We reload presets in order to remove the "(modified)" suffix in case user was
# prompted and chose to discard changes. # prompted and chose to discard changes.
$self->load_presets; $self->load_presets;
$preset->load_config if !$preset->_loaded; $self->reload_preset;
$self->config->clear;
$self->config->apply($preset->dirty_config);
eval { eval {
local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self);
@ -215,12 +233,13 @@ sub on_select_preset {
$self->_update; $self->_update;
$self->on_preset_loaded; $self->on_preset_loaded;
$self->reload_config;
}; };
if ($@) { if ($@) {
$@ = "I was unable to load the selected config file: $@"; $@ = "I was unable to load the selected config file: $@";
Slic3r::GUI::catch_error($self); Slic3r::GUI::catch_error($self);
} }
$self->{on_select_preset}->($self->name, $preset) if $self->{on_select_preset};
} }
sub add_options_page { sub add_options_page {
@ -240,6 +259,15 @@ sub add_options_page {
return $page; return $page;
} }
sub reload_preset {
my ($self) = @_;
$self->current_preset->load_config if !$self->current_preset->_loaded;
$self->config->clear;
$self->config->apply($self->current_preset->dirty_config);
$self->reload_config;
}
sub reload_config { sub reload_config {
my $self = shift; my $self = shift;
@ -441,7 +469,7 @@ sub options {
external_perimeter_extrusion_width infill_extrusion_width solid_infill_extrusion_width external_perimeter_extrusion_width infill_extrusion_width solid_infill_extrusion_width
top_infill_extrusion_width support_material_extrusion_width top_infill_extrusion_width support_material_extrusion_width
infill_overlap bridge_flow_ratio infill_overlap bridge_flow_ratio
xy_size_compensation resolution overridable compatible_printers xy_size_compensation resolution shortcuts compatible_printers
print_settings_id print_settings_id
) )
} }
@ -449,7 +477,7 @@ sub options {
sub build { sub build {
my $self = shift; my $self = shift;
my $overridable_widget = sub { my $shortcuts_widget = sub {
my ($parent) = @_; my ($parent) = @_;
my $Options = $Slic3r::Config::Options; my $Options = $Slic3r::Config::Options;
@ -458,15 +486,15 @@ sub build {
grep { exists $Options->{$_} && $Options->{$_}{category} } $self->options grep { exists $Options->{$_} && $Options->{$_}{category} } $self->options
); );
my @opt_keys = sort { $options{$a} cmp $options{$b} } keys %options; my @opt_keys = sort { $options{$a} cmp $options{$b} } keys %options;
$self->{overridable_opt_keys} = [ @opt_keys ]; $self->{shortcuts_opt_keys} = [ @opt_keys ];
my $listbox = $self->{overridable_list} = Wx::CheckListBox->new($parent, -1, my $listbox = $self->{shortcuts_list} = Wx::CheckListBox->new($parent, -1,
wxDefaultPosition, [-1, 320], [ map $options{$_}, @opt_keys ]); wxDefaultPosition, [-1, 320], [ map $options{$_}, @opt_keys ]);
EVT_CHECKLISTBOX($self, $listbox, sub { EVT_CHECKLISTBOX($self, $listbox, sub {
my $value = [ map $opt_keys[$_], grep $listbox->IsChecked($_), 0..$#opt_keys ]; my $value = [ map $opt_keys[$_], grep $listbox->IsChecked($_), 0..$#opt_keys ];
$self->config->set('overridable', $value); $self->config->set('shortcuts', $value);
$self->_on_value_change('overridable'); $self->_on_value_change('shortcuts');
}); });
my $sizer = Wx::BoxSizer->new(wxVERTICAL); my $sizer = Wx::BoxSizer->new(wxVERTICAL);
@ -715,7 +743,7 @@ sub build {
} }
{ {
my $page = $self->add_options_page('Overrides', 'wrench.png'); my $page = $self->add_options_page('Shortcuts', 'wrench.png');
{ {
my $optgroup = $page->new_optgroup('Profile preferences'); my $optgroup = $page->new_optgroup('Profile preferences');
{ {
@ -727,10 +755,10 @@ sub build {
} }
} }
{ {
my $optgroup = $page->new_optgroup('Overridable settings (they will be displayed in the plater for quick changes)'); my $optgroup = $page->new_optgroup('Show shortcuts for the following settings');
{ {
my $line = Slic3r::GUI::OptionsGroup::Line->new( my $line = Slic3r::GUI::OptionsGroup::Line->new(
widget => $overridable_widget, widget => $shortcuts_widget,
full_width => 1, full_width => 1,
); );
$optgroup->append_line($line); $optgroup->append_line($line);
@ -745,9 +773,9 @@ sub reload_config {
$self->_reload_compatible_printers_widget; $self->_reload_compatible_printers_widget;
{ {
my %overridable = map { $_ => 1 } @{ $self->config->get('overridable') }; my %shortcuts = map { $_ => 1 } @{ $self->config->get('shortcuts') };
for my $i (0..$#{$self->{overridable_opt_keys}}) { for my $i (0..$#{$self->{shortcuts_opt_keys}}) {
$self->{overridable_list}->Check($i, $overridable{ $self->{overridable_opt_keys}[$i] }); $self->{shortcuts_list}->Check($i, $shortcuts{ $self->{shortcuts_opt_keys}[$i] });
} }
} }

View File

@ -853,8 +853,9 @@ PrintConfigDef::PrintConfigDef()
def->cli = "overhangs|detect-bridging-perimeters!"; def->cli = "overhangs|detect-bridging-perimeters!";
def->default_value = new ConfigOptionBool(true); def->default_value = new ConfigOptionBool(true);
def = this->add("overridable", coStrings); def = this->add("shortcuts", coStrings);
def->label = "Overridable options"; def->label = "Shortcuts";
def->aliases.push_back("overridable");
{ {
ConfigOptionStrings* opt = new ConfigOptionStrings(); ConfigOptionStrings* opt = new ConfigOptionStrings();
opt->values.push_back("support_material"); opt->values.push_back("support_material");
@ -1383,7 +1384,7 @@ PrintConfigDef::PrintConfigDef()
def = this->add("support_material_interface_speed", coFloatOrPercent); def = this->add("support_material_interface_speed", coFloatOrPercent);
def->label = "↳ interface"; def->label = "↳ interface";
def->category = "Support material interface speed"; def->full_label = "Support material interface speed";
def->gui_type = "f_enum_open"; def->gui_type = "f_enum_open";
def->category = "Support material"; def->category = "Support material";
def->tooltip = "Speed for printing support material interface layers. If expressed as percentage (for example 50%) it will be calculated over support material speed."; def->tooltip = "Speed for printing support material interface layers. If expressed as percentage (for example 50%) it will be calculated over support material speed.";