mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 12:11:15 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			498 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			498 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| # A dialog group object. Used by the Tab, Preferences dialog, ManualControlDialog etc.
 | ||
| 
 | ||
| package Slic3r::GUI::OptionsGroup;
 | ||
| use Moo;
 | ||
| 
 | ||
| use List::Util qw(first);
 | ||
| use Wx qw(:combobox :font :misc :sizer :systemsettings :textctrl wxTheApp);
 | ||
| use Wx::Event qw(EVT_CHECKBOX EVT_COMBOBOX EVT_SPINCTRL EVT_TEXT EVT_KILL_FOCUS EVT_SLIDER);
 | ||
| 
 | ||
| has 'parent'        => (is => 'ro', required => 1);
 | ||
| has 'title'         => (is => 'ro', required => 1);
 | ||
| has 'on_change'     => (is => 'rw', default => sub { sub {} });
 | ||
| has 'staticbox'     => (is => 'ro', default => sub { 1 });
 | ||
| has 'label_width'   => (is => 'rw', default => sub { 180 });
 | ||
| has 'extra_column'  => (is => 'rw', default => sub { undef });
 | ||
| has 'label_font'    => (is => 'rw');
 | ||
| has 'sidetext_font' => (is => 'rw', default => sub { Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) });
 | ||
| has 'sizer'         => (is => 'rw');
 | ||
| has '_disabled'     => (is => 'rw', default => sub { 0 });
 | ||
| has '_grid_sizer'   => (is => 'rw');
 | ||
| has '_options'      => (is => 'ro', default => sub { {} });
 | ||
| has '_fields'       => (is => 'ro', default => sub { {} });
 | ||
| 
 | ||
| sub BUILD {
 | ||
|     my $self = shift;
 | ||
|     
 | ||
|     if ($self->staticbox) {
 | ||
|         my $box = Wx::StaticBox->new($self->parent, -1, $self->title);
 | ||
|         $self->sizer(Wx::StaticBoxSizer->new($box, wxVERTICAL));
 | ||
|     } else {
 | ||
|         $self->sizer(Wx::BoxSizer->new(wxVERTICAL));
 | ||
|     }
 | ||
|     
 | ||
|     my $num_columns = 1;
 | ||
|     ++$num_columns if $self->label_width != 0;
 | ||
|     ++$num_columns if $self->extra_column;
 | ||
|     $self->_grid_sizer(Wx::FlexGridSizer->new(0, $num_columns, 0, 0));
 | ||
|     $self->_grid_sizer->SetFlexibleDirection(wxHORIZONTAL);
 | ||
|     $self->_grid_sizer->AddGrowableCol($self->label_width != 0);
 | ||
|     
 | ||
|     # TODO: border size may be related to wxWidgets 2.8.x vs. 2.9.x instead of wxMAC specific
 | ||
|     $self->sizer->Add($self->_grid_sizer, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 5);
 | ||
| }
 | ||
| 
 | ||
| # this method accepts a Slic3r::GUI::OptionsGroup::Line object
 | ||
| sub append_line {
 | ||
|     my ($self, $line) = @_;
 | ||
|     
 | ||
|     if ($line->sizer || ($line->widget && $line->full_width)) {
 | ||
|         # full-width widgets are appended *after* the grid sizer, so after all the non-full-width lines
 | ||
|         my $sizer = $line->sizer // $line->widget->($self->parent);
 | ||
|         $self->sizer->Add($sizer, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 15);
 | ||
|         return;
 | ||
|     }
 | ||
|     
 | ||
|     my $grid_sizer = $self->_grid_sizer;
 | ||
|     
 | ||
|     # if we have an extra column, build it
 | ||
|     if ($self->extra_column) {
 | ||
|         if (defined (my $item = $self->extra_column->($line))) {
 | ||
|             $grid_sizer->Add($item, 0, wxALIGN_CENTER_VERTICAL, 0);
 | ||
|         } else {
 | ||
|             # if the callback provides no sizer for the extra cell, put a spacer
 | ||
|             $grid_sizer->AddSpacer(1);
 | ||
|         }
 | ||
|     }
 | ||
|     
 | ||
|     # build label if we have it
 | ||
|     my $label;
 | ||
|     if ($self->label_width != 0) {
 | ||
|         $label = Wx::StaticText->new($self->parent, -1, $line->label ? $line->label . ":" : "", wxDefaultPosition, [$self->label_width, -1]);
 | ||
|         $label->SetFont($self->label_font) if $self->label_font;
 | ||
|         $label->Wrap($self->label_width) ;  # needed to avoid Linux/GTK bug
 | ||
|         $grid_sizer->Add($label, 0, wxALIGN_CENTER_VERTICAL, 0);
 | ||
|         $label->SetToolTipString($line->label_tooltip) if $line->label_tooltip;
 | ||
|     }
 | ||
|     
 | ||
|     # if we have a widget, add it to the sizer
 | ||
|     if ($line->widget) {
 | ||
|         my $widget_sizer = $line->widget->($self->parent);
 | ||
|         $grid_sizer->Add($widget_sizer, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 15);
 | ||
|         return;
 | ||
|     }
 | ||
|     
 | ||
|     # 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 && !$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);
 | ||
|         return;
 | ||
|     }
 | ||
|     
 | ||
|     # if we're here, we have more than one option or a single option with sidetext
 | ||
|     # so we need a horizontal sizer to arrange these things
 | ||
|     my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
 | ||
|     $grid_sizer->Add($sizer, 0, 0, 0);
 | ||
|     
 | ||
|     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);
 | ||
|             $field_label->SetFont($self->sidetext_font);
 | ||
|             $sizer->Add($field_label, 0, wxALIGN_CENTER_VERTICAL, 0);
 | ||
|         }
 | ||
|         
 | ||
|         # add field
 | ||
|         my $field = $self->_build_field($option);
 | ||
|         $sizer->Add($field, 0, wxALIGN_CENTER_VERTICAL, 0);
 | ||
|         
 | ||
|         # add sidetext if any
 | ||
|         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);
 | ||
|         }
 | ||
|         
 | ||
|         # 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);
 | ||
|         }
 | ||
|     }
 | ||
|         
 | ||
|     # add extra sizers if any
 | ||
|     foreach my $extra_widget (@{$line->get_extra_widgets}) {
 | ||
|         $sizer->Add($extra_widget->($self->parent), 0, wxLEFT | wxALIGN_CENTER_VERTICAL , 4);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| sub create_single_option_line {
 | ||
|     my ($self, $option) = @_;
 | ||
|     
 | ||
|     my $line = Slic3r::GUI::OptionsGroup::Line->new(
 | ||
|         label           => $option->label,
 | ||
|         label_tooltip   => $option->tooltip,
 | ||
|     );
 | ||
|     $option->label("");
 | ||
|     $line->append_option($option);
 | ||
|     
 | ||
|     return $line;
 | ||
| }
 | ||
| 
 | ||
| sub append_single_option_line {
 | ||
|     my ($self, $option) = @_;
 | ||
|     return $self->append_line($self->create_single_option_line($option));
 | ||
| }
 | ||
| 
 | ||
| sub _build_field {
 | ||
|     my $self = shift;
 | ||
|     my ($opt) = @_;
 | ||
|     
 | ||
|     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;
 | ||
|     };
 | ||
|     my $on_kill_focus = sub {
 | ||
|         my ($opt_id) = @_;
 | ||
|         $self->_on_kill_focus($opt_id);
 | ||
|     };
 | ||
|     
 | ||
|     my $type = $opt->{gui_type} || $opt->{type};
 | ||
|     
 | ||
|     my $field;
 | ||
|     if ($type eq 'bool') {
 | ||
|         $field = Slic3r::GUI::OptionsGroup::Field::Checkbox->new(
 | ||
|             parent => $self->parent,
 | ||
|             option => $opt,
 | ||
|         );
 | ||
|     } elsif ($type eq 'i') {
 | ||
|         $field = Slic3r::GUI::OptionsGroup::Field::SpinCtrl->new(
 | ||
|             parent => $self->parent,
 | ||
|             option => $opt,
 | ||
|         );
 | ||
|     } elsif ($type eq 'color') {
 | ||
|         $field = Slic3r::GUI::OptionsGroup::Field::ColourPicker->new(
 | ||
|             parent => $self->parent,
 | ||
|             option => $opt,
 | ||
|         );
 | ||
|     } elsif ($type =~ /^(f|s|s@|percent)$/) {
 | ||
|         $field = Slic3r::GUI::OptionsGroup::Field::TextCtrl->new(
 | ||
|             parent => $self->parent,
 | ||
|             option => $opt,
 | ||
|         );
 | ||
|     } elsif ($type eq 'select' || $type eq 'select_open') {
 | ||
|         $field = Slic3r::GUI::OptionsGroup::Field::Choice->new(
 | ||
|             parent => $self->parent,
 | ||
|             option => $opt,
 | ||
|         );
 | ||
|     } elsif ($type eq 'f_enum_open' || $type eq 'i_enum_open' || $type eq 'i_enum_closed') {
 | ||
|         $field = Slic3r::GUI::OptionsGroup::Field::NumericChoice->new(
 | ||
|             parent => $self->parent,
 | ||
|             option => $opt,
 | ||
|         );
 | ||
|     } elsif ($type eq 'point') {
 | ||
|         $field = Slic3r::GUI::OptionsGroup::Field::Point->new(
 | ||
|             parent => $self->parent,
 | ||
|             option => $opt,
 | ||
|         );
 | ||
|     } elsif ($type eq 'slider') {
 | ||
|         $field = Slic3r::GUI::OptionsGroup::Field::Slider->new(
 | ||
|             parent => $self->parent,
 | ||
|             option => $opt,
 | ||
|         );
 | ||
|     }
 | ||
|     return undef if !$field;
 | ||
|     
 | ||
|     #! setting up a function that will be triggered when the field changes
 | ||
|     #! think of it as $field->on_change = ($on_change)
 | ||
|     $field->on_change($on_change);
 | ||
|     $field->on_kill_focus($on_kill_focus);
 | ||
|     $self->_fields->{$opt_id} = $field;
 | ||
|     
 | ||
|     return $field->isa('Slic3r::GUI::OptionsGroup::Field::wxWindow')
 | ||
|         ? $field->wxWindow
 | ||
|         : $field->wxSizer;
 | ||
| }
 | ||
| 
 | ||
| sub get_option {
 | ||
|     my ($self, $opt_id) = @_;
 | ||
|     return undef if !exists $self->_options->{$opt_id};
 | ||
|     return $self->_options->{$opt_id};
 | ||
| }
 | ||
| 
 | ||
| sub get_field {
 | ||
|     my ($self, $opt_id) = @_;
 | ||
|     return undef if !exists $self->_fields->{$opt_id};
 | ||
|     return $self->_fields->{$opt_id};
 | ||
| }
 | ||
| 
 | ||
| sub get_value {
 | ||
|     my ($self, $opt_id) = @_;
 | ||
|     
 | ||
|     return if !exists $self->_fields->{$opt_id};
 | ||
|     return $self->_fields->{$opt_id}->get_value;
 | ||
| }
 | ||
| 
 | ||
| sub set_value {
 | ||
|     my ($self, $opt_id, $value) = @_;
 | ||
|     
 | ||
|     return if !exists $self->_fields->{$opt_id};
 | ||
|     $self->_fields->{$opt_id}->set_value($value);
 | ||
| }
 | ||
| 
 | ||
| sub _on_change {
 | ||
|     my ($self, $opt_id, $value) = @_;
 | ||
|     $self->on_change->($opt_id, $value);
 | ||
| }
 | ||
| 
 | ||
| sub enable {
 | ||
|     my ($self) = @_;
 | ||
|     
 | ||
|     $_->enable for values %{$self->_fields};
 | ||
| }
 | ||
| 
 | ||
| sub disable {
 | ||
|     my ($self) = @_;
 | ||
|     
 | ||
|     $_->disable for values %{$self->_fields};
 | ||
| }
 | ||
| 
 | ||
| sub _on_kill_focus {
 | ||
|     my ($self, $opt_id) = @_;
 | ||
|     # nothing
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| package Slic3r::GUI::OptionsGroup::Line;
 | ||
| use Moo;
 | ||
| 
 | ||
| has 'label'         => (is => 'rw', default => sub { "" });
 | ||
| has 'full_width'    => (is => 'rw', default => sub { 0 });
 | ||
| has 'label_tooltip' => (is => 'rw', default => sub { "" });
 | ||
| has 'sizer'         => (is => 'rw');
 | ||
| has 'widget'        => (is => 'rw');
 | ||
| has '_options'      => (is => 'ro', default => sub { [] });
 | ||
| # Extra UI components after the label and the edit widget of the option.
 | ||
| has '_extra_widgets' => (is => 'ro', default => sub { [] });
 | ||
| 
 | ||
| # this method accepts a Slic3r::GUI::OptionsGroup::Option object
 | ||
| sub append_option {
 | ||
|     my ($self, $option) = @_;
 | ||
|     push @{$self->_options}, $option;
 | ||
| }
 | ||
| 
 | ||
| sub append_widget {
 | ||
|     my ($self, $widget) = @_;
 | ||
|     push @{$self->_extra_widgets}, $widget;
 | ||
| }
 | ||
| 
 | ||
| sub get_options {
 | ||
|     my ($self) = @_;
 | ||
|     return [ @{$self->_options} ];
 | ||
| }
 | ||
| 
 | ||
| sub get_extra_widgets {
 | ||
|     my ($self) = @_;
 | ||
|     return [ @{$self->_extra_widgets} ];
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| # Configuration of an option.
 | ||
| # This very much reflects the content of the C++ ConfigOptionDef class.
 | ||
| package Slic3r::GUI::OptionsGroup::Option;
 | ||
| use Moo;
 | ||
| 
 | ||
| has 'opt_id'        => (is => 'rw', required => 1);
 | ||
| has 'type'          => (is => 'rw', required => 1);
 | ||
| has 'default'       => (is => 'rw', required => 1);
 | ||
| has 'gui_type'      => (is => 'rw', default => sub { undef });
 | ||
| has 'gui_flags'     => (is => 'rw', default => sub { "" });
 | ||
| has 'label'         => (is => 'rw', default => sub { "" });
 | ||
| has 'sidetext'      => (is => 'rw', default => sub { "" });
 | ||
| has 'tooltip'       => (is => 'rw', default => sub { "" });
 | ||
| has 'multiline'     => (is => 'rw', default => sub { 0 });
 | ||
| has 'full_width'    => (is => 'rw', default => sub { 0 });
 | ||
| has 'width'         => (is => 'rw', default => sub { undef });
 | ||
| has 'height'        => (is => 'rw', default => sub { undef });
 | ||
| has 'min'           => (is => 'rw', default => sub { undef });
 | ||
| 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;
 | ||
| use Moo;
 | ||
| 
 | ||
| use List::Util qw(first);
 | ||
| 
 | ||
| extends 'Slic3r::GUI::OptionsGroup';
 | ||
| has 'config'        => (is => 'ro', required => 1);
 | ||
| has 'full_labels'   => (is => 'ro', default => sub { 0 });
 | ||
| has '_opt_map'      => (is => 'ro', default => sub { {} });
 | ||
| 
 | ||
| sub get_option {
 | ||
|     my ($self, $opt_key, $opt_index) = @_;
 | ||
|     
 | ||
|     $opt_index //= -1;
 | ||
|     
 | ||
|     if (!$self->config->has($opt_key)) {
 | ||
|         die "No $opt_key in ConfigOptionsGroup config";
 | ||
|     }
 | ||
|     
 | ||
|     my $opt_id = ($opt_index == -1 ? $opt_key : "${opt_key}#${opt_index}");
 | ||
|     $self->_opt_map->{$opt_id} = [ $opt_key, $opt_index ];
 | ||
|     
 | ||
|     # Slic3r::Config::Options is a C++ Slic3r::PrintConfigDef exported as a Perl hash of hashes.
 | ||
|     # The C++ counterpart is a constant singleton.
 | ||
|     my $optdef = $Slic3r::Config::Options->{$opt_key};    # we should access this from $self->config
 | ||
|     my $default_value = $self->_get_config_value($opt_key, $opt_index, $optdef->{gui_flags} =~ /\bserialized\b/);
 | ||
|     
 | ||
|     return Slic3r::GUI::OptionsGroup::Option->new(
 | ||
|         opt_id      => $opt_id,
 | ||
|         type        => $optdef->{type},
 | ||
|         default     => $default_value,
 | ||
|         gui_type    => $optdef->{gui_type},
 | ||
|         gui_flags   => $optdef->{gui_flags},
 | ||
|         label       => ($self->full_labels && defined $optdef->{full_label}) ? $optdef->{full_label} : $optdef->{label},
 | ||
|         sidetext    => $optdef->{sidetext},
 | ||
|         # calling serialize() ensures we get a stringified value
 | ||
|         tooltip     => $optdef->{tooltip} . " (default: " . $self->config->serialize($opt_key) . ")",
 | ||
|         multiline   => $optdef->{multiline},
 | ||
|         width       => $optdef->{width},
 | ||
|         min         => $optdef->{min},
 | ||
|         max         => $optdef->{max},
 | ||
|         labels      => $optdef->{labels},
 | ||
|         values      => $optdef->{values},
 | ||
|         readonly    => $optdef->{readonly},
 | ||
|     );
 | ||
| }
 | ||
| 
 | ||
| sub create_single_option_line {
 | ||
|     my ($self, $opt_key, $opt_index) = @_;
 | ||
|     
 | ||
|     my $option;
 | ||
|     if (ref($opt_key)) {
 | ||
|         $option = $opt_key;
 | ||
|     } else {
 | ||
|         $option = $self->get_option($opt_key, $opt_index);
 | ||
|     }
 | ||
|     return $self->SUPER::create_single_option_line($option);
 | ||
| }
 | ||
| 
 | ||
| sub append_single_option_line {
 | ||
|     my ($self, $option, $opt_index) = @_;
 | ||
|     return $self->append_line($self->create_single_option_line($option, $opt_index));
 | ||
| }
 | ||
| 
 | ||
| # Initialize UI components with the config values.
 | ||
| sub reload_config {
 | ||
|     my ($self) = @_;
 | ||
|     
 | ||
|     foreach my $opt_id (keys %{ $self->_opt_map }) {
 | ||
|         my ($opt_key, $opt_index) = @{ $self->_opt_map->{$opt_id} };
 | ||
|         my $option = $self->_options->{$opt_id};
 | ||
|         $self->set_value($opt_id, $self->_get_config_value($opt_key, $opt_index, $option->gui_flags =~ /\bserialized\b/));
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| sub get_fieldc {
 | ||
|     my ($self, $opt_key, $opt_index) = @_;
 | ||
|     
 | ||
|     $opt_index //= -1;
 | ||
|     my $opt_id = first { $self->_opt_map->{$_}[0] eq $opt_key && $self->_opt_map->{$_}[1] == $opt_index }
 | ||
|         keys %{$self->_opt_map};
 | ||
|     return defined($opt_id) ? $self->get_field($opt_id) : undef;
 | ||
| }
 | ||
| 
 | ||
| sub _get_config_value {
 | ||
|     my ($self, $opt_key, $opt_index, $deserialize) = @_;
 | ||
|     
 | ||
|     if ($deserialize) {
 | ||
|         # Want to edit a vector value (currently only multi-strings) in a single edit box.
 | ||
|         # Aggregate the strings the old way.
 | ||
|         # Currently used for the post_process config value only.
 | ||
|         die "Can't deserialize option indexed value" if $opt_index != -1;
 | ||
|         return join(';', @{$self->config->get($opt_key)});
 | ||
|     } else {
 | ||
|         return $opt_index == -1
 | ||
|             ? $self->config->get($opt_key)
 | ||
|             : $self->config->get_at($opt_key, $opt_index);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| sub _on_change {
 | ||
|     my ($self, $opt_id, $value) = @_;
 | ||
|     
 | ||
|     if (exists $self->_opt_map->{$opt_id}) {
 | ||
|         my ($opt_key, $opt_index) = @{ $self->_opt_map->{$opt_id} };
 | ||
|         my $option = $self->_options->{$opt_id};
 | ||
|         
 | ||
|         # get value
 | ||
|         my $field_value = $self->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);
 | ||
|             } else {
 | ||
|                 my $value = $self->config->get($opt_key);
 | ||
|                 $value->[$opt_index] = $field_value;
 | ||
|                 $self->config->set($opt_key, $value);
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
|     
 | ||
|     $self->SUPER::_on_change($opt_id, $value);
 | ||
| }
 | ||
| 
 | ||
| sub _on_kill_focus {
 | ||
|     my ($self, $opt_id) = @_;
 | ||
|     
 | ||
|     # when a field loses focus, reapply the config value to it
 | ||
|     # (thus discarding any invalid input and reverting to the last
 | ||
|     # accepted value)
 | ||
|     $self->reload_config;
 | ||
| }
 | ||
| 
 | ||
| # Static text shown among the options.
 | ||
| # Currently used for the filament cooling legend only.
 | ||
| package Slic3r::GUI::OptionsGroup::StaticText;
 | ||
| use Wx qw(:misc :systemsettings);
 | ||
| use base 'Wx::StaticText';
 | ||
| 
 | ||
| sub new {
 | ||
|     my ($class, $parent) = @_;
 | ||
|     
 | ||
|     my $self = $class->SUPER::new($parent, -1, "", wxDefaultPosition, wxDefaultSize);
 | ||
|     my $font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
 | ||
|     $self->SetFont($font);
 | ||
|     return $self;
 | ||
| }
 | ||
| 
 | ||
| sub SetText {
 | ||
|     my ($self, $value) = @_;
 | ||
|     
 | ||
|     $self->SetLabel($value);
 | ||
|     $self->Wrap(400);
 | ||
|     $self->GetParent->Layout;
 | ||
| }
 | ||
| 
 | ||
| 1;
 | 
