diff --git a/lib/Slic3r/GUI/Controller/PrinterPanel.pm b/lib/Slic3r/GUI/Controller/PrinterPanel.pm index edb450fa1..c6f155b07 100644 --- a/lib/Slic3r/GUI/Controller/PrinterPanel.pm +++ b/lib/Slic3r/GUI/Controller/PrinterPanel.pm @@ -72,6 +72,8 @@ sub new { { $self->{btn_rescan_serial} = my $btn = Wx::BitmapButton->new($box, -1, Wx::Bitmap->new("$Slic3r::var/arrow_rotate_clockwise.png", wxBITMAP_TYPE_PNG), wxDefaultPosition, wxDefaultSize, &Wx::wxBORDER_NONE); + $btn->SetToolTipString("Rescan serial ports") + if $btn->can('SetToolTipString'); $serial_port_sizer->Add($btn, 0, wxALIGN_CENTER_VERTICAL, 0); EVT_BUTTON($self, $btn, sub { $self->update_serial_ports }); } diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index d6a486828..e8f02ba68 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -83,7 +83,7 @@ sub append_line { # if we have a single option with no sidetext just add it directly to the grid sizer my @options = @{$line->get_options}; $self->_options->{$_->opt_id} = $_ for @options; - if (@options == 1 && !$options[0]->sidetext && !@{$line->get_extra_widgets}) { + if (@options == 1 && !$options[0]->sidetext && !$options[0]->side_widget && !@{$line->get_extra_widgets}) { my $option = $options[0]; my $field = $self->_build_field($option); $grid_sizer->Add($field, 0, ($option->full_width ? wxEXPAND : 0) | wxALIGN_CENTER_VERTICAL, 0); @@ -95,7 +95,9 @@ sub append_line { my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); $grid_sizer->Add($sizer, 0, 0, 0); - foreach my $option (@options) { + foreach my $i (0..$#options) { + my $option = $options[$i]; + # add label if any if ($option->label) { my $field_label = Wx::StaticText->new($self->parent, -1, $option->label . ":", wxDefaultPosition, wxDefaultSize); @@ -111,7 +113,16 @@ sub append_line { if ($option->sidetext) { my $sidetext = Wx::StaticText->new($self->parent, -1, $option->sidetext, wxDefaultPosition, wxDefaultSize); $sidetext->SetFont($self->sidetext_font); - $sizer->Add($sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL , 4); + $sizer->Add($sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4); + } + + # add side widget if any + if ($option->side_widget) { + $sizer->Add($option->side_widget->($self->parent), 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 1); + } + + if ($option != $#options) { + $sizer->AddSpacer(4); } } @@ -172,7 +183,7 @@ sub _build_field { parent => $self->parent, option => $opt, ); - } elsif ($type eq 'select') { + } elsif ($type eq 'select' || $type eq 'select_open') { $field = Slic3r::GUI::OptionsGroup::Field::Choice->new( parent => $self->parent, option => $opt, @@ -294,6 +305,7 @@ has 'max' => (is => 'rw', default => sub { undef }); has 'labels' => (is => 'rw', default => sub { [] }); has 'values' => (is => 'rw', default => sub { [] }); has 'readonly' => (is => 'rw', default => sub { 0 }); +has 'side_widget' => (is => 'rw', default => sub { undef }); package Slic3r::GUI::ConfigOptionsGroup; diff --git a/lib/Slic3r/GUI/OptionsGroup/Field.pm b/lib/Slic3r/GUI/OptionsGroup/Field.pm index 13b86cdfc..8a181355d 100644 --- a/lib/Slic3r/GUI/OptionsGroup/Field.pm +++ b/lib/Slic3r/GUI/OptionsGroup/Field.pm @@ -194,13 +194,15 @@ extends 'Slic3r::GUI::OptionsGroup::Field::wxWindow'; use List::Util qw(first); use Wx qw(:misc :combobox); -use Wx::Event qw(EVT_COMBOBOX); +use Wx::Event qw(EVT_COMBOBOX EVT_TEXT); sub BUILD { my ($self) = @_; + my $style = 0; + $style |= wxCB_READONLY if $self->option->gui_type ne 'select_open'; my $field = Wx::ComboBox->new($self->parent, -1, "", wxDefaultPosition, $self->_default_size, - $self->option->labels || $self->option->values, wxCB_READONLY); + $self->option->labels || $self->option->values || [], $style); $self->wxWindow($field); $self->set_value($self->option->default); @@ -208,24 +210,49 @@ sub BUILD { EVT_COMBOBOX($self->parent, $field, sub { $self->_on_change($self->option->opt_id); }); + EVT_TEXT($self->parent, $field, sub { + $self->_on_change($self->option->opt_id); + }); } sub set_value { my ($self, $value) = @_; - my $idx = first { $self->option->values->[$_] eq $value } 0..$#{$self->option->values}; + $self->disable_change_event(1); + + if ($self->option->values) { + my $idx = first { $self->option->values->[$_] eq $value } 0..$#{$self->option->values}; + $self->wxWindow->SetSelection($idx); + } else { + $self->wxWindow->SetValue($value); + } + + $self->disable_change_event(0); +} + +sub set_values { + my ($self, $values) = @_; $self->disable_change_event(1); - $self->wxWindow->SetSelection($idx); + + $self->wxWindow->Clear; + $self->wxWindow->Append($_) for @$values; + $self->disable_change_event(0); } sub get_value { my ($self) = @_; - return $self->option->values->[$self->wxWindow->GetSelection]; + + if ($self->option->values) { + my $idx = $self->wxWindow->GetSelection; + if ($idx != &Wx::wxNOT_FOUND) { + return $self->option->values->[$idx]; + } + } + return $self->wxWindow->GetValue; } - package Slic3r::GUI::OptionsGroup::Field::NumericChoice; use Moo; extends 'Slic3r::GUI::OptionsGroup::Field::wxWindow'; @@ -311,12 +338,14 @@ sub get_value { my ($self) = @_; my $label = $self->wxWindow->GetValue; - my $value_idx = first { $self->option->labels->[$_] eq $label } 0..$#{$self->option->labels}; - if (defined $value_idx) { - if ($self->option->values) { - return $self->option->values->[$value_idx]; + if ($self->option->labels) { + my $value_idx = first { $self->option->labels->[$_] eq $label } 0..$#{$self->option->labels}; + if (defined $value_idx) { + if ($self->option->values) { + return $self->option->values->[$value_idx]; + } + return $value_idx; } - return $value_idx; } return $label; } diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 741b5f99e..feecd365a 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -911,7 +911,7 @@ sub _update_description { package Slic3r::GUI::Tab::Printer; use base 'Slic3r::GUI::Tab'; -use Wx qw(:sizer :button :bitmap :misc :id); +use Wx qw(wxTheApp :sizer :button :bitmap :misc :id); use Wx::Event qw(EVT_BUTTON); sub name { 'printer' } @@ -1000,8 +1000,24 @@ sub build { } { my $optgroup = $page->new_optgroup('USB/Serial connection'); - $optgroup->append_single_option_line('serial_port'); - $optgroup->append_single_option_line('serial_speed'); + my $line = Slic3r::GUI::OptionsGroup::Line->new( + label => 'Serial port', + ); + my $serial_port = $optgroup->get_option('serial_port'); + $serial_port->side_widget(sub { + my ($parent) = @_; + + my $btn = Wx::BitmapButton->new($parent, -1, Wx::Bitmap->new("$Slic3r::var/arrow_rotate_clockwise.png", wxBITMAP_TYPE_PNG), + wxDefaultPosition, wxDefaultSize, &Wx::wxBORDER_NONE); + $btn->SetToolTipString("Rescan serial ports") + if $btn->can('SetToolTipString'); + EVT_BUTTON($self, $btn, \&_update_serial_ports); + + return $btn; + }); + $line->append_option($serial_port); + $line->append_option($optgroup->get_option('serial_speed')); + $optgroup->append_line($line); } { my $optgroup = $page->new_optgroup('OctoPrint upload'); @@ -1091,6 +1107,13 @@ sub build { $self->{extruder_pages} = []; $self->_build_extruder_pages; + $self->_update_serial_ports; +} + +sub _update_serial_ports { + my ($self) = @_; + + $self->get_field('serial_port')->set_values([ wxTheApp->scan_serial_ports ]); } sub _extruders_count_changed { @@ -1175,6 +1198,7 @@ sub _update { my $config = $self->{config}; + $self->get_field('serial_speed')->toggle($config->get('serial_port')); $self->get_field('octoprint_apikey')->toggle($config->get('octoprint_host')); my $have_multiple_extruders = $self->{extruders_count} > 1; diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index e2c69bb3a..8fda6d322 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -662,16 +662,23 @@ PrintConfigDef::build_def() { Options["seam_position"].enum_labels.push_back("Aligned"); Options["serial_port"].type = coString; - Options["serial_port"].label = "Serial port"; + Options["serial_port"].gui_type = "select_open"; + Options["serial_port"].label = ""; + Options["serial_port"].full_label = "Serial port"; Options["serial_port"].tooltip = "USB/serial port for printer connection."; Options["serial_port"].cli = "serial-port=s"; + Options["serial_port"].width = 200; Options["serial_speed"].type = coInt; + Options["serial_speed"].gui_type = "i_enum_open"; Options["serial_speed"].label = "Speed"; + Options["serial_speed"].full_label = "Serial port speed"; Options["serial_speed"].tooltip = "Speed (baud) of USB/serial port for printer connection."; Options["serial_speed"].cli = "serial-speed=i"; Options["serial_speed"].min = 1; Options["serial_speed"].max = 300000; + Options["serial_speed"].enum_values.push_back("115200"); + Options["serial_speed"].enum_values.push_back("250000"); Options["skirt_distance"].type = coFloat; Options["skirt_distance"].label = "Distance from object";