OverrideSettingsPanel.pm 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. # Included in ObjectSettingsDialog -> ObjectPartsPanel.
  2. # Maintains, displays, adds and removes overrides of slicing parameters for an object and its modifier mesh.
  3. package Slic3r::GUI::Plater::OverrideSettingsPanel;
  4. use strict;
  5. use warnings;
  6. use utf8;
  7. use List::Util qw(first);
  8. use Wx qw(:misc :sizer :button :combobox wxTAB_TRAVERSAL wxSUNKEN_BORDER wxBITMAP_TYPE_PNG wxTheApp);
  9. use Wx::Event qw(EVT_BUTTON EVT_COMBOBOX EVT_LEFT_DOWN EVT_MENU);
  10. use base 'Wx::ScrolledWindow';
  11. use constant ICON_MATERIAL => 0;
  12. use constant ICON_SOLIDMESH => 1;
  13. use constant ICON_MODIFIERMESH => 2;
  14. use constant TYPE_OBJECT => -1;
  15. use constant TYPE_PART => 0;
  16. use constant TYPE_MODIFIER => 1;
  17. use constant TYPE_SUPPORT_ENFORCER => 2;
  18. use constant TYPE_SUPPORT_BLOCKER => 3;
  19. my %icons = (
  20. 'Advanced' => 'wand.png',
  21. 'Extruders' => 'funnel.png',
  22. 'Extrusion Width' => 'funnel.png',
  23. 'Infill' => 'infill.png',
  24. 'Layers and Perimeters' => 'layers.png',
  25. 'Skirt and brim' => 'box.png',
  26. 'Speed' => 'time.png',
  27. 'Speed > Acceleration' => 'time.png',
  28. 'Support material' => 'building.png',
  29. );
  30. sub new {
  31. my ($class, $parent, %params) = @_;
  32. my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
  33. # C++ class Slic3r::DynamicPrintConfig, initially empty.
  34. $self->{default_config} = Slic3r::Config->new;
  35. $self->{config} = Slic3r::Config->new;
  36. # On change callback.
  37. $self->{on_change} = $params{on_change};
  38. $self->{type} = TYPE_OBJECT;
  39. $self->{fixed_options} = {};
  40. $self->{sizer} = Wx::BoxSizer->new(wxVERTICAL);
  41. $self->{options_sizer} = Wx::BoxSizer->new(wxVERTICAL);
  42. $self->{sizer}->Add($self->{options_sizer}, 0, wxEXPAND | wxALL, 0);
  43. # option selector
  44. {
  45. # create the button
  46. my $btn = $self->{btn_add} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new(Slic3r::var("add.png"), wxBITMAP_TYPE_PNG),
  47. wxDefaultPosition, wxDefaultSize, Wx::wxBORDER_NONE);
  48. EVT_LEFT_DOWN($btn, sub {
  49. my $menu = Wx::Menu->new;
  50. # create category submenus
  51. my %categories = (); # category => submenu
  52. foreach my $opt_key (@{$self->{options}}) {
  53. if (my $cat = $Slic3r::Config::Options->{$opt_key}{category}) {
  54. $categories{$cat} //= Wx::Menu->new;
  55. }
  56. }
  57. # append submenus to main menu
  58. my @categories = ('Layers and Perimeters', 'Infill', 'Support material', 'Speed', 'Extruders', 'Extrusion Width', 'Advanced');
  59. #foreach my $cat (sort keys %categories) {
  60. foreach my $cat (@categories) {
  61. wxTheApp->append_submenu($menu, $cat, "", $categories{$cat}, undef, $icons{$cat});
  62. }
  63. # append options to submenus
  64. foreach my $opt_key (@{$self->{options}}) {
  65. my $cat = $Slic3r::Config::Options->{$opt_key}{category} or next;
  66. my $cb = sub {
  67. $self->{config}->set($opt_key, $self->{default_config}->get($opt_key));
  68. $self->update_optgroup;
  69. $self->{on_change}->($opt_key) if $self->{on_change};
  70. };
  71. wxTheApp->append_menu_item($categories{$cat}, $self->{option_labels}{$opt_key},
  72. $Slic3r::Config::Options->{$opt_key}{tooltip}, $cb);
  73. }
  74. $self->PopupMenu($menu, $btn->GetPosition);
  75. $menu->Destroy;
  76. });
  77. my $h_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
  78. $h_sizer->Add($btn, 0, wxALL, 0);
  79. $self->{sizer}->Add($h_sizer, 0, wxEXPAND | wxBOTTOM, 10);
  80. }
  81. $self->SetSizer($self->{sizer});
  82. $self->SetScrollbars(0, 1, 0, 1);
  83. $self->set_opt_keys($params{opt_keys}) if $params{opt_keys};
  84. $self->update_optgroup;
  85. return $self;
  86. }
  87. sub set_default_config {
  88. my ($self, $config) = @_;
  89. $self->{default_config} = $config;
  90. }
  91. sub set_config {
  92. my ($self, $config) = @_;
  93. $self->{config} = $config;
  94. $self->update_optgroup;
  95. }
  96. sub set_opt_keys {
  97. my ($self, $opt_keys) = @_;
  98. # sort options by category+label
  99. $self->{option_labels} = { map { $_ => $Slic3r::Config::Options->{$_}{full_label} // $Slic3r::Config::Options->{$_}{label} } @$opt_keys };
  100. $self->{options} = [ sort { $self->{option_labels}{$a} cmp $self->{option_labels}{$b} } @$opt_keys ];
  101. }
  102. sub set_type {
  103. my ($self, $type) = @_;
  104. $self->{type} = $type;
  105. if ($type == TYPE_SUPPORT_ENFORCER || $type == TYPE_SUPPORT_BLOCKER) {
  106. $self->{btn_add}->Hide;
  107. } else {
  108. $self->{btn_add}->Show;
  109. }
  110. }
  111. sub set_fixed_options {
  112. my ($self, $opt_keys) = @_;
  113. $self->{fixed_options} = { map {$_ => 1} @$opt_keys };
  114. $self->update_optgroup;
  115. }
  116. sub update_optgroup {
  117. my $self = shift;
  118. $self->{options_sizer}->Clear(1);
  119. return if !defined $self->{config};
  120. if ($self->{type} != TYPE_OBJECT) {
  121. my $label = Wx::StaticText->new($self, -1, "Type:"),
  122. my $selection = [ "Part", "Modifier", "Support Enforcer", "Support Blocker" ];
  123. my $field = Wx::ComboBox->new($self, -1, $selection->[$self->{type}], wxDefaultPosition, Wx::Size->new(160, -1), $selection, wxCB_READONLY);
  124. my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
  125. $sizer->Add($label, 1, wxEXPAND | wxALL, 5);
  126. $sizer->Add($field, 0, wxALL, 5);
  127. EVT_COMBOBOX($self, $field, sub {
  128. my $idx = $field->GetSelection; # get index of selected value
  129. $self->{on_change}->("part_type", $idx) if $self->{on_change};
  130. });
  131. $self->{options_sizer}->Add($sizer, 0, wxEXPAND | wxBOTTOM, 0);
  132. }
  133. my %categories = ();
  134. if ($self->{type} != TYPE_SUPPORT_ENFORCER && $self->{type} != TYPE_SUPPORT_BLOCKER) {
  135. foreach my $opt_key (@{$self->{config}->get_keys}) {
  136. my $category = $Slic3r::Config::Options->{$opt_key}{category};
  137. $categories{$category} ||= [];
  138. push @{$categories{$category}}, $opt_key;
  139. }
  140. }
  141. foreach my $category (sort keys %categories) {
  142. my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(
  143. parent => $self,
  144. title => $category,
  145. config => $self->{config},
  146. full_labels => 1,
  147. label_font => $Slic3r::GUI::small_font,
  148. sidetext_font => $Slic3r::GUI::small_font,
  149. label_width => 150,
  150. on_change => sub { $self->{on_change}->() if $self->{on_change} },
  151. extra_column => sub {
  152. my ($line) = @_;
  153. my $opt_key = $line->get_options->[0]->opt_id; # we assume that we have one option per line
  154. # disallow deleting fixed options
  155. return undef if $self->{fixed_options}{$opt_key};
  156. my $btn = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new(Slic3r::var("delete.png"), wxBITMAP_TYPE_PNG),
  157. wxDefaultPosition, wxDefaultSize, Wx::wxBORDER_NONE);
  158. EVT_BUTTON($self, $btn, sub {
  159. $self->{config}->erase($opt_key);
  160. $self->{on_change}->() if $self->{on_change};
  161. wxTheApp->CallAfter(sub { $self->update_optgroup });
  162. });
  163. return $btn;
  164. },
  165. );
  166. foreach my $opt_key (sort @{$categories{$category}}) {
  167. $optgroup->append_single_option_line($opt_key);
  168. }
  169. $self->{options_sizer}->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM, 0);
  170. }
  171. $self->GetParent->Layout; # we need this for showing scrollbars
  172. }
  173. # work around a wxMAC bug causing controls not being disabled when calling Disable() on a Window
  174. sub enable {
  175. my ($self) = @_;
  176. $self->{btn_add}->Enable;
  177. $self->Enable;
  178. }
  179. sub disable {
  180. my ($self) = @_;
  181. $self->{btn_add}->Disable;
  182. $self->Disable;
  183. }
  184. 1;