OverrideSettingsPanel.pm 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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 wxTAB_TRAVERSAL wxSUNKEN_BORDER wxBITMAP_TYPE_PNG
  9. wxTheApp);
  10. use Wx::Event qw(EVT_BUTTON EVT_LEFT_DOWN EVT_MENU);
  11. use base 'Wx::ScrolledWindow';
  12. use constant ICON_MATERIAL => 0;
  13. use constant ICON_SOLIDMESH => 1;
  14. use constant ICON_MODIFIERMESH => 2;
  15. my %icons = (
  16. 'Advanced' => 'wand.png',
  17. 'Extruders' => 'funnel.png',
  18. 'Extrusion Width' => 'funnel.png',
  19. 'Infill' => 'infill.png',
  20. 'Layers and Perimeters' => 'layers.png',
  21. 'Skirt and brim' => 'box.png',
  22. 'Speed' => 'time.png',
  23. 'Speed > Acceleration' => 'time.png',
  24. 'Support material' => 'building.png',
  25. );
  26. sub new {
  27. my $class = shift;
  28. my ($parent, %params) = @_;
  29. my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
  30. # C++ class Slic3r::DynamicPrintConfig, initially empty.
  31. $self->{default_config} = Slic3r::Config->new;
  32. $self->{config} = Slic3r::Config->new;
  33. # On change callback.
  34. $self->{on_change} = $params{on_change};
  35. $self->{fixed_options} = {};
  36. $self->{sizer} = Wx::BoxSizer->new(wxVERTICAL);
  37. $self->{options_sizer} = Wx::BoxSizer->new(wxVERTICAL);
  38. $self->{sizer}->Add($self->{options_sizer}, 0, wxEXPAND | wxALL, 0);
  39. # option selector
  40. {
  41. # create the button
  42. my $btn = $self->{btn_add} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new($Slic3r::var->("add.png"), wxBITMAP_TYPE_PNG),
  43. wxDefaultPosition, wxDefaultSize, Wx::wxBORDER_NONE);
  44. EVT_LEFT_DOWN($btn, sub {
  45. my $menu = Wx::Menu->new;
  46. # create category submenus
  47. my %categories = (); # category => submenu
  48. foreach my $opt_key (@{$self->{options}}) {
  49. if (my $cat = $Slic3r::Config::Options->{$opt_key}{category}) {
  50. $categories{$cat} //= Wx::Menu->new;
  51. }
  52. }
  53. # append submenus to main menu
  54. my @categories = ('Layers and Perimeters', 'Infill', 'Support material', 'Speed', 'Extruders', 'Extrusion Width', 'Advanced');
  55. #foreach my $cat (sort keys %categories) {
  56. foreach my $cat (@categories) {
  57. wxTheApp->append_submenu($menu, $cat, "", $categories{$cat}, undef, $icons{$cat});
  58. }
  59. # append options to submenus
  60. foreach my $opt_key (@{$self->{options}}) {
  61. my $cat = $Slic3r::Config::Options->{$opt_key}{category} or next;
  62. my $cb = sub {
  63. $self->{config}->set($opt_key, $self->{default_config}->get($opt_key));
  64. $self->update_optgroup;
  65. $self->{on_change}->($opt_key) if $self->{on_change};
  66. };
  67. wxTheApp->append_menu_item($categories{$cat}, $self->{option_labels}{$opt_key},
  68. $Slic3r::Config::Options->{$opt_key}{tooltip}, $cb);
  69. }
  70. $self->PopupMenu($menu, $btn->GetPosition);
  71. $menu->Destroy;
  72. });
  73. my $h_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
  74. $h_sizer->Add($btn, 0, wxALL, 0);
  75. $self->{sizer}->Add($h_sizer, 0, wxEXPAND | wxBOTTOM, 10);
  76. }
  77. $self->SetSizer($self->{sizer});
  78. $self->SetScrollbars(0, 1, 0, 1);
  79. $self->set_opt_keys($params{opt_keys}) if $params{opt_keys};
  80. $self->update_optgroup;
  81. return $self;
  82. }
  83. sub set_default_config {
  84. my ($self, $config) = @_;
  85. $self->{default_config} = $config;
  86. }
  87. sub set_config {
  88. my ($self, $config) = @_;
  89. $self->{config} = $config;
  90. $self->update_optgroup;
  91. }
  92. sub set_opt_keys {
  93. my ($self, $opt_keys) = @_;
  94. # sort options by category+label
  95. $self->{option_labels} = { map { $_ => $Slic3r::Config::Options->{$_}{full_label} // $Slic3r::Config::Options->{$_}{label} } @$opt_keys };
  96. $self->{options} = [ sort { $self->{option_labels}{$a} cmp $self->{option_labels}{$b} } @$opt_keys ];
  97. }
  98. sub set_fixed_options {
  99. my ($self, $opt_keys) = @_;
  100. $self->{fixed_options} = { map {$_ => 1} @$opt_keys };
  101. $self->update_optgroup;
  102. }
  103. sub update_optgroup {
  104. my $self = shift;
  105. $self->{options_sizer}->Clear(1);
  106. return if !defined $self->{config};
  107. my %categories = ();
  108. foreach my $opt_key (@{$self->{config}->get_keys}) {
  109. my $category = $Slic3r::Config::Options->{$opt_key}{category};
  110. $categories{$category} ||= [];
  111. push @{$categories{$category}}, $opt_key;
  112. }
  113. foreach my $category (sort keys %categories) {
  114. my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(
  115. parent => $self,
  116. title => $category,
  117. config => $self->{config},
  118. full_labels => 1,
  119. label_font => $Slic3r::GUI::small_font,
  120. sidetext_font => $Slic3r::GUI::small_font,
  121. label_width => 120,
  122. on_change => sub { $self->{on_change}->() if $self->{on_change} },
  123. extra_column => sub {
  124. my ($line) = @_;
  125. my $opt_key = $line->get_options->[0]->opt_id; # we assume that we have one option per line
  126. # disallow deleting fixed options
  127. return undef if $self->{fixed_options}{$opt_key};
  128. my $btn = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new($Slic3r::var->("delete.png"), wxBITMAP_TYPE_PNG),
  129. wxDefaultPosition, wxDefaultSize, Wx::wxBORDER_NONE);
  130. EVT_BUTTON($self, $btn, sub {
  131. $self->{config}->erase($opt_key);
  132. $self->{on_change}->() if $self->{on_change};
  133. wxTheApp->CallAfter(sub { $self->update_optgroup });
  134. });
  135. return $btn;
  136. },
  137. );
  138. foreach my $opt_key (sort @{$categories{$category}}) {
  139. $optgroup->append_single_option_line($opt_key);
  140. }
  141. $self->{options_sizer}->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM, 0);
  142. }
  143. $self->GetParent->Layout; # we need this for showing scrollbars
  144. }
  145. # work around a wxMAC bug causing controls not being disabled when calling Disable() on a Window
  146. sub enable {
  147. my ($self) = @_;
  148. $self->{btn_add}->Enable;
  149. $self->Enable;
  150. }
  151. sub disable {
  152. my ($self) = @_;
  153. $self->{btn_add}->Disable;
  154. $self->Disable;
  155. }
  156. 1;