From 21ef09c228fa5f465264325b19e17ede61c6aacb Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 17 Jun 2012 22:27:05 +0200 Subject: [PATCH 001/106] Group settings using Treebooks --- MANIFEST | 1 + lib/Slic3r/GUI.pm | 1 + lib/Slic3r/GUI/SkeinPanel.pm | 97 ++------------- lib/Slic3r/GUI/Tab.pm | 228 +++++++++++++++++++++++++++++++++++ 4 files changed, 238 insertions(+), 89 deletions(-) create mode 100644 lib/Slic3r/GUI/Tab.pm diff --git a/MANIFEST b/MANIFEST index 1568fc498..035cef1a9 100644 --- a/MANIFEST +++ b/MANIFEST @@ -29,6 +29,7 @@ lib/Slic3r/GUI.pm lib/Slic3r/GUI/Plater.pm lib/Slic3r/GUI/OptionsGroup.pm lib/Slic3r/GUI/SkeinPanel.pm +lib/Slic3r/GUI/Tab.pm lib/Slic3r/Layer.pm lib/Slic3r/Line.pm lib/Slic3r/Point.pm diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 4059f1098..b6c4c6510 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -7,6 +7,7 @@ use FindBin; use Slic3r::GUI::Plater; use Slic3r::GUI::OptionsGroup; use Slic3r::GUI::SkeinPanel; +use Slic3r::GUI::Tab; use Wx 0.9901 qw(:sizer :frame wxID_EXIT wxID_ABOUT); use Wx::Event qw(EVT_MENU); diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index b5977ab38..d60402ad5 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -21,106 +21,25 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, -1); - my %panels = ( - printer => { - title => 'Printer', - options => [qw(nozzle_diameter bed_size print_center z_offset gcode_flavor use_relative_e_distances)], - }, - filament => { - title => 'Filament', - options => [qw(filament_diameter extrusion_multiplier temperature first_layer_temperature bed_temperature first_layer_bed_temperature)], - }, - print_speed => { - title => 'Print speed', - options => [qw(perimeter_speed small_perimeter_speed infill_speed solid_infill_speed top_solid_infill_speed bridge_speed)], - }, - speed => { - title => 'Other speed settings', - options => [qw(travel_speed first_layer_speed)], - }, - accuracy => { - title => 'Accuracy', - options => [qw(layer_height first_layer_height infill_every_layers)], - }, - print => { - title => 'Print settings', - options => [qw(perimeters solid_layers fill_density fill_angle fill_pattern solid_fill_pattern randomize_start support_material support_material_tool)], - }, - retract => { - title => 'Retraction', - options => [qw(retract_length retract_lift retract_speed retract_restart_extra retract_before_travel)], - }, - cooling => { - title => 'Cooling', - options => [qw(cooling min_fan_speed max_fan_speed bridge_fan_speed fan_below_layer_time slowdown_below_layer_time min_print_speed disable_fan_first_layers fan_always_on)], - label_width => 300, - }, - skirt => { - title => 'Skirt', - options => [qw(skirts skirt_distance skirt_height)], - }, - gcode => { - title => 'G-code', - options => [qw(start_gcode end_gcode layer_gcode gcode_comments post_process)], - label_width => 260, - }, - sequential_printing => { - title => 'Sequential printing', - options => [qw(complete_objects extruder_clearance_radius extruder_clearance_height)], - }, - extrusion => { - title => 'Extrusion', - options => [qw(extrusion_width first_layer_extrusion_width perimeters_extrusion_width infill_extrusion_width bridge_flow_ratio)], - }, - output => { - title => 'Output', - options => [qw(output_filename_format duplicate_distance)], - }, - other => { - title => 'Other', - options => [$Slic3r::have_threads ? qw(threads) : ()], - }, - notes => { - title => 'Notes', - options => [qw(notes)], - }, - ); - $self->{panels} = \%panels; - my $tabpanel = Wx::Notebook->new($self, -1, Wx::wxDefaultPosition, Wx::wxDefaultSize, &Wx::wxNB_TOP); - my $make_tab = sub { - my @cols = @_; + my $make_treebook_tab = sub { + my $class = shift; my $tab = Wx::Panel->new($tabpanel, -1); - my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); - foreach my $col (@cols) { - my $vertical_sizer = Wx::BoxSizer->new(wxVERTICAL); - for my $optgroup (@$col) { - next unless @{ $panels{$optgroup}{options} }; - my $optpanel = Slic3r::GUI::OptionsGroup->new($tab, %{$panels{$optgroup}}); - $vertical_sizer->Add($optpanel, 0, wxEXPAND | wxALL, 10); - } - $sizer->Add($vertical_sizer); - } - + my $sizer = Wx::BoxSizer->new(&Wx::wxVERTICAL); + $sizer->Add($class->new($tab), 1, &Wx::wxALL | &Wx::wxEXPAND, 5); $tab->SetSizer($sizer); return $tab; }; my @tabs = ( - $make_tab->([qw(accuracy skirt retract)], [qw(print notes)]), - $make_tab->([qw(cooling)]), - $make_tab->([qw(printer filament)], [qw(print_speed speed)]), - $make_tab->([qw(gcode)]), - $make_tab->([qw(extrusion other sequential_printing)], [qw(output)]), + $make_treebook_tab->('Slic3r::GUI::Tab::Print'), + $make_treebook_tab->('Slic3r::GUI::Tab::Printer'), ); $tabpanel->AddPage(Slic3r::GUI::Plater->new($tabpanel), "Plater"); - $tabpanel->AddPage($tabs[0], "Print Settings"); - $tabpanel->AddPage($tabs[1], "Cooling"); - $tabpanel->AddPage($tabs[2], "Printer and Filament"); - $tabpanel->AddPage($tabs[3], "G-code"); - $tabpanel->AddPage($tabs[4], "Advanced"); + $tabpanel->AddPage($tabs[0], "Print settings"); + $tabpanel->AddPage($tabs[1], "Filament/printer settings"); my $buttons_sizer; { diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm new file mode 100644 index 000000000..9f9e8bbc4 --- /dev/null +++ b/lib/Slic3r/GUI/Tab.pm @@ -0,0 +1,228 @@ +package Slic3r::GUI::Tab; +use strict; +use warnings; +use utf8; + +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Wx::Treebook'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, -1, [-1,-1], [-1,-1], &Wx::wxBK_LEFT); + + return $self; +} + +sub AddOptionsPage { + my $self = shift; + my $title = shift; + my $page = Slic3r::GUI::Tab::Page->new($self, @_); + $self->AddPage($page, $title); +} + +package Slic3r::GUI::Tab::Print; + +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Slic3r::GUI::Tab'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, -1); + + $self->AddOptionsPage('Layers and perimeters', optgroups => [ + { + title => 'Layer height', + options => [qw(layer_height first_layer_height)], + }, + { + title => 'Vertical shells', + options => [qw(perimeters randomize_start)], + }, + { + title => 'Horizontal shells', + options => [qw(solid_layers)], + }, + ]); + + $self->AddOptionsPage('Infill', optgroups => [ + { + title => 'Infill', + options => [qw(fill_density fill_angle fill_pattern solid_fill_pattern)], + }, + ]); + + $self->AddOptionsPage('Speed', optgroups => [ + { + title => 'Speed for print moves', + options => [qw(perimeter_speed small_perimeter_speed infill_speed solid_infill_speed top_solid_infill_speed bridge_speed)], + }, + { + title => 'Speed for non-print moves', + options => [qw(travel_speed)], + }, + { + title => 'Advanced', + options => [qw(first_layer_speed)], + }, + ]); + + $self->AddOptionsPage('Skirt', optgroups => [ + { + title => 'Skirt', + options => [qw(skirts skirt_distance skirt_height)], + }, + ]); + + $self->AddOptionsPage('Cooling', optgroups => [ + { + title => 'Enable', + options => [qw(cooling)], + }, + { + title => 'Fan settings', + options => [qw(min_fan_speed max_fan_speed bridge_fan_speed disable_fan_first_layers fan_always_on)], + }, + { + title => 'Cooling thresholds', + options => [qw(fan_below_layer_time slowdown_below_layer_time min_print_speed)], + }, + ]); + + $self->AddOptionsPage('Support material', optgroups => [ + { + title => 'Support material', + options => [qw(support_material support_material_tool)], + }, + ]); + + $self->AddOptionsPage('Notes', optgroups => [ + { + title => 'Notes', + options => [qw(notes)], + }, + ]); + + $self->AddOptionsPage('Output options', optgroups => [ + { + title => 'Sequential printing', + options => [qw(complete_objects extruder_clearance_radius extruder_clearance_height)], + }, + { + title => 'Output file', + options => [qw(gcode_comments output_filename_format)], + }, + { + title => 'Advanced', + options => [qw(post_process duplicate_distance)], # this is not the right place for duplicate_distance + }, + ]); + + $self->AddOptionsPage('Advanced', optgroups => [ + { + title => 'Extrusion width', + options => [qw(extrusion_width first_layer_extrusion_width perimeters_extrusion_width infill_extrusion_width)], + }, + { + title => 'Flow', + options => [qw(bridge_flow_ratio)], + }, + ]); + + + + + return $self; +} + +package Slic3r::GUI::Tab::Printer; + +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Slic3r::GUI::Tab'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, -1); + + $self->AddOptionsPage('General', optgroups => [ + { + title => 'Size and coordinates', + options => [qw(bed_size print_center z_offset)], + }, + { + title => 'Firmware', + options => [qw(gcode_flavor use_relative_e_distances)], + }, + ]); + + $self->AddOptionsPage('Extruder and filament', optgroups => [ + { + title => 'Size', + options => [qw(nozzle_diameter)], + }, + { + title => 'Filament', + options => [qw(filament_diameter extrusion_multiplier)], + }, + { + title => 'Temperature', + options => [qw(temperature first_layer_temperature bed_temperature first_layer_bed_temperature)], + }, + ]); + + $self->AddOptionsPage('Custom G-code', optgroups => [ + { + title => 'Custom G-code', + options => [qw(start_gcode end_gcode layer_gcode)], + }, + ]); + + $self->AddOptionsPage('Retraction', optgroups => [ + { + title => 'Retraction', + options => [qw(retract_length retract_lift retract_speed)], + }, + { + title => 'Advanced', + options => [qw(retract_restart_extra retract_before_travel)], + }, + ]); + + + return $self; +} + +package Slic3r::GUI::Tab::Page; + +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Wx::Panel'; + +sub new { + my $class = shift; + my ($parent, %params) = @_; + my $self = $class->SUPER::new($parent, -1); + + $self->{vsizer} = Wx::BoxSizer->new(&Wx::wxVERTICAL); + $self->SetSizer($self->{vsizer}); + + if ($params{optgroups}) { + $self->append_optgroup(%$_) for @{$params{optgroups}}; + } + + return $self; +} + +sub append_optgroup { + my $self = shift; + + my $optgroup = Slic3r::GUI::OptionsGroup->new($self, @_, label_width => 300); + $self->{vsizer}->Add($optgroup, 0, wxEXPAND | wxALL, 5); +} + +1; From ce9fdbc0471de744c49c7d4b81a1b8255edbf512 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 17 Jun 2012 22:54:08 +0200 Subject: [PATCH 002/106] Icons for settings --- lib/Slic3r/GUI/Tab.pm | 46 +++++++++++++++++++++++++----------------- var/arrow_up.png | Bin 0 -> 372 bytes var/box.png | Bin 0 -> 555 bytes var/building.png | Bin 0 -> 556 bytes var/cog.png | Bin 0 -> 512 bytes var/hourglass.png | Bin 0 -> 744 bytes var/note.png | Bin 0 -> 500 bytes var/page_white_go.png | Bin 0 -> 612 bytes var/printer_empty.png | Bin 0 -> 350 bytes var/shading.png | Bin 0 -> 225 bytes var/spool.png | Bin 0 -> 1304 bytes var/time.png | Bin 0 -> 793 bytes var/wrench.png | Bin 0 -> 610 bytes 13 files changed, 28 insertions(+), 18 deletions(-) create mode 100755 var/arrow_up.png create mode 100755 var/box.png create mode 100755 var/building.png create mode 100755 var/cog.png create mode 100755 var/hourglass.png create mode 100755 var/note.png create mode 100755 var/page_white_go.png create mode 100755 var/printer_empty.png create mode 100755 var/shading.png create mode 100644 var/spool.png create mode 100755 var/time.png create mode 100755 var/wrench.png diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 9f9e8bbc4..e121bf6ba 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -11,15 +11,28 @@ sub new { my $class = shift; my ($parent) = @_; my $self = $class->SUPER::new($parent, -1, [-1,-1], [-1,-1], &Wx::wxBK_LEFT); - + + $self->{images} = Wx::ImageList->new(16, 16, 1); + $self->AssignImageList($self->{images}); + $self->{imagecount} = -1; + return $self; } sub AddOptionsPage { my $self = shift; my $title = shift; + my $image = (ref $_[1]) ? undef : shift; my $page = Slic3r::GUI::Tab::Page->new($self, @_); - $self->AddPage($page, $title); + + my $bitmap = $image + ? Wx::Bitmap->new("$Slic3r::var/$image", &Wx::wxBITMAP_TYPE_PNG) + : undef; + if ($bitmap) { + $self->{images}->Add($bitmap); + $self->{imagecount}++; + } + $self->AddPage($page, $title, undef, $self->{imagecount}); } package Slic3r::GUI::Tab::Print; @@ -33,7 +46,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, -1); - $self->AddOptionsPage('Layers and perimeters', optgroups => [ + $self->AddOptionsPage('Layers and perimeters', 'layers.png', optgroups => [ { title => 'Layer height', options => [qw(layer_height first_layer_height)], @@ -48,14 +61,14 @@ sub new { }, ]); - $self->AddOptionsPage('Infill', optgroups => [ + $self->AddOptionsPage('Infill', 'shading.png', optgroups => [ { title => 'Infill', options => [qw(fill_density fill_angle fill_pattern solid_fill_pattern)], }, ]); - $self->AddOptionsPage('Speed', optgroups => [ + $self->AddOptionsPage('Speed', 'time.png', optgroups => [ { title => 'Speed for print moves', options => [qw(perimeter_speed small_perimeter_speed infill_speed solid_infill_speed top_solid_infill_speed bridge_speed)], @@ -70,14 +83,14 @@ sub new { }, ]); - $self->AddOptionsPage('Skirt', optgroups => [ + $self->AddOptionsPage('Skirt', 'box.png', optgroups => [ { title => 'Skirt', options => [qw(skirts skirt_distance skirt_height)], }, ]); - $self->AddOptionsPage('Cooling', optgroups => [ + $self->AddOptionsPage('Cooling', 'hourglass.png', optgroups => [ { title => 'Enable', options => [qw(cooling)], @@ -92,21 +105,21 @@ sub new { }, ]); - $self->AddOptionsPage('Support material', optgroups => [ + $self->AddOptionsPage('Support material', 'building.png', optgroups => [ { title => 'Support material', options => [qw(support_material support_material_tool)], }, ]); - $self->AddOptionsPage('Notes', optgroups => [ + $self->AddOptionsPage('Notes', 'note.png', optgroups => [ { title => 'Notes', options => [qw(notes)], }, ]); - $self->AddOptionsPage('Output options', optgroups => [ + $self->AddOptionsPage('Output options', 'page_white_go.png', optgroups => [ { title => 'Sequential printing', options => [qw(complete_objects extruder_clearance_radius extruder_clearance_height)], @@ -121,7 +134,7 @@ sub new { }, ]); - $self->AddOptionsPage('Advanced', optgroups => [ + $self->AddOptionsPage('Advanced', 'wrench.png', optgroups => [ { title => 'Extrusion width', options => [qw(extrusion_width first_layer_extrusion_width perimeters_extrusion_width infill_extrusion_width)], @@ -132,9 +145,6 @@ sub new { }, ]); - - - return $self; } @@ -149,7 +159,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, -1); - $self->AddOptionsPage('General', optgroups => [ + $self->AddOptionsPage('General', 'printer_empty.png', optgroups => [ { title => 'Size and coordinates', options => [qw(bed_size print_center z_offset)], @@ -160,7 +170,7 @@ sub new { }, ]); - $self->AddOptionsPage('Extruder and filament', optgroups => [ + $self->AddOptionsPage('Extruder and filament', 'spool.png', optgroups => [ { title => 'Size', options => [qw(nozzle_diameter)], @@ -175,14 +185,14 @@ sub new { }, ]); - $self->AddOptionsPage('Custom G-code', optgroups => [ + $self->AddOptionsPage('Custom G-code', 'cog.png', optgroups => [ { title => 'Custom G-code', options => [qw(start_gcode end_gcode layer_gcode)], }, ]); - $self->AddOptionsPage('Retraction', optgroups => [ + $self->AddOptionsPage('Retraction', 'arrow_up.png', optgroups => [ { title => 'Retraction', options => [qw(retract_length retract_lift retract_speed)], diff --git a/var/arrow_up.png b/var/arrow_up.png new file mode 100755 index 0000000000000000000000000000000000000000..1ebb193243780b8eb1919a51ef27c2a0d36ccec2 GIT binary patch literal 372 zcmV-)0gL{LP)6w#wHUuW*nL5>vZR zlg{G&%mT~|kL3ei%GW0*UOHUMs5XI$4uxe-L?I@SAefq*207}Iqtjm#e5*fP53AiC z)C|RQfwzxx<#_WfANRGZx{+tFDl8~Q?;~Ve=lM^*8UTTnVL?HTDz8uta0D@d28E9S z_)i8aLz^UE6PPKymi;2GJ`34{eIia-CtfAt0H61rk0 SPTNud0000i3lOYrtSl@<#7b-w zf}j{s!5HvocfT|9z82@(O@vrwU^wRt=bd>tXQpGD!`Kvuv@XEI8~tgUP2L`{+*)U@I@ zrVtr5X14??iAF(=0+k>q)v`Scm$9&=i`*knBsnaUVL1>ti*O1xfzmiD$%Md-h*6M( z@*iB)icu3eU424Ok{kp%Y!1dvp%f0`ac9vcupx^$vU0xuKpJcBvej0UYk%)EV>mIx2hV}QRf#LX^Uh(%`7hZ~|KEf#uQ31s002ovPDHLkV1hgQ{`mj^ literal 0 HcmV?d00001 diff --git a/var/building.png b/var/building.png new file mode 100755 index 0000000000000000000000000000000000000000..11a017cfaa73aef38f8f57db731dd0a7db835109 GIT binary patch literal 556 zcmV+{0@MA8P) zlTAwkQ51&X8OIL@qD-Qsuyhv$p|ucNxrho9Y}2|`xDEOTEecw+?FYDO86*-E5rS>n zv=AvFN@y{a*@rsg{b=qLr6CpRz~LV5-1D6GoVgdAbM)iS(J1e%9TO7RFz?{LbOt3dBco@bbZH_0OdOMw_$XmV%A>MsEcb`Yr*BlX@2gUVQP-&VZd< za>_O2!3tls`ejI^QczVDilWFhkw~CoyyJ1aXalrwqLnnQIvvPYZe=x1(-01a5s5@( zETH9D8Lj~r){d6fZGi3U)*z^IKH~J@tdy3AMUwEAiW;e6|7sTjUjW3U2TO;s**1U@ znlwz4-{}Q>zgCgCIR$evI2?{PBz>KRR(Ij;<3(IJKP7CpJp+2|*^>{$@+v3_xR>%u u#geUGuQH0)r!pqYfZJ_);(s2~f9wYukV^15?ld0&0000CQDsH?WF>AIFt zQuJ}i;w2$ZUU#3SZ6RY0Gw;kZ&ol1~2ky^QZ(fom$=jNJZt!z7w_pH~wdQ;R)Gh%BbQFCx+Nm!4SuS-vkr`vhhrX zM*>w%e+v~?m@q~ImPAgtLkR_3U<2F8LP3W5=LJ*ZN|S5p#sf4YFr$p~Q~Z*0Ngxf2 zjk#J#<7EAlhzlrV53~GF&pIzcCN_lz9@05UeoUXiK%N z#x+4o*i_c|6_Uu1+&TIho?3@y4k-#b8Y_o94zW*B3a1ne2-Y5s0uke$$|@=}OP-i= zNYZQA=>PrZu0MfSL=b8UhD_={W4IY1{b{)U)*gc45xtL%IYLY&hF;d`@GzI&7H&D# zh;z_BX$#hqh@q?AY3sJTod2%*Yd)_>YM0#q&ixGuh+PQsneK)F0000P)9Rl#FaScf1rbdiwsJlF($-D2a$MB1QH?*P$(@5T4@;&OA53{ z62x9;g=MzM@3B}Z6q2JnuH-? zUBh=^5nso`tIMpW;}SD*?>znX))|eYdi7(c&C5YW8_t?tIU z>Ny7&^Pebhjth`srpO|asbD=?gpU+WKXx%hg}DA%|J1=w1E3bQW2brAk)glQS%iL- z`SP4IjX^57**EKJK0N;yU_Z*GguxzUVD)Dq(FOHK%^eAtSc;pSVFoq==$r8wjtx+n z;uq8_iQsA|i!@V3bf!VptWTH>59QQ$XGs&d#Zun48g&^nWN z^4`U@k2?PS6UX#XYTlj3cBYJ6iA9-|t1JhG+#TUO+}j1X$SI>}h@{JnYgEm?zE z!-sF!^gVb+8rtpyctW0#N6uWni0LCt_6PoOdbjll_d4>B|?abUmpo8>v>h}Zj|Ya;Eu#qwvU1IVc9khP8VrtAsT2=e83P~$#!xXbw)n}FlPSEe7Hq1uCb zR8w;xqmBrUgA^pnkB=O@-lq0DPz$ay0yh_~I_IDpzxRb(4=Iy9CT||k!08w)Pe>W4 zElmH8fF;68$GMwZ#7{4ozI(ySrR%I+xs4-G1q^UxnUV7rlf9>Rn&_6Wike0000#DY{xaiib^#X=YT4@yE_&2#eBulEdzjE`u&@G%2(&u{J-<}d(^uY4W_kMfEX z@!X)AR9F&FL?RJyJRUzvBoeqN{5kY`z3wcM0+du73~_0|*lac! z42Dw(Eg1o{Ash}P8jXrqN+1w`*XxDD;ShmPCZC7#4;wWbHoMvBl$=zF-`?*9j*Nbjd=v@OWt_BgKxP-3wd zy37?ATx&$b+&zRM!K;BD%Okw`Sb@&Pak8$KRX19jWZmC0&n*Ggv%j8nvSPDFw zEkV65AGOoBQ8kf`R|}Px*&INNS%osq9b{Fq2I(x6@xM>tg=vRLF?I`0rWz01{r$78XkvMLD8LgLPI}p^3#ZkL-WmU{TI1 wPFcbdW00`FlWkSj%Pe9r%we8QTmJp#H==T7N?a3H(*OVf07*qoM6N<$g8eR!YybcN literal 0 HcmV?d00001 diff --git a/var/shading.png b/var/shading.png new file mode 100755 index 0000000000000000000000000000000000000000..09275f9c0914a2b6cbd48dc75244f698a8918c1e GIT binary patch literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmUzPnffIy#(?lOI#yL zg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4h+5i<5d%8G=Se#D&@&CWQ^SL#TFFMo+ zpUPu?w4CLJsKXtWq-Kjql`OW6@{Tv>DLhi_oR#=SOyS-!hh=FNvz5*&gc}4bkUS$- zpueTJs?jS>W4VH5cvDBnk}bYn&!Q$gHPEkM{Aeg6CFgw8)S-s+lpfn7J^^Wlx#}xw U_BgG30kodM)78&qol`;+07=(QkN^Mx literal 0 HcmV?d00001 diff --git a/var/spool.png b/var/spool.png new file mode 100644 index 0000000000000000000000000000000000000000..709006d387ec9486a1ced17fa63c4c13c9be8933 GIT binary patch literal 1304 zcmV+z1?T#SP)4Tx04R}-l+Q~PVHn51vyB)iL11Qkh@nGBs7w}RMCGo(*tBg~f0Po$?CiU{ zle4qa%26U(f|ru*d1uDm5$(qdGxK?$AK&MB z-{F0M8d)(-JtP5n!?BWmQR({Vm{j`_Asj&+!l+YJ+l(X<1E9fUv1@F;hrqupt$X|b zI_lE4ng@jaKh%lTb}(f=ak3uu6-!kMZ8FSKs7BM z|C+c%%_(W1MkH>@24YeH&g(_h@8=*r^~@L^r0;R+=`OQ-d=_TXN_RhT8}a8f>+a#2 z#Pb=gH%8n{&sxUn9rjo_p*gW3k3%Dd9v|?z$wwEp4JbjhwM#!rpOV)g4O?IHuKzA8qHe6NWHQ4?5 zW?+>pP^lFuS83d>RC0Yby(58Yf7(5YU7B8Os@7T+7jCT7FHP^*tHQ2TvC67;&Z}|3 zd?p?hPl_?ILp%pbyd-vt7sYOxofiix8N;NaVZv3ip-`5AN%ERI{+SmG@2t6_p^q8N z(o~6`|AbY@XgUiV(SNxAbMSk`qp>3J!UhhXuG%(|?j0gDE>~^N72v`*x)0t~ZOwEZ z4m|-D&ZtGJ}8;WLk96sqPn3I;4%{fxLET5GkbR{t#`+_*~}`j zbQ|omRIvUKAwJ#h}2u5Lx6R;p3~Q9Em8B+IPCJ zjj8)q9e8hE&hvZE?>*;$e#oCwGK_lgo&J8Vg+e)@{}Pa7GRf|yCKN^aTLBy4R4OH( zR8=lqy(0Ulmd>(sm3ahr_oc>~uJ3{!xx; z@*8hwRmR?pGo4m>!G}Ty08`F$t;fUlTQ_lUuH^Wxy_lzFF*G~auGR2sX_=Aq41RAr ziHX-zC}IT2X0t>F2dJG{;?#~ttY20rH(Drbtpm4%Mte0UPjuiiTRB2q&W^0H0FVgv z(Y8=U)g}iO2kXJJjk$?wB>fq)-OTf`R}8!y<-p}LD2hUKXej@Q2EgF&zDQ*B33JxP z)!UEXvHi4Q_j!?;tt?wi9J>)PDp literal 0 HcmV?d00001 diff --git a/var/time.png b/var/time.png new file mode 100755 index 0000000000000000000000000000000000000000..911da3f1d31fca4494a4beb22014e5c5c724c236 GIT binary patch literal 793 zcmV+!1LpjRP)`EB*FHYdKr%;k=xO&(k^EfNlSiKZ>5l+xr|%SFOV@6-ysFmD2F5 ze93OiS+LaQym;|2f6tbH%~V`D+ND?vc>4J^KSLxEMifJQ`8>*~y^+pGr&o-n=LJ zGWB(yB#;DR8&Lhqi{0(#wc#SwSB~jZKzIFx`8od>2Fo-Pfe7*M8^q#qw2yTxiXzd~ zRaz|F*rr78G`JZXG*YX~5K@5k>G@0HdlBo-6v1jHye?%qRwO@+-hO7J^4LlPG>@A1#{ zQFl4x7tnG)+cz_2Mq_f*H!U)kgg{iHqxT)Yr3ec@K!`)z_%h1c0Y2Eu(dMPkrhq5v zY+bKWfx|sTiOEB71HuwS*CDzA%ReBv4*7Zy7RM0n6`5#chfOJK`ze)Y6>d6Z?UmyNHH!3DdsP-ARyDo}1HO+>7_um7 zx_gj{+_aU_OUH_~Jd?KI#ICZujD`of2mDpCv_zFGE%6}tfL|j!WGu_i-u>4%{%d{$ X7`zMSfT21V00000NkvXXu0mjfkBx0` literal 0 HcmV?d00001 diff --git a/var/wrench.png b/var/wrench.png new file mode 100755 index 0000000000000000000000000000000000000000..5c8213fef5ab969f03189d4367e32e597e38bd7f GIT binary patch literal 610 zcmV-o0-gPdP)^jb z4`0v}DG1te)wmeb(>p90leRz?_mO+^JKy=v&2<29Od6?F%9%(c8los#f*@G`-%W&* z$)uBj2i@u-@SgX}gtyWPe6d*|w6h%R? zScK2#Yn%$sum0cy>90DmY*i{1XqpClEtktsRTZ)lCUe z<FogV^*tm>8*AlX za4oiR!&85LrobG57qUHUX#{>Vz(RHpB5|@>9O6N$jqB8>%($0wxE5R3)b>Y~xtCo$ zCgEk&A?_#IxHdN)9tqre^o{ho4{?hmPuf@^@I3-wncaRd%|~O3xbrKY=&TiwPYkJroM{;WUQTuMY8vp Date: Sun, 17 Jun 2012 23:24:10 +0200 Subject: [PATCH 003/106] Remove label for large text fields --- lib/Slic3r/Config.pm | 2 +- lib/Slic3r/GUI/OptionsGroup.pm | 23 +++++++++++++---------- lib/Slic3r/GUI/Tab.pm | 26 +++++++++++++++++++++----- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 13f79b522..728e4cc28 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -16,7 +16,7 @@ our $Options = { cli => 'notes=s', type => 's', multiline => 1, - width => 220, + width => 450, height => 130, serialize => sub { join '\n', split /\R/, $_[0] }, deserialize => sub { join "\n", split /\\n/, $_[0] }, diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index 993117752..0f582fe87 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -18,22 +18,25 @@ sub new { my $box = Wx::StaticBox->new($parent, -1, $p{title}); my $self = $class->SUPER::new($box, wxVERTICAL); - my $grid_sizer = Wx::FlexGridSizer->new(scalar(@{$p{options}}), 2, 2, 0); + my $grid_sizer = Wx::FlexGridSizer->new(scalar(@{$p{options}}), 2, ($p{no_labels} ? 1 : 2), 0); - #grab the default font, to fix Windows font issues/keep things consistent + # grab the default font, to fix Windows font issues/keep things consistent my $bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); $bold_font->SetWeight(&Wx::wxFONTWEIGHT_BOLD); - foreach my $opt_key (@{$p{options}}) { my $opt = $Slic3r::Config::Options->{$opt_key}; - my $label = Wx::StaticText->new($parent, -1, "$opt->{label}:", Wx::wxDefaultPosition, - [$p{label_width} || 180, -1]); - $label->Wrap($p{label_width} || 180); # needed to avoid Linux/GTK bug + my $label; + if (!$p{no_labels}) { + $label = Wx::StaticText->new($parent, -1, "$opt->{label}:", Wx::wxDefaultPosition, [$p{label_width} || 180, -1]); + $label->Wrap($p{label_width} || 180) ; # needed to avoid Linux/GTK bug + $grid_sizer->Add($label); + + # set the bold font point size to the same size as all the other labels (for consistency) + $bold_font->SetPointSize($label->GetFont()->GetPointSize()); + $label->SetFont($bold_font) if $opt->{important}; + } - #set the bold font point size to the same size as all the other labels (for consistency) - $bold_font->SetPointSize($label->GetFont()->GetPointSize()); - $label->SetFont($bold_font) if $opt->{important}; my $field; if ($opt->{type} =~ /^(i|f|s|s@)$/) { my $style = 0; @@ -92,7 +95,7 @@ sub new { } else { die "Unsupported option type: " . $opt->{type}; } - $grid_sizer->Add($_) for $label, $field; + $grid_sizer->Add($field); $fields{$opt_key} ||= [$field]; } diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index e121bf6ba..b1466d806 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -115,6 +115,7 @@ sub new { $self->AddOptionsPage('Notes', 'note.png', optgroups => [ { title => 'Notes', + no_labels => 1, options => [qw(notes)], }, ]); @@ -129,8 +130,13 @@ sub new { options => [qw(gcode_comments output_filename_format)], }, { - title => 'Advanced', - options => [qw(post_process duplicate_distance)], # this is not the right place for duplicate_distance + title => 'Post-processing scripts', + no_labels => 1, + options => [qw(post_process)], # this is not the right place for duplicate_distance + }, + { + title => 'Other', + options => [qw(duplicate_distance)], # this is not the right place for duplicate_distance }, ]); @@ -187,8 +193,19 @@ sub new { $self->AddOptionsPage('Custom G-code', 'cog.png', optgroups => [ { - title => 'Custom G-code', - options => [qw(start_gcode end_gcode layer_gcode)], + title => 'Start G-code', + no_labels => 1, + options => [qw(start_gcode)], + }, + { + title => 'End G-code', + no_labels => 1, + options => [qw(end_gcode)], + }, + { + title => 'Layer change G-code', + no_labels => 1, + options => [qw(layer_gcode)], }, ]); @@ -203,7 +220,6 @@ sub new { }, ]); - return $self; } From 72298877bbec3bba9692c7eadb905232c34a10df Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Jun 2012 10:19:24 +0200 Subject: [PATCH 004/106] Moved units of measure to the right of input fields --- lib/Slic3r/Config.pm | 138 ++++++++++++++++++++++----------- lib/Slic3r/GUI/OptionsGroup.pm | 13 +++- lib/Slic3r/GUI/Tab.pm | 6 +- 3 files changed, 107 insertions(+), 50 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 728e4cc28..988ab7e67 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -22,7 +22,8 @@ our $Options = { deserialize => sub { join "\n", split /\\n/, $_[0] }, }, 'threads' => { - label => 'Threads (more speed, more memory usage)', + label => 'Threads', + sidetext => '(more speed but more memory usage)', cli => 'threads|j=i', type => 'i', }, @@ -36,13 +37,15 @@ our $Options = { # printer options 'nozzle_diameter' => { - label => 'Nozzle diameter (mm)', + label => 'Nozzle diameter', + sidetext => 'mm', cli => 'nozzle-diameter=f', type => 'f', important => 1, }, 'print_center' => { - label => 'Print center (mm)', + label => 'Print center', + sidetext => 'mm', cli => 'print-center=s', type => 'point', serialize => sub { join ',', @{$_[0]} }, @@ -66,7 +69,8 @@ our $Options = { type => 's', }, 'z_offset' => { - label => 'Z offset (mm)', + label => 'Z offset', + sidetext => 'mm', cli => 'z-offset=f', type => 'f', }, @@ -88,7 +92,8 @@ our $Options = { # filament options 'filament_diameter' => { - label => 'Diameter (mm)', + label => 'Diameter', + sidetext => 'mm', cli => 'filament-diameter=f', type => 'f', important => 1, @@ -100,73 +105,85 @@ our $Options = { aliases => [qw(filament_packing_density)], }, 'first_layer_temperature' => { - label => 'First layer temperature (°C)', + label => 'First layer temperature', + sidetext => '°C', cli => 'first-layer-temperature=i', type => 'i', }, 'first_layer_bed_temperature' => { - label => 'First layer bed temperature (°C)', + label => 'First layer bed temperature', + sidetext => '°C', cli => 'first-layer-bed-temperature=i', type => 'i', }, 'temperature' => { - label => 'Temperature (°C)', + label => 'Temperature', + sidetext => '°C', cli => 'temperature=i', type => 'i', important => 1, }, 'bed_temperature' => { - label => 'Bed Temperature (°C)', + label => 'Bed Temperature', + sidetext => '°C', cli => 'bed-temperature=i', type => 'i', }, # speed options 'travel_speed' => { - label => 'Travel (mm/s)', + label => 'Travel', + sidetext => 'mm/s', cli => 'travel-speed=f', type => 'f', aliases => [qw(travel_feed_rate)], }, 'perimeter_speed' => { - label => 'Perimeters (mm/s)', + label => 'Perimeters', + sidetext => 'mm/s', cli => 'perimeter-speed=f', type => 'f', aliases => [qw(perimeter_feed_rate)], }, 'small_perimeter_speed' => { - label => 'Small perimeters (mm/s or %)', + label => 'Small perimeters', + sidetext => 'mm/s or %', cli => 'small-perimeter-speed=f', type => 'f', ratio_over => 'perimeter_speed', }, 'infill_speed' => { - label => 'Infill (mm/s)', + label => 'Infill', + sidetext => 'mm/s', cli => 'infill-speed=f', type => 'f', aliases => [qw(print_feed_rate infill_feed_rate)], }, 'solid_infill_speed' => { - label => 'Solid infill (mm/s or %)', + label => 'Solid infill', + sidetext => 'mm/s or %', cli => 'solid-infill-speed=f', type => 'f', ratio_over => 'infill_speed', aliases => [qw(solid_infill_feed_rate)], }, 'top_solid_infill_speed' => { - label => 'Top solid infill (mm/s or %)', + label => 'Top solid infill', + sidetext => 'mm/s or %', cli => 'top-solid-infill-speed=f', type => 'f', ratio_over => 'solid_infill_speed', }, 'bridge_speed' => { - label => 'Bridges (mm/s)', + label => 'Bridges', + sidetext => 'mm/s', cli => 'bridge-speed=f', type => 'f', aliases => [qw(bridge_feed_rate)], }, 'first_layer_speed' => { - label => 'First layer speed (mm/s or %)', + label => 'First layer speed', + sidetext => 'mm/s or %', cli => 'first-layer-speed=s', type => 'f', }, @@ -178,52 +195,61 @@ our $Options = { type => 'bool', }, 'perimeter_acceleration' => { - label => 'Perimeters (mm/s²)', + label => 'Perimeters', + sidetext => 'mm/s²', cli => 'perimeter-acceleration', type => 'f', }, 'infill_acceleration' => { - label => 'Infill (mm/s²)', + label => 'Infill', + sidetext => 'mm/s²', cli => 'infill-acceleration', type => 'f', }, # accuracy options 'layer_height' => { - label => 'Layer height (mm)', + label => 'Layer height', + sidetext => 'mm', cli => 'layer-height=f', type => 'f', }, 'first_layer_height' => { - label => 'First layer height (mm or %)', + label => 'First layer height', + sidetext => 'mm or %', cli => 'first-layer-height=s', type => 'f', ratio_over => 'layer_height', }, 'infill_every_layers' => { - label => 'Infill every N layers', + label => 'Infill every', + sidetext => 'layers', cli => 'infill-every-layers=i', type => 'i', }, # flow options 'extrusion_width' => { - label => 'Extrusion width (mm or %; leave zero to calculate automatically)', + label => 'Default extrusion width', + sidetext => 'mm or % (leave 0 for auto)', cli => 'extrusion-width=s', type => 'f', }, 'first_layer_extrusion_width' => { - label => 'First layer extrusion width (mm or % or 0 for default)', + label => 'First layer', + sidetext => 'mm or % (leave 0 for default)', cli => 'first-layer-extrusion-width=s', type => 'f', }, 'perimeters_extrusion_width' => { - label => 'Perimeters extrusion width (mm or % or 0 for default)', + label => 'Perimeters', + sidetext => 'mm or % (leave 0 for default)', cli => 'perimeters-extrusion-width=s', type => 'f', }, 'infill_extrusion_width' => { - label => 'Infill extrusion width (mm or % or 0 for default)', + label => 'Infill', + sidetext => 'mm or % (leave 0 for default)', cli => 'infill-extrusion-width=s', type => 'f', }, @@ -265,7 +291,8 @@ our $Options = { type => 'f', }, 'fill_angle' => { - label => 'Fill angle (°)', + label => 'Fill angle', + sidetext => '°', cli => 'fill-angle=i', type => 'i', }, @@ -329,27 +356,32 @@ our $Options = { # retraction options 'retract_length' => { - label => 'Length (mm)', + label => 'Length', + sidetext => 'mm (zero to disable)', cli => 'retract-length=f', type => 'f', }, 'retract_speed' => { - label => 'Speed (mm/s)', + label => 'Speed', + sidetext => 'mm/s', cli => 'retract-speed=f', type => 'i', }, 'retract_restart_extra' => { - label => 'Extra length on restart (mm)', + label => 'Extra length on restart', + sidetext => 'mm', cli => 'retract-restart-extra=f', type => 'f', }, 'retract_before_travel' => { - label => 'Minimum travel after retraction (mm)', + label => 'Minimum travel after retraction', + sidetext => 'mm', cli => 'retract-before-travel=f', type => 'f', }, 'retract_lift' => { - label => 'Lift Z (mm)', + label => 'Lift Z', + sidetext => 'mm', cli => 'retract-lift=f', type => 'f', }, @@ -361,37 +393,44 @@ our $Options = { type => 'bool', }, 'min_fan_speed' => { - label => 'Min fan speed (%)', + label => 'Min fan speed', + sidetext => '%', cli => 'min-fan-speed=i', type => 'i', }, 'max_fan_speed' => { - label => 'Max fan speed (%)', + label => 'Max fan speed', + sidetext => '%', cli => 'max-fan-speed=i', type => 'i', }, 'bridge_fan_speed' => { - label => 'Bridge fan speed (%)', + label => 'Bridge fan speed', + sidetext => '%', cli => 'bridge-fan-speed=i', type => 'i', }, 'fan_below_layer_time' => { - label => 'Enable fan if layer print time is below (approximate seconds)', + label => 'Enable fan if layer print time is below', + sidetext => 'approximate seconds', cli => 'fan-below-layer-time=i', type => 'i', }, 'slowdown_below_layer_time' => { - label => 'Slow down if layer print time is below (approximate seconds)', + label => 'Slow down if layer print time is below', + sidetext => 'approximate seconds', cli => 'slowdown-below-layer-time=i', type => 'i', }, 'min_print_speed' => { - label => 'Min print speed (mm/s)', + label => 'Min print speed', + sidetext => 'mm/s', cli => 'min-print-speed=f', type => 'i', }, 'disable_fan_first_layers' => { - label => 'Disable fan for the first N layers', + label => 'Disable fan for the first', + sidetext => 'layers', cli => 'disable-fan-first-layers=i', type => 'i', }, @@ -408,12 +447,14 @@ our $Options = { type => 'i', }, 'skirt_distance' => { - label => 'Distance from object (mm)', + label => 'Distance from object', + sidetext => 'mm', cli => 'skirt-distance=f', type => 'i', }, 'skirt_height' => { - label => 'Skirt height (layers)', + label => 'Skirt height', + sidetext => 'layers', cli => 'skirt-height=i', type => 'i', }, @@ -425,7 +466,8 @@ our $Options = { type => 'f', }, 'rotate' => { - label => 'Rotate (°)', + label => 'Rotate', + sidetext => '°', cli => 'rotate=i', type => 'i', }, @@ -442,7 +484,8 @@ our $Options = { type => 'i', }, 'bed_size' => { - label => 'Bed size (mm)', + label => 'Bed size', + sidetext => 'mm', cli => 'bed-size=s', type => 'point', serialize => sub { join ',', @{$_[0]} }, @@ -457,6 +500,7 @@ our $Options = { }, 'duplicate_distance' => { label => 'Distance between copies', + sidetext => 'mm', cli => 'duplicate-distance=f', type => 'i', aliases => [qw(multiply_distance)], @@ -464,17 +508,19 @@ our $Options = { # sequential printing options 'complete_objects' => { - label => 'Complete individual objects (watch out for extruder collisions)', + label => 'Complete individual objects', cli => 'complete-objects', type => 'bool', }, 'extruder_clearance_radius' => { - label => 'Extruder clearance radius (mm)', + label => 'Extruder clearance radius', + sidetext => 'mm', cli => 'extruder-clearance-radius=f', type => 'i', }, 'extruder_clearance_height' => { - label => 'Extruder clearance height (mm)', + label => 'Extruder clearance height', + sidetext => 'mm', cli => 'extruder-clearance-height=f', type => 'i', }, diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index 0f582fe87..a5e3e04b2 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -23,6 +23,8 @@ sub new { # grab the default font, to fix Windows font issues/keep things consistent my $bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); $bold_font->SetWeight(&Wx::wxFONTWEIGHT_BOLD); + my $sidetext_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + $sidetext_font->SetPointSize(12); foreach my $opt_key (@{$p{options}}) { my $opt = $Slic3r::Config::Options->{$opt_key}; @@ -95,7 +97,16 @@ sub new { } else { die "Unsupported option type: " . $opt->{type}; } - $grid_sizer->Add($field); + if ($opt->{sidetext}) { + my $sizer = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); + $sizer->Add($field); + my $sidetext = Wx::StaticText->new($parent, -1, $opt->{sidetext}, Wx::wxDefaultPosition, [-1, -1]); + $sidetext->SetFont($sidetext_font); + $sizer->Add($sidetext, 0, &Wx::wxLEFT, 4); + $grid_sizer->Add($sizer); + } else { + $grid_sizer->Add($field); + } $fields{$opt_key} ||= [$field]; } diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index b1466d806..4582a5638 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -64,7 +64,7 @@ sub new { $self->AddOptionsPage('Infill', 'shading.png', optgroups => [ { title => 'Infill', - options => [qw(fill_density fill_angle fill_pattern solid_fill_pattern)], + options => [qw(fill_density fill_angle fill_pattern solid_fill_pattern infill_every_layers)], }, ]); @@ -78,7 +78,7 @@ sub new { options => [qw(travel_speed)], }, { - title => 'Advanced', + title => 'Modifiers', options => [qw(first_layer_speed)], }, ]); @@ -247,7 +247,7 @@ sub new { sub append_optgroup { my $self = shift; - my $optgroup = Slic3r::GUI::OptionsGroup->new($self, @_, label_width => 300); + my $optgroup = Slic3r::GUI::OptionsGroup->new($self, @_, label_width => 200); $self->{vsizer}->Add($optgroup, 0, wxEXPAND | wxALL, 5); } From a59b82db061e858878ad6dd9e29e5fd13e076add Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Jun 2012 10:24:17 +0200 Subject: [PATCH 005/106] Switch from wxComboBox to wxChoice --- lib/Slic3r/GUI/OptionsGroup.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index a5e3e04b2..97c6ffee8 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -85,7 +85,7 @@ sub new { }; $fields{$opt_key} = [$x_field, $y_field]; } elsif ($opt->{type} eq 'select') { - $field = Wx::Choice->new($parent, -1, Wx::wxDefaultPosition, Wx::wxDefaultSize, $opt->{labels} || $opt->{values}); + $field = Wx::ComboBox->new($parent, -1, "", Wx::wxDefaultPosition, Wx::wxDefaultSize, $opt->{labels} || $opt->{values}, &Wx::wxCB_READONLY); EVT_CHOICE($parent, $field, sub { Slic3r::Config->set($opt_key, $opt->{values}[$field->GetSelection]); }); From 19a78de82fae6d1264b93da405ce134b134948c4 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Jun 2012 10:28:53 +0200 Subject: [PATCH 006/106] Enlarge the Output filename format field --- lib/Slic3r/Config.pm | 1 + lib/Slic3r/GUI/OptionsGroup.pm | 8 ++------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 988ab7e67..2a413b5f3 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -33,6 +33,7 @@ our $Options = { label => 'Output filename format', cli => 'output-filename-format=s', type => 's', + width => 300, }, # printer options diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index 97c6ffee8..a2398e8df 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -42,12 +42,8 @@ sub new { my $field; if ($opt->{type} =~ /^(i|f|s|s@)$/) { my $style = 0; - my $size = Wx::wxDefaultSize; - - if ($opt->{multiline}) { - $style = &Wx::wxTE_MULTILINE; - $size = Wx::Size->new($opt->{width} || -1, $opt->{height} || -1); - } + $style = &Wx::wxTE_MULTILINE if $opt->{multiline}; + my $size = Wx::Size->new($opt->{width} || -1, $opt->{height} || -1); my ($get, $set) = $opt->{type} eq 's@' ? qw(serialize deserialize) : qw(get set); From f38f2f139ee11642a1e922da1a27ff7adbda4fce Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Jun 2012 11:26:21 +0200 Subject: [PATCH 007/106] Make window resizable --- lib/Slic3r/Config.pm | 14 ++++++++------ lib/Slic3r/GUI.pm | 8 ++------ lib/Slic3r/GUI/OptionsGroup.pm | 6 ++++-- lib/Slic3r/GUI/Plater.pm | 2 +- lib/Slic3r/GUI/SkeinPanel.pm | 2 +- lib/Slic3r/GUI/Tab.pm | 17 ++++++++++------- 6 files changed, 26 insertions(+), 23 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 2a413b5f3..c9a4647b2 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -16,7 +16,7 @@ our $Options = { cli => 'notes=s', type => 's', multiline => 1, - width => 450, + full_width => 1, height => 130, serialize => sub { join '\n', split /\R/, $_[0] }, deserialize => sub { join "\n", split /\\n/, $_[0] }, @@ -33,7 +33,7 @@ our $Options = { label => 'Output filename format', cli => 'output-filename-format=s', type => 's', - width => 300, + full_width => 1, }, # printer options @@ -319,7 +319,7 @@ our $Options = { cli => 'start-gcode=s', type => 's', multiline => 1, - width => 350, + full_width => 1, height => 120, serialize => sub { join '\n', split /\R+/, $_[0] }, deserialize => sub { join "\n", split /\\n/, $_[0] }, @@ -329,7 +329,7 @@ our $Options = { cli => 'end-gcode=s', type => 's', multiline => 1, - width => 350, + full_width => 1, height => 120, serialize => sub { join '\n', split /\R+/, $_[0] }, deserialize => sub { join "\n", split /\\n/, $_[0] }, @@ -339,7 +339,7 @@ our $Options = { cli => 'layer-gcode=s', type => 's', multiline => 1, - width => 350, + full_width => 1, height => 50, serialize => sub { join '\n', split /\R+/, $_[0] }, deserialize => sub { join "\n", split /\\n/, $_[0] }, @@ -349,7 +349,7 @@ our $Options = { cli => 'post-process=s@', type => 's@', multiline => 1, - width => 350, + full_width => 1, height => 60, serialize => sub { join '; ', @{$_[0]} }, deserialize => sub { [ split /\s*;\s*/, $_[0] ] }, @@ -416,12 +416,14 @@ our $Options = { sidetext => 'approximate seconds', cli => 'fan-below-layer-time=i', type => 'i', + width => 60, }, 'slowdown_below_layer_time' => { label => 'Slow down if layer print time is below', sidetext => 'approximate seconds', cli => 'slowdown-below-layer-time=i', type => 'i', + width => 60, }, 'min_print_speed' => { label => 'Min print speed', diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index b6c4c6510..90eac2132 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -21,14 +21,11 @@ sub OnInit { $self->SetAppName('Slic3r'); Slic3r::debugf "wxWidgets version %s\n", &Wx::wxVERSION_STRING; - my $frame = Wx::Frame->new( undef, -1, 'Slic3r', [-1, -1], Wx::wxDefaultSize, - wxDEFAULT_FRAME_STYLE ^ (wxRESIZE_BORDER | wxMAXIMIZE_BOX) ); + my $frame = Wx::Frame->new(undef, -1, 'Slic3r', [-1, -1], [760,500], wxDEFAULT_FRAME_STYLE); Wx::Image::AddHandler(Wx::PNGHandler->new); $frame->SetIcon(Wx::Icon->new("$Slic3r::var/Slic3r_128px.png", &Wx::wxBITMAP_TYPE_PNG) ); my $panel = Slic3r::GUI::SkeinPanel->new($frame); - my $box = Wx::BoxSizer->new(wxVERTICAL); - $box->Add($panel, 0); if (eval "use Growl::GNTP; 1") { # register growl notifications @@ -75,8 +72,7 @@ sub OnInit { # will not be handled correctly $frame->SetMenuBar($menubar); - $box->SetSizeHints($frame); - $frame->SetSizer($box); + $frame->SetMinSize($frame->GetSize); $frame->Show; $frame->Layout; diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index a2398e8df..caf9956a0 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -19,7 +19,9 @@ sub new { my $self = $class->SUPER::new($box, wxVERTICAL); my $grid_sizer = Wx::FlexGridSizer->new(scalar(@{$p{options}}), 2, ($p{no_labels} ? 1 : 2), 0); - + $grid_sizer->SetFlexibleDirection(&Wx::wxHORIZONTAL); + $grid_sizer->AddGrowableCol($p{no_labels} ? 0 : 1); + # grab the default font, to fix Windows font issues/keep things consistent my $bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); $bold_font->SetWeight(&Wx::wxFONTWEIGHT_BOLD); @@ -101,7 +103,7 @@ sub new { $sizer->Add($sidetext, 0, &Wx::wxLEFT, 4); $grid_sizer->Add($sizer); } else { - $grid_sizer->Add($field); + $grid_sizer->Add($field, 0, $opt->{full_width} ? &Wx::wxEXPAND : 0); } $fields{$opt_key} ||= [$field]; } diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index c9d460f30..42611295b 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -49,7 +49,7 @@ sub new { $self->{list} = Wx::ListView->new($self, -1, [-1, -1], [-1, 180], &Wx::wxLC_SINGLE_SEL | &Wx::wxLC_REPORT | &Wx::wxBORDER_DEFAULT); $self->{list}->InsertColumn(0, "Name", &Wx::wxLIST_FORMAT_LEFT, 300); $self->{list}->InsertColumn(1, "Copies", &Wx::wxLIST_FORMAT_CENTER, 50); - $self->{list}->InsertColumn(2, "Scale", &Wx::wxLIST_FORMAT_CENTER, 50); + $self->{list}->InsertColumn(2, "Scale", &Wx::wxLIST_FORMAT_CENTER, &Wx::wxLIST_AUTOSIZE_USEHEADER); EVT_LIST_ITEM_SELECTED($self, $self->{list}, \&list_item_selected); EVT_LIST_ITEM_DESELECTED($self, $self->{list}, \&list_item_deselected); diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index d60402ad5..83873d44f 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -66,7 +66,7 @@ sub new { my $sizer = Wx::BoxSizer->new(wxVERTICAL); $sizer->Add($buttons_sizer, 0, wxEXPAND | wxALL, 10); - $sizer->Add($tabpanel); + $sizer->Add($tabpanel, 1, wxEXPAND); $sizer->SetSizeHints($self); $self->SetSizer($sizer); diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 4582a5638..70dc33de3 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -101,6 +101,7 @@ sub new { }, { title => 'Cooling thresholds', + label_width => 250, options => [qw(fan_below_layer_time slowdown_below_layer_time min_print_speed)], }, ]); @@ -132,11 +133,7 @@ sub new { { title => 'Post-processing scripts', no_labels => 1, - options => [qw(post_process)], # this is not the right place for duplicate_distance - }, - { - title => 'Other', - options => [qw(duplicate_distance)], # this is not the right place for duplicate_distance + options => [qw(post_process)], }, ]); @@ -149,6 +146,10 @@ sub new { title => 'Flow', options => [qw(bridge_flow_ratio)], }, + { + title => 'Other', + options => [qw(duplicate_distance)], + }, ]); return $self; @@ -227,13 +228,15 @@ package Slic3r::GUI::Tab::Page; use Wx qw(:sizer :progressdialog); use Wx::Event qw(); -use base 'Wx::Panel'; +use base 'Wx::ScrolledWindow'; sub new { my $class = shift; my ($parent, %params) = @_; my $self = $class->SUPER::new($parent, -1); + $self->SetScrollbars(1, 1, 1, 1); + $self->{vsizer} = Wx::BoxSizer->new(&Wx::wxVERTICAL); $self->SetSizer($self->{vsizer}); @@ -247,7 +250,7 @@ sub new { sub append_optgroup { my $self = shift; - my $optgroup = Slic3r::GUI::OptionsGroup->new($self, @_, label_width => 200); + my $optgroup = Slic3r::GUI::OptionsGroup->new($self, label_width => 200, @_); $self->{vsizer}->Add($optgroup, 0, wxEXPAND | wxALL, 5); } From d8a64f038657844e023ff04a428a13a552674911 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Jun 2012 11:52:45 +0200 Subject: [PATCH 008/106] Use spin controls for integer values --- lib/Slic3r/Config.pm | 26 ++++++++++++++++++++++---- lib/Slic3r/GUI/OptionsGroup.pm | 15 ++++++++++----- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index c9a4647b2..4e116df58 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -26,6 +26,8 @@ our $Options = { sidetext => '(more speed but more memory usage)', cli => 'threads|j=i', type => 'i', + min => 1, + max => 16, }, # output options @@ -110,18 +112,21 @@ our $Options = { sidetext => '°C', cli => 'first-layer-temperature=i', type => 'i', + max => 300, }, 'first_layer_bed_temperature' => { label => 'First layer bed temperature', sidetext => '°C', cli => 'first-layer-bed-temperature=i', type => 'i', + max => 300, }, 'temperature' => { label => 'Temperature', sidetext => '°C', cli => 'temperature=i', type => 'i', + max => 300, important => 1, }, 'bed_temperature' => { @@ -129,6 +134,7 @@ our $Options = { sidetext => '°C', cli => 'bed-temperature=i', type => 'i', + max => 300, }, # speed options @@ -227,6 +233,7 @@ our $Options = { sidetext => 'layers', cli => 'infill-every-layers=i', type => 'i', + min => 1, }, # flow options @@ -296,6 +303,7 @@ our $Options = { sidetext => '°', cli => 'fill-angle=i', type => 'i', + max => 359, }, 'randomize_start' => { label => 'Randomize starting points', @@ -367,6 +375,7 @@ our $Options = { sidetext => 'mm/s', cli => 'retract-speed=f', type => 'i', + max => 1000, }, 'retract_restart_extra' => { label => 'Extra length on restart', @@ -398,24 +407,28 @@ our $Options = { sidetext => '%', cli => 'min-fan-speed=i', type => 'i', + max => 1000, }, 'max_fan_speed' => { label => 'Max fan speed', sidetext => '%', cli => 'max-fan-speed=i', type => 'i', + max => 1000, }, 'bridge_fan_speed' => { label => 'Bridge fan speed', sidetext => '%', cli => 'bridge-fan-speed=i', type => 'i', + max => 1000, }, 'fan_below_layer_time' => { label => 'Enable fan if layer print time is below', sidetext => 'approximate seconds', cli => 'fan-below-layer-time=i', type => 'i', + max => 1000, width => 60, }, 'slowdown_below_layer_time' => { @@ -423,6 +436,7 @@ our $Options = { sidetext => 'approximate seconds', cli => 'slowdown-below-layer-time=i', type => 'i', + max => 1000, width => 60, }, 'min_print_speed' => { @@ -430,12 +444,14 @@ our $Options = { sidetext => 'mm/s', cli => 'min-print-speed=f', type => 'i', + max => 1000, }, 'disable_fan_first_layers' => { label => 'Disable fan for the first', sidetext => 'layers', cli => 'disable-fan-first-layers=i', type => 'i', + max => 1000, }, 'fan_always_on' => { label => 'Keep fan always on', @@ -453,7 +469,7 @@ our $Options = { label => 'Distance from object', sidetext => 'mm', cli => 'skirt-distance=f', - type => 'i', + type => 'f', }, 'skirt_height' => { label => 'Skirt height', @@ -473,6 +489,7 @@ our $Options = { sidetext => '°', cli => 'rotate=i', type => 'i', + max => 359, }, 'duplicate_mode' => { label => 'Duplicate', @@ -485,6 +502,7 @@ our $Options = { label => 'Copies (autoarrange)', cli => 'duplicate=i', type => 'i', + min => 1, }, 'bed_size' => { label => 'Bed size', @@ -505,7 +523,7 @@ our $Options = { label => 'Distance between copies', sidetext => 'mm', cli => 'duplicate-distance=f', - type => 'i', + type => 'f', aliases => [qw(multiply_distance)], }, @@ -519,13 +537,13 @@ our $Options = { label => 'Extruder clearance radius', sidetext => 'mm', cli => 'extruder-clearance-radius=f', - type => 'i', + type => 'f', }, 'extruder_clearance_height' => { label => 'Extruder clearance height', sidetext => 'mm', cli => 'extruder-clearance-height=f', - type => 'i', + type => 'f', }, }; diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index caf9956a0..dd36a6ad2 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -3,7 +3,7 @@ use strict; use warnings; use Wx qw(:sizer wxSYS_DEFAULT_GUI_FONT); -use Wx::Event qw(EVT_TEXT EVT_CHECKBOX EVT_CHOICE); +use Wx::Event qw(EVT_TEXT EVT_SPINCTRL EVT_CHECKBOX EVT_CHOICE); use base 'Wx::StaticBoxSizer'; @@ -49,9 +49,14 @@ sub new { my ($get, $set) = $opt->{type} eq 's@' ? qw(serialize deserialize) : qw(get set); - $field = Wx::TextCtrl->new($parent, -1, Slic3r::Config->$get($opt_key), - Wx::wxDefaultPosition, $size, $style); - EVT_TEXT($parent, $field, sub { Slic3r::Config->$set($opt_key, $field->GetValue) }); + if ($opt->{type} eq 'i') { + my $value = Slic3r::Config->$get($opt_key); + $field = Wx::SpinCtrl->new($parent, -1, $value, Wx::wxDefaultPosition, $size, $style, $opt->{min} || 0, $opt->{max} || 100, $value); + EVT_SPINCTRL($parent, $field, sub { Slic3r::Config->$set($opt_key, $field->GetValue) }); + } else { + $field = Wx::TextCtrl->new($parent, -1, Slic3r::Config->$get($opt_key), Wx::wxDefaultPosition, $size, $style); + EVT_TEXT($parent, $field, sub { Slic3r::Config->$set($opt_key, $field->GetValue) }); + } push @reload_callbacks, sub { $field->SetValue(Slic3r::Config->$get($opt_key)) }; } elsif ($opt->{type} eq 'bool') { $field = Wx::CheckBox->new($parent, -1, ""); @@ -100,7 +105,7 @@ sub new { $sizer->Add($field); my $sidetext = Wx::StaticText->new($parent, -1, $opt->{sidetext}, Wx::wxDefaultPosition, [-1, -1]); $sidetext->SetFont($sidetext_font); - $sizer->Add($sidetext, 0, &Wx::wxLEFT, 4); + $sizer->Add($sidetext, 0, &Wx::wxLEFT | &Wx::wxALIGN_CENTER_VERTICAL , 4); $grid_sizer->Add($sizer); } else { $grid_sizer->Add($field, 0, $opt->{full_width} ? &Wx::wxEXPAND : 0); From 2b6b91cd0176ab735343f30ef1ed58cf4eede7c3 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Jun 2012 13:49:14 +0200 Subject: [PATCH 009/106] Tooltips --- lib/Slic3r/Config.pm | 71 +++++++++++++++++++++++++++++++++- lib/Slic3r/GUI/OptionsGroup.pm | 8 +++- lib/Slic3r/Print.pm | 2 +- 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 4e116df58..0731c6084 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -13,6 +13,7 @@ our $Options = { # miscellaneous options 'notes' => { label => 'Configuration notes', + tooltip => 'You can put here your personal notes. This text will be added to the G-code header comments.', cli => 'notes=s', type => 's', multiline => 1, @@ -23,6 +24,7 @@ our $Options = { }, 'threads' => { label => 'Threads', + tooltip => 'Threads are used to parallelize long-running tasks. Optimal threads number is slightly above the number of available cores/processors. Beware that more threads consume more memory.', sidetext => '(more speed but more memory usage)', cli => 'threads|j=i', type => 'i', @@ -33,6 +35,7 @@ our $Options = { # output options 'output_filename_format' => { label => 'Output filename format', + tooltip => 'You can use all configuration options as variables inside this template. For example: [layer_height], [fill_density] etc. You can also use [timestamp], [year], [month], [day], [hour], [minute], [second], [version], [input_filename], [input_filename_base].', cli => 'output-filename-format=s', type => 's', full_width => 1, @@ -41,6 +44,7 @@ our $Options = { # printer options 'nozzle_diameter' => { label => 'Nozzle diameter', + tooltip => 'This is the diameter of your extruder nozzle (for example: 0.5, 0.35 etc.)', sidetext => 'mm', cli => 'nozzle-diameter=f', type => 'f', @@ -48,6 +52,7 @@ our $Options = { }, 'print_center' => { label => 'Print center', + tooltip => 'Enter the G-code coordinates of the point you want to center your print around.', sidetext => 'mm', cli => 'print-center=s', type => 'point', @@ -56,6 +61,7 @@ our $Options = { }, 'gcode_flavor' => { label => 'G-code flavor', + tooltip => 'Some G/M-code commands, including temperature control and others, are not universal. Set this option to your printer\'s firmware to get a compatible output. The "No extrusion" flavor prevents Slic3r from exporting any extrusion value at all.', cli => 'gcode-flavor=s', type => 'select', values => [qw(reprap teacup makerbot mach3 no-extrusion)], @@ -63,32 +69,38 @@ our $Options = { }, 'use_relative_e_distances' => { label => 'Use relative E distances', + tooltip => 'If your firmware requires relative E values, check this, otherwise leave it unchecked. Most firmwares use absolute values.', cli => 'use-relative-e-distances', type => 'bool', }, 'extrusion_axis' => { label => 'Extrusion axis', + tooltip => 'Use this option to set the axis letter associated to your printer\'s extruder (usually E but some printers use A).', cli => 'extrusion-axis=s', type => 's', }, 'z_offset' => { label => 'Z offset', + tooltip => 'This value will be added (or subtracted) from all the Z coordinates in the output G-code. It is used to compensate for bad Z endstop position: for example, if your endstop zero actually leaves the nozzle 0.3mm far from the print bed, set this to -0.3 (or fix your endstop).', sidetext => 'mm', cli => 'z-offset=f', type => 'f', }, 'gcode_arcs' => { label => 'Use native G-code arcs', + tooltip => 'This experimental feature tries to detect arcs from segments and generates G2/G3 arc commands instead of multiple straight G1 commands.', cli => 'gcode-arcs', type => 'bool', }, 'g0' => { label => 'Use G0 for travel moves', + tooltip => 'Only enable this if your firmware supports G0 properly (thus decouples all axes using their maximum speeds instead of synchronizing them). Travel moves and retractions will be combined in single commands, speeding the print up.', cli => 'g0', type => 'bool', }, 'gcode_comments' => { label => 'Verbose G-code', + tooltip => 'Enable this to get a commented G-code file, with each line explained by a descriptive text. If you print from SD card, the additional weight of the file could make your firmware slow down.', cli => 'gcode-comments', type => 'bool', }, @@ -96,6 +108,7 @@ our $Options = { # filament options 'filament_diameter' => { label => 'Diameter', + tooltip => 'Enter your filament diameter here. Good precision is required, so use a caliper and do multiple measurements along the filament, then compute the average.', sidetext => 'mm', cli => 'filament-diameter=f', type => 'f', @@ -103,12 +116,14 @@ our $Options = { }, 'extrusion_multiplier' => { label => 'Extrusion multiplier', + tooltip => 'This factor changes the amount of flow proportionally. You may need to tweak this setting to get nice surface finish and correct single wall widths. Usual values are between 0.9 and 1.1. If you think you need to change this more, check filament diameter and your firmware E steps.', cli => 'extrusion-multiplier=f', type => 'f', aliases => [qw(filament_packing_density)], }, 'first_layer_temperature' => { label => 'First layer temperature', + tooltip => 'Extruder temperature for first layer. If you want to control temperature manually during print, set this to zero to disable temperature control commands in the output file.', sidetext => '°C', cli => 'first-layer-temperature=i', type => 'i', @@ -116,6 +131,7 @@ our $Options = { }, 'first_layer_bed_temperature' => { label => 'First layer bed temperature', + tooltip => 'Heated build plate temperature for the first layer. Set this to zero to disable bed temperature control commands in the output.', sidetext => '°C', cli => 'first-layer-bed-temperature=i', type => 'i', @@ -123,6 +139,7 @@ our $Options = { }, 'temperature' => { label => 'Temperature', + tooltip => 'Extruder temperature for layers after the first one. Set this to zero to disable temperature control commands in the output.', sidetext => '°C', cli => 'temperature=i', type => 'i', @@ -131,6 +148,7 @@ our $Options = { }, 'bed_temperature' => { label => 'Bed Temperature', + tooltip => 'Bed temperature for layers after the first one. Set this to zero to disable bed temperature control commands in the output.', sidetext => '°C', cli => 'bed-temperature=i', type => 'i', @@ -140,6 +158,7 @@ our $Options = { # speed options 'travel_speed' => { label => 'Travel', + tooltip => 'Speed for travel moves (jumps between distant extrusion points).', sidetext => 'mm/s', cli => 'travel-speed=f', type => 'f', @@ -147,6 +166,7 @@ our $Options = { }, 'perimeter_speed' => { label => 'Perimeters', + tooltip => 'Speed for perimeters (contours, aka vertical shells).', sidetext => 'mm/s', cli => 'perimeter-speed=f', type => 'f', @@ -154,6 +174,7 @@ our $Options = { }, 'small_perimeter_speed' => { label => 'Small perimeters', + tooltip => 'This separate setting will affect the speed of perimeters having radius <= 6.5mm (usually holes). If expressed as percentage (for example: 80%) it will be calculated on the perimeters speed setting above.', sidetext => 'mm/s or %', cli => 'small-perimeter-speed=f', type => 'f', @@ -161,6 +182,7 @@ our $Options = { }, 'infill_speed' => { label => 'Infill', + tooltip => 'Speed for printing the internal fill.', sidetext => 'mm/s', cli => 'infill-speed=f', type => 'f', @@ -168,6 +190,7 @@ our $Options = { }, 'solid_infill_speed' => { label => 'Solid infill', + tooltip => 'Speed for printing solid regions (top/bottom/internal horizontal shells). This can be expressed as a percentage (for example: 80%) over the default infill speed above.', sidetext => 'mm/s or %', cli => 'solid-infill-speed=f', type => 'f', @@ -176,6 +199,7 @@ our $Options = { }, 'top_solid_infill_speed' => { label => 'Top solid infill', + tooltip => 'Speed for printing top solid regions. You may want to slow down this to get a nicer surface finish. This can be expressed as a percentage (for example: 80%) over the solid infill speed above.', sidetext => 'mm/s or %', cli => 'top-solid-infill-speed=f', type => 'f', @@ -183,6 +207,7 @@ our $Options = { }, 'bridge_speed' => { label => 'Bridges', + tooltip => 'Speed for printing bridges.', sidetext => 'mm/s', cli => 'bridge-speed=f', type => 'f', @@ -190,6 +215,7 @@ our $Options = { }, 'first_layer_speed' => { label => 'First layer speed', + tooltip => 'If expressed as absolute value in mm/s, this speed will be applied to all the print moves of the first layer, regardless of their type. If expressed as a percentage (for example: 40%) it will scale the default speeds.', sidetext => 'mm/s or %', cli => 'first-layer-speed=s', type => 'f', @@ -217,12 +243,14 @@ our $Options = { # accuracy options 'layer_height' => { label => 'Layer height', + tooltip => 'This setting control the height (and thus the total number) of the slices/layers. Thinner layers give better accuracy but take more time to print.', sidetext => 'mm', cli => 'layer-height=f', type => 'f', }, 'first_layer_height' => { label => 'First layer height', + tooltip => 'When printing with very low layer heights, you might still want to print a thicker bottom layer to improve adhesion and tolerance for non perfect build plates. This can be expressed as an absolute value or as a percentage (for example: 150%) over the default layer height.', sidetext => 'mm or %', cli => 'first-layer-height=s', type => 'f', @@ -230,6 +258,7 @@ our $Options = { }, 'infill_every_layers' => { label => 'Infill every', + tooltip => 'This feature allows to combine infill and speed up your print by extruding thicker infill layers while preserving thin perimeters, thus accuracy.', sidetext => 'layers', cli => 'infill-every-layers=i', type => 'i', @@ -239,30 +268,35 @@ our $Options = { # flow options 'extrusion_width' => { label => 'Default extrusion width', + tooltip => 'Set this to a non-zero value to set a manual extrusion width. If left to zero, Slic3r calculates a width automatically. If expressed as percentage (for example: 230%) it will be computed over layer height.', sidetext => 'mm or % (leave 0 for auto)', cli => 'extrusion-width=s', type => 'f', }, 'first_layer_extrusion_width' => { label => 'First layer', + tooltip => 'Set this to a non-zero value to set a manual extrusion width for first layer. You can use this to force fatter extrudates for better adhesion. If expressed as percentage (for example 120%) if will be computed over the default extrusion width (which could be calculated automatically or set manually using the option above).', sidetext => 'mm or % (leave 0 for default)', cli => 'first-layer-extrusion-width=s', type => 'f', }, 'perimeters_extrusion_width' => { label => 'Perimeters', + tooltip => 'Set this to a non-zero value to set a manual extrusion width for perimeters. You may want to use thinner extrudates to get more accurate surfaces. If expressed as percentage (for example 90%) if will be computed over the default extrusion width (which could be calculated automatically or set manually using the option above).', sidetext => 'mm or % (leave 0 for default)', cli => 'perimeters-extrusion-width=s', type => 'f', }, 'infill_extrusion_width' => { label => 'Infill', + tooltip => 'Set this to a non-zero value to set a manual extrusion width for infill. You may want to use fatter extrudates to speed up the infill and make your parts stronger. If expressed as percentage (for example 90%) if will be computed over the default extrusion width (which could be calculated automatically or set manually using the option above).', sidetext => 'mm or % (leave 0 for default)', cli => 'infill-extrusion-width=s', type => 'f', }, 'bridge_flow_ratio' => { label => 'Bridge flow ratio', + tooltip => 'This factor affects the amount of plastic for bridging. You can decrease it slightly to pull the extrudates and prevent sagging, although default settings are usually good and you should experiment with cooling (use a fan) before tweaking this.', cli => 'bridge-flow-ratio=f', type => 'f', }, @@ -270,24 +304,28 @@ our $Options = { # print options 'perimeters' => { label => 'Perimeters (minimum)', + tooltip => 'This option sets the number of perimeters to generate for each layer. Note that Slic3r will increase this number automatically when it detects sloping surfaces which benefit from a higher number of perimeters.', cli => 'perimeters=i', type => 'i', aliases => [qw(perimeter_offsets)], }, 'solid_layers' => { label => 'Solid layers', + tooltip => 'Number of solid layers to generate on top and bottom.', cli => 'solid-layers=i', type => 'i', }, 'fill_pattern' => { label => 'Fill pattern', + tooltip => 'Fill pattern for general low-density infill.', cli => 'fill-pattern=s', type => 'select', values => [qw(rectilinear line concentric honeycomb hilbertcurve archimedeanchords octagramspiral)], labels => [qw(rectilinear line concentric honeycomb), 'hilbertcurve (slow)', 'archimedeanchords (slow)', 'octagramspiral (slow)'], }, 'solid_fill_pattern' => { - label => 'Solid fill pattern', + label => 'Top/bottom fill pattern', + tooltip => 'Fill pattern for top/bottom infill.', cli => 'solid-fill-pattern=s', type => 'select', values => [qw(rectilinear concentric hilbertcurve archimedeanchords octagramspiral)], @@ -295,11 +333,13 @@ our $Options = { }, 'fill_density' => { label => 'Fill density', + tooltip => 'Density of internal infill, expressed in the range 0 - 1.', cli => 'fill-density=f', type => 'f', }, 'fill_angle' => { label => 'Fill angle', + tooltip => 'Default base angle for infill orientation. Cross-hatching will be applied to this. Bridges will be infilled using the best direction Slic3r can detect, so this setting does not affect them.', sidetext => '°', cli => 'fill-angle=i', type => 'i', @@ -307,16 +347,19 @@ our $Options = { }, 'randomize_start' => { label => 'Randomize starting points', + tooltip => 'Start each layer from a different vertex to prevent plastic build-up on the same corner.', cli => 'randomize-start', type => 'bool', }, 'support_material' => { label => 'Generate support material', + tooltip => 'Enable support material generation.', cli => 'support-material', type => 'bool', }, 'support_material_tool' => { label => 'Tool used to extrude support material', + tooltip => 'Use this option to assign support material to a secondary extruder.', cli => 'support-material-tool=i', type => 'select', values => [0,1], @@ -324,6 +367,7 @@ our $Options = { }, 'start_gcode' => { label => 'Start G-code', + tooltip => 'This start procedure is inserted at the beginning of the output file, right after the temperature control commands for extruder and bed. If Slic3r detects M104 or M190 in your custom codes, such commands will not be prepended automatically. Note that you can use placeholder variables for all Slic3r settings, so you can put a "M104 S[first_layer_temperature]" command wherever you want.', cli => 'start-gcode=s', type => 's', multiline => 1, @@ -334,6 +378,7 @@ our $Options = { }, 'end_gcode' => { label => 'End G-code', + tooltip => 'This end procedure is inserted at the end of the output file. Note that you can use placeholder variables for all Slic3r settings.', cli => 'end-gcode=s', type => 's', multiline => 1, @@ -344,6 +389,7 @@ our $Options = { }, 'layer_gcode' => { label => 'Layer change G-code', + tooltip => 'This custom code is inserted at every layer change, right after the Z move and before the extruder moves to the first layer point. Note that you can use placeholder variables for all Slic3r settings.', cli => 'layer-gcode=s', type => 's', multiline => 1, @@ -354,6 +400,7 @@ our $Options = { }, 'post_process' => { label => 'Post-processing scripts', + tooltip => 'If you want to process the output G-code through custom scripts, just list their absolute paths here. Separate multiple scripts with a semicolon. Scripts will be passed the absolute path to the G-code file as the first argument, and they can access the Slic3r config settings by reading environment variables.', cli => 'post-process=s@', type => 's@', multiline => 1, @@ -366,12 +413,14 @@ our $Options = { # retraction options 'retract_length' => { label => 'Length', + tooltip => 'When retraction is triggered, filament is pulled back for the specified amount (the length is measured on raw filament, before it enters the extruder).', sidetext => 'mm (zero to disable)', cli => 'retract-length=f', type => 'f', }, 'retract_speed' => { label => 'Speed', + tooltip => 'The speed for retractions (it only applies to the extruder motor).', sidetext => 'mm/s', cli => 'retract-speed=f', type => 'i', @@ -379,18 +428,21 @@ our $Options = { }, 'retract_restart_extra' => { label => 'Extra length on restart', + tooltip => 'When the retraction is compensated after the travel move, the extruder will push this additional amount of filament. This setting is rarely needed.', sidetext => 'mm', cli => 'retract-restart-extra=f', type => 'f', }, 'retract_before_travel' => { label => 'Minimum travel after retraction', + tooltip => 'Retraction is not triggered when travel moves are shorter than this length.', sidetext => 'mm', cli => 'retract-before-travel=f', type => 'f', }, 'retract_lift' => { label => 'Lift Z', + tooltip => 'If you set this to a positive value, Z is quickly raised every time a retraction is triggered.', sidetext => 'mm', cli => 'retract-lift=f', type => 'f', @@ -399,11 +451,13 @@ our $Options = { # cooling options 'cooling' => { label => 'Enable cooling', + tooltip => 'This flag enables all the cooling features.', cli => 'cooling', type => 'bool', }, 'min_fan_speed' => { label => 'Min fan speed', + tooltip => 'This setting represents the minimum PWM your fan needs to work.', sidetext => '%', cli => 'min-fan-speed=i', type => 'i', @@ -411,6 +465,7 @@ our $Options = { }, 'max_fan_speed' => { label => 'Max fan speed', + tooltip => 'This setting represents the maximum speed of your fan.', sidetext => '%', cli => 'max-fan-speed=i', type => 'i', @@ -418,6 +473,7 @@ our $Options = { }, 'bridge_fan_speed' => { label => 'Bridge fan speed', + tooltip => 'This fan speed is enforced during all bridges.', sidetext => '%', cli => 'bridge-fan-speed=i', type => 'i', @@ -425,6 +481,7 @@ our $Options = { }, 'fan_below_layer_time' => { label => 'Enable fan if layer print time is below', + tooltip => 'If layer print time is estimated below this number of seconds, fan will be enabled and its speed will be calculated by interpolating the minimum and maximum speeds.', sidetext => 'approximate seconds', cli => 'fan-below-layer-time=i', type => 'i', @@ -433,6 +490,7 @@ our $Options = { }, 'slowdown_below_layer_time' => { label => 'Slow down if layer print time is below', + tooltip => 'If layer print time is estimated below this number of seconds, print moves speed will be scaled down to extend duration to this value.', sidetext => 'approximate seconds', cli => 'slowdown-below-layer-time=i', type => 'i', @@ -441,6 +499,7 @@ our $Options = { }, 'min_print_speed' => { label => 'Min print speed', + tooltip => 'Slic3r will not scale speed down below this speed.', sidetext => 'mm/s', cli => 'min-print-speed=f', type => 'i', @@ -448,6 +507,7 @@ our $Options = { }, 'disable_fan_first_layers' => { label => 'Disable fan for the first', + tooltip => 'You can set this to a positive value to disable fan at all during the first layers, so that it does not make adhesion worse.', sidetext => 'layers', cli => 'disable-fan-first-layers=i', type => 'i', @@ -455,6 +515,7 @@ our $Options = { }, 'fan_always_on' => { label => 'Keep fan always on', + tooltip => 'If this is enabled, fan will never be disabled and will be kept running at least at its minimum speed. Useful for PLA, harmful for ABS.', cli => 'fan-always-on', type => 'bool', }, @@ -462,17 +523,20 @@ our $Options = { # skirt options 'skirts' => { label => 'Loops', + tooltip => 'Number of loops for this skirt, in other words its thickness. Set this to zero to disable skirt.', cli => 'skirts=i', type => 'i', }, 'skirt_distance' => { label => 'Distance from object', + tooltip => 'Distance between skirt and object(s). Set this to zero to attach the skirt to the object(s) and get a brim for better adhesion.', sidetext => 'mm', cli => 'skirt-distance=f', type => 'f', }, 'skirt_height' => { label => 'Skirt height', + tooltip => 'Height of skirt expressed in layers. Set this to a tall value to use skirt as a shield against drafts.', sidetext => 'layers', cli => 'skirt-height=i', type => 'i', @@ -506,6 +570,7 @@ our $Options = { }, 'bed_size' => { label => 'Bed size', + tooltip => 'Size of your bed. This is used to adjust the preview in the plater and for auto-arranging parts in it.', sidetext => 'mm', cli => 'bed-size=s', type => 'point', @@ -521,6 +586,7 @@ our $Options = { }, 'duplicate_distance' => { label => 'Distance between copies', + tooltip => 'Distance used for the auto-arrange feature of the plater.', sidetext => 'mm', cli => 'duplicate-distance=f', type => 'f', @@ -530,17 +596,20 @@ our $Options = { # sequential printing options 'complete_objects' => { label => 'Complete individual objects', + tooltip => 'When printing multiple objects or copies, this feature will complete each object before moving onto next one (and starting it from its bottom layer). This feature is useful to avoid the risk of ruined prints. Slic3r should warn and prevent you from extruder collisions, but beware.', cli => 'complete-objects', type => 'bool', }, 'extruder_clearance_radius' => { label => 'Extruder clearance radius', + tooltip => 'Set this to the clearance radius around your extruder. If the extruder is not centered, choose the largest value for safety. This setting is used to check for collisions and to display the graphical preview in the plater.', sidetext => 'mm', cli => 'extruder-clearance-radius=f', type => 'f', }, 'extruder_clearance_height' => { label => 'Extruder clearance height', + tooltip => 'Set this to the vertical distance between your nozzle tip and (usually) the X carriage rods. In other words, this is the height of the clearance cylinder around your extruder, and it represents the maximum depth the extruder can peek before colliding with other printed objects.', sidetext => 'mm', cli => 'extruder-clearance-height=f', type => 'f', diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index dd36a6ad2..8979bc742 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -67,12 +67,16 @@ sub new { $field = Wx::BoxSizer->new(wxHORIZONTAL); my $field_size = Wx::Size->new(40, -1); my $value = Slic3r::Config->get($opt_key); - $field->Add($_) for ( + my @items = ( Wx::StaticText->new($parent, -1, "x:"), my $x_field = Wx::TextCtrl->new($parent, -1, $value->[0], Wx::wxDefaultPosition, $field_size), Wx::StaticText->new($parent, -1, " y:"), my $y_field = Wx::TextCtrl->new($parent, -1, $value->[1], Wx::wxDefaultPosition, $field_size), ); + $field->Add($_) for @items; + if ($opt->{tooltip}) { + $_->SetToolTipString($opt->{tooltip}) for @items; + } my $set_value = sub { my ($i, $value) = @_; my $val = Slic3r::Config->get($opt_key); @@ -100,6 +104,8 @@ sub new { } else { die "Unsupported option type: " . $opt->{type}; } + $label->SetToolTipString($opt->{tooltip}) if $label && $opt->{tooltip}; + $field->SetToolTipString($opt->{tooltip}) if $opt->{tooltip} && $field->can('SetToolTipString'); if ($opt->{sidetext}) { my $sizer = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); $sizer->Add($field); diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 2bab4c7a2..4ff4f9cca 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -484,7 +484,7 @@ sub write_gcode { printf $fh $extruder->set_bed_temperature($Slic3r::first_layer_bed_temperature, 1), if $Slic3r::first_layer_bed_temperature && $Slic3r::start_gcode !~ /M190/i; printf $fh $extruder->set_temperature($Slic3r::first_layer_temperature) - if $Slic3r::first_layer_temperature; + if $Slic3r::first_layer_temperature && $Slic3r::start_gcode !~ /M104/i; printf $fh "%s\n", Slic3r::Config->replace_options($Slic3r::start_gcode); printf $fh $extruder->set_temperature($Slic3r::first_layer_temperature, 1) if $Slic3r::first_layer_temperature && $Slic3r::start_gcode !~ /M109/i; From 20e1a9c8606973998482c2ccb20c5f3a32c0ad2a Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Jun 2012 13:52:38 +0200 Subject: [PATCH 010/106] Updates to the description and the README --- README.markdown | 9 ++++++--- lib/Slic3r/GUI.pm | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.markdown b/README.markdown index 456f41879..e8ddca0ff 100644 --- a/README.markdown +++ b/README.markdown @@ -6,8 +6,8 @@ A: Yes. ## What's it? -Slic3r is an STL-to-GCODE translator for RepRap 3D printers, aiming to -be a modern and fast alternative to Skeinforge. +Slic3r is a G-code generator for 3D printers. It's compatible with RepRaps, +Makerbots, Ultimakers and many more machines. See the [project homepage](http://slic3r.org/) at slic3r.org for more information. @@ -63,8 +63,11 @@ download and run, with no dependencies required. ## Can I help? -Sure! Send patches and/or drop me a line at aar@cpan.org. You can also +Sure! Drop me a line at aar@cpan.org. You can also find me in #reprap and in #slic3r on FreeNode with the nickname _Sound_. +Before sending patches and pull requests contact me to discuss your proposed +changes: this way we'll ensure nobody wastes their time and no conflicts arise +in development. ## What's Slic3r license? diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 90eac2132..efce57ac8 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -86,7 +86,7 @@ sub About { $info->SetName('Slic3r'); $info->AddDeveloper('Alessandro Ranellucci'); $info->SetVersion($Slic3r::VERSION); - $info->SetDescription('STL-to-GCODE translator for RepRap printers'); + $info->SetDescription('G-code generator for 3D printers'); Wx::AboutBox($info); } From e810f9b898c84941b089e7f375072e36d414ede1 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Jun 2012 14:29:47 +0200 Subject: [PATCH 011/106] Moved filament settings to new Filament tab --- MANIFEST | 27 ++++++++++++ lib/Slic3r/GUI/SkeinPanel.pm | 4 +- lib/Slic3r/GUI/Tab.pm | 79 ++++++++++++++++++++--------------- var/funnel.png | Bin 0 -> 547 bytes 4 files changed, 75 insertions(+), 35 deletions(-) create mode 100644 var/funnel.png diff --git a/MANIFEST b/MANIFEST index 035cef1a9..56e61cd41 100644 --- a/MANIFEST +++ b/MANIFEST @@ -60,3 +60,30 @@ utils/stl-to-amf.pl var/Slic3r.icns var/Slic3r.ico var/Slic3r.png +var/Slic3r_128px.png +var/add.png +var/arrow_out.png +var/arrow_rotate_anticlockwise.png +var/arrow_rotate_clockwise.png +var/arrow_up.png +var/box.png +var/brick_add.png +var/brick_delete.png +var/brick_go.png +var/bricks.png +var/building.png +var/cog.png +var/cog_go.png +var/cross.png +var/delete.png +var/funnel.png +var/hourglass.png +var/layers.png +var/note.png +var/page_white_go.png +var/printer_empty.png +var/shading.png +var/shape_ungroup.png +var/spool.png +var/time.png +var/wrench.png diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 83873d44f..1b7b43838 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -34,12 +34,14 @@ sub new { my @tabs = ( $make_treebook_tab->('Slic3r::GUI::Tab::Print'), + $make_treebook_tab->('Slic3r::GUI::Tab::Filament'), $make_treebook_tab->('Slic3r::GUI::Tab::Printer'), ); $tabpanel->AddPage(Slic3r::GUI::Plater->new($tabpanel), "Plater"); $tabpanel->AddPage($tabs[0], "Print settings"); - $tabpanel->AddPage($tabs[1], "Filament/printer settings"); + $tabpanel->AddPage($tabs[1], "Filament settings"); + $tabpanel->AddPage($tabs[2], "Printer settings"); my $buttons_sizer; { diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 70dc33de3..b34892452 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -90,22 +90,6 @@ sub new { }, ]); - $self->AddOptionsPage('Cooling', 'hourglass.png', optgroups => [ - { - title => 'Enable', - options => [qw(cooling)], - }, - { - title => 'Fan settings', - options => [qw(min_fan_speed max_fan_speed bridge_fan_speed disable_fan_first_layers fan_always_on)], - }, - { - title => 'Cooling thresholds', - label_width => 250, - options => [qw(fan_below_layer_time slowdown_below_layer_time min_print_speed)], - }, - ]); - $self->AddOptionsPage('Support material', 'building.png', optgroups => [ { title => 'Support material', @@ -140,6 +124,7 @@ sub new { $self->AddOptionsPage('Advanced', 'wrench.png', optgroups => [ { title => 'Extrusion width', + label_width => 180, options => [qw(extrusion_width first_layer_extrusion_width perimeters_extrusion_width infill_extrusion_width)], }, { @@ -155,6 +140,47 @@ sub new { return $self; } +package Slic3r::GUI::Tab::Filament; + +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Slic3r::GUI::Tab'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, -1); + + $self->AddOptionsPage('Filament', 'spool.png', optgroups => [ + { + title => 'Filament', + options => [qw(filament_diameter extrusion_multiplier)], + }, + { + title => 'Temperature', + options => [qw(temperature first_layer_temperature bed_temperature first_layer_bed_temperature)], + }, + ]); + + $self->AddOptionsPage('Cooling', 'hourglass.png', optgroups => [ + { + title => 'Enable', + options => [qw(cooling)], + }, + { + title => 'Fan settings', + options => [qw(min_fan_speed max_fan_speed bridge_fan_speed disable_fan_first_layers fan_always_on)], + }, + { + title => 'Cooling thresholds', + label_width => 250, + options => [qw(fan_below_layer_time slowdown_below_layer_time min_print_speed)], + }, + ]); + + return $self; +} + package Slic3r::GUI::Tab::Printer; use Wx qw(:sizer :progressdialog); @@ -177,18 +203,14 @@ sub new { }, ]); - $self->AddOptionsPage('Extruder and filament', 'spool.png', optgroups => [ + $self->AddOptionsPage('Extruder 1', 'funnel.png', optgroups => [ { title => 'Size', options => [qw(nozzle_diameter)], }, { - title => 'Filament', - options => [qw(filament_diameter extrusion_multiplier)], - }, - { - title => 'Temperature', - options => [qw(temperature first_layer_temperature bed_temperature first_layer_bed_temperature)], + title => 'Retraction', + options => [qw(retract_length retract_lift retract_speed retract_restart_extra retract_before_travel)], }, ]); @@ -210,17 +232,6 @@ sub new { }, ]); - $self->AddOptionsPage('Retraction', 'arrow_up.png', optgroups => [ - { - title => 'Retraction', - options => [qw(retract_length retract_lift retract_speed)], - }, - { - title => 'Advanced', - options => [qw(retract_restart_extra retract_before_travel)], - }, - ]); - return $self; } diff --git a/var/funnel.png b/var/funnel.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef56a62929a6a6e07f8135c6ef485cc444fd87 GIT binary patch literal 547 zcmV+;0^I$HP)sZoogBOP20nya&E~uK0&YzgK@4K2EY-SL1jYY~ z|I@pxkpxre!8e!OpHJ>bE-u3`pjN9r1AvT5q9oK4>JcTtugy^3s4tX``ao&LVzKL{ z?D>5D6a)c6p%4TD0r30%;PraJuanE=@?}1s!)!)Oa53O?Izc=h z=iU{bVxXSU4PpNF)N$Xq3GuiqLE}IcEZLjYi|GP$)n!7z9a@;GWg%b#gf? zKt-n@aCW-Fu72!_KU>~_1WthQRMfX<&t zBr4Qn15h#gT&vak6QJul*O)yvz<$4nOeUk^y`pIvKa))BcDq!kq|<5j27sT510;l0 z#^W)N%%aU^1Jmi0b0&~_Y!jqXDOM~N<1yRq_Vw-ke*ZeUX*Wl(TB%f`qcH3OgnT}) z{u@9eQ;fV*{sussXtl*+!7=hqd27rOKyRj)Il(=E`(6Pp7JZG&<~agf^gEZ!Wv7)l lF6;V^syG!?t5x_BU;s1WHWucnS~~y$002ovPDHLkV1m3|^t}K8 literal 0 HcmV?d00001 From 9e6e3bd269840225c6d2f932fe72214765c4ac01 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Jun 2012 16:46:43 +0200 Subject: [PATCH 012/106] Custom Treebook implementation --- lib/Slic3r/GUI/SkeinPanel.pm | 22 +++--------------- lib/Slic3r/GUI/Tab.pm | 43 +++++++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 1b7b43838..25a7ca674 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -22,26 +22,10 @@ sub new { my $self = $class->SUPER::new($parent, -1); my $tabpanel = Wx::Notebook->new($self, -1, Wx::wxDefaultPosition, Wx::wxDefaultSize, &Wx::wxNB_TOP); - my $make_treebook_tab = sub { - my $class = shift; - - my $tab = Wx::Panel->new($tabpanel, -1); - my $sizer = Wx::BoxSizer->new(&Wx::wxVERTICAL); - $sizer->Add($class->new($tab), 1, &Wx::wxALL | &Wx::wxEXPAND, 5); - $tab->SetSizer($sizer); - return $tab; - }; - - my @tabs = ( - $make_treebook_tab->('Slic3r::GUI::Tab::Print'), - $make_treebook_tab->('Slic3r::GUI::Tab::Filament'), - $make_treebook_tab->('Slic3r::GUI::Tab::Printer'), - ); - $tabpanel->AddPage(Slic3r::GUI::Plater->new($tabpanel), "Plater"); - $tabpanel->AddPage($tabs[0], "Print settings"); - $tabpanel->AddPage($tabs[1], "Filament settings"); - $tabpanel->AddPage($tabs[2], "Printer settings"); + $tabpanel->AddPage(Slic3r::GUI::Tab::Print->new($tabpanel), "Print settings"); + $tabpanel->AddPage(Slic3r::GUI::Tab::Filament->new($tabpanel), "Filament settings"); + $tabpanel->AddPage(Slic3r::GUI::Tab::Printer->new($tabpanel), "Printer settings"); my $buttons_sizer; { diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index b34892452..27b04857a 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -4,17 +4,36 @@ use warnings; use utf8; use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); -use base 'Wx::Treebook'; +use Wx::Event qw(EVT_TREE_SEL_CHANGED); +use base 'Wx::Panel'; sub new { my $class = shift; my ($parent) = @_; my $self = $class->SUPER::new($parent, -1, [-1,-1], [-1,-1], &Wx::wxBK_LEFT); - $self->{images} = Wx::ImageList->new(16, 16, 1); - $self->AssignImageList($self->{images}); - $self->{imagecount} = -1; + $self->{sizer} = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); + $self->{sizer}->SetSizeHints($self); + $self->SetSizer($self->{sizer}); + + $self->{treectrl} = Wx::TreeCtrl->new($self, -1, [-1, -1], [200, -1], &Wx::wxTR_NO_BUTTONS | &Wx::wxTR_HIDE_ROOT | &Wx::wxTR_SINGLE | &Wx::wxTR_NO_LINES); + $self->{sizer}->Add($self->{treectrl}, 0, &Wx::wxEXPAND); + + $self->{icons} = Wx::ImageList->new(16, 16, 1); + $self->{treectrl}->AssignImageList($self->{icons}); + $self->{iconcount} = -1; + + $self->{treectrl}->AddRoot("root"); + $self->{pages} = {}; + $self->{treectrl}->SetIndent(0); + EVT_TREE_SEL_CHANGED($parent, $self->{treectrl}, sub { + $_->Hide for values %{$self->{pages}}; + $self->{sizer}->Remove(1); + my $page = $self->{pages}->{ $self->{treectrl}->GetItemText($self->{treectrl}->GetSelection) }; + $page->Show; + $self->{sizer}->Add($page, 1, &Wx::wxEXPAND | &Wx::wxLEFT, 5); + $self->{sizer}->Layout; + }); return $self; } @@ -22,17 +41,19 @@ sub new { sub AddOptionsPage { my $self = shift; my $title = shift; - my $image = (ref $_[1]) ? undef : shift; + my $icon = (ref $_[1]) ? undef : shift; my $page = Slic3r::GUI::Tab::Page->new($self, @_); - my $bitmap = $image - ? Wx::Bitmap->new("$Slic3r::var/$image", &Wx::wxBITMAP_TYPE_PNG) + my $bitmap = $icon + ? Wx::Bitmap->new("$Slic3r::var/$icon", &Wx::wxBITMAP_TYPE_PNG) : undef; if ($bitmap) { - $self->{images}->Add($bitmap); - $self->{imagecount}++; + $self->{icons}->Add($bitmap); + $self->{iconcount}++; } - $self->AddPage($page, $title, undef, $self->{imagecount}); + $page->Hide; + $self->{treectrl}->AppendItem($self->{treectrl}->GetRootItem, $title, $self->{iconcount}); + $self->{pages}{$title} = $page; } package Slic3r::GUI::Tab::Print; From 35f36e0446f192b5eb93de7163d45157b8a97831 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Jun 2012 22:27:57 +0200 Subject: [PATCH 013/106] New preset management (unfinished) --- lib/Slic3r.pm | 6 +- lib/Slic3r/Config.pm | 50 ++++++-- lib/Slic3r/GUI.pm | 90 +++++++++----- lib/Slic3r/GUI/OptionsGroup.pm | 31 ++--- lib/Slic3r/GUI/SkeinPanel.pm | 4 +- lib/Slic3r/GUI/Tab.pm | 210 +++++++++++++++++++++++++++++---- var/disk.png | Bin 0 -> 620 bytes 7 files changed, 307 insertions(+), 84 deletions(-) create mode 100755 var/disk.png diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index b31e2643f..fb6112df0 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -73,9 +73,9 @@ our $gcode_comments = 0; our $filament_diameter = 3; # mm our $extrusion_multiplier = 1; our $temperature = 200; -our $first_layer_temperature; +our $first_layer_temperature = $temperature; our $bed_temperature = 0; -our $first_layer_bed_temperature; +our $first_layer_bed_temperature = $bed_temperature; # speed options our $travel_speed = 130; # mm/s @@ -168,6 +168,8 @@ our $complete_objects = 0; our $extruder_clearance_radius = 20; # mm our $extruder_clearance_height = 20; # mm +our $Defaults = Slic3r::Config->current; + sub parallelize { my %params = @_; diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 0731c6084..48ee6de43 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -8,6 +8,12 @@ use constant PI => 4 * atan2(1, 1); # cemetery of old config settings our @Ignore = qw(duplicate_x duplicate_y multiply_x multiply_y); +our %Groups = ( + print => [qw(layer_height first_layer_height perimeters randomize_start solid_layers fill_density fill_angle fill_pattern solid_fill_pattern infill_every_layers perimeter_speed small_perimeter_speed infill_speed solid_infill_speed top_solid_infill_speed bridge_speed travel_speed first_layer_speed skirts skirt_distance skirt_height support_material support_material_tool notes complete_objects extruder_clearance_radius extruder_clearance_height gcode_comments output_filename_format post_process extrusion_width first_layer_extrusion_width perimeters_extrusion_width infill_extrusion_width bridge_flow_ratio duplicate_distance)], + filament => [qw(filament_diameter extrusion_multiplier temperature first_layer_temperature bed_temperature first_layer_bed_temperature cooling min_fan_speed max_fan_speed bridge_fan_speed disable_fan_first_layers fan_always_on fan_below_layer_time slowdown_below_layer_time min_print_speed)], + printer => [qw(bed_size print_center z_offset gcode_flavor use_relative_e_distances nozzle_diameter retract_length retract_lift retract_speed retract_restart_extra retract_before_travel start_gcode end_gcode layer_gcode)], +); + our $Options = { # miscellaneous options @@ -243,7 +249,7 @@ our $Options = { # accuracy options 'layer_height' => { label => 'Layer height', - tooltip => 'This setting control the height (and thus the total number) of the slices/layers. Thinner layers give better accuracy but take more time to print.', + tooltip => 'This setting controls the height (and thus the total number) of the slices/layers. Thinner layers give better accuracy but take more time to print.', sidetext => 'mm', cli => 'layer-height=f', type => 'f', @@ -651,11 +657,12 @@ sub deserialize { sub save { my $class = shift; - my ($file) = @_; + my ($file, $group) = @_; open my $fh, '>', $file; binmode $fh, ':utf8'; foreach my $opt (sort keys %$Options) { + next if defined $group && not ($opt ~~ @{$Groups{$group}}); next if $Options->{$opt}{gui_only}; my $value = get($opt); $value = $Options->{$opt}{serialize}->($value) if $Options->{$opt}{serialize}; @@ -674,22 +681,42 @@ sub setenv { } } -sub load { +sub current { + my $class = shift; + return { map +($_ => get($_)), sort keys %$Options }; +} + +sub read_ini { my $class = shift; my ($file) = @_; - my %ignore = map { $_ => 1 } @Ignore; - local $/ = "\n"; open my $fh, '<', $file; binmode $fh, ':utf8'; + + my $ini = { _ => {} }; + my $category = '_'; while (<$fh>) { s/\R+$//; next if /^\s+/; next if /^$/; next if /^\s*#/; /^(\w+) = (.*)/ or die "Unreadable configuration file (invalid data at line $.)\n"; - my ($key, $val) = ($1, $2); + $ini->{$category}{$1} = $2; + } + close $fh; + + return $ini; +} + +sub load_hash { + my $class = shift; + my ($hash, $group, $deserialized) = @_; + + my %ignore = map { $_ => 1 } @Ignore; + foreach my $key (sort keys %$hash) { + next if defined $group && not ($key ~~ @{$Groups{$group}}); + my $val = $hash->{$key}; # handle legacy options next if $ignore{$key}; @@ -705,9 +732,16 @@ sub load { } next unless $key; my $opt = $Options->{$key}; - set($key, $opt->{deserialize} ? $opt->{deserialize}->($val) : $val); + set($key, ($opt->{deserialize} && !$deserialized) ? $opt->{deserialize}->($val) : $val); } - close $fh; +} + +sub load { + my $class = shift; + my ($file) = @_; + + my $ini = __PACKAGE__->read_ini($file); + __PACKAGE__->load_hash($ini->{_}); } sub validate_cli { diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index efce57ac8..277d751f6 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -14,6 +14,7 @@ use Wx::Event qw(EVT_MENU); use base 'Wx::App'; my $growler; +our $datadir; sub OnInit { my $self = shift; @@ -21,12 +22,6 @@ sub OnInit { $self->SetAppName('Slic3r'); Slic3r::debugf "wxWidgets version %s\n", &Wx::wxVERSION_STRING; - my $frame = Wx::Frame->new(undef, -1, 'Slic3r', [-1, -1], [760,500], wxDEFAULT_FRAME_STYLE); - Wx::Image::AddHandler(Wx::PNGHandler->new); - $frame->SetIcon(Wx::Icon->new("$Slic3r::var/Slic3r_128px.png", &Wx::wxBITMAP_TYPE_PNG) ); - - my $panel = Slic3r::GUI::SkeinPanel->new($frame); - if (eval "use Growl::GNTP; 1") { # register growl notifications eval { @@ -34,9 +29,20 @@ sub OnInit { $growler->register([{Name => 'SKEIN_DONE', DisplayName => 'Slicing Done'}]); }; } + + # locate or create data directory + $datadir = Wx::StandardPaths::Get->GetUserDataDir; + for ($datadir, "$datadir/print", "$datadir/filament", "$datadir/printer") { + mkdir or $self->fatal_error("Slic3r was unable to create its data directory at $_ (errno: $!).") + unless -d $_; + } + + # application frame + Wx::Image::AddHandler(Wx::PNGHandler->new); + my $frame = Wx::Frame->new(undef, -1, 'Slic3r', [-1, -1], [760,500], wxDEFAULT_FRAME_STYLE); + $frame->SetIcon(Wx::Icon->new("$Slic3r::var/Slic3r_128px.png", &Wx::wxBITMAP_TYPE_PNG) ); + my $panel = Slic3r::GUI::SkeinPanel->new($frame); - # menubar - my $menubar = Wx::MenuBar->new; # status bar $frame->{statusbar} = Slic3r::GUI::ProgressStatusBar->new($frame, -1); @@ -44,33 +50,41 @@ sub OnInit { # File menu my $fileMenu = Wx::Menu->new; - $fileMenu->Append(1, "Save Config…"); - $fileMenu->Append(2, "Open Config…"); - $fileMenu->AppendSeparator(); - $fileMenu->Append(3, "Slice…"); - $fileMenu->Append(4, "Reslice"); - $fileMenu->Append(5, "Slice and Save As…"); - $fileMenu->Append(6, "Export SVG…"); - $fileMenu->AppendSeparator(); - $fileMenu->Append(wxID_EXIT, "&Quit"); - $menubar->Append($fileMenu, "&File"); - EVT_MENU($frame, 1, sub { $panel->save_config }); - EVT_MENU($frame, 2, sub { $panel->load_config }); - EVT_MENU($frame, 3, sub { $panel->do_slice }); - EVT_MENU($frame, 4, sub { $panel->do_slice(reslice => 1) }); - EVT_MENU($frame, 5, sub { $panel->do_slice(save_as => 1) }); - EVT_MENU($frame, 6, sub { $panel->do_slice(save_as => 1, export_svg => 1) }); - EVT_MENU($frame, wxID_EXIT, sub {$_[0]->Close(1)}); - + { + $fileMenu->Append(1, "Save Config…"); + $fileMenu->Append(2, "Open Config…"); + $fileMenu->AppendSeparator(); + $fileMenu->Append(3, "Slice…"); + $fileMenu->Append(4, "Reslice"); + $fileMenu->Append(5, "Slice and Save As…"); + $fileMenu->Append(6, "Export SVG…"); + $fileMenu->AppendSeparator(); + $fileMenu->Append(wxID_EXIT, "&Quit"); + EVT_MENU($frame, 1, sub { $panel->save_config }); + EVT_MENU($frame, 2, sub { $panel->load_config }); + EVT_MENU($frame, 3, sub { $panel->do_slice }); + EVT_MENU($frame, 4, sub { $panel->do_slice(reslice => 1) }); + EVT_MENU($frame, 5, sub { $panel->do_slice(save_as => 1) }); + EVT_MENU($frame, 6, sub { $panel->do_slice(save_as => 1, export_svg => 1) }); + EVT_MENU($frame, wxID_EXIT, sub {$_[0]->Close(1)}); + } + # Help menu my $helpMenu = Wx::Menu->new; - $helpMenu->Append(wxID_ABOUT, "&About"); - $menubar->Append($helpMenu, "&Help"); - EVT_MENU($frame, wxID_ABOUT, \&About); - - # Set the menubar after appending items, otherwise special items + { + $helpMenu->Append(wxID_ABOUT, "&About"); + EVT_MENU($frame, wxID_ABOUT, \&About); + } + + # menubar + # assign menubar to frame after appending items, otherwise special items # will not be handled correctly - $frame->SetMenuBar($menubar); + { + my $menubar = Wx::MenuBar->new; + $menubar->Append($fileMenu, "&File"); + $menubar->Append($helpMenu, "&Help"); + $frame->SetMenuBar($menubar); + } $frame->SetMinSize($frame->GetSize); $frame->Show; @@ -104,6 +118,18 @@ sub catch_error { return 0; } +sub show_error { + my $self = shift; + my ($message) = @_; + Wx::MessageDialog->new($self, $message, 'Error', &Wx::wxOK | &Wx::wxICON_ERROR)->ShowModal; +} + +sub fatal_error { + my $self = shift; + $self->show_error(@_); + exit 1; +} + sub warning_catcher { my ($self, $message_dialog) = @_; return sub { diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index 8979bc742..c0c1d22d7 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -3,13 +3,13 @@ use strict; use warnings; use Wx qw(:sizer wxSYS_DEFAULT_GUI_FONT); -use Wx::Event qw(EVT_TEXT EVT_SPINCTRL EVT_CHECKBOX EVT_CHOICE); +use Wx::Event qw(EVT_TEXT EVT_SPINCTRL EVT_CHECKBOX EVT_COMBOBOX); use base 'Wx::StaticBoxSizer'; # not very elegant, but this solution is temporary waiting for a better GUI -our @reload_callbacks = (); -our %fields = (); # $key => [$control] +our %reload_callbacks = (); # key => $cb +our %fields = (); # $key => [$control] sub new { my $class = shift; @@ -28,6 +28,8 @@ sub new { my $sidetext_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); $sidetext_font->SetPointSize(12); + my $onChange = $p{on_change} || sub {}; + foreach my $opt_key (@{$p{options}}) { my $opt = $Slic3r::Config::Options->{$opt_key}; my $label; @@ -52,17 +54,17 @@ sub new { if ($opt->{type} eq 'i') { my $value = Slic3r::Config->$get($opt_key); $field = Wx::SpinCtrl->new($parent, -1, $value, Wx::wxDefaultPosition, $size, $style, $opt->{min} || 0, $opt->{max} || 100, $value); - EVT_SPINCTRL($parent, $field, sub { Slic3r::Config->$set($opt_key, $field->GetValue) }); + EVT_SPINCTRL($parent, $field, sub { Slic3r::Config->$set($opt_key, $field->GetValue); $onChange->($opt_key) }); } else { $field = Wx::TextCtrl->new($parent, -1, Slic3r::Config->$get($opt_key), Wx::wxDefaultPosition, $size, $style); - EVT_TEXT($parent, $field, sub { Slic3r::Config->$set($opt_key, $field->GetValue) }); + EVT_TEXT($parent, $field, sub { Slic3r::Config->$set($opt_key, $field->GetValue); $onChange->($opt_key) }); } - push @reload_callbacks, sub { $field->SetValue(Slic3r::Config->$get($opt_key)) }; + $reload_callbacks{$opt_key} = sub { $field->SetValue(Slic3r::Config->$get($opt_key)) }; } elsif ($opt->{type} eq 'bool') { $field = Wx::CheckBox->new($parent, -1, ""); $field->SetValue(Slic3r::Config->get($opt_key)); - EVT_CHECKBOX($parent, $field, sub { Slic3r::Config->set($opt_key, $field->GetValue) }); - push @reload_callbacks, sub { $field->SetValue(Slic3r::Config->get($opt_key)) }; + EVT_CHECKBOX($parent, $field, sub { Slic3r::Config->set($opt_key, $field->GetValue); $onChange->($opt_key) }); + $reload_callbacks{$opt_key} = sub { $field->SetValue(Slic3r::Config->get($opt_key)) }; } elsif ($opt->{type} eq 'point') { $field = Wx::BoxSizer->new(wxHORIZONTAL); my $field_size = Wx::Size->new(40, -1); @@ -83,9 +85,9 @@ sub new { $val->[$i] = $value; Slic3r::Config->set($opt_key, $val); }; - EVT_TEXT($parent, $x_field, sub { $set_value->(0, $x_field->GetValue) }); - EVT_TEXT($parent, $y_field, sub { $set_value->(1, $y_field->GetValue) }); - push @reload_callbacks, sub { + EVT_TEXT($parent, $x_field, sub { $set_value->(0, $x_field->GetValue); $onChange->($opt_key) }); + EVT_TEXT($parent, $y_field, sub { $set_value->(1, $y_field->GetValue); $onChange->($opt_key) }); + $reload_callbacks{$opt_key} = sub { my $value = Slic3r::Config->get($opt_key); $x_field->SetValue($value->[0]); $y_field->SetValue($value->[1]); @@ -93,14 +95,15 @@ sub new { $fields{$opt_key} = [$x_field, $y_field]; } elsif ($opt->{type} eq 'select') { $field = Wx::ComboBox->new($parent, -1, "", Wx::wxDefaultPosition, Wx::wxDefaultSize, $opt->{labels} || $opt->{values}, &Wx::wxCB_READONLY); - EVT_CHOICE($parent, $field, sub { + EVT_COMBOBOX($parent, $field, sub { Slic3r::Config->set($opt_key, $opt->{values}[$field->GetSelection]); + $onChange->($opt_key); }); - push @reload_callbacks, sub { + $reload_callbacks{$opt_key} = sub { my $value = Slic3r::Config->get($opt_key); $field->SetSelection(grep $opt->{values}[$_] eq $value, 0..$#{$opt->{values}}); }; - $reload_callbacks[-1]->(); + $reload_callbacks{$opt_key}->(); } else { die "Unsupported option type: " . $opt->{type}; } diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 25a7ca674..38082878a 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -58,8 +58,6 @@ sub new { $self->SetSizer($sizer); $self->Layout; - $_->() for @Slic3r::GUI::OptionsGroup::reload_callbacks; - return $self; } @@ -214,7 +212,7 @@ sub load_config { Slic3r::Config->load($file); }; Slic3r::GUI::catch_error($self); - $_->() for @Slic3r::GUI::OptionsGroup::reload_callbacks; + $_->() for values %Slic3r::GUI::OptionsGroup::reload_callbacks; } $dlg->Destroy; } diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 27b04857a..3f381ec30 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -3,26 +3,60 @@ use strict; use warnings; use utf8; +use List::Util qw(first); use Wx qw(:sizer :progressdialog); -use Wx::Event qw(EVT_TREE_SEL_CHANGED); +use Wx::Event qw(EVT_TREE_SEL_CHANGED EVT_CHOICE EVT_BUTTON); use base 'Wx::Panel'; +my $small_font = Wx::SystemSettings::GetFont(&Wx::wxSYS_DEFAULT_GUI_FONT); +$small_font->SetPointSize(11); + sub new { my $class = shift; my ($parent) = @_; my $self = $class->SUPER::new($parent, -1, [-1,-1], [-1,-1], &Wx::wxBK_LEFT); + # horizontal sizer $self->{sizer} = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); $self->{sizer}->SetSizeHints($self); $self->SetSizer($self->{sizer}); - $self->{treectrl} = Wx::TreeCtrl->new($self, -1, [-1, -1], [200, -1], &Wx::wxTR_NO_BUTTONS | &Wx::wxTR_HIDE_ROOT | &Wx::wxTR_SINGLE | &Wx::wxTR_NO_LINES); - $self->{sizer}->Add($self->{treectrl}, 0, &Wx::wxEXPAND); + # left vertical sizer + my $left_sizer = Wx::BoxSizer->new(&Wx::wxVERTICAL); + $self->{sizer}->Add($left_sizer, 0, &Wx::wxEXPAND); + my $left_col_width = 200; + + # preset chooser + { + my $box = Wx::StaticBox->new($self, -1, "Presets:", [-1, -1], [$left_col_width, 50]); + $left_sizer->Add($box, 0, &Wx::wxEXPAND | &Wx::wxBOTTOM, 5); + + # choice menu + $self->{presets_choice} = Wx::Choice->new($box, -1, [-1, -1], [-1, -1], []); + $self->{presets_choice}->SetFont($small_font); + + # buttons + $self->{btn_save_preset} = Wx::BitmapButton->new($box, -1, Wx::Bitmap->new("$Slic3r::var/disk.png", &Wx::wxBITMAP_TYPE_PNG)); + $self->{btn_delete_preset} = Wx::BitmapButton->new($box, -1, Wx::Bitmap->new("$Slic3r::var/delete.png", &Wx::wxBITMAP_TYPE_PNG)); + $self->{btn_save_preset}->SetToolTipString("Save current settings"); + $self->{btn_delete_preset}->SetToolTipString("Delete this preset"); + $self->{btn_save_preset}->Disable; + $self->{btn_delete_preset}->Disable; + + my $hsizer = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); + $box->SetSizer($hsizer); + $hsizer->Add($self->{presets_choice}, 1, &Wx::wxRIGHT | &Wx::wxALIGN_CENTER_VERTICAL, 3); + $hsizer->Add($self->{btn_save_preset}, 0, &Wx::wxALIGN_CENTER_VERTICAL); + $hsizer->Add($self->{btn_delete_preset}, 0, &Wx::wxALIGN_CENTER_VERTICAL); + } + + # tree + $self->{treectrl} = Wx::TreeCtrl->new($self, -1, [-1, -1], [$left_col_width, -1], &Wx::wxTR_NO_BUTTONS | &Wx::wxTR_HIDE_ROOT | &Wx::wxTR_SINGLE | &Wx::wxTR_NO_LINES); + $left_sizer->Add($self->{treectrl}, 1, &Wx::wxEXPAND); $self->{icons} = Wx::ImageList->new(16, 16, 1); $self->{treectrl}->AssignImageList($self->{icons}); $self->{iconcount} = -1; - $self->{treectrl}->AddRoot("root"); $self->{pages} = {}; $self->{treectrl}->SetIndent(0); @@ -35,14 +69,57 @@ sub new { $self->{sizer}->Layout; }); + EVT_CHOICE($parent, $self->{presets_choice}, sub { + if (defined $self->{dirty}) { + # TODO: prompt user? + $self->set_dirty(0); + } + + my $i = $self->{presets_choice}->GetSelection; + if ($i == 0) { + Slic3r::Config->load_hash($Slic3r::Defaults, $self->{presets_group}, 1); + $self->{btn_delete_preset}->Disable; + } else { + my $file = "$Slic3r::GUI::datadir/$self->{presets_group}/" . $self->{presets}[$i-1]; + if (!-e $file) { + Slic3r::GUI::show_error($self, "The selected preset does not exist anymore ($file)."); + return; + } + Slic3r::Config->load($file, $self->{presets_group}); + $self->{btn_delete_preset}->Enable; + } + $_->() for @Slic3r::GUI::OptionsGroup::reload_callbacks{@{$Slic3r::Config::Groups{$self->{presets_group}}}}; + $self->set_dirty(0); + }); + + EVT_BUTTON($self, $self->{btn_save_preset}, sub { + my $i = $self->{presets_choice}->GetSelection; + my $default = $i == 0 ? 'Untitled' : $self->{presets}[$i-1]; + $default =~ s/\.ini$//i; + + my $dlg = Slic3r::GUI::SavePresetWindow->new($self, + default => $default, + values => [ map { $_ =~ s/\.ini$//i; $_ } @{$self->{presets}} ], + ); + return unless $dlg->ShowModal; + + my $file = sprintf "$Slic3r::GUI::datadir/$self->{presets_group}/%s.ini", $dlg->get_name; + Slic3r::Config->save($file, $self->{presets_group}); + $self->set_dirty(0); + $self->load_presets; + $self->{presets_choice}->SetSelection(1 + first { $self->{presets}[$_] eq $dlg->get_name . ".ini" } 0 .. $#{$self->{presets}}); + }); + return $self; } -sub AddOptionsPage { +sub add_options_page { my $self = shift; my $title = shift; my $icon = (ref $_[1]) ? undef : shift; - my $page = Slic3r::GUI::Tab::Page->new($self, @_); + my $page = Slic3r::GUI::Tab::Page->new($self, @_, on_change => sub { + $self->set_dirty(1); + }); my $bitmap = $icon ? Wx::Bitmap->new("$Slic3r::var/$icon", &Wx::wxBITMAP_TYPE_PNG) @@ -52,12 +129,55 @@ sub AddOptionsPage { $self->{iconcount}++; } $page->Hide; - $self->{treectrl}->AppendItem($self->{treectrl}->GetRootItem, $title, $self->{iconcount}); + my $itemId = $self->{treectrl}->AppendItem($self->{treectrl}->GetRootItem, $title, $self->{iconcount}); $self->{pages}{$title} = $page; + if (keys %{$self->{pages}} == 1) { + $self->{treectrl}->SelectItem($itemId); + } +} + +sub set_dirty { + my $self = shift; + my ($dirty) = @_; + + my $i = $self->{dirty} // $self->{presets_choice}->GetSelection; #/ + my $text = $self->{presets_choice}->GetString($i); + + if ($dirty) { + $self->{dirty} = $i; + $self->{btn_save_preset}->Enable; + if ($text !~ / \(modified\)$/) { + $self->{presets_choice}->SetString($i, "$text (modified)"); + } + } else { + $self->{dirty} = undef; + $self->{btn_save_preset}->Disable; + $text =~ s/ \(modified\)$//; + $self->{presets_choice}->SetString($i, $text); + } +} + +sub load_presets { + my $self = shift; + my ($group) = @_; + + $self->{presets_group} ||= $group; + $self->{presets} = []; + + opendir my $dh, "$Slic3r::GUI::datadir/$self->{presets_group}" or die "Failed to read directory $Slic3r::GUI::datadir/$self->{presets_group} (errno: $!)\n"; + my @presets = sort grep /\.ini$/i, readdir $dh; + closedir $dh; + + $self->{presets_choice}->Clear; + $self->{presets_choice}->Append("- default -"); + foreach my $preset (@presets) { + push @{$self->{presets}}, $preset; + $preset =~ s/\.ini$//i; + $self->{presets_choice}->Append($preset); + } } package Slic3r::GUI::Tab::Print; - use Wx qw(:sizer :progressdialog); use Wx::Event qw(); use base 'Slic3r::GUI::Tab'; @@ -67,7 +187,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, -1); - $self->AddOptionsPage('Layers and perimeters', 'layers.png', optgroups => [ + $self->add_options_page('Layers and perimeters', 'layers.png', optgroups => [ { title => 'Layer height', options => [qw(layer_height first_layer_height)], @@ -82,14 +202,14 @@ sub new { }, ]); - $self->AddOptionsPage('Infill', 'shading.png', optgroups => [ + $self->add_options_page('Infill', 'shading.png', optgroups => [ { title => 'Infill', options => [qw(fill_density fill_angle fill_pattern solid_fill_pattern infill_every_layers)], }, ]); - $self->AddOptionsPage('Speed', 'time.png', optgroups => [ + $self->add_options_page('Speed', 'time.png', optgroups => [ { title => 'Speed for print moves', options => [qw(perimeter_speed small_perimeter_speed infill_speed solid_infill_speed top_solid_infill_speed bridge_speed)], @@ -104,21 +224,21 @@ sub new { }, ]); - $self->AddOptionsPage('Skirt', 'box.png', optgroups => [ + $self->add_options_page('Skirt', 'box.png', optgroups => [ { title => 'Skirt', options => [qw(skirts skirt_distance skirt_height)], }, ]); - $self->AddOptionsPage('Support material', 'building.png', optgroups => [ + $self->add_options_page('Support material', 'building.png', optgroups => [ { title => 'Support material', options => [qw(support_material support_material_tool)], }, ]); - $self->AddOptionsPage('Notes', 'note.png', optgroups => [ + $self->add_options_page('Notes', 'note.png', optgroups => [ { title => 'Notes', no_labels => 1, @@ -126,7 +246,7 @@ sub new { }, ]); - $self->AddOptionsPage('Output options', 'page_white_go.png', optgroups => [ + $self->add_options_page('Output options', 'page_white_go.png', optgroups => [ { title => 'Sequential printing', options => [qw(complete_objects extruder_clearance_radius extruder_clearance_height)], @@ -142,7 +262,7 @@ sub new { }, ]); - $self->AddOptionsPage('Advanced', 'wrench.png', optgroups => [ + $self->add_options_page('Advanced', 'wrench.png', optgroups => [ { title => 'Extrusion width', label_width => 180, @@ -158,11 +278,12 @@ sub new { }, ]); + $self->load_presets('print'); + return $self; } package Slic3r::GUI::Tab::Filament; - use Wx qw(:sizer :progressdialog); use Wx::Event qw(); use base 'Slic3r::GUI::Tab'; @@ -172,7 +293,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, -1); - $self->AddOptionsPage('Filament', 'spool.png', optgroups => [ + $self->add_options_page('Filament', 'spool.png', optgroups => [ { title => 'Filament', options => [qw(filament_diameter extrusion_multiplier)], @@ -183,7 +304,7 @@ sub new { }, ]); - $self->AddOptionsPage('Cooling', 'hourglass.png', optgroups => [ + $self->add_options_page('Cooling', 'hourglass.png', optgroups => [ { title => 'Enable', options => [qw(cooling)], @@ -199,11 +320,12 @@ sub new { }, ]); + $self->load_presets('filament'); + return $self; } package Slic3r::GUI::Tab::Printer; - use Wx qw(:sizer :progressdialog); use Wx::Event qw(); use base 'Slic3r::GUI::Tab'; @@ -213,7 +335,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, -1); - $self->AddOptionsPage('General', 'printer_empty.png', optgroups => [ + $self->add_options_page('General', 'printer_empty.png', optgroups => [ { title => 'Size and coordinates', options => [qw(bed_size print_center z_offset)], @@ -224,7 +346,7 @@ sub new { }, ]); - $self->AddOptionsPage('Extruder 1', 'funnel.png', optgroups => [ + $self->add_options_page('Extruder 1', 'funnel.png', optgroups => [ { title => 'Size', options => [qw(nozzle_diameter)], @@ -235,7 +357,7 @@ sub new { }, ]); - $self->AddOptionsPage('Custom G-code', 'cog.png', optgroups => [ + $self->add_options_page('Custom G-code', 'cog.png', optgroups => [ { title => 'Start G-code', no_labels => 1, @@ -253,11 +375,12 @@ sub new { }, ]); + $self->load_presets('printer'); + return $self; } package Slic3r::GUI::Tab::Page; - use Wx qw(:sizer :progressdialog); use Wx::Event qw(); use base 'Wx::ScrolledWindow'; @@ -273,7 +396,7 @@ sub new { $self->SetSizer($self->{vsizer}); if ($params{optgroups}) { - $self->append_optgroup(%$_) for @{$params{optgroups}}; + $self->append_optgroup(%$_, on_change => $params{on_change}) for @{$params{optgroups}}; } return $self; @@ -286,4 +409,41 @@ sub append_optgroup { $self->{vsizer}->Add($optgroup, 0, wxEXPAND | wxALL, 5); } +package Slic3r::GUI::SavePresetWindow; +use Wx qw(:sizer); +use Wx::Event qw(EVT_BUTTON); +use base 'Wx::Dialog'; + +sub new { + my $class = shift; + my ($parent, %params) = @_; + my $self = $class->SUPER::new($parent, -1, "Save preset", [-1, -1], [-1, -1]); + + my $text = Wx::StaticText->new($self, -1, "Save settings as:", [-1, -1], [-1, -1]); + my $combo = Wx::ComboBox->new($self, -1, $params{default}, [-1, -1], [-1, -1], $params{values}); + my $buttons = $self->CreateStdDialogButtonSizer(&Wx::wxOK | &Wx::wxCANCEL); + + my $sizer = Wx::BoxSizer->new(wxVERTICAL); + $sizer->Add($text, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 10); + $sizer->Add($combo, 0, wxEXPAND | wxLEFT | wxRIGHT, 10); + $sizer->Add($buttons, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10); + + EVT_BUTTON($self, &Wx::wxID_OK, sub { + if (($self->{chosen_name} = $combo->GetValue) && $self->{chosen_name} =~ /^[a-z0-9 _-]+$/i) { + $self->EndModal(1); + } + }); + + $self->SetSizer($sizer); + $sizer->SetSizeHints($self); + $self->SetReturnCode(0); + + return $self; +} + +sub get_name { + my $self = shift; + return $self->{chosen_name}; +} + 1; diff --git a/var/disk.png b/var/disk.png new file mode 100755 index 0000000000000000000000000000000000000000..99d532e8b1750115952f97302a92d713c0486f97 GIT binary patch literal 620 zcmV-y0+aoTP)~H+MJzd|s z^YP1Hc07G_>)Lgir!F1{Qn4GcTg%?koHo<=1qRN{}nPDolOeI^o4N5I>! zU$N=L=sg~ zDx#dOA*B0N~cqPsWI(^rbbkh)DS0_H_UN0C4l_kvWIm2#Kyy6%BCh z(yIUf003&1xdx>t$*eR2ZvXxT0001Z_R$y3Iju92q*wg58};}zm(OaAH=p|y0002M zh5O5#fxp|~jc?yi@+7$`d4Q6Hl%z;WiWG??NXR{Hx%)pMd~SE0000OQI literal 0 HcmV?d00001 From 0003c093e38ab909792a459816edd30a972f5b51 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Tue, 19 Jun 2012 14:47:02 +0200 Subject: [PATCH 014/106] Reflect external configs in preset menus --- lib/Slic3r/GUI/SkeinPanel.pm | 10 ++++++---- lib/Slic3r/GUI/Tab.pm | 34 ++++++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 38082878a..b529ee98f 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -21,11 +21,12 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, -1); + $self->{options_tabs} = {}; my $tabpanel = Wx::Notebook->new($self, -1, Wx::wxDefaultPosition, Wx::wxDefaultSize, &Wx::wxNB_TOP); $tabpanel->AddPage(Slic3r::GUI::Plater->new($tabpanel), "Plater"); - $tabpanel->AddPage(Slic3r::GUI::Tab::Print->new($tabpanel), "Print settings"); - $tabpanel->AddPage(Slic3r::GUI::Tab::Filament->new($tabpanel), "Filament settings"); - $tabpanel->AddPage(Slic3r::GUI::Tab::Printer->new($tabpanel), "Printer settings"); + $tabpanel->AddPage($self->{options_tabs}{print} = Slic3r::GUI::Tab::Print->new($tabpanel), "Print settings"); + $tabpanel->AddPage($self->{options_tabs}{filament} = Slic3r::GUI::Tab::Filament->new($tabpanel), "Filament settings"); + $tabpanel->AddPage($self->{options_tabs}{printer} = Slic3r::GUI::Tab::Printer->new($tabpanel), "Printer settings"); my $buttons_sizer; { @@ -36,7 +37,7 @@ sub new { $buttons_sizer->Add($slice_button, 0, wxRIGHT, 20); EVT_BUTTON($self, $slice_button, sub { $self->do_slice }); - my $save_button = Wx::Button->new($self, -1, "Save config..."); + my $save_button = Wx::Button->new($self, -1, "Export config..."); $buttons_sizer->Add($save_button, 0, wxRIGHT, 5); EVT_BUTTON($self, $save_button, sub { $self->save_config }); @@ -213,6 +214,7 @@ sub load_config { }; Slic3r::GUI::catch_error($self); $_->() for values %Slic3r::GUI::OptionsGroup::reload_callbacks; + $_->external_config_loaded($file) for values %{$self->{options_tabs}}; } $dlg->Destroy; } diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 3f381ec30..3dbf3a2ff 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -3,6 +3,7 @@ use strict; use warnings; use utf8; +use File::Basename qw(basename); use List::Util qw(first); use Wx qw(:sizer :progressdialog); use Wx::Event qw(EVT_TREE_SEL_CHANGED EVT_CHOICE EVT_BUTTON); @@ -80,7 +81,7 @@ sub new { Slic3r::Config->load_hash($Slic3r::Defaults, $self->{presets_group}, 1); $self->{btn_delete_preset}->Disable; } else { - my $file = "$Slic3r::GUI::datadir/$self->{presets_group}/" . $self->{presets}[$i-1]; + my $file = $self->{presets}[$i-1]; if (!-e $file) { Slic3r::GUI::show_error($self, "The selected preset does not exist anymore ($file)."); return; @@ -94,20 +95,20 @@ sub new { EVT_BUTTON($self, $self->{btn_save_preset}, sub { my $i = $self->{presets_choice}->GetSelection; - my $default = $i == 0 ? 'Untitled' : $self->{presets}[$i-1]; + my $default = $i == 0 ? 'Untitled' : basename($self->{presets}[$i-1]); $default =~ s/\.ini$//i; my $dlg = Slic3r::GUI::SavePresetWindow->new($self, default => $default, - values => [ map { $_ =~ s/\.ini$//i; $_ } @{$self->{presets}} ], + values => [ map { my $filename = basename($_); $filename =~ /^(.*?)\.ini$/i; $1 } @{$self->{presets}} ], ); - return unless $dlg->ShowModal; + return unless $dlg->ShowModal == &Wx::wxID_OK; my $file = sprintf "$Slic3r::GUI::datadir/$self->{presets_group}/%s.ini", $dlg->get_name; Slic3r::Config->save($file, $self->{presets_group}); $self->set_dirty(0); $self->load_presets; - $self->{presets_choice}->SetSelection(1 + first { $self->{presets}[$_] eq $dlg->get_name . ".ini" } 0 .. $#{$self->{presets}}); + $self->{presets_choice}->SetSelection(1 + first { basename($self->{presets}[$_]) eq $dlg->get_name . ".ini" } 0 .. $#{$self->{presets}}); }); return $self; @@ -171,12 +172,30 @@ sub load_presets { $self->{presets_choice}->Clear; $self->{presets_choice}->Append("- default -"); foreach my $preset (@presets) { - push @{$self->{presets}}, $preset; + push @{$self->{presets}}, "$Slic3r::GUI::datadir/$self->{presets_group}/$preset"; $preset =~ s/\.ini$//i; $self->{presets_choice}->Append($preset); } } +sub external_config_loaded { + my $self = shift; + my ($file) = @_; + + # look for the loaded config among the existing menu items + my $i = first { $self->{presets}[$_] eq $file } 0..$#{$self->{presets}}; + if (!$i) { + push @{$self->{presets}}, $file; + my $preset_name = basename($file); # leave the .ini suffix + $self->{presets_choice}->Append($preset_name); + $i = $#{$self->{presets}}; + } + $self->{presets_choice}->SetSelection(1 + $i); + $self->set_dirty(0); + $self->{btn_save_preset}->Enable; + $self->{btn_delete_preset}->Disable; +} + package Slic3r::GUI::Tab::Print; use Wx qw(:sizer :progressdialog); use Wx::Event qw(); @@ -430,13 +449,12 @@ sub new { EVT_BUTTON($self, &Wx::wxID_OK, sub { if (($self->{chosen_name} = $combo->GetValue) && $self->{chosen_name} =~ /^[a-z0-9 _-]+$/i) { - $self->EndModal(1); + $self->EndModal(&Wx::wxID_OK); } }); $self->SetSizer($sizer); $sizer->SetSizeHints($self); - $self->SetReturnCode(0); return $self; } From b910840f76063ef269d4ceed72b4763648e7ed25 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Tue, 19 Jun 2012 17:23:10 +0200 Subject: [PATCH 015/106] Preset shortcuts in the plater tab --- lib/Slic3r/GUI.pm | 5 +++ lib/Slic3r/GUI/Plater.pm | 26 +++++++++-- lib/Slic3r/GUI/SkeinPanel.pm | 16 ++++--- lib/Slic3r/GUI/Tab.pm | 87 +++++++++++++++++++++++------------- 4 files changed, 94 insertions(+), 40 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 277d751f6..88e8fead2 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -16,6 +16,11 @@ use base 'Wx::App'; my $growler; our $datadir; +our $small_font = Wx::SystemSettings::GetFont(&Wx::wxSYS_DEFAULT_GUI_FONT); +$small_font->SetPointSize(11); +our $medium_font = Wx::SystemSettings::GetFont(&Wx::wxSYS_DEFAULT_GUI_FONT); +$medium_font->SetPointSize(12); + sub OnInit { my $self = shift; diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 42611295b..d52dd5df2 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -193,9 +193,29 @@ sub new { $vertical_sizer->Add($list_sizer, 0, wxEXPAND | &Wx::wxBOTTOM, 10); $vertical_sizer->Add($buttons, 0, wxEXPAND); - my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); - $sizer->Add($self->{canvas}, 0, wxALL, 10); - $sizer->Add($vertical_sizer, 1, wxEXPAND | wxALL, 10); + my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL); + $hsizer->Add($self->{canvas}, 0, wxALL, 10); + $hsizer->Add($vertical_sizer, 1, wxEXPAND | wxALL, 10); + + my $presets = Wx::BoxSizer->new(wxHORIZONTAL); + my %group_labels = ( + print => 'Print settings', + filament => 'Filament', + printer => 'Printer', + ); + $self->{preset_choosers} = {}; + for my $group (qw(print filament printer)) { + my $text = Wx::StaticText->new($self, -1, "$group_labels{$group}:", [-1, -1], [-1, -1], wxALIGN_RIGHT); + $text->SetFont($Slic3r::GUI::medium_font); + $self->{preset_choosers}{$group} = Wx::Choice->new($self, -1, [-1, -1], [-1, -1], []); + $presets->Add($text, 1, wxALIGN_RIGHT | wxRIGHT, 4); + $presets->Add($self->{preset_choosers}{$group}, 2, wxRIGHT, 15); + } + + my $sizer = Wx::BoxSizer->new(wxVERTICAL); + $sizer->Add($hsizer, 0, wxEXPAND | wxBOTTOM, 10); + $sizer->Add($presets, 0, wxEXPAND | wxLEFT | wxRIGHT, 20); + $sizer->SetSizeHints($self); $self->SetSizer($sizer); } diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index b529ee98f..2e4c4bced 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -21,13 +21,17 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, -1); - $self->{options_tabs} = {}; my $tabpanel = Wx::Notebook->new($self, -1, Wx::wxDefaultPosition, Wx::wxDefaultSize, &Wx::wxNB_TOP); - $tabpanel->AddPage(Slic3r::GUI::Plater->new($tabpanel), "Plater"); - $tabpanel->AddPage($self->{options_tabs}{print} = Slic3r::GUI::Tab::Print->new($tabpanel), "Print settings"); - $tabpanel->AddPage($self->{options_tabs}{filament} = Slic3r::GUI::Tab::Filament->new($tabpanel), "Filament settings"); - $tabpanel->AddPage($self->{options_tabs}{printer} = Slic3r::GUI::Tab::Printer->new($tabpanel), "Printer settings"); - + $tabpanel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($tabpanel), "Plater"); + $self->{options_tabs} = { + print => Slic3r::GUI::Tab::Print->new ($tabpanel, sync_presets_with => $self->{plater}{preset_choosers}{print}), + filament => Slic3r::GUI::Tab::Filament->new ($tabpanel, sync_presets_with => $self->{plater}{preset_choosers}{filament}), + printer => Slic3r::GUI::Tab::Printer->new ($tabpanel, sync_presets_with => $self->{plater}{preset_choosers}{printer}), + }; + $tabpanel->AddPage($self->{options_tabs}{print}, "Print settings"); + $tabpanel->AddPage($self->{options_tabs}{filament}, "Filament settings"); + $tabpanel->AddPage($self->{options_tabs}{printer}, "Printer settings"); + my $buttons_sizer; { $buttons_sizer = Wx::BoxSizer->new(wxHORIZONTAL); diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 3dbf3a2ff..c653ede49 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -9,14 +9,17 @@ use Wx qw(:sizer :progressdialog); use Wx::Event qw(EVT_TREE_SEL_CHANGED EVT_CHOICE EVT_BUTTON); use base 'Wx::Panel'; -my $small_font = Wx::SystemSettings::GetFont(&Wx::wxSYS_DEFAULT_GUI_FONT); -$small_font->SetPointSize(11); - sub new { my $class = shift; - my ($parent) = @_; + my ($parent, %params) = @_; my $self = $class->SUPER::new($parent, -1, [-1,-1], [-1,-1], &Wx::wxBK_LEFT); + $self->{sync_presets_with} = $params{sync_presets_with}; + EVT_CHOICE($parent, $self->{sync_presets_with}, sub { + $self->{presets_choice}->SetSelection($self->{sync_presets_with}->GetSelection); + $self->on_select_preset; + }); + # horizontal sizer $self->{sizer} = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); $self->{sizer}->SetSizeHints($self); @@ -35,7 +38,7 @@ sub new { # choice menu $self->{presets_choice} = Wx::Choice->new($box, -1, [-1, -1], [-1, -1], []); - $self->{presets_choice}->SetFont($small_font); + $self->{presets_choice}->SetFont($Slic3r::GUI::small_font); # buttons $self->{btn_save_preset} = Wx::BitmapButton->new($box, -1, Wx::Bitmap->new("$Slic3r::var/disk.png", &Wx::wxBITMAP_TYPE_PNG)); @@ -71,26 +74,8 @@ sub new { }); EVT_CHOICE($parent, $self->{presets_choice}, sub { - if (defined $self->{dirty}) { - # TODO: prompt user? - $self->set_dirty(0); - } - - my $i = $self->{presets_choice}->GetSelection; - if ($i == 0) { - Slic3r::Config->load_hash($Slic3r::Defaults, $self->{presets_group}, 1); - $self->{btn_delete_preset}->Disable; - } else { - my $file = $self->{presets}[$i-1]; - if (!-e $file) { - Slic3r::GUI::show_error($self, "The selected preset does not exist anymore ($file)."); - return; - } - Slic3r::Config->load($file, $self->{presets_group}); - $self->{btn_delete_preset}->Enable; - } - $_->() for @Slic3r::GUI::OptionsGroup::reload_callbacks{@{$Slic3r::Config::Groups{$self->{presets_group}}}}; - $self->set_dirty(0); + $self->on_select_preset; + $self->sync_presets; }); EVT_BUTTON($self, $self->{btn_save_preset}, sub { @@ -109,17 +94,44 @@ sub new { $self->set_dirty(0); $self->load_presets; $self->{presets_choice}->SetSelection(1 + first { basename($self->{presets}[$_]) eq $dlg->get_name . ".ini" } 0 .. $#{$self->{presets}}); + $self->sync_presets; }); return $self; } +sub on_select_preset { + my $self = shift; + + if (defined $self->{dirty}) { + # TODO: prompt user? + $self->set_dirty(0); + } + + my $i = $self->{presets_choice}->GetSelection; + if ($i == 0) { + Slic3r::Config->load_hash($Slic3r::Defaults, $self->{presets_group}, 1); + $self->{btn_delete_preset}->Disable; + } else { + my $file = $self->{presets}[$i-1]; + if (!-e $file) { + Slic3r::GUI::show_error($self, "The selected preset does not exist anymore ($file)."); + return; + } + Slic3r::Config->load($file, $self->{presets_group}); + $self->{btn_delete_preset}->Enable; + } + $_->() for @Slic3r::GUI::OptionsGroup::reload_callbacks{@{$Slic3r::Config::Groups{$self->{presets_group}}}}; + $self->set_dirty(0); +} + sub add_options_page { my $self = shift; my $title = shift; my $icon = (ref $_[1]) ? undef : shift; my $page = Slic3r::GUI::Tab::Page->new($self, @_, on_change => sub { $self->set_dirty(1); + $self->sync_presets; }); my $bitmap = $icon @@ -156,6 +168,7 @@ sub set_dirty { $text =~ s/ \(modified\)$//; $self->{presets_choice}->SetString($i, $text); } + $self->sync_presets; } sub load_presets { @@ -176,6 +189,7 @@ sub load_presets { $preset =~ s/\.ini$//i; $self->{presets_choice}->Append($preset); } + $self->sync_presets; } sub external_config_loaded { @@ -194,6 +208,17 @@ sub external_config_loaded { $self->set_dirty(0); $self->{btn_save_preset}->Enable; $self->{btn_delete_preset}->Disable; + $self->sync_presets; +} + +sub sync_presets { + my $self = shift; + return unless $self->{sync_presets_with}; + $self->{sync_presets_with}->Clear; + foreach my $item ($self->{presets_choice}->GetStrings) { + $self->{sync_presets_with}->Append($item); + } + $self->{sync_presets_with}->SetSelection($self->{presets_choice}->GetSelection); } package Slic3r::GUI::Tab::Print; @@ -203,8 +228,8 @@ use base 'Slic3r::GUI::Tab'; sub new { my $class = shift; - my ($parent) = @_; - my $self = $class->SUPER::new($parent, -1); + my ($parent, %params) = @_; + my $self = $class->SUPER::new($parent, %params); $self->add_options_page('Layers and perimeters', 'layers.png', optgroups => [ { @@ -309,8 +334,8 @@ use base 'Slic3r::GUI::Tab'; sub new { my $class = shift; - my ($parent) = @_; - my $self = $class->SUPER::new($parent, -1); + my ($parent, %params) = @_; + my $self = $class->SUPER::new($parent, %params); $self->add_options_page('Filament', 'spool.png', optgroups => [ { @@ -351,8 +376,8 @@ use base 'Slic3r::GUI::Tab'; sub new { my $class = shift; - my ($parent) = @_; - my $self = $class->SUPER::new($parent, -1); + my ($parent, %params) = @_; + my $self = $class->SUPER::new($parent, %params); $self->add_options_page('General', 'printer_empty.png', optgroups => [ { From 0ef8da42a6b56e7c28ac06d408f1cb11288a463d Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Tue, 19 Jun 2012 17:47:48 +0200 Subject: [PATCH 016/106] Preset deletion --- lib/Slic3r/GUI/Tab.pm | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index c653ede49..9562eba05 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -97,6 +97,21 @@ sub new { $self->sync_presets; }); + EVT_BUTTON($self, $self->{btn_delete_preset}, sub { + my $i = $self->{presets_choice}->GetSelection; + return if $i == 0; # this shouldn't happen but let's trap it anyway + my $res = Wx::MessageDialog->new($self, "Are you sure you want to delete the selected preset?", 'Delete Preset', &Wx::wxYES_NO | &Wx::wxNO_DEFAULT | &Wx::wxICON_QUESTION)->ShowModal; + return unless $res == &Wx::wxID_YES; + if (-e $self->{presets}[$i-1]) { + unlink $self->{presets}[$i-1]; + } + splice @{$self->{presets}}, $i-1, 1; + $self->{presets_choice}->Delete($i); + $self->{presets_choice}->SetSelection(0); + $self->on_select_preset; + $self->sync_presets; + }); + return $self; } From a664709b3139d62a8f238af8c67864f3ab79ae29 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Tue, 19 Jun 2012 18:11:51 +0200 Subject: [PATCH 017/106] Remember last presets --- lib/Slic3r.pm | 1 + lib/Slic3r/Config.pm | 33 +++++++++++++++++++++++++++++---- lib/Slic3r/GUI.pm | 6 ++++++ lib/Slic3r/GUI/Tab.pm | 13 ++++++++++++- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index fb6112df0..dd2dbef18 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -169,6 +169,7 @@ our $extruder_clearance_radius = 20; # mm our $extruder_clearance_height = 20; # mm our $Defaults = Slic3r::Config->current; +our $Settings = { presets => {} }; # application settings sub parallelize { my %params = @_; diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 48ee6de43..d8f4fd0a3 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -655,20 +655,41 @@ sub deserialize { : set($opt_key, $value); } +sub write_ini { + my $class = shift; + my ($file, $ini) = @_; + + open my $fh, '>', $file; + binmode $fh, ':utf8'; + foreach my $category (sort keys %$ini) { + printf $fh "\n[%s]\n", $category if $category ne '_'; + foreach my $key (sort keys %{$ini->{$category}}) { + printf $fh "%s = %s\n", $key, $ini->{$category}{$key}; + } + } + close $fh; +} + sub save { my $class = shift; my ($file, $group) = @_; - open my $fh, '>', $file; - binmode $fh, ':utf8'; + my $ini = { _ => {} }; foreach my $opt (sort keys %$Options) { next if defined $group && not ($opt ~~ @{$Groups{$group}}); next if $Options->{$opt}{gui_only}; my $value = get($opt); $value = $Options->{$opt}{serialize}->($value) if $Options->{$opt}{serialize}; - printf $fh "%s = %s\n", $opt, $value; + $ini->{_}{$opt} = $value; } - close $fh; + $class->write_ini($file, $ini); +} + +sub save_settings { + my $class = shift; + my ($file) = @_; + + $class->write_ini($file, $Slic3r::Settings); } sub setenv { @@ -701,6 +722,10 @@ sub read_ini { next if /^\s+/; next if /^$/; next if /^\s*#/; + if (/^\[(\w+)\]$/) { + $category = $1; + next; + } /^(\w+) = (.*)/ or die "Unreadable configuration file (invalid data at line $.)\n"; $ini->{$category}{$1} = $2; } diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 88e8fead2..9f453622c 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -42,6 +42,12 @@ sub OnInit { unless -d $_; } + # load settings + if (-f "$datadir/slic3r.ini") { + my $ini = eval { Slic3r::Config->read_ini("$datadir/slic3r.ini") }; + $Slic3r::Settings = $ini if $ini; + } + # application frame Wx::Image::AddHandler(Wx::PNGHandler->new); my $frame = Wx::Frame->new(undef, -1, 'Slic3r', [-1, -1], [760,500], wxDEFAULT_FRAME_STYLE); diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 9562eba05..60aac59a7 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -94,6 +94,7 @@ sub new { $self->set_dirty(0); $self->load_presets; $self->{presets_choice}->SetSelection(1 + first { basename($self->{presets}[$_]) eq $dlg->get_name . ".ini" } 0 .. $#{$self->{presets}}); + $self->on_select_preset; $self->sync_presets; }); @@ -124,11 +125,12 @@ sub on_select_preset { } my $i = $self->{presets_choice}->GetSelection; + my $file; if ($i == 0) { Slic3r::Config->load_hash($Slic3r::Defaults, $self->{presets_group}, 1); $self->{btn_delete_preset}->Disable; } else { - my $file = $self->{presets}[$i-1]; + $file = $self->{presets}[$i-1]; if (!-e $file) { Slic3r::GUI::show_error($self, "The selected preset does not exist anymore ($file)."); return; @@ -138,6 +140,8 @@ sub on_select_preset { } $_->() for @Slic3r::GUI::OptionsGroup::reload_callbacks{@{$Slic3r::Config::Groups{$self->{presets_group}}}}; $self->set_dirty(0); + $Slic3r::Settings->{presets}{$self->{presets_group}} = $file ? basename($file) : ''; + Slic3r::Config->save_settings("$Slic3r::GUI::datadir/slic3r.ini"); } sub add_options_page { @@ -204,6 +208,13 @@ sub load_presets { $preset =~ s/\.ini$//i; $self->{presets_choice}->Append($preset); } + { + my $i = first { basename($self->{presets}[$_]) eq ($Slic3r::Settings->{presets}{$self->{presets_group}} || '') } 0 .. $#{$self->{presets}}; + if (defined $i) { + $self->{presets_choice}->SetSelection($i + 1); + $self->on_select_preset; + } + } $self->sync_presets; } From 69c3f12c604f499a5e65fba284dbafb1343f132e Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 20 Jun 2012 17:08:38 +0200 Subject: [PATCH 018/106] Workaround for GTK issues --- lib/Slic3r/GUI/Tab.pm | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 60aac59a7..5e64ab217 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -33,23 +33,26 @@ sub new { # preset chooser { - my $box = Wx::StaticBox->new($self, -1, "Presets:", [-1, -1], [$left_col_width, 50]); - $left_sizer->Add($box, 0, &Wx::wxEXPAND | &Wx::wxBOTTOM, 5); # choice menu - $self->{presets_choice} = Wx::Choice->new($box, -1, [-1, -1], [-1, -1], []); + $self->{presets_choice} = Wx::Choice->new($self, -1, [-1, -1], [-1, -1], []); $self->{presets_choice}->SetFont($Slic3r::GUI::small_font); # buttons - $self->{btn_save_preset} = Wx::BitmapButton->new($box, -1, Wx::Bitmap->new("$Slic3r::var/disk.png", &Wx::wxBITMAP_TYPE_PNG)); - $self->{btn_delete_preset} = Wx::BitmapButton->new($box, -1, Wx::Bitmap->new("$Slic3r::var/delete.png", &Wx::wxBITMAP_TYPE_PNG)); + $self->{btn_save_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/disk.png", &Wx::wxBITMAP_TYPE_PNG)); + $self->{btn_delete_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/delete.png", &Wx::wxBITMAP_TYPE_PNG)); $self->{btn_save_preset}->SetToolTipString("Save current settings"); $self->{btn_delete_preset}->SetToolTipString("Delete this preset"); $self->{btn_save_preset}->Disable; $self->{btn_delete_preset}->Disable; + ### These cause GTK warnings: + ###my $box = Wx::StaticBox->new($self, -1, "Presets:", [-1, -1], [$left_col_width, 50]); + ###my $hsizer = Wx::StaticBoxSizer->new($box, &Wx::wxHORIZONTAL); + my $hsizer = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); - $box->SetSizer($hsizer); + + $left_sizer->Add($hsizer, 0, &Wx::wxEXPAND | &Wx::wxBOTTOM, 5); $hsizer->Add($self->{presets_choice}, 1, &Wx::wxRIGHT | &Wx::wxALIGN_CENTER_VERTICAL, 3); $hsizer->Add($self->{btn_save_preset}, 0, &Wx::wxALIGN_CENTER_VERTICAL); $hsizer->Add($self->{btn_delete_preset}, 0, &Wx::wxALIGN_CENTER_VERTICAL); From 8d465aca340bb3364069e01ff4ca1d2f5a3d0c89 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 20 Jun 2012 17:17:07 +0200 Subject: [PATCH 019/106] A couple fixes for GTK --- lib/Slic3r/GUI.pm | 2 +- lib/Slic3r/GUI/Tab.pm | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 9f453622c..34e8cd1ba 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -50,7 +50,7 @@ sub OnInit { # application frame Wx::Image::AddHandler(Wx::PNGHandler->new); - my $frame = Wx::Frame->new(undef, -1, 'Slic3r', [-1, -1], [760,500], wxDEFAULT_FRAME_STYLE); + my $frame = Wx::Frame->new(undef, -1, 'Slic3r', [-1, -1], [760,520], wxDEFAULT_FRAME_STYLE); $frame->SetIcon(Wx::Icon->new("$Slic3r::var/Slic3r_128px.png", &Wx::wxBITMAP_TYPE_PNG) ); my $panel = Slic3r::GUI::SkeinPanel->new($frame); diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 5e64ab217..2bcafa562 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -213,10 +213,8 @@ sub load_presets { } { my $i = first { basename($self->{presets}[$_]) eq ($Slic3r::Settings->{presets}{$self->{presets_group}} || '') } 0 .. $#{$self->{presets}}; - if (defined $i) { - $self->{presets_choice}->SetSelection($i + 1); - $self->on_select_preset; - } + $self->{presets_choice}->SetSelection(defined $i ? $i + 1 : 0); + $self->on_select_preset; } $self->sync_presets; } From ac59297e39c12c6c754ea8471d2fe8c0f1b8bb06 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 20 Jun 2012 21:43:06 +0200 Subject: [PATCH 020/106] Fixes for Windows --- lib/Slic3r/GUI.pm | 2 +- lib/Slic3r/GUI/OptionsGroup.pm | 1 - lib/Slic3r/GUI/Plater.pm | 5 ++--- lib/Slic3r/GUI/Tab.pm | 2 ++ 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 34e8cd1ba..ab0f83049 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -17,7 +17,7 @@ my $growler; our $datadir; our $small_font = Wx::SystemSettings::GetFont(&Wx::wxSYS_DEFAULT_GUI_FONT); -$small_font->SetPointSize(11); +$small_font->SetPointSize(11) if !&Wx::wxMSW; our $medium_font = Wx::SystemSettings::GetFont(&Wx::wxSYS_DEFAULT_GUI_FONT); $medium_font->SetPointSize(12); diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index c0c1d22d7..acfb6b8cb 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -26,7 +26,6 @@ sub new { my $bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); $bold_font->SetWeight(&Wx::wxFONTWEIGHT_BOLD); my $sidetext_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); - $sidetext_font->SetPointSize(12); my $onChange = $p{on_change} || sub {}; diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index d52dd5df2..fdc6315ea 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -206,10 +206,9 @@ sub new { $self->{preset_choosers} = {}; for my $group (qw(print filament printer)) { my $text = Wx::StaticText->new($self, -1, "$group_labels{$group}:", [-1, -1], [-1, -1], wxALIGN_RIGHT); - $text->SetFont($Slic3r::GUI::medium_font); $self->{preset_choosers}{$group} = Wx::Choice->new($self, -1, [-1, -1], [-1, -1], []); - $presets->Add($text, 1, wxALIGN_RIGHT | wxRIGHT, 4); - $presets->Add($self->{preset_choosers}{$group}, 2, wxRIGHT, 15); + $presets->Add($text, 1, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxRIGHT, 4); + $presets->Add($self->{preset_choosers}{$group}, 2, wxALIGN_CENTER_VERTICAL | wxRIGHT, 15); } my $sizer = Wx::BoxSizer->new(wxVERTICAL); diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 2bcafa562..855eb0dc2 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -183,12 +183,14 @@ sub set_dirty { $self->{btn_save_preset}->Enable; if ($text !~ / \(modified\)$/) { $self->{presets_choice}->SetString($i, "$text (modified)"); + $self->{presets_choice}->SetSelection($i); # wxMSW needs this after every SetString() } } else { $self->{dirty} = undef; $self->{btn_save_preset}->Disable; $text =~ s/ \(modified\)$//; $self->{presets_choice}->SetString($i, $text); + $self->{presets_choice}->SetSelection($i); # wxMSW needs this after every SetString() } $self->sync_presets; } From 81a5267cc714e8a47ac20f7e5ebc911bdad28890 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 20 Jun 2012 22:50:38 +0200 Subject: [PATCH 021/106] Fix widths on plater --- lib/Slic3r/GUI/Plater.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index fdc6315ea..d004c13b5 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -206,9 +206,9 @@ sub new { $self->{preset_choosers} = {}; for my $group (qw(print filament printer)) { my $text = Wx::StaticText->new($self, -1, "$group_labels{$group}:", [-1, -1], [-1, -1], wxALIGN_RIGHT); - $self->{preset_choosers}{$group} = Wx::Choice->new($self, -1, [-1, -1], [-1, -1], []); - $presets->Add($text, 1, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxRIGHT, 4); - $presets->Add($self->{preset_choosers}{$group}, 2, wxALIGN_CENTER_VERTICAL | wxRIGHT, 15); + $self->{preset_choosers}{$group} = Wx::Choice->new($self, -1, [-1, -1], [150, -1], []); + $presets->Add($text, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxRIGHT, 4); + $presets->Add($self->{preset_choosers}{$group}, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 15); } my $sizer = Wx::BoxSizer->new(wxVERTICAL); From f69903573a0475a18a73ac1105484d9cfec1481f Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Thu, 21 Jun 2012 12:20:18 +0200 Subject: [PATCH 022/106] Always enable preset save button. --- lib/Slic3r/GUI/Tab.pm | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 855eb0dc2..1388d928d 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -43,7 +43,6 @@ sub new { $self->{btn_delete_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/delete.png", &Wx::wxBITMAP_TYPE_PNG)); $self->{btn_save_preset}->SetToolTipString("Save current settings"); $self->{btn_delete_preset}->SetToolTipString("Delete this preset"); - $self->{btn_save_preset}->Disable; $self->{btn_delete_preset}->Disable; ### These cause GTK warnings: @@ -180,14 +179,12 @@ sub set_dirty { if ($dirty) { $self->{dirty} = $i; - $self->{btn_save_preset}->Enable; if ($text !~ / \(modified\)$/) { $self->{presets_choice}->SetString($i, "$text (modified)"); $self->{presets_choice}->SetSelection($i); # wxMSW needs this after every SetString() } } else { $self->{dirty} = undef; - $self->{btn_save_preset}->Disable; $text =~ s/ \(modified\)$//; $self->{presets_choice}->SetString($i, $text); $self->{presets_choice}->SetSelection($i); # wxMSW needs this after every SetString() @@ -235,7 +232,6 @@ sub external_config_loaded { } $self->{presets_choice}->SetSelection(1 + $i); $self->set_dirty(0); - $self->{btn_save_preset}->Enable; $self->{btn_delete_preset}->Disable; $self->sync_presets; } From c4f8c36ecca7e56cbd5f497cf528030609af3b8d Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Thu, 21 Jun 2012 13:01:59 +0200 Subject: [PATCH 023/106] Handle ENTER key in Slic3r::GUI::SavePresetWindow --- lib/Slic3r/GUI/Tab.pm | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 1388d928d..2401afdf2 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -480,7 +480,7 @@ sub append_optgroup { package Slic3r::GUI::SavePresetWindow; use Wx qw(:sizer); -use Wx::Event qw(EVT_BUTTON); +use Wx::Event qw(EVT_BUTTON EVT_TEXT_ENTER); use base 'Wx::Dialog'; sub new { @@ -489,19 +489,17 @@ sub new { my $self = $class->SUPER::new($parent, -1, "Save preset", [-1, -1], [-1, -1]); my $text = Wx::StaticText->new($self, -1, "Save settings as:", [-1, -1], [-1, -1]); - my $combo = Wx::ComboBox->new($self, -1, $params{default}, [-1, -1], [-1, -1], $params{values}); + $self->{combo} = Wx::ComboBox->new($self, -1, $params{default}, [-1, -1], [-1, -1], $params{values}, + &Wx::wxTE_PROCESS_ENTER); my $buttons = $self->CreateStdDialogButtonSizer(&Wx::wxOK | &Wx::wxCANCEL); my $sizer = Wx::BoxSizer->new(wxVERTICAL); $sizer->Add($text, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 10); - $sizer->Add($combo, 0, wxEXPAND | wxLEFT | wxRIGHT, 10); + $sizer->Add($self->{combo}, 0, wxEXPAND | wxLEFT | wxRIGHT, 10); $sizer->Add($buttons, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10); - EVT_BUTTON($self, &Wx::wxID_OK, sub { - if (($self->{chosen_name} = $combo->GetValue) && $self->{chosen_name} =~ /^[a-z0-9 _-]+$/i) { - $self->EndModal(&Wx::wxID_OK); - } - }); + EVT_BUTTON($self, &Wx::wxID_OK, \&accept); + EVT_TEXT_ENTER($self, $self->{combo}, \&accept); $self->SetSizer($sizer); $sizer->SetSizeHints($self); @@ -509,6 +507,14 @@ sub new { return $self; } +sub accept { + my ($self, $event) = @_; + + if (($self->{chosen_name} = $self->{combo}->GetValue) && $self->{chosen_name} =~ /^[a-z0-9 _-]+$/i) { + $self->EndModal(&Wx::wxID_OK); + } +} + sub get_name { my $self = shift; return $self->{chosen_name}; From f2617bffda60a945fbf008c15cd69887cb2a56f4 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Thu, 21 Jun 2012 13:21:42 +0200 Subject: [PATCH 024/106] Add debug information for locating a users data directory --- lib/Slic3r/GUI.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index ab0f83049..84754e23f 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -37,6 +37,7 @@ sub OnInit { # locate or create data directory $datadir = Wx::StandardPaths::Get->GetUserDataDir; + Slic3r::debugf "Data directory: %s\n", $datadir; for ($datadir, "$datadir/print", "$datadir/filament", "$datadir/printer") { mkdir or $self->fatal_error("Slic3r was unable to create its data directory at $_ (errno: $!).") unless -d $_; From 60ff9938ef54c5ad658872676e6f7dbb17289243 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Thu, 21 Jun 2012 13:28:55 +0200 Subject: [PATCH 025/106] - Add Slic3r::Config::get_raw() for getting the raw, uncalculated values. - Use get_raw() for saving and displaying options in GUI Forward-ported from 4031cf26b41fb03a97b827561ceeac476e87c2f7 --- lib/Slic3r/Config.pm | 16 ++++++++++++---- lib/Slic3r/GUI/OptionsGroup.pm | 14 +++++++------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index d8f4fd0a3..cb956cfee 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -632,6 +632,14 @@ sub get { return $value; } +sub get_raw { + my $class = @_ == 2 ? shift : undef; + my ($opt_key) = @_; + no strict 'refs'; + my $value = ${"Slic3r::$opt_key"}; + return $value; +} + sub set { my $class = @_ == 3 ? shift : undef; my ($opt_key, $value) = @_; @@ -643,8 +651,8 @@ sub serialize { my $class = @_ == 2 ? shift : undef; my ($opt_key) = @_; return $Options->{$opt_key}{serialize} - ? $Options->{$opt_key}{serialize}->(get($opt_key)) - : get($opt_key); + ? $Options->{$opt_key}{serialize}->(get_raw($opt_key)) + : get_raw($opt_key); } sub deserialize { @@ -678,7 +686,7 @@ sub save { foreach my $opt (sort keys %$Options) { next if defined $group && not ($opt ~~ @{$Groups{$group}}); next if $Options->{$opt}{gui_only}; - my $value = get($opt); + my $value = get_raw($opt); $value = $Options->{$opt}{serialize}->($value) if $Options->{$opt}{serialize}; $ini->{_}{$opt} = $value; } @@ -704,7 +712,7 @@ sub setenv { sub current { my $class = shift; - return { map +($_ => get($_)), sort keys %$Options }; + return { map +($_ => get_raw($_)), sort keys %$Options }; } sub read_ini { diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index acfb6b8cb..a26e27a35 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -48,7 +48,7 @@ sub new { $style = &Wx::wxTE_MULTILINE if $opt->{multiline}; my $size = Wx::Size->new($opt->{width} || -1, $opt->{height} || -1); - my ($get, $set) = $opt->{type} eq 's@' ? qw(serialize deserialize) : qw(get set); + my ($get, $set) = $opt->{type} eq 's@' ? qw(serialize deserialize) : qw(get_raw set); if ($opt->{type} eq 'i') { my $value = Slic3r::Config->$get($opt_key); @@ -61,13 +61,13 @@ sub new { $reload_callbacks{$opt_key} = sub { $field->SetValue(Slic3r::Config->$get($opt_key)) }; } elsif ($opt->{type} eq 'bool') { $field = Wx::CheckBox->new($parent, -1, ""); - $field->SetValue(Slic3r::Config->get($opt_key)); + $field->SetValue(Slic3r::Config->get_raw($opt_key)); EVT_CHECKBOX($parent, $field, sub { Slic3r::Config->set($opt_key, $field->GetValue); $onChange->($opt_key) }); - $reload_callbacks{$opt_key} = sub { $field->SetValue(Slic3r::Config->get($opt_key)) }; + $reload_callbacks{$opt_key} = sub { $field->SetValue(Slic3r::Config->get_raw($opt_key)) }; } elsif ($opt->{type} eq 'point') { $field = Wx::BoxSizer->new(wxHORIZONTAL); my $field_size = Wx::Size->new(40, -1); - my $value = Slic3r::Config->get($opt_key); + my $value = Slic3r::Config->get_raw($opt_key); my @items = ( Wx::StaticText->new($parent, -1, "x:"), my $x_field = Wx::TextCtrl->new($parent, -1, $value->[0], Wx::wxDefaultPosition, $field_size), @@ -80,14 +80,14 @@ sub new { } my $set_value = sub { my ($i, $value) = @_; - my $val = Slic3r::Config->get($opt_key); + my $val = Slic3r::Config->get_raw($opt_key); $val->[$i] = $value; Slic3r::Config->set($opt_key, $val); }; EVT_TEXT($parent, $x_field, sub { $set_value->(0, $x_field->GetValue); $onChange->($opt_key) }); EVT_TEXT($parent, $y_field, sub { $set_value->(1, $y_field->GetValue); $onChange->($opt_key) }); $reload_callbacks{$opt_key} = sub { - my $value = Slic3r::Config->get($opt_key); + my $value = Slic3r::Config->get_raw($opt_key); $x_field->SetValue($value->[0]); $y_field->SetValue($value->[1]); }; @@ -99,7 +99,7 @@ sub new { $onChange->($opt_key); }); $reload_callbacks{$opt_key} = sub { - my $value = Slic3r::Config->get($opt_key); + my $value = Slic3r::Config->get_raw($opt_key); $field->SetSelection(grep $opt->{values}[$_] eq $value, 0..$#{$opt->{values}}); }; $reload_callbacks{$opt_key}->(); From b59040f95495519f4b8f98f71483673a72b8d1cc Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Thu, 21 Jun 2012 22:50:40 +0200 Subject: [PATCH 026/106] Rename 'Save Config' menu item to 'Export Config' to match button label. --- lib/Slic3r/GUI.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 84754e23f..f4e08f414 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -63,7 +63,7 @@ sub OnInit { # File menu my $fileMenu = Wx::Menu->new; { - $fileMenu->Append(1, "Save Config…"); + $fileMenu->Append(1, "Export Config…"); $fileMenu->Append(2, "Open Config…"); $fileMenu->AppendSeparator(); $fileMenu->Append(3, "Slice…"); From 1409cbf7f77bbf8dd7229fb078f4d5304914e85f Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sat, 23 Jun 2012 17:38:19 +0200 Subject: [PATCH 027/106] Add Slic3r::GUI::Tab::is_dirty() --- lib/Slic3r/GUI/Tab.pm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 2401afdf2..10abcd1f3 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -192,6 +192,11 @@ sub set_dirty { $self->sync_presets; } +sub is_dirty { + my $self = shift; + return $self->{dirty}; +} + sub load_presets { my $self = shift; my ($group) = @_; From d0588c2ef805b735c77bd8f468dbbd03af6953ad Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sat, 23 Jun 2012 17:39:20 +0200 Subject: [PATCH 028/106] Ask for confirmation before closing if there are unsaved presets. --- lib/Slic3r/GUI.pm | 26 ++++++++++++++++---------- lib/Slic3r/GUI/SkeinPanel.pm | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index f4e08f414..c1d5c2d59 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -10,7 +10,7 @@ use Slic3r::GUI::SkeinPanel; use Slic3r::GUI::Tab; use Wx 0.9901 qw(:sizer :frame wxID_EXIT wxID_ABOUT); -use Wx::Event qw(EVT_MENU); +use Wx::Event qw(EVT_MENU EVT_CLOSE); use base 'Wx::App'; my $growler; @@ -53,8 +53,7 @@ sub OnInit { Wx::Image::AddHandler(Wx::PNGHandler->new); my $frame = Wx::Frame->new(undef, -1, 'Slic3r', [-1, -1], [760,520], wxDEFAULT_FRAME_STYLE); $frame->SetIcon(Wx::Icon->new("$Slic3r::var/Slic3r_128px.png", &Wx::wxBITMAP_TYPE_PNG) ); - my $panel = Slic3r::GUI::SkeinPanel->new($frame); - + $frame->{skeinpanel} = Slic3r::GUI::SkeinPanel->new($frame); # status bar $frame->{statusbar} = Slic3r::GUI::ProgressStatusBar->new($frame, -1); @@ -72,13 +71,13 @@ sub OnInit { $fileMenu->Append(6, "Export SVG…"); $fileMenu->AppendSeparator(); $fileMenu->Append(wxID_EXIT, "&Quit"); - EVT_MENU($frame, 1, sub { $panel->save_config }); - EVT_MENU($frame, 2, sub { $panel->load_config }); - EVT_MENU($frame, 3, sub { $panel->do_slice }); - EVT_MENU($frame, 4, sub { $panel->do_slice(reslice => 1) }); - EVT_MENU($frame, 5, sub { $panel->do_slice(save_as => 1) }); - EVT_MENU($frame, 6, sub { $panel->do_slice(save_as => 1, export_svg => 1) }); - EVT_MENU($frame, wxID_EXIT, sub {$_[0]->Close(1)}); + EVT_MENU($frame, 1, sub { $frame->{skeinpanel}->save_config }); + EVT_MENU($frame, 2, sub { $frame->{skeinpanel}->load_config }); + EVT_MENU($frame, 3, sub { $frame->{skeinpanel}->do_slice }); + EVT_MENU($frame, 4, sub { $frame->{skeinpanel}->do_slice(reslice => 1) }); + EVT_MENU($frame, 5, sub { $frame->{skeinpanel}->do_slice(save_as => 1) }); + EVT_MENU($frame, 6, sub { $frame->{skeinpanel}->do_slice(save_as => 1, export_svg => 1) }); + EVT_MENU($frame, wxID_EXIT, sub {$_[0]->Close(0)}); } # Help menu @@ -98,6 +97,8 @@ sub OnInit { $frame->SetMenuBar($menubar); } + EVT_CLOSE($frame, \&on_close); + $frame->SetMinSize($frame->GetSize); $frame->Show; $frame->Layout; @@ -117,6 +118,11 @@ sub About { Wx::AboutBox($info); } +sub on_close { + my ($frame, $event) = @_; + $event->CanVeto ? $event->Skip($frame->{skeinpanel}->on_close) : $event->Skip(1); +} + sub catch_error { my ($self, $cb, $message_dialog) = @_; if (my $err = $@) { diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 2e4c4bced..f67d64f99 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -223,4 +223,22 @@ sub load_config { $dlg->Destroy; } +sub on_close { + my $self = shift; + + my @dirty; + foreach (keys %{$self->{options_tabs}}) { + push (@dirty, $_) if $self->{options_tabs}{$_}->is_dirty; + } + + if (@dirty) { + my $titles = join ', ', @dirty; + my $confirm = Wx::MessageDialog->new($self, "You have unsaved changes ($titles). Exit anyway?", + 'Unsaved Presets', wxICON_QUESTION | wxOK | wxCANCEL); + return ($confirm->ShowModal == wxID_OK); + } + + return 1; +} + 1; From 30d88d7ffa3aeeb7a19a468239dfa8a538798e7a Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 24 Jun 2012 10:20:42 +0200 Subject: [PATCH 029/106] Store the tab name within each tab for reuse --- lib/Slic3r/GUI/SkeinPanel.pm | 6 +++--- lib/Slic3r/GUI/Tab.pm | 15 +++++++++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index f67d64f99..217fd3ae5 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -28,9 +28,9 @@ sub new { filament => Slic3r::GUI::Tab::Filament->new ($tabpanel, sync_presets_with => $self->{plater}{preset_choosers}{filament}), printer => Slic3r::GUI::Tab::Printer->new ($tabpanel, sync_presets_with => $self->{plater}{preset_choosers}{printer}), }; - $tabpanel->AddPage($self->{options_tabs}{print}, "Print settings"); - $tabpanel->AddPage($self->{options_tabs}{filament}, "Filament settings"); - $tabpanel->AddPage($self->{options_tabs}{printer}, "Printer settings"); + $tabpanel->AddPage($self->{options_tabs}{print}, $self->{options_tabs}{print}->title); + $tabpanel->AddPage($self->{options_tabs}{filament}, $self->{options_tabs}{filament}->title); + $tabpanel->AddPage($self->{options_tabs}{printer}, $self->{options_tabs}{printer}->title); my $buttons_sizer; { diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 10abcd1f3..e00a8387f 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -11,9 +11,11 @@ use base 'Wx::Panel'; sub new { my $class = shift; - my ($parent, %params) = @_; + my ($parent, $title, %params) = @_; my $self = $class->SUPER::new($parent, -1, [-1,-1], [-1,-1], &Wx::wxBK_LEFT); + $self->{title} = $title; + $self->{sync_presets_with} = $params{sync_presets_with}; EVT_CHOICE($parent, $self->{sync_presets_with}, sub { $self->{presets_choice}->SetSelection($self->{sync_presets_with}->GetSelection); @@ -197,6 +199,11 @@ sub is_dirty { return $self->{dirty}; } +sub title { + my $self = shift; + return $self->{title} +} + sub load_presets { my $self = shift; my ($group) = @_; @@ -259,7 +266,7 @@ use base 'Slic3r::GUI::Tab'; sub new { my $class = shift; my ($parent, %params) = @_; - my $self = $class->SUPER::new($parent, %params); + my $self = $class->SUPER::new($parent, 'Print Settings', %params); $self->add_options_page('Layers and perimeters', 'layers.png', optgroups => [ { @@ -365,7 +372,7 @@ use base 'Slic3r::GUI::Tab'; sub new { my $class = shift; my ($parent, %params) = @_; - my $self = $class->SUPER::new($parent, %params); + my $self = $class->SUPER::new($parent, 'Filament Settings', %params); $self->add_options_page('Filament', 'spool.png', optgroups => [ { @@ -407,7 +414,7 @@ use base 'Slic3r::GUI::Tab'; sub new { my $class = shift; my ($parent, %params) = @_; - my $self = $class->SUPER::new($parent, %params); + my $self = $class->SUPER::new($parent, 'Printer Settings', %params); $self->add_options_page('General', 'printer_empty.png', optgroups => [ { From f07ad630c4d0f40b490b70ebcb1ea516f26d203f Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 24 Jun 2012 10:22:44 +0200 Subject: [PATCH 030/106] Use tab title in close confirmation dialog --- lib/Slic3r/GUI/SkeinPanel.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 217fd3ae5..907e9c0d9 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -227,8 +227,8 @@ sub on_close { my $self = shift; my @dirty; - foreach (keys %{$self->{options_tabs}}) { - push (@dirty, $_) if $self->{options_tabs}{$_}->is_dirty; + foreach (values %{$self->{options_tabs}}) { + push (@dirty, $_->title) if $_->is_dirty; } if (@dirty) { From e024c31ce54434b7c17fd8dd4a0c4f1fd57d771e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 24 Jun 2012 10:31:00 +0200 Subject: [PATCH 031/106] Use settings title to make save dialogs and tooltips more clear --- lib/Slic3r/GUI/Tab.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index e00a8387f..2633097b5 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -43,7 +43,7 @@ sub new { # buttons $self->{btn_save_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/disk.png", &Wx::wxBITMAP_TYPE_PNG)); $self->{btn_delete_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/delete.png", &Wx::wxBITMAP_TYPE_PNG)); - $self->{btn_save_preset}->SetToolTipString("Save current settings"); + $self->{btn_save_preset}->SetToolTipString("Save current " . lc($title)); $self->{btn_delete_preset}->SetToolTipString("Delete this preset"); $self->{btn_delete_preset}->Disable; @@ -88,6 +88,7 @@ sub new { $default =~ s/\.ini$//i; my $dlg = Slic3r::GUI::SavePresetWindow->new($self, + title => lc($title), default => $default, values => [ map { my $filename = basename($_); $filename =~ /^(.*?)\.ini$/i; $1 } @{$self->{presets}} ], ); @@ -500,7 +501,7 @@ sub new { my ($parent, %params) = @_; my $self = $class->SUPER::new($parent, -1, "Save preset", [-1, -1], [-1, -1]); - my $text = Wx::StaticText->new($self, -1, "Save settings as:", [-1, -1], [-1, -1]); + my $text = Wx::StaticText->new($self, -1, "Save " . lc($params{title}) . " as:", [-1, -1], [-1, -1]); $self->{combo} = Wx::ComboBox->new($self, -1, $params{default}, [-1, -1], [-1, -1], $params{values}, &Wx::wxTE_PROCESS_ENTER); my $buttons = $self->CreateStdDialogButtonSizer(&Wx::wxOK | &Wx::wxCANCEL); From a861b95b122c13860af4ddcec15fe0faa9cd719f Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 24 Jun 2012 12:09:48 +0200 Subject: [PATCH 032/106] - Change about menu item title to match UI guidelines on Mac OS X, GTK+ and MSW - Lower-case Slic3r::GUI::about() to match other, custom methods --- lib/Slic3r/GUI.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index c1d5c2d59..3aa776048 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -83,8 +83,8 @@ sub OnInit { # Help menu my $helpMenu = Wx::Menu->new; { - $helpMenu->Append(wxID_ABOUT, "&About"); - EVT_MENU($frame, wxID_ABOUT, \&About); + $helpMenu->Append(wxID_ABOUT, "&About Slic3r"); + EVT_MENU($frame, wxID_ABOUT, \&about); } # menubar @@ -106,7 +106,7 @@ sub OnInit { return 1; } -sub About { +sub about { my $frame = shift; my $info = Wx::AboutDialogInfo->new; From a4de0e659d360497e55abe446a47b834232c8492 Mon Sep 17 00:00:00 2001 From: Mark Hindess Date: Mon, 25 Jun 2012 22:51:20 +0100 Subject: [PATCH 033/106] Trivial typo/grammar. --- lib/Slic3r/Config.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index cb956cfee..58fc01a3c 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -100,7 +100,7 @@ our $Options = { }, 'g0' => { label => 'Use G0 for travel moves', - tooltip => 'Only enable this if your firmware supports G0 properly (thus decouples all axes using their maximum speeds instead of synchronizing them). Travel moves and retractions will be combined in single commands, speeding the print up.', + tooltip => 'Only enable this if your firmware supports G0 properly (thus decouples all axes using their maximum speeds instead of synchronizing them). Travel moves and retractions will be combined in single commands, speeding them print up.', cli => 'g0', type => 'bool', }, @@ -419,7 +419,7 @@ our $Options = { # retraction options 'retract_length' => { label => 'Length', - tooltip => 'When retraction is triggered, filament is pulled back for the specified amount (the length is measured on raw filament, before it enters the extruder).', + tooltip => 'When retraction is triggered, filament is pulled back by the specified amount (the length is measured on raw filament, before it enters the extruder).', sidetext => 'mm (zero to disable)', cli => 'retract-length=f', type => 'f', From de3347c825198ffd4f13a81e63b052e77c928b4e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 26 Jun 2012 17:42:29 +0200 Subject: [PATCH 034/106] Add initial configuration wizard --- lib/Slic3r/GUI.pm | 3 + lib/Slic3r/GUI/ConfigWizard.pm | 359 +++++++++++++++++++++++++++++++++ lib/Slic3r/GUI/SkeinPanel.pm | 9 + 3 files changed, 371 insertions(+) create mode 100644 lib/Slic3r/GUI/ConfigWizard.pm diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 3aa776048..b59b5a405 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -4,6 +4,7 @@ use warnings; use utf8; use FindBin; +use Slic3r::GUI::ConfigWizard; use Slic3r::GUI::Plater; use Slic3r::GUI::OptionsGroup; use Slic3r::GUI::SkeinPanel; @@ -83,7 +84,9 @@ sub OnInit { # Help menu my $helpMenu = Wx::Menu->new; { + $helpMenu->Append(7, "Configuration Wizard…"); $helpMenu->Append(wxID_ABOUT, "&About Slic3r"); + EVT_MENU($frame, 7, sub { $frame->{skeinpanel}->config_wizard }); EVT_MENU($frame, wxID_ABOUT, \&about); } diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm new file mode 100644 index 000000000..4db58edd0 --- /dev/null +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -0,0 +1,359 @@ +package Slic3r::GUI::ConfigWizard; +use strict; +use warnings; +use utf8; + +use Wx qw(:sizer :progressdialog); +use base 'Wx::Wizard'; + +sub new { + my $class = shift; + my ($parent) = @_; + # TODO: Add instructional bitmaps + my $self = $class->SUPER::new($parent, -1, 'Configuration Wizard', + Wx::Bitmap->new("$Slic3r::var/slic3r_128px.png", &Wx::wxBITMAP_TYPE_PNG)); + + $self->add_page(Slic3r::GUI::ConfigWizard::Page::Welcome->new($self)); + $self->add_page(Slic3r::GUI::ConfigWizard::Page::Firmware->new($self)); + $self->add_page(Slic3r::GUI::ConfigWizard::Page::Bed->new($self)); + $self->add_page(Slic3r::GUI::ConfigWizard::Page::Cooling->new($self)); + $self->add_page(Slic3r::GUI::ConfigWizard::Page::Filament->new($self)); + $self->add_page(Slic3r::GUI::ConfigWizard::Page::Temperature->new($self)); + $self->add_page(Slic3r::GUI::ConfigWizard::Page::BedTemperature->new($self)); + $self->add_page(Slic3r::GUI::ConfigWizard::Page::Finished->new($self)); + + return $self; +} + +sub add_page { + my $self = shift; + my ($page) = @_; + + my $n = push @{$self->{pages}}, $page; + # add first page to the page area sizer + $self->GetPageAreaSizer->Add($page) if $n == 1; + # link pages + $self->{pages}[$n-2]->set_next_page($page) if $n >= 2; + $page->set_previous_page($self->{pages}[$n-2]) if $n >= 2; +} + +sub run { + my $self = shift; + + my $finished = Wx::Wizard::RunWizard($self, $self->{pages}[0]); + if ($finished) { + $_->apply for @{$self->{pages}}; + } + $self->Destroy; + + return $finished; +} + +package Slic3r::GUI::ConfigWizard::Option; +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(EVT_SPINCTRL EVT_TEXT EVT_CHECKBOX EVT_COMBOBOX); +use base 'Wx::StaticBoxSizer'; + +sub new { + my $class = shift; + my ($parent, %params) = @_; + my $box = Wx::StaticBox->new($parent, -1, ''); + my $self = $class->SUPER::new($box, &Wx::wxHORIZONTAL); + + my $label_width = 200; + + my $opt_key = $params{option}; + my $opt = $Slic3r::Config::Options->{$opt_key}; + + my $callback = $params{callback} || sub {}; + + # label + my $label = Wx::StaticText->new($parent, -1, "$opt->{label}:", &Wx::wxDefaultPosition, [$label_width, -1]); + $label->Wrap($label_width); + $self->Add($label, 1, &Wx::wxEXPAND); + + # input field(s) and unit + my $field; + if ($opt->{type} =~ /^(i|f|s|s@)$/) { + my $style = $opt->{multiline} ? &Wx::wxTE_MULTILINE : 0; + my $size = Wx::Size->new($opt->{width} || -1, $opt->{height} || -1); + + my ($get, $set) = $opt->{type} eq 's@' ? qw(serialize deserialize) : qw(get_raw set); + + if ($opt->{type} eq 'i') { + my $value = Slic3r::Config->$get($opt_key); + $field = Wx::SpinCtrl->new($parent, -1, $value, &Wx::wxDefaultPosition, $size, $style, $opt->{min} || 0, $opt->{max} || 100, $value); + EVT_SPINCTRL($parent, $field, sub { $callback->($opt_key, $field->GetValue) }); + } else { + $field = Wx::TextCtrl->new($parent, -1, Slic3r::Config->$get($opt_key), Wx::wxDefaultPosition, $size, $style); + EVT_TEXT($parent, $field, sub { $callback->($opt_key, $field->GetValue) }); + } + } elsif ($opt->{type} eq 'bool') { + $field = Wx::CheckBox->new($parent, -1, ''); + $field->SetValue(Slic3r::Config->get_raw($opt_key)); + EVT_CHECKBOX($parent, $field, sub { $callback->($opt_key, $field->GetValue) }); + } elsif ($opt->{type} eq 'point') { + $field = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); + my $field_size = Wx::Size->new(40, -1); + my $value = Slic3r::Config->get_raw($opt_key); + my @items = ( + Wx::StaticText->new($parent, -1, 'x:'), + my $x_field = Wx::TextCtrl->new($parent, -1, $value->[0], &Wx::wxDefaultPosition, $field_size), + Wx::StaticText->new($parent, -1, ' y:'), + my $y_field = Wx::TextCtrl->new($parent, -1, $value->[1], &Wx::wxDefaultPosition, $field_size), + ); + $field->Add($_) for @items; + EVT_TEXT($parent, $x_field, sub { $callback->($opt_key, [$x_field->GetValue, $y_field->GetValue]) }); + EVT_TEXT($parent, $y_field, sub { $callback->($opt_key, [$x_field->GetValue, $y_field->GetValue]) }); + } elsif ($opt->{type} eq 'select') { + $field = Wx::ComboBox->new($parent, -1, '', &Wx::wxDefaultPosition, &Wx::wxDefaultSize, $opt->{labels} || $opt->{values}, &Wx::wxCB_READONLY); + my $value = Slic3r::Config->get_raw($opt_key); + $field->SetSelection(grep $opt->{values}[$_] eq $value, 0..$#{$opt->{values}}); + EVT_COMBOBOX($parent, $field, sub { $callback->($opt_key, $opt->{values}[$field->GetSelection]) }); + } else { + die 'Unsupported option type: ' . $opt->{type}; + } + if ($opt->{sidetext}) { + my $sizer = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); + $sizer->Add($field); + my $sidetext = Wx::StaticText->new($parent, -1, $opt->{sidetext}, &Wx::wxDefaultPosition, [-1, -1]); + $sizer->Add($sidetext, 0, &Wx::wxLEFT | &Wx::wxALIGN_CENTER_VERTICAL, 4); + $self->Add($sizer); + } else { + $self->Add($field, 0, $opt->{full_width} ? &Wx::wxEXPAND : 0); + } + + return $self; +} + +package Slic3r::GUI::ConfigWizard::Page; +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Wx::WizardPage'; + +sub new { + my $class = shift; + my ($parent, $title) = @_; + my $self = $class->SUPER::new($parent); + + $self->{width} = 400; + $self->{vsizer} = Wx::BoxSizer->new(&Wx::wxVERTICAL); + $self->SetSizer($self->{vsizer}); + + # title + my $text = Wx::StaticText->new($self, -1, $title, &Wx::wxDefaultPosition, &Wx::wxDefaultSize, &Wx::wxALIGN_LEFT); + my $bold_font = Wx::SystemSettings::GetFont(&Wx::wxSYS_DEFAULT_GUI_FONT); + $bold_font->SetWeight(&Wx::wxFONTWEIGHT_BOLD); + $bold_font->SetPointSize(14); + $text->SetFont($bold_font); + $self->{vsizer}->Add($text, 0, &Wx::wxALIGN_LEFT | &Wx::wxALL, 10); + + return $self; +} + +sub append_text { + my $self = shift; + my ($text) = @_; + + my $para = Wx::StaticText->new($self, -1, $text, &Wx::wxDefaultPosition, &Wx::wxDefaultSize, &Wx::wxALIGN_LEFT); + $para->Wrap($self->{width}); + $self->{vsizer}->Add($para, 0, &Wx::wxALIGN_LEFT | &Wx::wxALL, 10); +} + +sub append_option { + my $self = shift; + my ($opt_key) = @_; + + my $option = Slic3r::GUI::ConfigWizard::Option->new($self, option => $opt_key, + callback => sub { + my ($opt_key, $value) = @_; + $self->{options}->{$opt_key} = $value; + }); + $self->{vsizer}->Add($option, 0, &Wx::wxEXPAND | &Wx::wxALL, 10); +} + +sub apply { + my $self = shift; + Slic3r::Config->set($_, $self->{options}->{$_}) foreach (keys %{$self->{options}}); +} + +sub set_previous_page { + my $self = shift; + my ($previous_page) = @_; + $self->{previous_page} = $previous_page; +} + +sub GetPrev { + my $self = shift; + return $self->{previous_page}; +} + +sub set_next_page { + my $self = shift; + my ($next_page) = @_; + $self->{next_page} = $next_page; +} + +sub GetNext { + my $self = shift; + return $self->{next_page}; +} + +package Slic3r::GUI::ConfigWizard::Page::Welcome; +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Slic3r::GUI::ConfigWizard::Page'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, 'Welcome'); + + $self->append_text('This configuration wizard will guide you through the most important settings of Slic3r in a few easy steps. ' . + 'Configuration will be based on your current configuration.'); + + return $self; +} + +package Slic3r::GUI::ConfigWizard::Page::Firmware; +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Slic3r::GUI::ConfigWizard::Page'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, 'Firmware Type'); + + $self->append_text('Choose the type of firmware used by your printer below.'); + $self->append_option('gcode_flavor'); + + return $self; +} + +package Slic3r::GUI::ConfigWizard::Page::Bed; +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Slic3r::GUI::ConfigWizard::Page'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, 'Bed Size'); + + $self->append_text('Enter the size of your printers bed below.'); + $self->append_option('bed_size'); + + return $self; +} + +sub apply { + my $self = shift; + $self->SUPER::apply; + + # set print_center to centre of bed_size + my $bed_size = Slic3r::Config->get_raw('bed_size'); + Slic3r::Config->set('print_center', [$bed_size->[0]/2, $bed_size->[1]/2]); +} + +package Slic3r::GUI::ConfigWizard::Page::Cooling; +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Slic3r::GUI::ConfigWizard::Page'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, 'Fan'); + + $self->append_text('If your printer has a fan for cooling the printed object, check the box below.'); + $self->append_option('cooling'); + + return $self; +} + +package Slic3r::GUI::ConfigWizard::Page::Filament; +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Slic3r::GUI::ConfigWizard::Page'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, 'Filament Diameter'); + + $self->append_text('Enter your filament diameter below. ' . + 'Good precision is required, so use a caliper and do multiple measurements along the filament, then compute the average.'); + $self->append_option('filament_diameter'); + + return $self; +} + +package Slic3r::GUI::ConfigWizard::Page::Temperature; +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Slic3r::GUI::ConfigWizard::Page'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, 'Extrusion Temperature'); + + $self->append_text('Enter the temperature needed for extruding your filament below. ' . + 'A rule of thumb is 160 to 230 °C for PLA and 215 to 250 °C for ABS. '); + $self->append_option('temperature'); + + return $self; +} + +sub apply { + my $self = shift; + $self->SUPER::apply; + + # set first_layer_temperature to temperature + 5 + my $temperature = Slic3r::Config->get_raw('temperature'); + Slic3r::Config->set('first_layer_temperature', $temperature + 5); +} + +package Slic3r::GUI::ConfigWizard::Page::BedTemperature; +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Slic3r::GUI::ConfigWizard::Page'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, 'Bed Temperature'); + + $self->append_text('Enter the bed temperature needed for getting your filament to stick to your heated bed below. ' . + 'A rule of thumb is 60 °C for PLA and 110 °C for ABS.'); + $self->append_option('bed_temperature'); + + return $self; +} + +sub apply { + my $self = shift; + $self->SUPER::apply; + + # set first_layer_bed_temperature to temperature + 5 + my $temperature = Slic3r::Config->get_raw('bed_temperature'); + Slic3r::Config->set('first_layer_bed_temperature', $temperature + 5); +} + +package Slic3r::GUI::ConfigWizard::Page::Finished; +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Slic3r::GUI::ConfigWizard::Page'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, 'Congratulations!'); + + $self->append_text('Slic3r is now configured for your particular printer and filament.'); + + return $self; +} + +1; diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 907e9c0d9..fc7d0fa81 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -223,6 +223,15 @@ sub load_config { $dlg->Destroy; } +sub config_wizard { + my $self = shift; + + if (Slic3r::GUI::ConfigWizard->new($self)->run) { + $_->() for values %Slic3r::GUI::OptionsGroup::reload_callbacks; + $_->set_dirty(1) for values %{$self->{options_tabs}}; + } +} + sub on_close { my $self = shift; From 373b341280578717950eb9f0ae9bc1815641050a Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 26 Jun 2012 22:47:10 +0200 Subject: [PATCH 035/106] Remove cooling option from wizard --- lib/Slic3r/GUI/ConfigWizard.pm | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index 4db58edd0..4c24b8bbb 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -16,7 +16,6 @@ sub new { $self->add_page(Slic3r::GUI::ConfigWizard::Page::Welcome->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Firmware->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Bed->new($self)); - $self->add_page(Slic3r::GUI::ConfigWizard::Page::Cooling->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Filament->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Temperature->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::BedTemperature->new($self)); @@ -256,22 +255,6 @@ sub apply { Slic3r::Config->set('print_center', [$bed_size->[0]/2, $bed_size->[1]/2]); } -package Slic3r::GUI::ConfigWizard::Page::Cooling; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); -use base 'Slic3r::GUI::ConfigWizard::Page'; - -sub new { - my $class = shift; - my ($parent) = @_; - my $self = $class->SUPER::new($parent, 'Fan'); - - $self->append_text('If your printer has a fan for cooling the printed object, check the box below.'); - $self->append_option('cooling'); - - return $self; -} - package Slic3r::GUI::ConfigWizard::Page::Filament; use Wx qw(:sizer :progressdialog); use Wx::Event qw(); From 406e31a20dc6e5100c710f3c6cbad05a25a1663f Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 26 Jun 2012 22:47:58 +0200 Subject: [PATCH 036/106] Fix icon file name --- lib/Slic3r/GUI/ConfigWizard.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index 4c24b8bbb..724367f4e 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -11,7 +11,7 @@ sub new { my ($parent) = @_; # TODO: Add instructional bitmaps my $self = $class->SUPER::new($parent, -1, 'Configuration Wizard', - Wx::Bitmap->new("$Slic3r::var/slic3r_128px.png", &Wx::wxBITMAP_TYPE_PNG)); + Wx::Bitmap->new("$Slic3r::var/Slic3r_128px.png", &Wx::wxBITMAP_TYPE_PNG)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Welcome->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Firmware->new($self)); From cd48dc403109f11c9f4b556c9a98649909db3e36 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 27 Jun 2012 17:59:29 +0200 Subject: [PATCH 037/106] - Add nozzle_diameter to Configuration Wizard - Automatically set layer_height to (nozzle_diameter - 0.1) --- lib/Slic3r/GUI/ConfigWizard.pm | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index 724367f4e..e6be8c7a9 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -16,6 +16,7 @@ sub new { $self->add_page(Slic3r::GUI::ConfigWizard::Page::Welcome->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Firmware->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Bed->new($self)); + $self->add_page(Slic3r::GUI::ConfigWizard::Page::Nozzle->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Filament->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Temperature->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::BedTemperature->new($self)); @@ -255,6 +256,31 @@ sub apply { Slic3r::Config->set('print_center', [$bed_size->[0]/2, $bed_size->[1]/2]); } +package Slic3r::GUI::ConfigWizard::Page::Nozzle; +use Wx qw(:sizer :progressdialog); +use Wx::Event qw(); +use base 'Slic3r::GUI::ConfigWizard::Page'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, 'Nozzle Diameter'); + + $self->append_text('Enter the diameter of your printers hot end nozzle below.'); + $self->append_option('nozzle_diameter'); + + return $self; +} + +sub apply { + my $self = shift; + $self->SUPER::apply; + + # set layer_height to nozzle_diameter - 0.1 + my $nozzle = Slic3r::Config->get_raw('nozzle_diameter'); + Slic3r::Config->set('layer_height', $nozzle - 0.1); +} + package Slic3r::GUI::ConfigWizard::Page::Filament; use Wx qw(:sizer :progressdialog); use Wx::Event qw(); From 52872753dfa587eada47eb0bbe1f1defe1b3e167 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 27 Jun 2012 19:41:37 +0200 Subject: [PATCH 038/106] Minor changes to text and layout to look more like other wizards --- lib/Slic3r/GUI/ConfigWizard.pm | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index e6be8c7a9..a4e953233 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -147,6 +147,8 @@ sub new { $bold_font->SetPointSize(14); $text->SetFont($bold_font); $self->{vsizer}->Add($text, 0, &Wx::wxALIGN_LEFT | &Wx::wxALL, 10); + my $line = Wx::StaticLine->new($self, -1, &Wx::wxDefaultPosition, &Wx::wxDefaultSize, &Wx::wxLI_HORIZONTAL, ''); + $self->{vsizer}->Add($line, 0, &Wx::wxEXPAND| &Wx::wxALL, 10); return $self; } @@ -207,10 +209,11 @@ use base 'Slic3r::GUI::ConfigWizard::Page'; sub new { my $class = shift; my ($parent) = @_; - my $self = $class->SUPER::new($parent, 'Welcome'); + my $self = $class->SUPER::new($parent, 'Welcome to the Slic3r Configuration Wizard'); $self->append_text('This configuration wizard will guide you through the most important settings of Slic3r in a few easy steps. ' . 'Configuration will be based on your current configuration.'); + $self->append_text('To continue, click Next.'); return $self; } @@ -225,7 +228,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, 'Firmware Type'); - $self->append_text('Choose the type of firmware used by your printer below.'); + $self->append_text('Choose the type of firmware used by your printer, then click Next.'); $self->append_option('gcode_flavor'); return $self; @@ -241,7 +244,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, 'Bed Size'); - $self->append_text('Enter the size of your printers bed below.'); + $self->append_text('Enter the size of your printers bed, then click Next.'); $self->append_option('bed_size'); return $self; @@ -266,7 +269,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, 'Nozzle Diameter'); - $self->append_text('Enter the diameter of your printers hot end nozzle below.'); + $self->append_text('Enter the diameter of your printers hot end nozzle, then click Next.'); $self->append_option('nozzle_diameter'); return $self; @@ -291,8 +294,8 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, 'Filament Diameter'); - $self->append_text('Enter your filament diameter below. ' . - 'Good precision is required, so use a caliper and do multiple measurements along the filament, then compute the average.'); + $self->append_text('Enter the diameter of your filament, then click Next.'); + $self->append_text('Good precision is required, so use a caliper and do multiple measurements along the filament, then compute the average.'); $self->append_option('filament_diameter'); return $self; @@ -308,8 +311,8 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, 'Extrusion Temperature'); - $self->append_text('Enter the temperature needed for extruding your filament below. ' . - 'A rule of thumb is 160 to 230 °C for PLA and 215 to 250 °C for ABS. '); + $self->append_text('Enter the temperature needed for extruding your filament, then click Next.'); + $self->append_text('A rule of thumb is 160 to 230 °C for PLA and 215 to 250 °C for ABS.'); $self->append_option('temperature'); return $self; @@ -334,8 +337,8 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, 'Bed Temperature'); - $self->append_text('Enter the bed temperature needed for getting your filament to stick to your heated bed below. ' . - 'A rule of thumb is 60 °C for PLA and 110 °C for ABS.'); + $self->append_text('Enter the bed temperature needed for getting your filament to stick to your heated bed, then click Next.'); + $self->append_text('A rule of thumb is 60 °C for PLA and 110 °C for ABS.'); $self->append_option('bed_temperature'); return $self; @@ -361,6 +364,7 @@ sub new { my $self = $class->SUPER::new($parent, 'Congratulations!'); $self->append_text('Slic3r is now configured for your particular printer and filament.'); + $self->append_text('Click Finish to apply the newly created configuration and close this wizard.'); return $self; } From dbc42f68418cb6d7ca41f10401ac469f402d8ec9 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 27 Jun 2012 19:56:47 +0200 Subject: [PATCH 039/106] Make it more clear that the wizard uses your current configuration as basis --- lib/Slic3r/GUI/ConfigWizard.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index a4e953233..6f55347b3 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -211,8 +211,8 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, 'Welcome to the Slic3r Configuration Wizard'); - $self->append_text('This configuration wizard will guide you through the most important settings of Slic3r in a few easy steps. ' . - 'Configuration will be based on your current configuration.'); + $self->append_text('This configuration wizard will guide you through the most important settings of Slic3r in a few easy steps.'); + $self->append_text('Configuration will be based on your current configuration.'); $self->append_text('To continue, click Next.'); return $self; From 145b9076cc59ea00c9880792e14a3e37f0d6f47b Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 27 Jun 2012 21:03:57 +0200 Subject: [PATCH 040/106] Let the wizard automatically set first_layer_height = nozzle_diameter --- lib/Slic3r/GUI/ConfigWizard.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index 6f55347b3..3bfeb3bcc 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -279,8 +279,9 @@ sub apply { my $self = shift; $self->SUPER::apply; - # set layer_height to nozzle_diameter - 0.1 + # set first_layer_height + layer_height based on nozzle_diameter my $nozzle = Slic3r::Config->get_raw('nozzle_diameter'); + Slic3r::Config->set('first_layer_height', $nozzle); Slic3r::Config->set('layer_height', $nozzle - 0.1); } From 7211561ab3fe77f02758df7f8d64ca97d6eca8ec Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 27 Jun 2012 21:51:12 +0200 Subject: [PATCH 041/106] Change wizard welcome text a bit --- lib/Slic3r/GUI/ConfigWizard.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index 3bfeb3bcc..0e28c78be 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -211,7 +211,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, 'Welcome to the Slic3r Configuration Wizard'); - $self->append_text('This configuration wizard will guide you through the most important settings of Slic3r in a few easy steps.'); + $self->append_text('Hello, welcome to Slic3r! This wizard will help you with the initial configuration; just a few settings and you will be ready to print.'); $self->append_text('Configuration will be based on your current configuration.'); $self->append_text('To continue, click Next.'); From 84cfe7afc7b673004d7a92065c510f7101bb95f6 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 27 Jun 2012 22:13:57 +0200 Subject: [PATCH 042/106] Automatically show configuration wizard on first run --- lib/Slic3r/GUI.pm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index b59b5a405..e33319234 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -39,6 +39,7 @@ sub OnInit { # locate or create data directory $datadir = Wx::StandardPaths::Get->GetUserDataDir; Slic3r::debugf "Data directory: %s\n", $datadir; + my $run_wizard = (-d $datadir) ? 0 : 1; for ($datadir, "$datadir/print", "$datadir/filament", "$datadir/printer") { mkdir or $self->fatal_error("Slic3r was unable to create its data directory at $_ (errno: $!).") unless -d $_; @@ -106,6 +107,8 @@ sub OnInit { $frame->Show; $frame->Layout; + $frame->{skeinpanel}->config_wizard if $run_wizard; + return 1; } From ed9f6e1f1eba3ceb0a6c5736977f97bd5f62bb3e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 27 Jun 2012 23:20:29 +0200 Subject: [PATCH 043/106] Rephrase a few of the wizard instructions --- lib/Slic3r/GUI/ConfigWizard.pm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index 0e28c78be..ddaf66494 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -211,7 +211,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, 'Welcome to the Slic3r Configuration Wizard'); - $self->append_text('Hello, welcome to Slic3r! This wizard will help you with the initial configuration; just a few settings and you will be ready to print.'); + $self->append_text('Hello, welcome to Slic3r! This wizard helps you with the initial configuration; just a few settings and you will be ready to print.'); $self->append_text('Configuration will be based on your current configuration.'); $self->append_text('To continue, click Next.'); @@ -364,8 +364,9 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, 'Congratulations!'); - $self->append_text('Slic3r is now configured for your particular printer and filament.'); - $self->append_text('Click Finish to apply the newly created configuration and close this wizard.'); + $self->append_text('You have successfully completed the Slic3r Configuration Wizard. ' . + 'Slic3r is now configured for your printer and filament.'); + $self->append_text('To close this wizard and apply the newly created configuration, click Finish.'); return $self; } From 4f179a5197331fc432ce2d660fa6b3d60c69a99e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Thu, 28 Jun 2012 23:20:10 +0200 Subject: [PATCH 044/106] Explicitly set top level window (to ensure the wizard is not assumed to be the top level window) --- lib/Slic3r/GUI.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index e33319234..7f1787ad3 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -56,6 +56,7 @@ sub OnInit { my $frame = Wx::Frame->new(undef, -1, 'Slic3r', [-1, -1], [760,520], wxDEFAULT_FRAME_STYLE); $frame->SetIcon(Wx::Icon->new("$Slic3r::var/Slic3r_128px.png", &Wx::wxBITMAP_TYPE_PNG) ); $frame->{skeinpanel} = Slic3r::GUI::SkeinPanel->new($frame); + $self->SetTopWindow($frame); # status bar $frame->{statusbar} = Slic3r::GUI::ProgressStatusBar->new($frame, -1); From d884856b2ec0f941afd9426179ad7e1ca063df1e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Thu, 28 Jun 2012 23:47:31 +0200 Subject: [PATCH 045/106] Add information about the Silk icon set. --- README.markdown | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.markdown b/README.markdown index e8ddca0ff..e00890384 100644 --- a/README.markdown +++ b/README.markdown @@ -74,6 +74,10 @@ in development. Slic3r is licensed under the _GNU Affero General Public License, version 3_. The author is Alessandro Ranellucci. +The [Silk icon set](http://www.famfamfam.com/lab/icons/silk/) used in Slic3r is +licensed under the _Creative Commons Attribution 3.0 License_. +The author of the Silk icon set is Mark James. + ## How can I invoke slic3r.pl using the command line? Usage: slic3r.pl [ OPTIONS ] file.stl From a0f8078ee11509df5489f0afa7206d2a01b9b065 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sat, 30 Jun 2012 22:34:13 +0200 Subject: [PATCH 046/106] Warn on dirty default presets as well --- lib/Slic3r/GUI/Tab.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 2633097b5..77477bbbf 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -197,7 +197,7 @@ sub set_dirty { sub is_dirty { my $self = shift; - return $self->{dirty}; + return (defined $self->{dirty}); } sub title { From df658eb63601a8ff95f75ba39a49dfd008578e5b Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sat, 30 Jun 2012 22:57:30 +0200 Subject: [PATCH 047/106] Rename SkeinPanel::on_close() to make it more generice --- lib/Slic3r/GUI.pm | 2 +- lib/Slic3r/GUI/SkeinPanel.pm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 7f1787ad3..5d366e65a 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -127,7 +127,7 @@ sub about { sub on_close { my ($frame, $event) = @_; - $event->CanVeto ? $event->Skip($frame->{skeinpanel}->on_close) : $event->Skip(1); + $event->CanVeto ? $event->Skip($frame->{skeinpanel}->check_unsaved_changes) : $event->Skip(1); } sub catch_error { diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index fc7d0fa81..ed83a5bef 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -232,7 +232,7 @@ sub config_wizard { } } -sub on_close { +sub check_unsaved_changes { my $self = shift; my @dirty; @@ -242,7 +242,7 @@ sub on_close { if (@dirty) { my $titles = join ', ', @dirty; - my $confirm = Wx::MessageDialog->new($self, "You have unsaved changes ($titles). Exit anyway?", + my $confirm = Wx::MessageDialog->new($self, "You have unsaved changes ($titles). Discard changes and continue anyway?", 'Unsaved Presets', wxICON_QUESTION | wxOK | wxCANCEL); return ($confirm->ShowModal == wxID_OK); } From d90e82faa3ac47b908ef16bd334eeb20aa6f31dd Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sat, 30 Jun 2012 23:00:05 +0200 Subject: [PATCH 048/106] Check for unsaved changes before running configuration wizard --- lib/Slic3r/GUI/SkeinPanel.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index ed83a5bef..7999d98aa 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -226,6 +226,7 @@ sub load_config { sub config_wizard { my $self = shift; + return unless $self->check_unsaved_changes; if (Slic3r::GUI::ConfigWizard->new($self)->run) { $_->() for values %Slic3r::GUI::OptionsGroup::reload_callbacks; $_->set_dirty(1) for values %{$self->{options_tabs}}; From 757da9d39d549c2e56d3204281e8c29531407836 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sat, 30 Jun 2012 23:28:07 +0200 Subject: [PATCH 049/106] Clean up imports --- lib/Slic3r/GUI/ConfigWizard.pm | 72 +++++++++++++--------------------- 1 file changed, 28 insertions(+), 44 deletions(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index ddaf66494..14ac7faa3 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -3,7 +3,7 @@ use strict; use warnings; use utf8; -use Wx qw(:sizer :progressdialog); +use Wx qw(:bitmap); use base 'Wx::Wizard'; sub new { @@ -11,7 +11,7 @@ sub new { my ($parent) = @_; # TODO: Add instructional bitmaps my $self = $class->SUPER::new($parent, -1, 'Configuration Wizard', - Wx::Bitmap->new("$Slic3r::var/Slic3r_128px.png", &Wx::wxBITMAP_TYPE_PNG)); + Wx::Bitmap->new("$Slic3r::var/Slic3r_128px.png", wxBITMAP_TYPE_PNG)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Welcome->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Firmware->new($self)); @@ -50,7 +50,7 @@ sub run { } package Slic3r::GUI::ConfigWizard::Option; -use Wx qw(:sizer :progressdialog); +use Wx qw(:combobox :misc :sizer :textctrl); use Wx::Event qw(EVT_SPINCTRL EVT_TEXT EVT_CHECKBOX EVT_COMBOBOX); use base 'Wx::StaticBoxSizer'; @@ -58,7 +58,7 @@ sub new { my $class = shift; my ($parent, %params) = @_; my $box = Wx::StaticBox->new($parent, -1, ''); - my $self = $class->SUPER::new($box, &Wx::wxHORIZONTAL); + my $self = $class->SUPER::new($box, wxHORIZONTAL); my $label_width = 200; @@ -68,24 +68,24 @@ sub new { my $callback = $params{callback} || sub {}; # label - my $label = Wx::StaticText->new($parent, -1, "$opt->{label}:", &Wx::wxDefaultPosition, [$label_width, -1]); + my $label = Wx::StaticText->new($parent, -1, "$opt->{label}:", wxDefaultPosition, [$label_width, -1]); $label->Wrap($label_width); - $self->Add($label, 1, &Wx::wxEXPAND); + $self->Add($label, 1, wxEXPAND); # input field(s) and unit my $field; if ($opt->{type} =~ /^(i|f|s|s@)$/) { - my $style = $opt->{multiline} ? &Wx::wxTE_MULTILINE : 0; + my $style = $opt->{multiline} ? wxTE_MULTILINE : 0; my $size = Wx::Size->new($opt->{width} || -1, $opt->{height} || -1); my ($get, $set) = $opt->{type} eq 's@' ? qw(serialize deserialize) : qw(get_raw set); if ($opt->{type} eq 'i') { my $value = Slic3r::Config->$get($opt_key); - $field = Wx::SpinCtrl->new($parent, -1, $value, &Wx::wxDefaultPosition, $size, $style, $opt->{min} || 0, $opt->{max} || 100, $value); + $field = Wx::SpinCtrl->new($parent, -1, $value, wxDefaultPosition, $size, $style, $opt->{min} || 0, $opt->{max} || 100, $value); EVT_SPINCTRL($parent, $field, sub { $callback->($opt_key, $field->GetValue) }); } else { - $field = Wx::TextCtrl->new($parent, -1, Slic3r::Config->$get($opt_key), Wx::wxDefaultPosition, $size, $style); + $field = Wx::TextCtrl->new($parent, -1, Slic3r::Config->$get($opt_key), wxDefaultPosition, $size, $style); EVT_TEXT($parent, $field, sub { $callback->($opt_key, $field->GetValue) }); } } elsif ($opt->{type} eq 'bool') { @@ -93,20 +93,20 @@ sub new { $field->SetValue(Slic3r::Config->get_raw($opt_key)); EVT_CHECKBOX($parent, $field, sub { $callback->($opt_key, $field->GetValue) }); } elsif ($opt->{type} eq 'point') { - $field = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); + $field = Wx::BoxSizer->new(wxHORIZONTAL); my $field_size = Wx::Size->new(40, -1); my $value = Slic3r::Config->get_raw($opt_key); my @items = ( Wx::StaticText->new($parent, -1, 'x:'), - my $x_field = Wx::TextCtrl->new($parent, -1, $value->[0], &Wx::wxDefaultPosition, $field_size), + my $x_field = Wx::TextCtrl->new($parent, -1, $value->[0], wxDefaultPosition, $field_size), Wx::StaticText->new($parent, -1, ' y:'), - my $y_field = Wx::TextCtrl->new($parent, -1, $value->[1], &Wx::wxDefaultPosition, $field_size), + my $y_field = Wx::TextCtrl->new($parent, -1, $value->[1], wxDefaultPosition, $field_size), ); $field->Add($_) for @items; EVT_TEXT($parent, $x_field, sub { $callback->($opt_key, [$x_field->GetValue, $y_field->GetValue]) }); EVT_TEXT($parent, $y_field, sub { $callback->($opt_key, [$x_field->GetValue, $y_field->GetValue]) }); } elsif ($opt->{type} eq 'select') { - $field = Wx::ComboBox->new($parent, -1, '', &Wx::wxDefaultPosition, &Wx::wxDefaultSize, $opt->{labels} || $opt->{values}, &Wx::wxCB_READONLY); + $field = Wx::ComboBox->new($parent, -1, '', wxDefaultPosition, wxDefaultSize, $opt->{labels} || $opt->{values}, wxCB_READONLY); my $value = Slic3r::Config->get_raw($opt_key); $field->SetSelection(grep $opt->{values}[$_] eq $value, 0..$#{$opt->{values}}); EVT_COMBOBOX($parent, $field, sub { $callback->($opt_key, $opt->{values}[$field->GetSelection]) }); @@ -114,20 +114,20 @@ sub new { die 'Unsupported option type: ' . $opt->{type}; } if ($opt->{sidetext}) { - my $sizer = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); + my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); $sizer->Add($field); - my $sidetext = Wx::StaticText->new($parent, -1, $opt->{sidetext}, &Wx::wxDefaultPosition, [-1, -1]); - $sizer->Add($sidetext, 0, &Wx::wxLEFT | &Wx::wxALIGN_CENTER_VERTICAL, 4); + my $sidetext = Wx::StaticText->new($parent, -1, $opt->{sidetext}, wxDefaultPosition, [-1, -1]); + $sizer->Add($sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4); $self->Add($sizer); } else { - $self->Add($field, 0, $opt->{full_width} ? &Wx::wxEXPAND : 0); + $self->Add($field, 0, $opt->{full_width} ? wxEXPAND : 0); } return $self; } package Slic3r::GUI::ConfigWizard::Page; -use Wx qw(:sizer :progressdialog); +use Wx qw(:font :misc :sizer :staticline :systemsettings); use Wx::Event qw(); use base 'Wx::WizardPage'; @@ -137,18 +137,18 @@ sub new { my $self = $class->SUPER::new($parent); $self->{width} = 400; - $self->{vsizer} = Wx::BoxSizer->new(&Wx::wxVERTICAL); + $self->{vsizer} = Wx::BoxSizer->new(wxVERTICAL); $self->SetSizer($self->{vsizer}); # title - my $text = Wx::StaticText->new($self, -1, $title, &Wx::wxDefaultPosition, &Wx::wxDefaultSize, &Wx::wxALIGN_LEFT); - my $bold_font = Wx::SystemSettings::GetFont(&Wx::wxSYS_DEFAULT_GUI_FONT); - $bold_font->SetWeight(&Wx::wxFONTWEIGHT_BOLD); + my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); + my $bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + $bold_font->SetWeight(wxFONTWEIGHT_BOLD); $bold_font->SetPointSize(14); $text->SetFont($bold_font); - $self->{vsizer}->Add($text, 0, &Wx::wxALIGN_LEFT | &Wx::wxALL, 10); - my $line = Wx::StaticLine->new($self, -1, &Wx::wxDefaultPosition, &Wx::wxDefaultSize, &Wx::wxLI_HORIZONTAL, ''); - $self->{vsizer}->Add($line, 0, &Wx::wxEXPAND| &Wx::wxALL, 10); + $self->{vsizer}->Add($text, 0, wxALIGN_LEFT | wxALL, 10); + my $line = Wx::StaticLine->new($self, -1, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL, ''); + $self->{vsizer}->Add($line, 0, wxEXPAND| wxALL, 10); return $self; } @@ -157,9 +157,9 @@ sub append_text { my $self = shift; my ($text) = @_; - my $para = Wx::StaticText->new($self, -1, $text, &Wx::wxDefaultPosition, &Wx::wxDefaultSize, &Wx::wxALIGN_LEFT); + my $para = Wx::StaticText->new($self, -1, $text, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); $para->Wrap($self->{width}); - $self->{vsizer}->Add($para, 0, &Wx::wxALIGN_LEFT | &Wx::wxALL, 10); + $self->{vsizer}->Add($para, 0, wxALIGN_LEFT | wxALL, 10); } sub append_option { @@ -171,7 +171,7 @@ sub append_option { my ($opt_key, $value) = @_; $self->{options}->{$opt_key} = $value; }); - $self->{vsizer}->Add($option, 0, &Wx::wxEXPAND | &Wx::wxALL, 10); + $self->{vsizer}->Add($option, 0, wxEXPAND | wxALL, 10); } sub apply { @@ -202,8 +202,6 @@ sub GetNext { } package Slic3r::GUI::ConfigWizard::Page::Welcome; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); use base 'Slic3r::GUI::ConfigWizard::Page'; sub new { @@ -219,8 +217,6 @@ sub new { } package Slic3r::GUI::ConfigWizard::Page::Firmware; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); use base 'Slic3r::GUI::ConfigWizard::Page'; sub new { @@ -235,8 +231,6 @@ sub new { } package Slic3r::GUI::ConfigWizard::Page::Bed; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); use base 'Slic3r::GUI::ConfigWizard::Page'; sub new { @@ -260,8 +254,6 @@ sub apply { } package Slic3r::GUI::ConfigWizard::Page::Nozzle; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); use base 'Slic3r::GUI::ConfigWizard::Page'; sub new { @@ -286,8 +278,6 @@ sub apply { } package Slic3r::GUI::ConfigWizard::Page::Filament; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); use base 'Slic3r::GUI::ConfigWizard::Page'; sub new { @@ -303,8 +293,6 @@ sub new { } package Slic3r::GUI::ConfigWizard::Page::Temperature; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); use base 'Slic3r::GUI::ConfigWizard::Page'; sub new { @@ -329,8 +317,6 @@ sub apply { } package Slic3r::GUI::ConfigWizard::Page::BedTemperature; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); use base 'Slic3r::GUI::ConfigWizard::Page'; sub new { @@ -355,8 +341,6 @@ sub apply { } package Slic3r::GUI::ConfigWizard::Page::Finished; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); use base 'Slic3r::GUI::ConfigWizard::Page'; sub new { From e656c30d4ff1a38c0b28e2439ed5c44c4d3a962a Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sat, 30 Jun 2012 23:30:52 +0200 Subject: [PATCH 050/106] Clean up imports --- lib/Slic3r/GUI/ConfigWizard.pm | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index 14ac7faa3..f49e8690f 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -128,7 +128,6 @@ sub new { package Slic3r::GUI::ConfigWizard::Page; use Wx qw(:font :misc :sizer :staticline :systemsettings); -use Wx::Event qw(); use base 'Wx::WizardPage'; sub new { From bb193c659c1e63a6b23099eb447535d4df8ccec0 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sat, 30 Jun 2012 23:56:11 +0200 Subject: [PATCH 051/106] Start configuration wizard from sane default settings --- lib/Slic3r/GUI/ConfigWizard.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index f49e8690f..d5354736a 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -13,6 +13,9 @@ sub new { my $self = $class->SUPER::new($parent, -1, 'Configuration Wizard', Wx::Bitmap->new("$Slic3r::var/Slic3r_128px.png", wxBITMAP_TYPE_PNG)); + # Start from sane defaults + Slic3r::Config->load_hash($Slic3r::Defaults, undef, 1); + $self->add_page(Slic3r::GUI::ConfigWizard::Page::Welcome->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Firmware->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Bed->new($self)); @@ -209,7 +212,6 @@ sub new { my $self = $class->SUPER::new($parent, 'Welcome to the Slic3r Configuration Wizard'); $self->append_text('Hello, welcome to Slic3r! This wizard helps you with the initial configuration; just a few settings and you will be ready to print.'); - $self->append_text('Configuration will be based on your current configuration.'); $self->append_text('To continue, click Next.'); return $self; From 8f0aab3520dbdc44f03e0a581d9179fcf77208d0 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 1 Jul 2012 00:10:48 +0200 Subject: [PATCH 052/106] Restore old configuration if configuration wizrd is cancelled --- lib/Slic3r/GUI/ConfigWizard.pm | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index d5354736a..aa92f7a6e 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -14,6 +14,7 @@ sub new { Wx::Bitmap->new("$Slic3r::var/Slic3r_128px.png", wxBITMAP_TYPE_PNG)); # Start from sane defaults + $self->{old} = Slic3r::Config->current; Slic3r::Config->load_hash($Slic3r::Defaults, undef, 1); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Welcome->new($self)); @@ -43,13 +44,18 @@ sub add_page { sub run { my $self = shift; - my $finished = Wx::Wizard::RunWizard($self, $self->{pages}[0]); - if ($finished) { + my $modified; + if (Wx::Wizard::RunWizard($self, $self->{pages}[0])) { $_->apply for @{$self->{pages}}; + $modified = 1; + } else { + Slic3r::Config->load_hash($self->{old}, undef, 1); + $modified = 0; } + $self->Destroy; - return $finished; + return $modified; } package Slic3r::GUI::ConfigWizard::Option; From bfe7108cea2df116779d6746effa2d6ff29f1040 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 1 Jul 2012 00:17:48 +0200 Subject: [PATCH 053/106] Provide instructions for loading an existing configuration instead of using the wizard --- lib/Slic3r/GUI/ConfigWizard.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index aa92f7a6e..049155b20 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -218,6 +218,7 @@ sub new { my $self = $class->SUPER::new($parent, 'Welcome to the Slic3r Configuration Wizard'); $self->append_text('Hello, welcome to Slic3r! This wizard helps you with the initial configuration; just a few settings and you will be ready to print.'); + $self->append_text('To import an existing configuration instead, cancel this wizard and use the Open Config menu item found in the File menu.'); $self->append_text('To continue, click Next.'); return $self; From a72b914eb0cd6d4976db80aeed8d591cbaa38bf8 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 1 Jul 2012 00:24:55 +0200 Subject: [PATCH 054/106] Add lib/Slic3r/GUI/ConfigWizard.pm to MANIFEST --- MANIFEST | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST b/MANIFEST index 56e61cd41..136441411 100644 --- a/MANIFEST +++ b/MANIFEST @@ -26,6 +26,7 @@ lib/Slic3r/Format/STL.pm lib/Slic3r/Geometry.pm lib/Slic3r/Geometry/Clipper.pm lib/Slic3r/GUI.pm +lib/Slic3r/GUI/ConfigWizard.pm lib/Slic3r/GUI/Plater.pm lib/Slic3r/GUI/OptionsGroup.pm lib/Slic3r/GUI/SkeinPanel.pm From 7746040af51191c8cf1dd8c5c04a819ec08185c2 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 1 Jul 2012 19:24:06 +0200 Subject: [PATCH 055/106] Clean up Wx imports --- lib/Slic3r/GUI.pm | 19 +++++---- lib/Slic3r/GUI/OptionsGroup.pm | 30 ++++++------- lib/Slic3r/GUI/Plater.pm | 77 ++++++++++++++++------------------ lib/Slic3r/GUI/SkeinPanel.pm | 13 +++--- lib/Slic3r/GUI/Tab.pm | 63 +++++++++++++--------------- 5 files changed, 96 insertions(+), 106 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 3aa776048..d7a3a5ab5 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -9,16 +9,16 @@ use Slic3r::GUI::OptionsGroup; use Slic3r::GUI::SkeinPanel; use Slic3r::GUI::Tab; -use Wx 0.9901 qw(:sizer :frame wxID_EXIT wxID_ABOUT); -use Wx::Event qw(EVT_MENU EVT_CLOSE); +use Wx 0.9901 qw(:bitmap :dialog :frame :icon :id :systemsettings); +use Wx::Event qw(EVT_CLOSE EVT_MENU); use base 'Wx::App'; my $growler; our $datadir; -our $small_font = Wx::SystemSettings::GetFont(&Wx::wxSYS_DEFAULT_GUI_FONT); +our $small_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); $small_font->SetPointSize(11) if !&Wx::wxMSW; -our $medium_font = Wx::SystemSettings::GetFont(&Wx::wxSYS_DEFAULT_GUI_FONT); +our $medium_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); $medium_font->SetPointSize(12); sub OnInit { @@ -52,7 +52,7 @@ sub OnInit { # application frame Wx::Image::AddHandler(Wx::PNGHandler->new); my $frame = Wx::Frame->new(undef, -1, 'Slic3r', [-1, -1], [760,520], wxDEFAULT_FRAME_STYLE); - $frame->SetIcon(Wx::Icon->new("$Slic3r::var/Slic3r_128px.png", &Wx::wxBITMAP_TYPE_PNG) ); + $frame->SetIcon(Wx::Icon->new("$Slic3r::var/Slic3r_128px.png", wxBITMAP_TYPE_PNG) ); $frame->{skeinpanel} = Slic3r::GUI::SkeinPanel->new($frame); # status bar @@ -127,7 +127,7 @@ sub catch_error { my ($self, $cb, $message_dialog) = @_; if (my $err = $@) { $cb->() if $cb; - my @params = ($err, 'Error', &Wx::wxOK | &Wx::wxICON_ERROR); + my @params = ($err, 'Error', wxOK | wxICON_ERROR); $message_dialog ? $message_dialog->(@params) : Wx::MessageDialog->new($self, @params)->ShowModal; @@ -139,7 +139,7 @@ sub catch_error { sub show_error { my $self = shift; my ($message) = @_; - Wx::MessageDialog->new($self, $message, 'Error', &Wx::wxOK | &Wx::wxICON_ERROR)->ShowModal; + Wx::MessageDialog->new($self, $message, 'Error', wxOK | wxICON_ERROR)->ShowModal; } sub fatal_error { @@ -152,7 +152,7 @@ sub warning_catcher { my ($self, $message_dialog) = @_; return sub { my $message = shift; - my @params = ($message, 'Warning', &Wx::wxOK | &Wx::wxICON_WARNING); + my @params = ($message, 'Warning', wxOK | wxICON_WARNING); $message_dialog ? $message_dialog->(@params) : Wx::MessageDialog->new($self, @params)->ShowModal; @@ -169,6 +169,7 @@ sub notify { } package Slic3r::GUI::ProgressStatusBar; +use Wx qw(:gauge); use base 'Wx::StatusBar'; sub new { @@ -178,7 +179,7 @@ sub new { $self->{_changed} = 0; $self->{busy} = 0; $self->{timer} = Wx::Timer->new($self); - $self->{prog} = Wx::Gauge->new($self, &Wx::wxGA_HORIZONTAL, 100, [-1,-1], [-1,-1]); + $self->{prog} = Wx::Gauge->new($self, wxGA_HORIZONTAL, 100, [-1,-1], [-1,-1]); $self->{prog}->Hide; $self->{cancelbutton} = Wx::Button->new($self, -1, "Cancel", [-1,-1], [-1,8]); $self->{cancelbutton}->Hide; diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index a26e27a35..4780b12d3 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -2,8 +2,8 @@ package Slic3r::GUI::OptionsGroup; use strict; use warnings; -use Wx qw(:sizer wxSYS_DEFAULT_GUI_FONT); -use Wx::Event qw(EVT_TEXT EVT_SPINCTRL EVT_CHECKBOX EVT_COMBOBOX); +use Wx qw(:combobox :font :misc :sizer :systemsettings :textctrl); +use Wx::Event qw(EVT_CHECKBOX EVT_COMBOBOX EVT_SPINCTRL EVT_TEXT); use base 'Wx::StaticBoxSizer'; @@ -19,12 +19,12 @@ sub new { my $self = $class->SUPER::new($box, wxVERTICAL); my $grid_sizer = Wx::FlexGridSizer->new(scalar(@{$p{options}}), 2, ($p{no_labels} ? 1 : 2), 0); - $grid_sizer->SetFlexibleDirection(&Wx::wxHORIZONTAL); + $grid_sizer->SetFlexibleDirection(wxHORIZONTAL); $grid_sizer->AddGrowableCol($p{no_labels} ? 0 : 1); # grab the default font, to fix Windows font issues/keep things consistent my $bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); - $bold_font->SetWeight(&Wx::wxFONTWEIGHT_BOLD); + $bold_font->SetWeight(wxFONTWEIGHT_BOLD); my $sidetext_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); my $onChange = $p{on_change} || sub {}; @@ -33,7 +33,7 @@ sub new { my $opt = $Slic3r::Config::Options->{$opt_key}; my $label; if (!$p{no_labels}) { - $label = Wx::StaticText->new($parent, -1, "$opt->{label}:", Wx::wxDefaultPosition, [$p{label_width} || 180, -1]); + $label = Wx::StaticText->new($parent, -1, "$opt->{label}:", wxDefaultPosition, [$p{label_width} || 180, -1]); $label->Wrap($p{label_width} || 180) ; # needed to avoid Linux/GTK bug $grid_sizer->Add($label); @@ -45,17 +45,17 @@ sub new { my $field; if ($opt->{type} =~ /^(i|f|s|s@)$/) { my $style = 0; - $style = &Wx::wxTE_MULTILINE if $opt->{multiline}; + $style = wxTE_MULTILINE if $opt->{multiline}; my $size = Wx::Size->new($opt->{width} || -1, $opt->{height} || -1); my ($get, $set) = $opt->{type} eq 's@' ? qw(serialize deserialize) : qw(get_raw set); if ($opt->{type} eq 'i') { my $value = Slic3r::Config->$get($opt_key); - $field = Wx::SpinCtrl->new($parent, -1, $value, Wx::wxDefaultPosition, $size, $style, $opt->{min} || 0, $opt->{max} || 100, $value); + $field = Wx::SpinCtrl->new($parent, -1, $value, wxDefaultPosition, $size, $style, $opt->{min} || 0, $opt->{max} || 100, $value); EVT_SPINCTRL($parent, $field, sub { Slic3r::Config->$set($opt_key, $field->GetValue); $onChange->($opt_key) }); } else { - $field = Wx::TextCtrl->new($parent, -1, Slic3r::Config->$get($opt_key), Wx::wxDefaultPosition, $size, $style); + $field = Wx::TextCtrl->new($parent, -1, Slic3r::Config->$get($opt_key), wxDefaultPosition, $size, $style); EVT_TEXT($parent, $field, sub { Slic3r::Config->$set($opt_key, $field->GetValue); $onChange->($opt_key) }); } $reload_callbacks{$opt_key} = sub { $field->SetValue(Slic3r::Config->$get($opt_key)) }; @@ -70,9 +70,9 @@ sub new { my $value = Slic3r::Config->get_raw($opt_key); my @items = ( Wx::StaticText->new($parent, -1, "x:"), - my $x_field = Wx::TextCtrl->new($parent, -1, $value->[0], Wx::wxDefaultPosition, $field_size), + my $x_field = Wx::TextCtrl->new($parent, -1, $value->[0], wxDefaultPosition, $field_size), Wx::StaticText->new($parent, -1, " y:"), - my $y_field = Wx::TextCtrl->new($parent, -1, $value->[1], Wx::wxDefaultPosition, $field_size), + my $y_field = Wx::TextCtrl->new($parent, -1, $value->[1], wxDefaultPosition, $field_size), ); $field->Add($_) for @items; if ($opt->{tooltip}) { @@ -93,7 +93,7 @@ sub new { }; $fields{$opt_key} = [$x_field, $y_field]; } elsif ($opt->{type} eq 'select') { - $field = Wx::ComboBox->new($parent, -1, "", Wx::wxDefaultPosition, Wx::wxDefaultSize, $opt->{labels} || $opt->{values}, &Wx::wxCB_READONLY); + $field = Wx::ComboBox->new($parent, -1, "", wxDefaultPosition, wxDefaultSize, $opt->{labels} || $opt->{values}, wxCB_READONLY); EVT_COMBOBOX($parent, $field, sub { Slic3r::Config->set($opt_key, $opt->{values}[$field->GetSelection]); $onChange->($opt_key); @@ -109,14 +109,14 @@ sub new { $label->SetToolTipString($opt->{tooltip}) if $label && $opt->{tooltip}; $field->SetToolTipString($opt->{tooltip}) if $opt->{tooltip} && $field->can('SetToolTipString'); if ($opt->{sidetext}) { - my $sizer = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); + my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); $sizer->Add($field); - my $sidetext = Wx::StaticText->new($parent, -1, $opt->{sidetext}, Wx::wxDefaultPosition, [-1, -1]); + my $sidetext = Wx::StaticText->new($parent, -1, $opt->{sidetext}, wxDefaultPosition, [-1, -1]); $sidetext->SetFont($sidetext_font); - $sizer->Add($sidetext, 0, &Wx::wxLEFT | &Wx::wxALIGN_CENTER_VERTICAL , 4); + $sizer->Add($sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL , 4); $grid_sizer->Add($sizer); } else { - $grid_sizer->Add($field, 0, $opt->{full_width} ? &Wx::wxEXPAND : 0); + $grid_sizer->Add($field, 0, $opt->{full_width} ? wxEXPAND : 0); } $fields{$opt_key} ||= [$field]; } diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index d004c13b5..fe408923e 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -8,10 +8,8 @@ use Math::ConvexHull qw(convex_hull); use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 scale unscale); use Slic3r::Geometry::Clipper qw(JT_ROUND); use threads::shared qw(shared_clone); -use Wx qw(:sizer :progressdialog wxOK wxICON_INFORMATION wxICON_WARNING wxICON_ERROR wxICON_QUESTION - wxOK wxCANCEL wxID_OK wxFD_OPEN wxFD_SAVE wxDEFAULT wxNORMAL); -use Wx::Event qw(EVT_BUTTON EVT_PAINT EVT_MOUSE_EVENTS EVT_LIST_ITEM_SELECTED EVT_LIST_ITEM_DESELECTED - EVT_COMMAND EVT_TOOL); +use Wx qw(:bitmap :brush :button :dialog :filedialog :font :icon :id :listctrl :pen :sizer :toolbar :window); +use Wx::Event qw(EVT_BUTTON EVT_COMMAND EVT_LIST_ITEM_DESELECTED EVT_LIST_ITEM_SELECTED EVT_MOUSE_EVENTS EVT_PAINT EVT_TOOL); use base 'Wx::Panel'; use constant TB_MORE => 1; @@ -38,53 +36,53 @@ sub new { EVT_PAINT($self->{canvas}, \&repaint); EVT_MOUSE_EVENTS($self->{canvas}, \&mouse_event); - $self->{objects_brush} = Wx::Brush->new(Wx::Colour->new(210,210,210), &Wx::wxSOLID); - $self->{selected_brush} = Wx::Brush->new(Wx::Colour->new(255,128,128), &Wx::wxSOLID); - $self->{transparent_brush} = Wx::Brush->new(Wx::Colour->new(0,0,0), &Wx::wxTRANSPARENT); - $self->{grid_pen} = Wx::Pen->new(Wx::Colour->new(230,230,230), 1, &Wx::wxSOLID); - $self->{print_center_pen} = Wx::Pen->new(Wx::Colour->new(200,200,200), 1, &Wx::wxSOLID); - $self->{clearance_pen} = Wx::Pen->new(Wx::Colour->new(0,0,200), 1, &Wx::wxSOLID); - $self->{skirt_pen} = Wx::Pen->new(Wx::Colour->new(150,150,150), 1, &Wx::wxSOLID); + $self->{objects_brush} = Wx::Brush->new(Wx::Colour->new(210,210,210), wxSOLID); + $self->{selected_brush} = Wx::Brush->new(Wx::Colour->new(255,128,128), wxSOLID); + $self->{transparent_brush} = Wx::Brush->new(Wx::Colour->new(0,0,0), wxTRANSPARENT); + $self->{grid_pen} = Wx::Pen->new(Wx::Colour->new(230,230,230), 1, wxSOLID); + $self->{print_center_pen} = Wx::Pen->new(Wx::Colour->new(200,200,200), 1, wxSOLID); + $self->{clearance_pen} = Wx::Pen->new(Wx::Colour->new(0,0,200), 1, wxSOLID); + $self->{skirt_pen} = Wx::Pen->new(Wx::Colour->new(150,150,150), 1, wxSOLID); - $self->{list} = Wx::ListView->new($self, -1, [-1, -1], [-1, 180], &Wx::wxLC_SINGLE_SEL | &Wx::wxLC_REPORT | &Wx::wxBORDER_DEFAULT); - $self->{list}->InsertColumn(0, "Name", &Wx::wxLIST_FORMAT_LEFT, 300); - $self->{list}->InsertColumn(1, "Copies", &Wx::wxLIST_FORMAT_CENTER, 50); - $self->{list}->InsertColumn(2, "Scale", &Wx::wxLIST_FORMAT_CENTER, &Wx::wxLIST_AUTOSIZE_USEHEADER); + $self->{list} = Wx::ListView->new($self, -1, [-1, -1], [-1, 180], wxLC_SINGLE_SEL | wxLC_REPORT | wxBORDER_DEFAULT); + $self->{list}->InsertColumn(0, "Name", wxLIST_FORMAT_LEFT, 300); + $self->{list}->InsertColumn(1, "Copies", wxLIST_FORMAT_CENTER, 50); + $self->{list}->InsertColumn(2, "Scale", wxLIST_FORMAT_CENTER, wxLIST_AUTOSIZE_USEHEADER); EVT_LIST_ITEM_SELECTED($self, $self->{list}, \&list_item_selected); EVT_LIST_ITEM_DESELECTED($self, $self->{list}, \&list_item_deselected); # toolbar for object manipulation if (!&Wx::wxMSW) { Wx::ToolTip::Enable(1); - $self->{htoolbar} = Wx::ToolBar->new($self, -1, [-1, -1], [-1, -1], &Wx::wxTB_HORIZONTAL | &Wx::wxTB_HORZ_TEXT); - $self->{htoolbar}->AddTool(TB_MORE, "More", Wx::Bitmap->new("$Slic3r::var/add.png", &Wx::wxBITMAP_TYPE_PNG), ''); - $self->{htoolbar}->AddTool(TB_LESS, "Less", Wx::Bitmap->new("$Slic3r::var/delete.png", &Wx::wxBITMAP_TYPE_PNG), ''); + $self->{htoolbar} = Wx::ToolBar->new($self, -1, [-1, -1], [-1, -1], wxTB_HORIZONTAL | wxTB_HORZ_TEXT); + $self->{htoolbar}->AddTool(TB_MORE, "More", Wx::Bitmap->new("$Slic3r::var/add.png", wxBITMAP_TYPE_PNG), ''); + $self->{htoolbar}->AddTool(TB_LESS, "Less", Wx::Bitmap->new("$Slic3r::var/delete.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddSeparator; - $self->{htoolbar}->AddTool(TB_45CCW, "45° ccw", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_anticlockwise.png", &Wx::wxBITMAP_TYPE_PNG), ''); - $self->{htoolbar}->AddTool(TB_45CW, "45° cw", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_clockwise.png", &Wx::wxBITMAP_TYPE_PNG), ''); - $self->{htoolbar}->AddTool(TB_ROTATE, "Rotate...", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_clockwise.png", &Wx::wxBITMAP_TYPE_PNG), ''); + $self->{htoolbar}->AddTool(TB_45CCW, "45° ccw", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_anticlockwise.png", wxBITMAP_TYPE_PNG), ''); + $self->{htoolbar}->AddTool(TB_45CW, "45° cw", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_clockwise.png", wxBITMAP_TYPE_PNG), ''); + $self->{htoolbar}->AddTool(TB_ROTATE, "Rotate...", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_clockwise.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddSeparator; - $self->{htoolbar}->AddTool(TB_SCALE, "Scale...", Wx::Bitmap->new("$Slic3r::var/arrow_out.png", &Wx::wxBITMAP_TYPE_PNG), ''); + $self->{htoolbar}->AddTool(TB_SCALE, "Scale...", Wx::Bitmap->new("$Slic3r::var/arrow_out.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddSeparator; - $self->{htoolbar}->AddTool(TB_SPLIT, "Split", Wx::Bitmap->new("$Slic3r::var/shape_ungroup.png", &Wx::wxBITMAP_TYPE_PNG), ''); + $self->{htoolbar}->AddTool(TB_SPLIT, "Split", Wx::Bitmap->new("$Slic3r::var/shape_ungroup.png", wxBITMAP_TYPE_PNG), ''); } else { my %tbar_buttons = (increase => "More", decrease => "Less", rotate45ccw => "45°", rotate45cw => "45°", rotate => "Rotate…", changescale => "Scale…", split => "Split"); $self->{btoolbar} = Wx::BoxSizer->new(wxHORIZONTAL); for (qw(increase decrease rotate45ccw rotate45cw rotate changescale split)) { - $self->{"btn_$_"} = Wx::Button->new($self, -1, $tbar_buttons{$_}, [-1,-1], [-1,-1], &Wx::wxBU_EXACTFIT); + $self->{"btn_$_"} = Wx::Button->new($self, -1, $tbar_buttons{$_}, [-1,-1], [-1,-1], wxBU_EXACTFIT); $self->{btoolbar}->Add($self->{"btn_$_"}); } } # general buttons - $self->{btn_load} = Wx::Button->new($self, -1, "Add…", [-1,-1], [-1,-1], &Wx::wxBU_LEFT); - $self->{btn_remove} = Wx::Button->new($self, -1, "Delete", [-1,-1], [-1,-1], &Wx::wxBU_LEFT); - $self->{btn_reset} = Wx::Button->new($self, -1, "Delete All", [-1,-1], [-1,-1], &Wx::wxBU_LEFT); - $self->{btn_arrange} = Wx::Button->new($self, -1, "Autoarrange", [-1,-1], [-1,-1], &Wx::wxBU_LEFT); - $self->{btn_export_gcode} = Wx::Button->new($self, -1, "Export G-code…", [-1,-1], [-1,-1], &Wx::wxBU_LEFT); + $self->{btn_load} = Wx::Button->new($self, -1, "Add…", [-1,-1], [-1,-1], wxBU_LEFT); + $self->{btn_remove} = Wx::Button->new($self, -1, "Delete", [-1,-1], [-1,-1], wxBU_LEFT); + $self->{btn_reset} = Wx::Button->new($self, -1, "Delete All", [-1,-1], [-1,-1], wxBU_LEFT); + $self->{btn_arrange} = Wx::Button->new($self, -1, "Autoarrange", [-1,-1], [-1,-1], wxBU_LEFT); + $self->{btn_export_gcode} = Wx::Button->new($self, -1, "Export G-code…", [-1,-1], [-1,-1], wxBU_LEFT); $self->{btn_export_gcode}->SetDefault; - $self->{btn_export_stl} = Wx::Button->new($self, -1, "Export STL…", [-1,-1], [-1,-1], &Wx::wxBU_LEFT); + $self->{btn_export_stl} = Wx::Button->new($self, -1, "Export STL…", [-1,-1], [-1,-1], wxBU_LEFT); if (&Wx::wxVERSION_STRING =~ / 2\.9\.[1-9]/) { my %icons = qw( @@ -104,7 +102,7 @@ sub new { split shape_ungroup.png ); for (grep $self->{"btn_$_"}, keys %icons) { - $self->{"btn_$_"}->SetBitmap(Wx::Bitmap->new("$Slic3r::var/$icons{$_}", &Wx::wxBITMAP_TYPE_PNG)); + $self->{"btn_$_"}->SetBitmap(Wx::Bitmap->new("$Slic3r::var/$icons{$_}", wxBITMAP_TYPE_PNG)); } } $self->selection_changed(0); @@ -190,7 +188,7 @@ sub new { my $vertical_sizer = Wx::BoxSizer->new(wxVERTICAL); $vertical_sizer->Add($self->{htoolbar}, 0, wxEXPAND, 0) if $self->{htoolbar}; $vertical_sizer->Add($self->{btoolbar}, 0, wxEXPAND, 0) if $self->{btoolbar}; - $vertical_sizer->Add($list_sizer, 0, wxEXPAND | &Wx::wxBOTTOM, 10); + $vertical_sizer->Add($list_sizer, 0, wxEXPAND | wxBOTTOM, 10); $vertical_sizer->Add($buttons, 0, wxEXPAND); my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL); @@ -225,7 +223,7 @@ sub load { my $self = shift; my $dir = $Slic3r::GUI::SkeinPanel::last_skein_dir || $Slic3r::GUI::SkeinPanel::last_config_dir || ""; - my $dialog = Wx::FileDialog->new($self, 'Choose one or more files (STL/OBJ/AMF):', $dir, "", $Slic3r::GUI::SkeinPanel::model_wildcard, wxFD_OPEN | &Wx::wxFD_MULTIPLE | &Wx::wxFD_FILE_MUST_EXIST); + my $dialog = Wx::FileDialog->new($self, 'Choose one or more files (STL/OBJ/AMF):', $dir, "", $Slic3r::GUI::SkeinPanel::model_wildcard, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); if ($dialog->ShowModal != wxID_OK) { $dialog->Destroy; return; @@ -443,7 +441,7 @@ sub export_gcode { my $self = shift; if ($self->{export_thread}) { - Wx::MessageDialog->new($self, "Another slicing job is currently running.", 'Error', wxOK | &Wx::wxICON_ERROR)->ShowModal; + Wx::MessageDialog->new($self, "Another slicing job is currently running.", 'Error', wxOK | wxICON_ERROR)->ShowModal; return; } @@ -579,7 +577,7 @@ sub export_stl { $output_file = $print->expanded_output_filepath($output_file); $output_file =~ s/\.gcode$/.stl/i; my $dlg = Wx::FileDialog->new($self, 'Save STL file as:', dirname($output_file), - basename($output_file), $Slic3r::GUI::SkeinPanel::model_wildcard, wxFD_SAVE | &Wx::wxFD_OVERWRITE_PROMPT); + basename($output_file), $Slic3r::GUI::SkeinPanel::model_wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if ($dlg->ShowModal != wxID_OK) { $dlg->Destroy; return; @@ -692,12 +690,12 @@ sub repaint { $dc->DrawLine(0, $size[Y]/2, $size[X], $size[Y]/2); $dc->SetTextForeground(Wx::Colour->new(0,0,0)); $dc->SetFont(Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL)); - $dc->DrawLabel("X = " . $Slic3r::print_center->[X], Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), &Wx::wxALIGN_CENTER_HORIZONTAL | &Wx::wxALIGN_BOTTOM); + $dc->DrawLabel("X = " . $Slic3r::print_center->[X], Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM); $dc->DrawRotatedText("Y = " . $Slic3r::print_center->[Y], 0, $size[Y]/2+15, 90); } # draw frame - $dc->SetPen(Wx::wxBLACK_PEN); + $dc->SetPen(wxBLACK_PEN); $dc->SetBrush($parent->{transparent_brush}); $dc->DrawRectangle(0, 0, @size); @@ -705,11 +703,11 @@ sub repaint { if (!@{$print->objects}) { $dc->SetTextForeground(Wx::Colour->new(150,50,50)); $dc->SetFont(Wx::Font->new(14, wxDEFAULT, wxNORMAL, wxNORMAL)); - $dc->DrawLabel("Drag your objects here", Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), &Wx::wxALIGN_CENTER_HORIZONTAL | &Wx::wxALIGN_CENTER_VERTICAL); + $dc->DrawLabel("Drag your objects here", Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); } # draw thumbnails - $dc->SetPen(Wx::wxBLACK_PEN); + $dc->SetPen(wxBLACK_PEN); @{$parent->{object_previews}} = (); for my $obj_idx (0 .. $#{$print->objects}) { next unless $parent->{thumbnails}[$obj_idx]; @@ -852,7 +850,6 @@ sub _y { } package Slic3r::GUI::Plater::DropTarget; - use Wx::DND; use base 'Wx::FileDropTarget'; diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 907e9c0d9..158f7230b 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -5,8 +5,7 @@ use utf8; use File::Basename qw(basename dirname); use Slic3r::Geometry qw(X Y); -use Wx qw(:sizer :progressdialog wxOK wxICON_INFORMATION wxICON_WARNING wxICON_ERROR wxICON_QUESTION - wxOK wxCANCEL wxID_OK wxFD_OPEN wxFD_SAVE wxDEFAULT wxNORMAL); +use Wx qw(:dialog :filedialog :font :icon :id :misc :notebook :sizer); use Wx::Event qw(EVT_BUTTON); use base 'Wx::Panel'; @@ -21,7 +20,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, -1); - my $tabpanel = Wx::Notebook->new($self, -1, Wx::wxDefaultPosition, Wx::wxDefaultSize, &Wx::wxNB_TOP); + my $tabpanel = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP); $tabpanel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($tabpanel), "Plater"); $self->{options_tabs} = { print => Slic3r::GUI::Tab::Print->new ($tabpanel, sync_presets_with => $self->{plater}{preset_choosers}{print}), @@ -49,7 +48,7 @@ sub new { $buttons_sizer->Add($load_button, 0, wxRIGHT, 5); EVT_BUTTON($self, $load_button, sub { $self->load_config }); - my $text = Wx::StaticText->new($self, -1, "Remember to check for updates at http://slic3r.org/\nVersion: $Slic3r::VERSION", Wx::wxDefaultPosition, Wx::wxDefaultSize, wxALIGN_RIGHT); + my $text = Wx::StaticText->new($self, -1, "Remember to check for updates at http://slic3r.org/\nVersion: $Slic3r::VERSION", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); my $font = Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL); $text->SetFont($font); $buttons_sizer->Add($text, 1, wxEXPAND | wxALIGN_RIGHT); @@ -94,7 +93,7 @@ sub do_slice { my $input_file; if (!$params{reslice}) { - my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF):', $dir, "", $model_wildcard, wxFD_OPEN | &Wx::wxFD_FILE_MUST_EXIST); + my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF):', $dir, "", $model_wildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST); if ($dialog->ShowModal != wxID_OK) { $dialog->Destroy; return; @@ -192,7 +191,7 @@ sub save_config { my $dir = $last_config ? dirname($last_config) : $last_config_dir || $last_skein_dir || ""; my $filename = $last_config ? basename($last_config) : "config.ini"; my $dlg = Wx::FileDialog->new($self, 'Save configuration as:', $dir, $filename, - $ini_wildcard, wxFD_SAVE | &Wx::wxFD_OVERWRITE_PROMPT); + $ini_wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if ($dlg->ShowModal == wxID_OK) { my $file = $dlg->GetPath; $last_config_dir = dirname($file); @@ -207,7 +206,7 @@ sub load_config { my $dir = $last_config ? dirname($last_config) : $last_config_dir || $last_skein_dir || ""; my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini", - $ini_wildcard, wxFD_OPEN | &Wx::wxFD_FILE_MUST_EXIST); + $ini_wildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST); if ($dlg->ShowModal == wxID_OK) { my ($file) = $dlg->GetPaths; $last_config_dir = dirname($file); diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 77477bbbf..f6190e28b 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -5,14 +5,14 @@ use utf8; use File::Basename qw(basename); use List::Util qw(first); -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(EVT_TREE_SEL_CHANGED EVT_CHOICE EVT_BUTTON); +use Wx qw(:bookctrl :dialog :icon :id :sizer :treectrl); +use Wx::Event qw(EVT_BUTTON EVT_CHOICE EVT_TREE_SEL_CHANGED); use base 'Wx::Panel'; sub new { my $class = shift; my ($parent, $title, %params) = @_; - my $self = $class->SUPER::new($parent, -1, [-1,-1], [-1,-1], &Wx::wxBK_LEFT); + my $self = $class->SUPER::new($parent, -1, [-1,-1], [-1,-1], wxBK_LEFT); $self->{title} = $title; @@ -23,13 +23,13 @@ sub new { }); # horizontal sizer - $self->{sizer} = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); + $self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL); $self->{sizer}->SetSizeHints($self); $self->SetSizer($self->{sizer}); # left vertical sizer - my $left_sizer = Wx::BoxSizer->new(&Wx::wxVERTICAL); - $self->{sizer}->Add($left_sizer, 0, &Wx::wxEXPAND); + my $left_sizer = Wx::BoxSizer->new(wxVERTICAL); + $self->{sizer}->Add($left_sizer, 0, wxEXPAND); my $left_col_width = 200; @@ -41,27 +41,27 @@ sub new { $self->{presets_choice}->SetFont($Slic3r::GUI::small_font); # buttons - $self->{btn_save_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/disk.png", &Wx::wxBITMAP_TYPE_PNG)); - $self->{btn_delete_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/delete.png", &Wx::wxBITMAP_TYPE_PNG)); + $self->{btn_save_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/disk.png", wxBITMAP_TYPE_PNG)); + $self->{btn_delete_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/delete.png", wxBITMAP_TYPE_PNG)); $self->{btn_save_preset}->SetToolTipString("Save current " . lc($title)); $self->{btn_delete_preset}->SetToolTipString("Delete this preset"); $self->{btn_delete_preset}->Disable; ### These cause GTK warnings: ###my $box = Wx::StaticBox->new($self, -1, "Presets:", [-1, -1], [$left_col_width, 50]); - ###my $hsizer = Wx::StaticBoxSizer->new($box, &Wx::wxHORIZONTAL); + ###my $hsizer = Wx::StaticBoxSizer->new($box, wxHORIZONTAL); - my $hsizer = Wx::BoxSizer->new(&Wx::wxHORIZONTAL); + my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL); - $left_sizer->Add($hsizer, 0, &Wx::wxEXPAND | &Wx::wxBOTTOM, 5); - $hsizer->Add($self->{presets_choice}, 1, &Wx::wxRIGHT | &Wx::wxALIGN_CENTER_VERTICAL, 3); - $hsizer->Add($self->{btn_save_preset}, 0, &Wx::wxALIGN_CENTER_VERTICAL); - $hsizer->Add($self->{btn_delete_preset}, 0, &Wx::wxALIGN_CENTER_VERTICAL); + $left_sizer->Add($hsizer, 0, wxEXPAND | wxBOTTOM, 5); + $hsizer->Add($self->{presets_choice}, 1, wxRIGHT | wxALIGN_CENTER_VERTICAL, 3); + $hsizer->Add($self->{btn_save_preset}, 0, wxALIGN_CENTER_VERTICAL); + $hsizer->Add($self->{btn_delete_preset}, 0, wxALIGN_CENTER_VERTICAL); } # tree - $self->{treectrl} = Wx::TreeCtrl->new($self, -1, [-1, -1], [$left_col_width, -1], &Wx::wxTR_NO_BUTTONS | &Wx::wxTR_HIDE_ROOT | &Wx::wxTR_SINGLE | &Wx::wxTR_NO_LINES); - $left_sizer->Add($self->{treectrl}, 1, &Wx::wxEXPAND); + $self->{treectrl} = Wx::TreeCtrl->new($self, -1, [-1, -1], [$left_col_width, -1], wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES); + $left_sizer->Add($self->{treectrl}, 1, wxEXPAND); $self->{icons} = Wx::ImageList->new(16, 16, 1); $self->{treectrl}->AssignImageList($self->{icons}); $self->{iconcount} = -1; @@ -73,7 +73,7 @@ sub new { $self->{sizer}->Remove(1); my $page = $self->{pages}->{ $self->{treectrl}->GetItemText($self->{treectrl}->GetSelection) }; $page->Show; - $self->{sizer}->Add($page, 1, &Wx::wxEXPAND | &Wx::wxLEFT, 5); + $self->{sizer}->Add($page, 1, wxEXPAND | wxLEFT, 5); $self->{sizer}->Layout; }); @@ -92,7 +92,7 @@ sub new { default => $default, values => [ map { my $filename = basename($_); $filename =~ /^(.*?)\.ini$/i; $1 } @{$self->{presets}} ], ); - return unless $dlg->ShowModal == &Wx::wxID_OK; + return unless $dlg->ShowModal == wxID_OK; my $file = sprintf "$Slic3r::GUI::datadir/$self->{presets_group}/%s.ini", $dlg->get_name; Slic3r::Config->save($file, $self->{presets_group}); @@ -106,8 +106,8 @@ sub new { EVT_BUTTON($self, $self->{btn_delete_preset}, sub { my $i = $self->{presets_choice}->GetSelection; return if $i == 0; # this shouldn't happen but let's trap it anyway - my $res = Wx::MessageDialog->new($self, "Are you sure you want to delete the selected preset?", 'Delete Preset', &Wx::wxYES_NO | &Wx::wxNO_DEFAULT | &Wx::wxICON_QUESTION)->ShowModal; - return unless $res == &Wx::wxID_YES; + my $res = Wx::MessageDialog->new($self, "Are you sure you want to delete the selected preset?", 'Delete Preset', wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION)->ShowModal; + return unless $res == wxID_YES; if (-e $self->{presets}[$i-1]) { unlink $self->{presets}[$i-1]; } @@ -159,7 +159,7 @@ sub add_options_page { }); my $bitmap = $icon - ? Wx::Bitmap->new("$Slic3r::var/$icon", &Wx::wxBITMAP_TYPE_PNG) + ? Wx::Bitmap->new("$Slic3r::var/$icon", wxBITMAP_TYPE_PNG) : undef; if ($bitmap) { $self->{icons}->Add($bitmap); @@ -260,8 +260,6 @@ sub sync_presets { } package Slic3r::GUI::Tab::Print; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); use base 'Slic3r::GUI::Tab'; sub new { @@ -366,8 +364,6 @@ sub new { } package Slic3r::GUI::Tab::Filament; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); use base 'Slic3r::GUI::Tab'; sub new { @@ -408,8 +404,6 @@ sub new { } package Slic3r::GUI::Tab::Printer; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); use base 'Slic3r::GUI::Tab'; sub new { @@ -463,8 +457,7 @@ sub new { } package Slic3r::GUI::Tab::Page; -use Wx qw(:sizer :progressdialog); -use Wx::Event qw(); +use Wx qw(:sizer); use base 'Wx::ScrolledWindow'; sub new { @@ -474,7 +467,7 @@ sub new { $self->SetScrollbars(1, 1, 1, 1); - $self->{vsizer} = Wx::BoxSizer->new(&Wx::wxVERTICAL); + $self->{vsizer} = Wx::BoxSizer->new(wxVERTICAL); $self->SetSizer($self->{vsizer}); if ($params{optgroups}) { @@ -492,7 +485,7 @@ sub append_optgroup { } package Slic3r::GUI::SavePresetWindow; -use Wx qw(:sizer); +use Wx qw(:combobox :dialog :id :sizer); use Wx::Event qw(EVT_BUTTON EVT_TEXT_ENTER); use base 'Wx::Dialog'; @@ -503,15 +496,15 @@ sub new { my $text = Wx::StaticText->new($self, -1, "Save " . lc($params{title}) . " as:", [-1, -1], [-1, -1]); $self->{combo} = Wx::ComboBox->new($self, -1, $params{default}, [-1, -1], [-1, -1], $params{values}, - &Wx::wxTE_PROCESS_ENTER); - my $buttons = $self->CreateStdDialogButtonSizer(&Wx::wxOK | &Wx::wxCANCEL); + wxTE_PROCESS_ENTER); + my $buttons = $self->CreateStdDialogButtonSizer(wxOK | wxCANCEL); my $sizer = Wx::BoxSizer->new(wxVERTICAL); $sizer->Add($text, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 10); $sizer->Add($self->{combo}, 0, wxEXPAND | wxLEFT | wxRIGHT, 10); $sizer->Add($buttons, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10); - EVT_BUTTON($self, &Wx::wxID_OK, \&accept); + EVT_BUTTON($self, wxID_OK, \&accept); EVT_TEXT_ENTER($self, $self->{combo}, \&accept); $self->SetSizer($sizer); @@ -524,7 +517,7 @@ sub accept { my ($self, $event) = @_; if (($self->{chosen_name} = $self->{combo}->GetValue) && $self->{chosen_name} =~ /^[a-z0-9 _-]+$/i) { - $self->EndModal(&Wx::wxID_OK); + $self->EndModal(wxID_OK); } } From a4219ba352a72b3a8c41206d79f5b93eb81aa300 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 1 Jul 2012 19:35:48 +0200 Subject: [PATCH 056/106] Sort imported events alphabetically --- lib/Slic3r/GUI/ConfigWizard.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index 049155b20..06ffe24b3 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -60,7 +60,7 @@ sub run { package Slic3r::GUI::ConfigWizard::Option; use Wx qw(:combobox :misc :sizer :textctrl); -use Wx::Event qw(EVT_SPINCTRL EVT_TEXT EVT_CHECKBOX EVT_COMBOBOX); +use Wx::Event qw(EVT_CHECKBOX EVT_COMBOBOX EVT_SPINCTRL EVT_TEXT); use base 'Wx::StaticBoxSizer'; sub new { From cd7661aa2ae667769ab1bad1a8f1610eba2f2792 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 1 Jul 2012 23:29:56 +0200 Subject: [PATCH 057/106] Use proper ellipsis for all GUI '...' strings --- lib/Slic3r/GUI/Plater.pm | 14 +++++++------- lib/Slic3r/GUI/SkeinPanel.pm | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index fe408923e..c765a1480 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -60,9 +60,9 @@ sub new { $self->{htoolbar}->AddSeparator; $self->{htoolbar}->AddTool(TB_45CCW, "45° ccw", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_anticlockwise.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_45CW, "45° cw", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_clockwise.png", wxBITMAP_TYPE_PNG), ''); - $self->{htoolbar}->AddTool(TB_ROTATE, "Rotate...", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_clockwise.png", wxBITMAP_TYPE_PNG), ''); + $self->{htoolbar}->AddTool(TB_ROTATE, "Rotate…", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_clockwise.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddSeparator; - $self->{htoolbar}->AddTool(TB_SCALE, "Scale...", Wx::Bitmap->new("$Slic3r::var/arrow_out.png", wxBITMAP_TYPE_PNG), ''); + $self->{htoolbar}->AddTool(TB_SCALE, "Scale…", Wx::Bitmap->new("$Slic3r::var/arrow_out.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddSeparator; $self->{htoolbar}->AddTool(TB_SPLIT, "Split", Wx::Bitmap->new("$Slic3r::var/shape_ungroup.png", wxBITMAP_TYPE_PNG), ''); } else { @@ -146,7 +146,7 @@ sub new { my ($self, $event) = @_; my ($percent, $message) = @{$event->GetData}; $self->statusbar->SetProgress($percent); - $self->statusbar->SetStatusText("$message..."); + $self->statusbar->SetStatusText("$message…"); }); EVT_COMMAND($self, -1, $MESSAGE_DIALOG_EVENT, sub { @@ -239,7 +239,7 @@ sub load_file { $Slic3r::GUI::SkeinPanel::last_input_file = $input_file; - my $process_dialog = Wx::ProgressDialog->new('Loading...', "Processing input file...", 100, $self, 0); + my $process_dialog = Wx::ProgressDialog->new('Loading…', "Processing input file…", 100, $self, 0); $process_dialog->Pulse; local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); $self->{print}->add_object_from_file($input_file); @@ -353,7 +353,7 @@ sub rotate { return if !$angle || $angle == -1; } - $self->statusbar->SetStatusText("Rotating object..."); + $self->statusbar->SetStatusText("Rotating object…"); $self->statusbar->StartBusy; # rotate, realign to 0,0 and update size @@ -390,7 +390,7 @@ sub changescale { $scale = Wx::GetNumberFromUser("", "Enter the scale % for the selected object:", "Scale", $scale*100, 0, 1000, $self); return if !$scale || $scale == -1; - $self->statusbar->SetStatusText("Scaling object..."); + $self->statusbar->SetStatusText("Scaling object…"); $self->statusbar->StartBusy; my $object = $self->{print}->objects->[$obj_idx]; @@ -487,7 +487,7 @@ sub export_gcode { progressbar => sub { my ($percent, $message) = @_; $self->statusbar->SetProgress($percent); - $self->statusbar->SetStatusText("$message..."); + $self->statusbar->SetStatusText("$message…"); }, message_dialog => sub { Wx::MessageDialog->new($self, @_)->ShowModal }, on_completed => sub { $self->on_export_completed(@_) }, diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 158f7230b..0d2675262 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -40,11 +40,11 @@ sub new { $buttons_sizer->Add($slice_button, 0, wxRIGHT, 20); EVT_BUTTON($self, $slice_button, sub { $self->do_slice }); - my $save_button = Wx::Button->new($self, -1, "Export config..."); + my $save_button = Wx::Button->new($self, -1, "Export config…"); $buttons_sizer->Add($save_button, 0, wxRIGHT, 5); EVT_BUTTON($self, $save_button, sub { $self->save_config }); - my $load_button = Wx::Button->new($self, -1, "Load config..."); + my $load_button = Wx::Button->new($self, -1, "Load config…"); $buttons_sizer->Add($load_button, 0, wxRIGHT, 5); EVT_BUTTON($self, $load_button, sub { $self->load_config }); @@ -139,7 +139,7 @@ sub do_slice { } # show processbar dialog - $process_dialog = Wx::ProgressDialog->new('Slicing...', "Processing $input_file_basename...", + $process_dialog = Wx::ProgressDialog->new('Slicing…', "Processing $input_file_basename…", 100, $self, 0); $process_dialog->Pulse; @@ -151,7 +151,7 @@ sub do_slice { status_cb => sub { my ($percent, $message) = @_; if (&Wx::wxVERSION_STRING =~ / 2\.(8\.|9\.[2-9])/) { - $process_dialog->Update($percent, "$message..."); + $process_dialog->Update($percent, "$message…"); } }, ); From e8a20eed6a91b0e00dd27d204643ea21da0498b0 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 3 Jul 2012 00:42:06 +0200 Subject: [PATCH 058/106] Use wxDefaultSize instead of [-1, -1] --- lib/Slic3r/GUI/ConfigWizard.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index 06ffe24b3..94f5ff833 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -125,7 +125,7 @@ sub new { if ($opt->{sidetext}) { my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); $sizer->Add($field); - my $sidetext = Wx::StaticText->new($parent, -1, $opt->{sidetext}, wxDefaultPosition, [-1, -1]); + my $sidetext = Wx::StaticText->new($parent, -1, $opt->{sidetext}, wxDefaultPosition, wxDefaultSize); $sizer->Add($sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4); $self->Add($sizer); } else { From 92ec70c8606a45c0b029c0ccd99dafa8dd504bb9 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 3 Jul 2012 01:20:30 +0200 Subject: [PATCH 059/106] Use wxDefaultPosition and wxDefaultSize to improve readability --- lib/Slic3r/GUI.pm | 10 +++++----- lib/Slic3r/GUI/OptionsGroup.pm | 2 +- lib/Slic3r/GUI/Plater.pm | 26 +++++++++++++------------- lib/Slic3r/GUI/Tab.pm | 18 +++++++++--------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index d7a3a5ab5..346de87ed 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -9,7 +9,7 @@ use Slic3r::GUI::OptionsGroup; use Slic3r::GUI::SkeinPanel; use Slic3r::GUI::Tab; -use Wx 0.9901 qw(:bitmap :dialog :frame :icon :id :systemsettings); +use Wx 0.9901 qw(:bitmap :dialog :frame :icon :id :misc :systemsettings); use Wx::Event qw(EVT_CLOSE EVT_MENU); use base 'Wx::App'; @@ -51,7 +51,7 @@ sub OnInit { # application frame Wx::Image::AddHandler(Wx::PNGHandler->new); - my $frame = Wx::Frame->new(undef, -1, 'Slic3r', [-1, -1], [760,520], wxDEFAULT_FRAME_STYLE); + my $frame = Wx::Frame->new(undef, -1, 'Slic3r', wxDefaultPosition, [760,520], wxDEFAULT_FRAME_STYLE); $frame->SetIcon(Wx::Icon->new("$Slic3r::var/Slic3r_128px.png", wxBITMAP_TYPE_PNG) ); $frame->{skeinpanel} = Slic3r::GUI::SkeinPanel->new($frame); @@ -169,7 +169,7 @@ sub notify { } package Slic3r::GUI::ProgressStatusBar; -use Wx qw(:gauge); +use Wx qw(:gauge :misc); use base 'Wx::StatusBar'; sub new { @@ -179,9 +179,9 @@ sub new { $self->{_changed} = 0; $self->{busy} = 0; $self->{timer} = Wx::Timer->new($self); - $self->{prog} = Wx::Gauge->new($self, wxGA_HORIZONTAL, 100, [-1,-1], [-1,-1]); + $self->{prog} = Wx::Gauge->new($self, wxGA_HORIZONTAL, 100, wxDefaultPosition, wxDefaultSize); $self->{prog}->Hide; - $self->{cancelbutton} = Wx::Button->new($self, -1, "Cancel", [-1,-1], [-1,8]); + $self->{cancelbutton} = Wx::Button->new($self, -1, "Cancel", wxDefaultPosition, [-1,8]); $self->{cancelbutton}->Hide; $self->SetFieldsCount(3); diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index 4780b12d3..1c7aa96d8 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -111,7 +111,7 @@ sub new { if ($opt->{sidetext}) { my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); $sizer->Add($field); - my $sidetext = Wx::StaticText->new($parent, -1, $opt->{sidetext}, wxDefaultPosition, [-1, -1]); + my $sidetext = Wx::StaticText->new($parent, -1, $opt->{sidetext}, wxDefaultPosition, wxDefaultSize); $sidetext->SetFont($sidetext_font); $sizer->Add($sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL , 4); $grid_sizer->Add($sizer); diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index c765a1480..48297e304 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -8,7 +8,7 @@ use Math::ConvexHull qw(convex_hull); use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 scale unscale); use Slic3r::Geometry::Clipper qw(JT_ROUND); use threads::shared qw(shared_clone); -use Wx qw(:bitmap :brush :button :dialog :filedialog :font :icon :id :listctrl :pen :sizer :toolbar :window); +use Wx qw(:bitmap :brush :button :dialog :filedialog :font :icon :id :listctrl :misc :pen :sizer :toolbar :window); use Wx::Event qw(EVT_BUTTON EVT_COMMAND EVT_LIST_ITEM_DESELECTED EVT_LIST_ITEM_SELECTED EVT_MOUSE_EVENTS EVT_PAINT EVT_TOOL); use base 'Wx::Panel'; @@ -31,7 +31,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, -1); - $self->{canvas} = Wx::Panel->new($self, -1, [-1, -1], [300, 300]); + $self->{canvas} = Wx::Panel->new($self, -1, wxDefaultPosition, [300, 300]); $self->{canvas}->SetBackgroundColour(Wx::wxWHITE); EVT_PAINT($self->{canvas}, \&repaint); EVT_MOUSE_EVENTS($self->{canvas}, \&mouse_event); @@ -44,7 +44,7 @@ sub new { $self->{clearance_pen} = Wx::Pen->new(Wx::Colour->new(0,0,200), 1, wxSOLID); $self->{skirt_pen} = Wx::Pen->new(Wx::Colour->new(150,150,150), 1, wxSOLID); - $self->{list} = Wx::ListView->new($self, -1, [-1, -1], [-1, 180], wxLC_SINGLE_SEL | wxLC_REPORT | wxBORDER_DEFAULT); + $self->{list} = Wx::ListView->new($self, -1, wxDefaultPosition, [-1, 180], wxLC_SINGLE_SEL | wxLC_REPORT | wxBORDER_DEFAULT); $self->{list}->InsertColumn(0, "Name", wxLIST_FORMAT_LEFT, 300); $self->{list}->InsertColumn(1, "Copies", wxLIST_FORMAT_CENTER, 50); $self->{list}->InsertColumn(2, "Scale", wxLIST_FORMAT_CENTER, wxLIST_AUTOSIZE_USEHEADER); @@ -54,7 +54,7 @@ sub new { # toolbar for object manipulation if (!&Wx::wxMSW) { Wx::ToolTip::Enable(1); - $self->{htoolbar} = Wx::ToolBar->new($self, -1, [-1, -1], [-1, -1], wxTB_HORIZONTAL | wxTB_HORZ_TEXT); + $self->{htoolbar} = Wx::ToolBar->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxTB_HORZ_TEXT); $self->{htoolbar}->AddTool(TB_MORE, "More", Wx::Bitmap->new("$Slic3r::var/add.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_LESS, "Less", Wx::Bitmap->new("$Slic3r::var/delete.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddSeparator; @@ -70,19 +70,19 @@ sub new { rotate => "Rotate…", changescale => "Scale…", split => "Split"); $self->{btoolbar} = Wx::BoxSizer->new(wxHORIZONTAL); for (qw(increase decrease rotate45ccw rotate45cw rotate changescale split)) { - $self->{"btn_$_"} = Wx::Button->new($self, -1, $tbar_buttons{$_}, [-1,-1], [-1,-1], wxBU_EXACTFIT); + $self->{"btn_$_"} = Wx::Button->new($self, -1, $tbar_buttons{$_}, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); $self->{btoolbar}->Add($self->{"btn_$_"}); } } # general buttons - $self->{btn_load} = Wx::Button->new($self, -1, "Add…", [-1,-1], [-1,-1], wxBU_LEFT); - $self->{btn_remove} = Wx::Button->new($self, -1, "Delete", [-1,-1], [-1,-1], wxBU_LEFT); - $self->{btn_reset} = Wx::Button->new($self, -1, "Delete All", [-1,-1], [-1,-1], wxBU_LEFT); - $self->{btn_arrange} = Wx::Button->new($self, -1, "Autoarrange", [-1,-1], [-1,-1], wxBU_LEFT); - $self->{btn_export_gcode} = Wx::Button->new($self, -1, "Export G-code…", [-1,-1], [-1,-1], wxBU_LEFT); + $self->{btn_load} = Wx::Button->new($self, -1, "Add…", wxDefaultPosition, wxDefaultSize, wxBU_LEFT); + $self->{btn_remove} = Wx::Button->new($self, -1, "Delete", wxDefaultPosition, wxDefaultSize, wxBU_LEFT); + $self->{btn_reset} = Wx::Button->new($self, -1, "Delete All", wxDefaultPosition, wxDefaultSize, wxBU_LEFT); + $self->{btn_arrange} = Wx::Button->new($self, -1, "Autoarrange", wxDefaultPosition, wxDefaultSize, wxBU_LEFT); + $self->{btn_export_gcode} = Wx::Button->new($self, -1, "Export G-code…", wxDefaultPosition, wxDefaultSize, wxBU_LEFT); $self->{btn_export_gcode}->SetDefault; - $self->{btn_export_stl} = Wx::Button->new($self, -1, "Export STL…", [-1,-1], [-1,-1], wxBU_LEFT); + $self->{btn_export_stl} = Wx::Button->new($self, -1, "Export STL…", wxDefaultPosition, wxDefaultSize, wxBU_LEFT); if (&Wx::wxVERSION_STRING =~ / 2\.9\.[1-9]/) { my %icons = qw( @@ -203,8 +203,8 @@ sub new { ); $self->{preset_choosers} = {}; for my $group (qw(print filament printer)) { - my $text = Wx::StaticText->new($self, -1, "$group_labels{$group}:", [-1, -1], [-1, -1], wxALIGN_RIGHT); - $self->{preset_choosers}{$group} = Wx::Choice->new($self, -1, [-1, -1], [150, -1], []); + my $text = Wx::StaticText->new($self, -1, "$group_labels{$group}:", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); + $self->{preset_choosers}{$group} = Wx::Choice->new($self, -1, wxDefaultPosition, [150, -1], []); $presets->Add($text, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxRIGHT, 4); $presets->Add($self->{preset_choosers}{$group}, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 15); } diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index f6190e28b..75e9e919c 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -5,14 +5,14 @@ use utf8; use File::Basename qw(basename); use List::Util qw(first); -use Wx qw(:bookctrl :dialog :icon :id :sizer :treectrl); +use Wx qw(:bookctrl :dialog :icon :id :misc :sizer :treectrl); use Wx::Event qw(EVT_BUTTON EVT_CHOICE EVT_TREE_SEL_CHANGED); use base 'Wx::Panel'; sub new { my $class = shift; my ($parent, $title, %params) = @_; - my $self = $class->SUPER::new($parent, -1, [-1,-1], [-1,-1], wxBK_LEFT); + my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxBK_LEFT); $self->{title} = $title; @@ -37,7 +37,7 @@ sub new { { # choice menu - $self->{presets_choice} = Wx::Choice->new($self, -1, [-1, -1], [-1, -1], []); + $self->{presets_choice} = Wx::Choice->new($self, -1, wxDefaultPosition, wxDefaultSize, []); $self->{presets_choice}->SetFont($Slic3r::GUI::small_font); # buttons @@ -48,7 +48,7 @@ sub new { $self->{btn_delete_preset}->Disable; ### These cause GTK warnings: - ###my $box = Wx::StaticBox->new($self, -1, "Presets:", [-1, -1], [$left_col_width, 50]); + ###my $box = Wx::StaticBox->new($self, -1, "Presets:", wxDefaultPosition, [$left_col_width, 50]); ###my $hsizer = Wx::StaticBoxSizer->new($box, wxHORIZONTAL); my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL); @@ -60,7 +60,7 @@ sub new { } # tree - $self->{treectrl} = Wx::TreeCtrl->new($self, -1, [-1, -1], [$left_col_width, -1], wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES); + $self->{treectrl} = Wx::TreeCtrl->new($self, -1, wxDefaultPosition, [$left_col_width, -1], wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES); $left_sizer->Add($self->{treectrl}, 1, wxEXPAND); $self->{icons} = Wx::ImageList->new(16, 16, 1); $self->{treectrl}->AssignImageList($self->{icons}); @@ -485,17 +485,17 @@ sub append_optgroup { } package Slic3r::GUI::SavePresetWindow; -use Wx qw(:combobox :dialog :id :sizer); +use Wx qw(:combobox :dialog :id :misc :sizer); use Wx::Event qw(EVT_BUTTON EVT_TEXT_ENTER); use base 'Wx::Dialog'; sub new { my $class = shift; my ($parent, %params) = @_; - my $self = $class->SUPER::new($parent, -1, "Save preset", [-1, -1], [-1, -1]); + my $self = $class->SUPER::new($parent, -1, "Save preset", wxDefaultPosition, wxDefaultSize); - my $text = Wx::StaticText->new($self, -1, "Save " . lc($params{title}) . " as:", [-1, -1], [-1, -1]); - $self->{combo} = Wx::ComboBox->new($self, -1, $params{default}, [-1, -1], [-1, -1], $params{values}, + my $text = Wx::StaticText->new($self, -1, "Save " . lc($params{title}) . " as:", wxDefaultPosition, wxDefaultSize); + $self->{combo} = Wx::ComboBox->new($self, -1, $params{default}, wxDefaultPosition, wxDefaultSize, $params{values}, wxTE_PROCESS_ENTER); my $buttons = $self->CreateStdDialogButtonSizer(wxOK | wxCANCEL); From 3fa58cf85bd6953c9d24b90f74464ca07282e079 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 3 Jul 2012 17:21:32 +0200 Subject: [PATCH 060/106] Add a friendly index --- lib/Slic3r/GUI/ConfigWizard.pm | 103 +++++++++++++++++++++++++++------ var/bullet_black.png | Bin 0 -> 211 bytes var/bullet_blue.png | Bin 0 -> 289 bytes var/bullet_white.png | Bin 0 -> 201 bytes 4 files changed, 85 insertions(+), 18 deletions(-) create mode 100755 var/bullet_black.png create mode 100755 var/bullet_blue.png create mode 100755 var/bullet_white.png diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index 94f5ff833..9dd382cde 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -3,15 +3,13 @@ use strict; use warnings; use utf8; -use Wx qw(:bitmap); +use Wx; use base 'Wx::Wizard'; sub new { my $class = shift; my ($parent) = @_; - # TODO: Add instructional bitmaps - my $self = $class->SUPER::new($parent, -1, 'Configuration Wizard', - Wx::Bitmap->new("$Slic3r::var/Slic3r_128px.png", wxBITMAP_TYPE_PNG)); + my $self = $class->SUPER::new($parent, -1, 'Configuration Wizard'); # Start from sane defaults $self->{old} = Slic3r::Config->current; @@ -26,6 +24,8 @@ sub new { $self->add_page(Slic3r::GUI::ConfigWizard::Page::BedTemperature->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Finished->new($self)); + $_->build_index for @{$self->{pages}}; + return $self; } @@ -77,7 +77,7 @@ sub new { my $callback = $params{callback} || sub {}; # label - my $label = Wx::StaticText->new($parent, -1, "$opt->{label}:", wxDefaultPosition, [$label_width, -1]); + my $label = Wx::StaticText->new($parent, -1, "$opt->{label}:", wxDefaultPosition, wxDefaultSize); $label->Wrap($label_width); $self->Add($label, 1, wxEXPAND); @@ -135,18 +135,62 @@ sub new { return $self; } -package Slic3r::GUI::ConfigWizard::Page; -use Wx qw(:font :misc :sizer :staticline :systemsettings); -use base 'Wx::WizardPage'; +package Slic3r::GUI::ConfigWizard::Index; +use Wx qw(:bitmap :font :misc :sizer :systemsettings); +use base 'Wx::Panel'; sub new { my $class = shift; my ($parent, $title) = @_; my $self = $class->SUPER::new($parent); - $self->{width} = 400; - $self->{vsizer} = Wx::BoxSizer->new(wxVERTICAL); - $self->SetSizer($self->{vsizer}); + $self->{sizer} = Wx::FlexGridSizer->new(0, 2, 5, 0); + $self->SetSizer($self->{sizer}); + + my $bitmap = Wx::StaticBitmap->new($self, -1, Wx::Bitmap->new("$Slic3r::var/bullet_blue.png", wxBITMAP_TYPE_PNG)); + $self->{sizer}->Add($bitmap, 0, wxALIGN_CENTER_VERTICAL, 0); + + my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize); + $self->{sizer}->Add($text, 0, wxALIGN_CENTER_VERTICAL, 0); + + return $self; +} + +sub prepend_title { + my $self = shift; + my ($title) = @_; + + my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize); + $self->{sizer}->Prepend($text, 0, wxALIGN_CENTER_VERTICAL, 0); + + my $bitmap = Wx::StaticBitmap->new($self, -1, Wx::Bitmap->new("$Slic3r::var/bullet_black.png", wxBITMAP_TYPE_PNG)); + $self->{sizer}->Prepend($bitmap, 0, wxALIGN_CENTER_VERTICAL, 0); +} + +sub append_title { + my $self = shift; + my ($title) = @_; + + my $bitmap = Wx::StaticBitmap->new($self, -1, Wx::Bitmap->new("$Slic3r::var/bullet_white.png", wxBITMAP_TYPE_PNG)); + $self->{sizer}->Add($bitmap, 0, wxALIGN_CENTER_VERTICAL, 0); + + my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize); + $text->SetForegroundColour(Wx::Colour->new(128, 128, 128)); + $self->{sizer}->Add($text, 0, wxALIGN_CENTER_VERTICAL, 0); +} + +package Slic3r::GUI::ConfigWizard::Page; +use Wx qw(:font :misc :sizer :staticline :systemsettings); +use base 'Wx::WizardPage'; + +sub new { + my $class = shift; + my ($parent, $title, $short_title) = @_; + my $self = $class->SUPER::new($parent); + + my $sizer = Wx::FlexGridSizer->new(0, 2, 10, 10); + $sizer->AddStretchSpacer(0); + $self->SetSizer($sizer); # title my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); @@ -154,9 +198,17 @@ sub new { $bold_font->SetWeight(wxFONTWEIGHT_BOLD); $bold_font->SetPointSize(14); $text->SetFont($bold_font); - $self->{vsizer}->Add($text, 0, wxALIGN_LEFT | wxALL, 10); - my $line = Wx::StaticLine->new($self, -1, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL, ''); - $self->{vsizer}->Add($line, 0, wxEXPAND| wxALL, 10); + $sizer->Add($text, 0, wxALIGN_LEFT, 0); + + # index + $self->{short_title} = $short_title ? $short_title : $title; + $self->{index} = Slic3r::GUI::ConfigWizard::Index->new($self, $self->{short_title}); + $sizer->Add($self->{index}, 0, wxTOP | wxRIGHT, 10); + + # contents + $self->{width} = 400; + $self->{vsizer} = Wx::BoxSizer->new(wxVERTICAL); + $sizer->Add($self->{vsizer}, 0, wxEXPAND, 0); return $self; } @@ -167,7 +219,8 @@ sub append_text { my $para = Wx::StaticText->new($self, -1, $text, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); $para->Wrap($self->{width}); - $self->{vsizer}->Add($para, 0, wxALIGN_LEFT | wxALL, 10); + $para->SetMinSize([$self->{width}, -1]); + $self->{vsizer}->Add($para, 0, wxALIGN_LEFT | wxTOP | wxBOTTOM, 10); } sub append_option { @@ -179,7 +232,7 @@ sub append_option { my ($opt_key, $value) = @_; $self->{options}->{$opt_key} = $value; }); - $self->{vsizer}->Add($option, 0, wxEXPAND | wxALL, 10); + $self->{vsizer}->Add($option, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); } sub apply { @@ -209,13 +262,27 @@ sub GetNext { return $self->{next_page}; } +sub get_short_title { + my $self = shift; + return $self->{short_title}; +} + +sub build_index { + my $self = shift; + + my $page = $self; + $self->{index}->prepend_title($page->get_short_title) while ($page = $page->GetPrev); + $page = $self; + $self->{index}->append_title($page->get_short_title) while ($page = $page->GetNext); +} + package Slic3r::GUI::ConfigWizard::Page::Welcome; use base 'Slic3r::GUI::ConfigWizard::Page'; sub new { my $class = shift; my ($parent) = @_; - my $self = $class->SUPER::new($parent, 'Welcome to the Slic3r Configuration Wizard'); + my $self = $class->SUPER::new($parent, 'Welcome to the Slic3r Configuration Wizard', 'Welcome'); $self->append_text('Hello, welcome to Slic3r! This wizard helps you with the initial configuration; just a few settings and you will be ready to print.'); $self->append_text('To import an existing configuration instead, cancel this wizard and use the Open Config menu item found in the File menu.'); @@ -354,7 +421,7 @@ use base 'Slic3r::GUI::ConfigWizard::Page'; sub new { my $class = shift; my ($parent) = @_; - my $self = $class->SUPER::new($parent, 'Congratulations!'); + my $self = $class->SUPER::new($parent, 'Congratulations!', 'Finish'); $self->append_text('You have successfully completed the Slic3r Configuration Wizard. ' . 'Slic3r is now configured for your printer and filament.'); diff --git a/var/bullet_black.png b/var/bullet_black.png new file mode 100755 index 0000000000000000000000000000000000000000..57619706d10d9736b1849a83f2c5694fbe09c53b GIT binary patch literal 211 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-$h^>lFz(Kw&{<9vg>5sw~gS5O!4 zr|{HuUFIBKiQyL}eBJ-L{`UVT|6_O~L{G%N{Wbre{kQtZ_0LvEhDX@>Vt8IAj)#jg!+?Z23wnf7d! zNAH#A4i6V)y_WtvZQ1hT)TAWgjoY{t%BOsI;8VOzQvNniDZk5xCy$)UQWb1PRjRoz l1#moJy|?3|{zvx%+C#5QQ<|d}62BjvZR2H60wE-%M_H=O!(Kvthf+1gnf`Cilxr3SC zCq+y2HhAz(;&}R`x^q^&(wiOs&2u-u^*?dO$=Q}CfYva0y85}Sb4q9e0M-pfO8@`> literal 0 HcmV?d00001 From 5a8c4bf1bf6670f0cd2079c5dc3cf7b14cdc3093 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Tue, 3 Jul 2012 19:16:45 +0200 Subject: [PATCH 061/106] Move Load Config... and Export Config... to the File menu --- lib/Slic3r/GUI.pm | 17 +++++++++-------- lib/Slic3r/GUI/SkeinPanel.pm | 8 -------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index a2e7e4904..b4ddb7335 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -65,17 +65,18 @@ sub OnInit { # File menu my $fileMenu = Wx::Menu->new; { - $fileMenu->Append(1, "Export Config…"); - $fileMenu->Append(2, "Open Config…"); + $fileMenu->Append(1, "Load Config…"); + $fileMenu->Append(2, "Export Config…"); $fileMenu->AppendSeparator(); - $fileMenu->Append(3, "Slice…"); - $fileMenu->Append(4, "Reslice"); - $fileMenu->Append(5, "Slice and Save As…"); - $fileMenu->Append(6, "Export SVG…"); + $fileMenu->Append(3, "Quick Slice…"); + $fileMenu->Append(4, "Quick Slice (last file)"); + $fileMenu->Append(5, "Quick Slice and Save As…"); + $fileMenu->AppendSeparator(); + $fileMenu->Append(6, "Slice to SVG…"); $fileMenu->AppendSeparator(); $fileMenu->Append(wxID_EXIT, "&Quit"); - EVT_MENU($frame, 1, sub { $frame->{skeinpanel}->save_config }); - EVT_MENU($frame, 2, sub { $frame->{skeinpanel}->load_config }); + EVT_MENU($frame, 1, sub { $frame->{skeinpanel}->load_config }); + EVT_MENU($frame, 2, sub { $frame->{skeinpanel}->save_config }); EVT_MENU($frame, 3, sub { $frame->{skeinpanel}->do_slice }); EVT_MENU($frame, 4, sub { $frame->{skeinpanel}->do_slice(reslice => 1) }); EVT_MENU($frame, 5, sub { $frame->{skeinpanel}->do_slice(save_as => 1) }); diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 5762792dc..ce0aaf920 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -40,14 +40,6 @@ sub new { $buttons_sizer->Add($slice_button, 0, wxRIGHT, 20); EVT_BUTTON($self, $slice_button, sub { $self->do_slice }); - my $save_button = Wx::Button->new($self, -1, "Export config…"); - $buttons_sizer->Add($save_button, 0, wxRIGHT, 5); - EVT_BUTTON($self, $save_button, sub { $self->save_config }); - - my $load_button = Wx::Button->new($self, -1, "Load config…"); - $buttons_sizer->Add($load_button, 0, wxRIGHT, 5); - EVT_BUTTON($self, $load_button, sub { $self->load_config }); - my $text = Wx::StaticText->new($self, -1, "Remember to check for updates at http://slic3r.org/\nVersion: $Slic3r::VERSION", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); my $font = Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL); $text->SetFont($font); From a5c772a488975250182ba5e9b65a01805f28d3c4 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 4 Jul 2012 00:03:05 +0200 Subject: [PATCH 062/106] Add semi-transparent Slic3r icon as backdrop for the configuration wizard --- lib/Slic3r/GUI/ConfigWizard.pm | 27 +++++++++++++++++++++++++-- var/Slic3r_192px_transparent.png | Bin 0 -> 25521 bytes 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 var/Slic3r_192px_transparent.png diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index 9dd382cde..ce9eca72f 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -137,6 +137,7 @@ sub new { package Slic3r::GUI::ConfigWizard::Index; use Wx qw(:bitmap :font :misc :sizer :systemsettings); +use Wx::Event qw(EVT_ERASE_BACKGROUND); use base 'Wx::Panel'; sub new { @@ -153,9 +154,29 @@ sub new { my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize); $self->{sizer}->Add($text, 0, wxALIGN_CENTER_VERTICAL, 0); + $self->{background} = Wx::Bitmap->new("$Slic3r::var/Slic3r_192px_transparent.png", wxBITMAP_TYPE_PNG); + $self->SetMinSize(Wx::Size->new($self->{background}->GetWidth, $self->{background}->GetHeight)); + EVT_ERASE_BACKGROUND($self, \&on_erase_background); + return $self; } +sub on_erase_background { + my ($self, $event) = @_; + + my $dc = $event->GetDC; + unless (defined $dc) { + $dc = Wx::ClientDC->new($self); + my $rect = $self->GetUpdateRegion->GetBox; + $dc->SetClippingRect($rect); + } + + my $size = $self->GetClientSize; + my $h = $self->{background}->GetHeight; + my $w = $self->{background}->GetWidth; + $dc->DrawBitmap($self->{background}, ($size->GetWidth - $w) / 2, ($size->GetHeight - $h) / 2, 0); +} + sub prepend_title { my $self = shift; my ($title) = @_; @@ -189,6 +210,8 @@ sub new { my $self = $class->SUPER::new($parent); my $sizer = Wx::FlexGridSizer->new(0, 2, 10, 10); + $sizer->AddGrowableCol(1, 1); + $sizer->AddGrowableRow(1, 1); $sizer->AddStretchSpacer(0); $self->SetSizer($sizer); @@ -203,12 +226,12 @@ sub new { # index $self->{short_title} = $short_title ? $short_title : $title; $self->{index} = Slic3r::GUI::ConfigWizard::Index->new($self, $self->{short_title}); - $sizer->Add($self->{index}, 0, wxTOP | wxRIGHT, 10); + $sizer->Add($self->{index}, 1, wxEXPAND | wxTOP | wxRIGHT, 10); # contents $self->{width} = 400; $self->{vsizer} = Wx::BoxSizer->new(wxVERTICAL); - $sizer->Add($self->{vsizer}, 0, wxEXPAND, 0); + $sizer->Add($self->{vsizer}, 1, wxEXPAND, 0); return $self; } diff --git a/var/Slic3r_192px_transparent.png b/var/Slic3r_192px_transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..fb73cb114b9a42d814b5e7ee1a8b0803da00b00d GIT binary patch literal 25521 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 Eg1gG8yZ`_I literal 0 HcmV?d00001 From 0982203f76c4cba7447eaea13b06d3c2be77d5cb Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 4 Jul 2012 00:38:23 +0200 Subject: [PATCH 063/106] Fix configuration wizard background under wxGTK --- lib/Slic3r/GUI/ConfigWizard.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index ce9eca72f..ed8c00ad1 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -136,7 +136,7 @@ sub new { } package Slic3r::GUI::ConfigWizard::Index; -use Wx qw(:bitmap :font :misc :sizer :systemsettings); +use Wx qw(:bitmap :font :misc :sizer :systemsettings :window); use Wx::Event qw(EVT_ERASE_BACKGROUND); use base 'Wx::Panel'; @@ -154,6 +154,7 @@ sub new { my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize); $self->{sizer}->Add($text, 0, wxALIGN_CENTER_VERTICAL, 0); + $self->SetBackgroundStyle(wxBG_STYLE_CUSTOM) if &Wx::wxGTK; $self->{background} = Wx::Bitmap->new("$Slic3r::var/Slic3r_192px_transparent.png", wxBITMAP_TYPE_PNG); $self->SetMinSize(Wx::Size->new($self->{background}->GetWidth, $self->{background}->GetHeight)); EVT_ERASE_BACKGROUND($self, \&on_erase_background); @@ -174,7 +175,7 @@ sub on_erase_background { my $size = $self->GetClientSize; my $h = $self->{background}->GetHeight; my $w = $self->{background}->GetWidth; - $dc->DrawBitmap($self->{background}, ($size->GetWidth - $w) / 2, ($size->GetHeight - $h) / 2, 0); + $dc->DrawBitmap($self->{background}, ($size->GetWidth - $w) / 2, ($size->GetHeight - $h) / 2, 1); } sub prepend_title { From cd7ea418e26ed7e94087b52277a4724fd450a469 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 8 Jul 2012 19:41:13 +0200 Subject: [PATCH 064/106] Fix background logo on wxMSW. Wx::StaticText + Wx::StaticBitmap does not support transparent backgrounds on wxMSW; fixed by using a custom paint routine instead. --- lib/Slic3r/GUI/ConfigWizard.pm | 72 +++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index ed8c00ad1..fcbd2b9d8 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -136,8 +136,8 @@ sub new { } package Slic3r::GUI::ConfigWizard::Index; -use Wx qw(:bitmap :font :misc :sizer :systemsettings :window); -use Wx::Event qw(EVT_ERASE_BACKGROUND); +use Wx qw(:bitmap :dc :font :misc :sizer :systemsettings :window); +use Wx::Event qw(EVT_ERASE_BACKGROUND EVT_PAINT); use base 'Wx::Panel'; sub new { @@ -145,60 +145,68 @@ sub new { my ($parent, $title) = @_; my $self = $class->SUPER::new($parent); - $self->{sizer} = Wx::FlexGridSizer->new(0, 2, 5, 0); - $self->SetSizer($self->{sizer}); + push @{$self->{titles}}, $title; + $self->{own_index} = 0; - my $bitmap = Wx::StaticBitmap->new($self, -1, Wx::Bitmap->new("$Slic3r::var/bullet_blue.png", wxBITMAP_TYPE_PNG)); - $self->{sizer}->Add($bitmap, 0, wxALIGN_CENTER_VERTICAL, 0); + $self->{bullets}->{before} = Wx::Bitmap->new("$Slic3r::var/bullet_black.png", wxBITMAP_TYPE_PNG); + $self->{bullets}->{own} = Wx::Bitmap->new("$Slic3r::var/bullet_blue.png", wxBITMAP_TYPE_PNG); + $self->{bullets}->{after} = Wx::Bitmap->new("$Slic3r::var/bullet_white.png", wxBITMAP_TYPE_PNG); - my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize); - $self->{sizer}->Add($text, 0, wxALIGN_CENTER_VERTICAL, 0); - - $self->SetBackgroundStyle(wxBG_STYLE_CUSTOM) if &Wx::wxGTK; $self->{background} = Wx::Bitmap->new("$Slic3r::var/Slic3r_192px_transparent.png", wxBITMAP_TYPE_PNG); $self->SetMinSize(Wx::Size->new($self->{background}->GetWidth, $self->{background}->GetHeight)); - EVT_ERASE_BACKGROUND($self, \&on_erase_background); + + EVT_PAINT($self, \&repaint); return $self; } -sub on_erase_background { +sub repaint { my ($self, $event) = @_; + my $size = $self->GetClientSize; + my $gab = 5; - my $dc = $event->GetDC; - unless (defined $dc) { - $dc = Wx::ClientDC->new($self); - my $rect = $self->GetUpdateRegion->GetBox; - $dc->SetClippingRect($rect); + my $dc = Wx::PaintDC->new($self); + $dc->SetBackgroundMode(wxTRANSPARENT); + $dc->SetFont($self->GetFont); + $dc->SetTextForeground($self->GetForegroundColour); + + my $background_h = $self->{background}->GetHeight; + my $background_w = $self->{background}->GetWidth; + $dc->DrawBitmap($self->{background}, ($size->GetWidth - $background_w) / 2, ($size->GetHeight - $background_h) / 2, 1); + + my $label_h = $self->{bullets}->{own}->GetHeight; + $label_h = $dc->GetCharHeight if $dc->GetCharHeight > $label_h; + my $label_w = $size->GetWidth; + + my $i = 0; + foreach (@{$self->{titles}}) { + my $bullet = $self->{bullets}->{own}; + $bullet = $self->{bullets}->{before} if $i < $self->{own_index}; + $bullet = $self->{bullets}->{after} if $i > $self->{own_index}; + + $dc->SetTextForeground(Wx::Colour->new(128, 128, 128)) if $i > $self->{own_index}; + $dc->DrawLabel($_, $bullet, Wx::Rect->new(0, $i * ($label_h + $gab), $label_w, $label_h)); + $i++; } - my $size = $self->GetClientSize; - my $h = $self->{background}->GetHeight; - my $w = $self->{background}->GetWidth; - $dc->DrawBitmap($self->{background}, ($size->GetWidth - $w) / 2, ($size->GetHeight - $h) / 2, 1); + $event->Skip; } sub prepend_title { my $self = shift; my ($title) = @_; - my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize); - $self->{sizer}->Prepend($text, 0, wxALIGN_CENTER_VERTICAL, 0); - - my $bitmap = Wx::StaticBitmap->new($self, -1, Wx::Bitmap->new("$Slic3r::var/bullet_black.png", wxBITMAP_TYPE_PNG)); - $self->{sizer}->Prepend($bitmap, 0, wxALIGN_CENTER_VERTICAL, 0); + unshift @{$self->{titles}}, $title; + $self->{own_index}++; + $self->Refresh; } sub append_title { my $self = shift; my ($title) = @_; - my $bitmap = Wx::StaticBitmap->new($self, -1, Wx::Bitmap->new("$Slic3r::var/bullet_white.png", wxBITMAP_TYPE_PNG)); - $self->{sizer}->Add($bitmap, 0, wxALIGN_CENTER_VERTICAL, 0); - - my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize); - $text->SetForegroundColour(Wx::Colour->new(128, 128, 128)); - $self->{sizer}->Add($text, 0, wxALIGN_CENTER_VERTICAL, 0); + push @{$self->{titles}}, $title; + $self->Refresh; } package Slic3r::GUI::ConfigWizard::Page; From 023e7254c79d6a036f9cc9d45108e4d726f2dbee Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 8 Jul 2012 22:16:46 +0200 Subject: [PATCH 065/106] Make reports of time spent on slicing more user-friendly. --- lib/Slic3r/GUI/Plater.pm | 10 ++++++---- lib/Slic3r/GUI/SkeinPanel.pm | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 48297e304..da4a451e3 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -531,10 +531,12 @@ sub export_gcode2 { } my $message = "Your files were successfully sliced"; - $message .= sprintf " in %d minutes and %.3f seconds", - int($print->processing_time/60), - $print->processing_time - int($print->processing_time/60)*60 - if $print->processing_time; + if ($print->processing_time) { + $message .= ' in'; + my $minutes = int($print->processing_time/60); + $message .= sprintf " %d minutes and", $minutes if $minutes; + $message .= sprintf " %.1f seconds", $print->processing_time - $minutes*60; + } $message .= "."; Slic3r::GUI::notify($message); $params{on_completed}->($message); diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index ce0aaf920..85840983a 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -158,10 +158,12 @@ sub do_slice { undef $process_dialog; my $message = "$input_file_basename was successfully sliced"; - $message .= sprintf " in %d minutes and %.3f seconds", - int($print->processing_time/60), - $print->processing_time - int($print->processing_time/60)*60 - if $print->processing_time; + if ($print->processing_time) { + $message .= ' in'; + my $minutes = int($print->processing_time/60); + $message .= sprintf " %d minutes and", $minutes if $minutes; + $message .= sprintf " %.1f seconds", $print->processing_time - $minutes*60; + } $message .= "."; Slic3r::GUI::notify($message); Wx::MessageDialog->new($self, $message, 'Done!', From 37a4967883b3e576a440081de68a28fb7cca282d Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 8 Jul 2012 22:43:52 +0200 Subject: [PATCH 066/106] Remove dead code. --- lib/Slic3r/GUI/Plater.pm | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index da4a451e3..ecf53c7be 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -183,7 +183,6 @@ sub new { my $list_sizer = Wx::BoxSizer->new(wxHORIZONTAL); $list_sizer->Add($self->{list}, 1, wxEXPAND | wxALL, 0); - $list_sizer->Add($self->{vtoolbar}, 0, wxEXPAND, 0) if $self->{vtoolbar}; my $vertical_sizer = Wx::BoxSizer->new(wxVERTICAL); $vertical_sizer->Add($self->{htoolbar}, 0, wxEXPAND, 0) if $self->{htoolbar}; From 025c3a1b07e4c479e9ef43594f2b9089af16807c Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 10 Jul 2012 23:09:11 +0200 Subject: [PATCH 067/106] Fix statusbar cancel button size on wxGTK. #431 --- lib/Slic3r/GUI.pm | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index b4ddb7335..03c50312c 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -189,7 +189,7 @@ sub new { $self->{timer} = Wx::Timer->new($self); $self->{prog} = Wx::Gauge->new($self, wxGA_HORIZONTAL, 100, wxDefaultPosition, wxDefaultSize); $self->{prog}->Hide; - $self->{cancelbutton} = Wx::Button->new($self, -1, "Cancel", wxDefaultPosition, [-1,8]); + $self->{cancelbutton} = Wx::Button->new($self, -1, "Cancel", wxDefaultPosition, wxDefaultSize); $self->{cancelbutton}->Hide; $self->SetFieldsCount(3); @@ -214,19 +214,21 @@ sub DESTROY { sub _Reposition { my $self = shift; + my %fields = ( + # 0 is reserved for status text + 1 => $self->{cancelbutton}, + 2 => $self->{prog}, + ); + ##if ($self->{_changed}) { - { - my $rect = $self->GetFieldRect($self->GetFieldsCount - 1); - my $prog_pos = [$rect->GetX + 2, $rect->GetY + 2]; - $self->{prog}->Move($prog_pos); - $self->{prog}->SetSize($rect->GetWidth - 8, $rect->GetHeight - 4); - } - { - my $rect = $self->GetFieldRect($self->GetFieldsCount - 2); - my $pos = [$rect->GetX + 2, $rect->GetY + 2]; - $self->{cancelbutton}->Move($pos); - $self->{cancelbutton}->SetSize($rect->GetWidth - 8, $rect->GetHeight - 4); + foreach (keys %fields) { + my $rect = $self->GetFieldRect($_); + my $offset = &Wx::wxGTK ? 1 : 0; # add a cosmetic 1 pixel offset on wxGTK + my $pos = [$rect->GetX + $offset, $rect->GetY + $offset]; + $fields{$_}->Move($pos); + $fields{$_}->SetSize($rect->GetWidth - $offset, $rect->GetHeight); } + $self->{_changed} = 0; } From 772ee033e0ed3701443cabb4bdba19c79012278d Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 10 Jul 2012 23:17:03 +0200 Subject: [PATCH 068/106] Remove dead code. --- lib/Slic3r/GUI.pm | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 03c50312c..614848a82 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -184,7 +184,6 @@ sub new { my $class = shift; my $self = $class->SUPER::new(@_); - $self->{_changed} = 0; $self->{busy} = 0; $self->{timer} = Wx::Timer->new($self); $self->{prog} = Wx::Gauge->new($self, wxGA_HORIZONTAL, 100, wxDefaultPosition, wxDefaultSize); @@ -220,7 +219,6 @@ sub _Reposition { 2 => $self->{prog}, ); - ##if ($self->{_changed}) { foreach (keys %fields) { my $rect = $self->GetFieldRect($_); my $offset = &Wx::wxGTK ? 1 : 0; # add a cosmetic 1 pixel offset on wxGTK @@ -228,14 +226,11 @@ sub _Reposition { $fields{$_}->Move($pos); $fields{$_}->SetSize($rect->GetWidth - $offset, $rect->GetHeight); } - - $self->{_changed} = 0; } sub OnSize { my ($self, $event) = @_; - $self->{_changed} = 1; $self->_Reposition; $event->Skip; } From 5e5dc0201624989bcf91d7ca7746e16b47cbd5db Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 11 Jul 2012 16:31:17 +0200 Subject: [PATCH 069/106] Add menu item shortcut for http://slic3r.org/ --- lib/Slic3r/GUI.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 614848a82..a27cba14c 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -88,8 +88,10 @@ sub OnInit { my $helpMenu = Wx::Menu->new; { $helpMenu->Append(7, "Configuration Wizard…"); + $helpMenu->Append(8, "Slic3r Website"); $helpMenu->Append(wxID_ABOUT, "&About Slic3r"); EVT_MENU($frame, 7, sub { $frame->{skeinpanel}->config_wizard }); + EVT_MENU($frame, 8, sub { Wx::LaunchDefaultBrowser('http://slic3r.org/') }); EVT_MENU($frame, wxID_ABOUT, \&about); } From 500e44f8ea272e6e3663a5ec892501817c84037e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 11 Jul 2012 16:55:47 +0200 Subject: [PATCH 070/106] Reposition of Slic3r::GUI::ProgressStatusBar fields are only needed in ::OnSize() --- lib/Slic3r/GUI.pm | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index a27cba14c..22b7bea6a 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -196,7 +196,6 @@ sub new { $self->SetFieldsCount(3); $self->SetStatusWidths(-1, 150, 155); - Wx::Event::EVT_IDLE($self, sub { $self->_Reposition }); Wx::Event::EVT_TIMER($self, \&OnTimer, $self->{timer}); Wx::Event::EVT_SIZE($self, \&OnSize); Wx::Event::EVT_BUTTON($self, $self->{cancelbutton}, sub { @@ -212,8 +211,8 @@ sub DESTROY { $self->{timer}->Stop if $self->{timer} && $self->{timer}->IsRunning; } -sub _Reposition { - my $self = shift; +sub OnSize { + my ($self, $event) = @_; my %fields = ( # 0 is reserved for status text @@ -228,12 +227,7 @@ sub _Reposition { $fields{$_}->Move($pos); $fields{$_}->SetSize($rect->GetWidth - $offset, $rect->GetHeight); } -} -sub OnSize { - my ($self, $event) = @_; - - $self->_Reposition; $event->Skip; } @@ -293,7 +287,6 @@ sub ShowProgress { my $self = shift; my ($show) = @_; - $self->_Reposition; $self->{prog}->Show($show); $self->{prog}->Pulse; } @@ -303,7 +296,6 @@ sub StartBusy { my $rate = shift || 100; $self->{_busy} = 1; - $self->_Reposition; $self->ShowProgress(1); if (!$self->{timer}->IsRunning) { $self->{timer}->Start($rate); From 57316a4ffaf6572cbb2abcbeac52e91006f190a1 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Fri, 13 Jul 2012 23:46:39 +0200 Subject: [PATCH 071/106] Add custom about dialog. --- lib/Slic3r/GUI.pm | 11 ++-- lib/Slic3r/GUI/AboutDialog.pm | 108 ++++++++++++++++++++++++++++++++++ var/Slic3r_192px.png | Bin 0 -> 33278 bytes 3 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 lib/Slic3r/GUI/AboutDialog.pm create mode 100644 var/Slic3r_192px.png diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 22b7bea6a..b24fa5a27 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -4,6 +4,7 @@ use warnings; use utf8; use FindBin; +use Slic3r::GUI::AboutDialog; use Slic3r::GUI::ConfigWizard; use Slic3r::GUI::Plater; use Slic3r::GUI::OptionsGroup; @@ -119,13 +120,9 @@ sub OnInit { sub about { my $frame = shift; - my $info = Wx::AboutDialogInfo->new; - $info->SetName('Slic3r'); - $info->AddDeveloper('Alessandro Ranellucci'); - $info->SetVersion($Slic3r::VERSION); - $info->SetDescription('G-code generator for 3D printers'); - - Wx::AboutBox($info); + my $about = Slic3r::GUI::AboutDialog->new($frame); + $about->ShowModal; + $about->Destroy; } sub on_close { diff --git a/lib/Slic3r/GUI/AboutDialog.pm b/lib/Slic3r/GUI/AboutDialog.pm new file mode 100644 index 000000000..26fad8324 --- /dev/null +++ b/lib/Slic3r/GUI/AboutDialog.pm @@ -0,0 +1,108 @@ +package Slic3r::GUI::AboutDialog; +use strict; +use warnings; +use utf8; + +use Wx qw(:font :html :misc :sizer :systemsettings); +use Wx::Event qw(EVT_HTML_LINK_CLICKED); +use Wx::Html; +use base 'Wx::Dialog'; + +sub new { + my $class = shift; + my ($parent) = @_; + my $self = $class->SUPER::new($parent, -1, 'About Slic3r', wxDefaultPosition, [600, 270]); + + $self->SetBackgroundColour(Wx::wxWHITE); + my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL); + $self->SetSizer($hsizer); + + # logo + my $logo = Slic3r::GUI::AboutDialog::Logo->new($self, -1, wxDefaultPosition, wxDefaultSize); + $logo->SetBackgroundColour(Wx::wxWHITE); + $hsizer->Add($logo, 0, wxEXPAND | wxLEFT | wxRIGHT, 30); + + my $vsizer = Wx::BoxSizer->new(wxVERTICAL); + $hsizer->Add($vsizer, 1, wxEXPAND, 0); + + # title + my $title = Wx::StaticText->new($self, -1, 'Slic3r', wxDefaultPosition, wxDefaultSize); + my $title_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + $title_font->SetWeight(wxFONTWEIGHT_BOLD); + $title_font->SetFamily(wxFONTFAMILY_ROMAN); + $title_font->SetPointSize(24); + $title->SetFont($title_font); + $vsizer->Add($title, 0, wxALIGN_LEFT | wxTOP, 30); + + # version + my $version = Wx::StaticText->new($self, -1, "Version $Slic3r::VERSION", wxDefaultPosition, wxDefaultSize); + my $version_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + $version_font->SetPointSize(&Wx::wxMSW ? 9 : 11); + $version->SetFont($version_font); + $vsizer->Add($version, 0, wxALIGN_LEFT | wxBOTTOM, 10); + + # text + my $text = + '' . + '' . + '' . + 'Copyright © 2011-2012 Alessandro Ranellucci. All rights reserved. ' . + 'Slic3r is licensed under the ' . + 'GNU Affero General Public License, version 3.' . + '


' . + 'Slic3r logo designed by Corey Daniels, Silk Icon Set designed by Mark James. ' . + 'Contributions by Henrik Brix Andersen, Nicolas Dandrimont, Mark Hindess and numerous others.' . + '
' . + '' . + ''; + my $html = Wx::HtmlWindow->new($self, -1, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER); + my $font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + my $size = &Wx::wxMSW ? 8 : 10; + $html->SetFonts($font->GetFaceName, $font->GetFaceName, [$size, $size, $size, $size, $size, $size, $size]); + $html->SetBorders(2); + $html->SetPage($text); + $vsizer->Add($html, 1, wxEXPAND | wxALIGN_LEFT | wxRIGHT | wxBOTTOM, 20); + EVT_HTML_LINK_CLICKED($self, $html, \&link_clicked); + + return $self; +} + +sub link_clicked { + my ($self, $event) = @_; + + Wx::LaunchDefaultBrowser($event->GetLinkInfo->GetHref); + $event->Skip(0); +} + +package Slic3r::GUI::AboutDialog::Logo; +use Wx qw(:bitmap :dc); +use Wx::Event qw(EVT_PAINT); +use base 'Wx::Panel'; + +sub new { + my $class = shift; + my $self = $class->SUPER::new(@_); + + $self->{logo} = Wx::Bitmap->new("$Slic3r::var/Slic3r_192px.png", wxBITMAP_TYPE_PNG); + $self->SetMinSize(Wx::Size->new($self->{logo}->GetWidth, $self->{logo}->GetHeight)); + + EVT_PAINT($self, \&repaint); + + return $self; +} + +sub repaint { + my ($self, $event) = @_; + + my $dc = Wx::PaintDC->new($self); + $dc->SetBackgroundMode(wxTRANSPARENT); + + my $size = $self->GetSize; + my $logo_w = $self->{logo}->GetWidth; + my $logo_h = $self->{logo}->GetHeight; + $dc->DrawBitmap($self->{logo}, ($size->GetWidth - $logo_w) / 2, ($size->GetHeight - $logo_h) / 2, 1); + + $event->Skip; +} + +1; diff --git a/var/Slic3r_192px.png b/var/Slic3r_192px.png new file mode 100644 index 0000000000000000000000000000000000000000..cfb7a574b60a132f58960eaef54628c9560ea52a GIT binary patch literal 33278 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 QK(8}+y85}Sb4q9e04)?KSO5S3 literal 0 HcmV?d00001 From 4a94c64f7d84c782ee905b4098c1a922143ac4a3 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sat, 14 Jul 2012 11:58:58 +0200 Subject: [PATCH 072/106] Silence warning by importing Wx::Print before Wx::Html --- lib/Slic3r/GUI/AboutDialog.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Slic3r/GUI/AboutDialog.pm b/lib/Slic3r/GUI/AboutDialog.pm index 26fad8324..f8936338e 100644 --- a/lib/Slic3r/GUI/AboutDialog.pm +++ b/lib/Slic3r/GUI/AboutDialog.pm @@ -5,6 +5,7 @@ use utf8; use Wx qw(:font :html :misc :sizer :systemsettings); use Wx::Event qw(EVT_HTML_LINK_CLICKED); +use Wx::Print; use Wx::Html; use base 'Wx::Dialog'; From e228b834e2a94c5f98d304ddc3f57dbedaaae5f2 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 16:37:59 +0200 Subject: [PATCH 073/106] Retire the 'important' flag for options now that we have a configuration wizard. --- lib/Slic3r/Config.pm | 3 --- lib/Slic3r/GUI/OptionsGroup.pm | 7 ------- 2 files changed, 10 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 58fc01a3c..2a9eb0674 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -54,7 +54,6 @@ our $Options = { sidetext => 'mm', cli => 'nozzle-diameter=f', type => 'f', - important => 1, }, 'print_center' => { label => 'Print center', @@ -118,7 +117,6 @@ our $Options = { sidetext => 'mm', cli => 'filament-diameter=f', type => 'f', - important => 1, }, 'extrusion_multiplier' => { label => 'Extrusion multiplier', @@ -150,7 +148,6 @@ our $Options = { cli => 'temperature=i', type => 'i', max => 300, - important => 1, }, 'bed_temperature' => { label => 'Bed Temperature', diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index 1c7aa96d8..c68bcb644 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -22,9 +22,6 @@ sub new { $grid_sizer->SetFlexibleDirection(wxHORIZONTAL); $grid_sizer->AddGrowableCol($p{no_labels} ? 0 : 1); - # grab the default font, to fix Windows font issues/keep things consistent - my $bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); - $bold_font->SetWeight(wxFONTWEIGHT_BOLD); my $sidetext_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); my $onChange = $p{on_change} || sub {}; @@ -36,10 +33,6 @@ sub new { $label = Wx::StaticText->new($parent, -1, "$opt->{label}:", wxDefaultPosition, [$p{label_width} || 180, -1]); $label->Wrap($p{label_width} || 180) ; # needed to avoid Linux/GTK bug $grid_sizer->Add($label); - - # set the bold font point size to the same size as all the other labels (for consistency) - $bold_font->SetPointSize($label->GetFont()->GetPointSize()); - $label->SetFont($bold_font) if $opt->{important}; } my $field; From 9210c708fc63edf0e92a05fc1f7229de57880b99 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 15 Jul 2012 17:54:57 +0200 Subject: [PATCH 074/106] Compatibility with --load and new GUI --- lib/Slic3r/Config.pm | 2 +- lib/Slic3r/GUI.pm | 34 +++++++------- lib/Slic3r/GUI/SkeinPanel.pm | 36 ++++++--------- lib/Slic3r/GUI/Tab.pm | 90 +++++++++++++++++++++--------------- slic3r.pl | 5 +- 5 files changed, 90 insertions(+), 77 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 2a9eb0674..e7389306f 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -722,7 +722,7 @@ sub read_ini { my $ini = { _ => {} }; my $category = '_'; - while (<$fh>) { + while (my $_ = <$fh>) { s/\R+$//; next if /^\s+/; next if /^$/; diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index b24fa5a27..38223c45d 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -56,7 +56,7 @@ sub OnInit { Wx::Image::AddHandler(Wx::PNGHandler->new); my $frame = Wx::Frame->new(undef, -1, 'Slic3r', wxDefaultPosition, [760,520], wxDEFAULT_FRAME_STYLE); $frame->SetIcon(Wx::Icon->new("$Slic3r::var/Slic3r_128px.png", wxBITMAP_TYPE_PNG) ); - $frame->{skeinpanel} = Slic3r::GUI::SkeinPanel->new($frame); + $self->{skeinpanel} = Slic3r::GUI::SkeinPanel->new($frame); $self->SetTopWindow($frame); # status bar @@ -76,12 +76,12 @@ sub OnInit { $fileMenu->Append(6, "Slice to SVG…"); $fileMenu->AppendSeparator(); $fileMenu->Append(wxID_EXIT, "&Quit"); - EVT_MENU($frame, 1, sub { $frame->{skeinpanel}->load_config }); - EVT_MENU($frame, 2, sub { $frame->{skeinpanel}->save_config }); - EVT_MENU($frame, 3, sub { $frame->{skeinpanel}->do_slice }); - EVT_MENU($frame, 4, sub { $frame->{skeinpanel}->do_slice(reslice => 1) }); - EVT_MENU($frame, 5, sub { $frame->{skeinpanel}->do_slice(save_as => 1) }); - EVT_MENU($frame, 6, sub { $frame->{skeinpanel}->do_slice(save_as => 1, export_svg => 1) }); + EVT_MENU($frame, 1, sub { $self->{skeinpanel}->load_config }); + EVT_MENU($frame, 2, sub { $self->{skeinpanel}->save_config }); + EVT_MENU($frame, 3, sub { $self->{skeinpanel}->do_slice }); + EVT_MENU($frame, 4, sub { $self->{skeinpanel}->do_slice(reslice => 1) }); + EVT_MENU($frame, 5, sub { $self->{skeinpanel}->do_slice(save_as => 1) }); + EVT_MENU($frame, 6, sub { $self->{skeinpanel}->do_slice(save_as => 1, export_svg => 1) }); EVT_MENU($frame, wxID_EXIT, sub {$_[0]->Close(0)}); } @@ -91,7 +91,7 @@ sub OnInit { $helpMenu->Append(7, "Configuration Wizard…"); $helpMenu->Append(8, "Slic3r Website"); $helpMenu->Append(wxID_ABOUT, "&About Slic3r"); - EVT_MENU($frame, 7, sub { $frame->{skeinpanel}->config_wizard }); + EVT_MENU($frame, 7, sub { $self->{skeinpanel}->config_wizard }); EVT_MENU($frame, 8, sub { Wx::LaunchDefaultBrowser('http://slic3r.org/') }); EVT_MENU($frame, wxID_ABOUT, \&about); } @@ -106,13 +106,20 @@ sub OnInit { $frame->SetMenuBar($menubar); } - EVT_CLOSE($frame, \&on_close); - + EVT_CLOSE($frame, sub { + my (undef, $event) = @_; + if ($event->CanVeto && !$self->{skeinpanel}->check_unsaved_changes) { + $event->Veto; + return; + } + $event->Skip; + }); + $frame->SetMinSize($frame->GetSize); $frame->Show; $frame->Layout; - $frame->{skeinpanel}->config_wizard if $run_wizard; + $self->{skeinpanel}->config_wizard if $run_wizard; return 1; } @@ -125,11 +132,6 @@ sub about { $about->Destroy; } -sub on_close { - my ($frame, $event) = @_; - $event->CanVeto ? $event->Skip($frame->{skeinpanel}->check_unsaved_changes) : $event->Skip(1); -} - sub catch_error { my ($self, $cb, $message_dialog) = @_; if (my $err = $@) { diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 85840983a..a35bd6c89 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -197,23 +197,19 @@ sub save_config { sub load_config { my $self = shift; + my ($file) = @_; - my $dir = $last_config ? dirname($last_config) : $last_config_dir || $last_skein_dir || ""; - my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini", - $ini_wildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST); - if ($dlg->ShowModal == wxID_OK) { - my ($file) = $dlg->GetPaths; - $last_config_dir = dirname($file); - $last_config = $file; - eval { - local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); - Slic3r::Config->load($file); - }; - Slic3r::GUI::catch_error($self); - $_->() for values %Slic3r::GUI::OptionsGroup::reload_callbacks; - $_->external_config_loaded($file) for values %{$self->{options_tabs}}; + if (!$file) { + my $dir = $last_config ? dirname($last_config) : $last_config_dir || $last_skein_dir || ""; + my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini", + $ini_wildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST); + return unless $dlg->ShowModal == wxID_OK; + ($file) = $dlg->GetPaths; + $dlg->Destroy; } - $dlg->Destroy; + $last_config_dir = dirname($file); + $last_config = $file; + $_->external_config_loaded($file) for values %{$self->{options_tabs}}; } sub config_wizard { @@ -228,19 +224,15 @@ sub config_wizard { sub check_unsaved_changes { my $self = shift; - - my @dirty; - foreach (values %{$self->{options_tabs}}) { - push (@dirty, $_->title) if $_->is_dirty; - } - + + my @dirty = map $_->title, grep $_->is_dirty, values %{$self->{options_tabs}}; if (@dirty) { my $titles = join ', ', @dirty; my $confirm = Wx::MessageDialog->new($self, "You have unsaved changes ($titles). Discard changes and continue anyway?", 'Unsaved Presets', wxICON_QUESTION | wxOK | wxCANCEL); return ($confirm->ShowModal == wxID_OK); } - + return 1; } diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 75e9e919c..5a3b9fe9c 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -83,14 +83,13 @@ sub new { }); EVT_BUTTON($self, $self->{btn_save_preset}, sub { - my $i = $self->{presets_choice}->GetSelection; - my $default = $i == 0 ? 'Untitled' : basename($self->{presets}[$i-1]); - $default =~ s/\.ini$//i; + my $preset = $self->current_preset; + my $default_name = $preset->{default} ? 'Untitled' : basename($preset->{name}); my $dlg = Slic3r::GUI::SavePresetWindow->new($self, - title => lc($title), - default => $default, - values => [ map { my $filename = basename($_); $filename =~ /^(.*?)\.ini$/i; $1 } @{$self->{presets}} ], + title => lc($title), + default => $default_name, + values => [ map { my $filename = basename($_->{file}); $filename =~ /^(.*?)\.ini$/i; $1 } @{$self->{presets}} ], ); return unless $dlg->ShowModal == wxID_OK; @@ -98,7 +97,7 @@ sub new { Slic3r::Config->save($file, $self->{presets_group}); $self->set_dirty(0); $self->load_presets; - $self->{presets_choice}->SetSelection(1 + first { basename($self->{presets}[$_]) eq $dlg->get_name . ".ini" } 0 .. $#{$self->{presets}}); + $self->{presets_choice}->SetSelection(first { basename($self->{presets}[$_]{file}) eq $dlg->get_name . ".ini" } 0 .. $#{$self->{presets}}); $self->on_select_preset; $self->sync_presets; }); @@ -108,8 +107,8 @@ sub new { return if $i == 0; # this shouldn't happen but let's trap it anyway my $res = Wx::MessageDialog->new($self, "Are you sure you want to delete the selected preset?", 'Delete Preset', wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION)->ShowModal; return unless $res == wxID_YES; - if (-e $self->{presets}[$i-1]) { - unlink $self->{presets}[$i-1]; + if (-e $self->{presets}[$i-1]{file}) { + unlink $self->{presets}[$i-1]{file}; } splice @{$self->{presets}}, $i-1, 1; $self->{presets_choice}->Delete($i); @@ -121,6 +120,11 @@ sub new { return $self; } +sub current_preset { + my $self = shift; + return $self->{presets}[ $self->{presets_choice}->GetSelection ]; +} + sub on_select_preset { my $self = shift; @@ -129,23 +133,28 @@ sub on_select_preset { $self->set_dirty(0); } - my $i = $self->{presets_choice}->GetSelection; - my $file; - if ($i == 0) { + my $preset = $self->current_preset; + if ($preset->{default}) { + # default settings: disable the delete button Slic3r::Config->load_hash($Slic3r::Defaults, $self->{presets_group}, 1); $self->{btn_delete_preset}->Disable; } else { - $file = $self->{presets}[$i-1]; - if (!-e $file) { - Slic3r::GUI::show_error($self, "The selected preset does not exist anymore ($file)."); + if (!-e $preset->{file}) { + Slic3r::GUI::show_error($self, "The selected preset does not exist anymore ($preset->{file})."); return; } - Slic3r::Config->load($file, $self->{presets_group}); - $self->{btn_delete_preset}->Enable; + eval { + local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); + Slic3r::Config->load($preset->{file}, $self->{presets_group}); + }; + Slic3r::GUI::catch_error($self); + $preset->{external} + ? $self->{btn_delete_preset}->Disable + : $self->{btn_delete_preset}->Enable; } $_->() for @Slic3r::GUI::OptionsGroup::reload_callbacks{@{$Slic3r::Config::Groups{$self->{presets_group}}}}; $self->set_dirty(0); - $Slic3r::Settings->{presets}{$self->{presets_group}} = $file ? basename($file) : ''; + $Slic3r::Settings->{presets}{$self->{presets_group}} = $preset->{file} ? basename($preset->{file}) : ''; Slic3r::Config->save_settings("$Slic3r::GUI::datadir/slic3r.ini"); } @@ -179,7 +188,7 @@ sub set_dirty { my $i = $self->{dirty} // $self->{presets_choice}->GetSelection; #/ my $text = $self->{presets_choice}->GetString($i); - + if ($dirty) { $self->{dirty} = $i; if ($text !~ / \(modified\)$/) { @@ -202,7 +211,7 @@ sub is_dirty { sub title { my $self = shift; - return $self->{title} + return $self->{title}; } sub load_presets { @@ -210,22 +219,28 @@ sub load_presets { my ($group) = @_; $self->{presets_group} ||= $group; - $self->{presets} = []; + $self->{presets} = [{ + default => 1, + name => '- default -', + }]; opendir my $dh, "$Slic3r::GUI::datadir/$self->{presets_group}" or die "Failed to read directory $Slic3r::GUI::datadir/$self->{presets_group} (errno: $!)\n"; - my @presets = sort grep /\.ini$/i, readdir $dh; + foreach my $file (sort grep /\.ini$/i, readdir $dh) { + my $name = basename($file); + $name =~ s/\.ini$//; + push @{$self->{presets}}, { + file => "$Slic3r::GUI::datadir/$self->{presets_group}/$file", + name => $name, + }; + } closedir $dh; $self->{presets_choice}->Clear; - $self->{presets_choice}->Append("- default -"); - foreach my $preset (@presets) { - push @{$self->{presets}}, "$Slic3r::GUI::datadir/$self->{presets_group}/$preset"; - $preset =~ s/\.ini$//i; - $self->{presets_choice}->Append($preset); - } + $self->{presets_choice}->Append($_->{name}) for @{$self->{presets}}; { - my $i = first { basename($self->{presets}[$_]) eq ($Slic3r::Settings->{presets}{$self->{presets_group}} || '') } 0 .. $#{$self->{presets}}; - $self->{presets_choice}->SetSelection(defined $i ? $i + 1 : 0); + # load last used preset + my $i = first { basename($self->{presets}[$_]{file}) eq ($Slic3r::Settings->{presets}{$self->{presets_group}} || '') } 1 .. $#{$self->{presets}}; + $self->{presets_choice}->SetSelection($i || 0); $self->on_select_preset; } $self->sync_presets; @@ -236,16 +251,19 @@ sub external_config_loaded { my ($file) = @_; # look for the loaded config among the existing menu items - my $i = first { $self->{presets}[$_] eq $file } 0..$#{$self->{presets}}; + my $i = first { $self->{presets}[$_]{file} eq $file && $self->{presets}[$_]{external} } 1..$#{$self->{presets}}; if (!$i) { - push @{$self->{presets}}, $file; - my $preset_name = basename($file); # leave the .ini suffix + my $preset_name = basename($file); # keep the .ini suffix + push @{$self->{presets}}, { + file => $file, + name => $preset_name, + external => 1, + }; $self->{presets_choice}->Append($preset_name); $i = $#{$self->{presets}}; } - $self->{presets_choice}->SetSelection(1 + $i); - $self->set_dirty(0); - $self->{btn_delete_preset}->Disable; + $self->{presets_choice}->SetSelection($i); + $self->on_select_preset; $self->sync_presets; } diff --git a/slic3r.pl b/slic3r.pl index 15e3904ae..d9113747b 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -72,8 +72,9 @@ Slic3r::Config->save($opt{save}) if $opt{save}; # start GUI if (!@ARGV && !$opt{save} && eval "require Slic3r::GUI; 1") { no warnings 'once'; - $Slic3r::GUI::SkeinPanel::last_config = $opt{load} ? $opt{load}[0] : undef; - Slic3r::GUI->new->MainLoop; + my $gui = Slic3r::GUI->new; + $gui->{skeinpanel}->load_config($opt{load}[0]) if $opt{load}; + $gui->MainLoop; exit; } die $@ if $@ && $opt{gui}; From b37a77ee633ff556303908d54bc744c27edb80fd Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 15 Jul 2012 18:37:00 +0200 Subject: [PATCH 075/106] Apply command line options to GUI --- lib/Slic3r/GUI/Tab.pm | 5 +++-- slic3r.pl | 31 +++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 5a3b9fe9c..92263833b 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -85,11 +85,12 @@ sub new { EVT_BUTTON($self, $self->{btn_save_preset}, sub { my $preset = $self->current_preset; my $default_name = $preset->{default} ? 'Untitled' : basename($preset->{name}); + $default_name =~ s/\.ini$//i; my $dlg = Slic3r::GUI::SavePresetWindow->new($self, title => lc($title), default => $default_name, - values => [ map { my $filename = basename($_->{file}); $filename =~ /^(.*?)\.ini$/i; $1 } @{$self->{presets}} ], + values => [ map { my $name = $_->{name}; $name =~ s/\.ini$//i; $name } @{$self->{presets}} ], ); return unless $dlg->ShowModal == wxID_OK; @@ -97,7 +98,7 @@ sub new { Slic3r::Config->save($file, $self->{presets_group}); $self->set_dirty(0); $self->load_presets; - $self->{presets_choice}->SetSelection(first { basename($self->{presets}[$_]{file}) eq $dlg->get_name . ".ini" } 0 .. $#{$self->{presets}}); + $self->{presets_choice}->SetSelection(first { basename($self->{presets}[$_]{file}) eq $dlg->get_name . ".ini" } 1 .. $#{$self->{presets}}); $self->on_select_preset; $self->sync_presets; }); diff --git a/slic3r.pl b/slic3r.pl index d9113747b..b573cc312 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -9,6 +9,7 @@ BEGIN { } use Getopt::Long qw(:config no_auto_abbrev); +use List::Util qw(first); use Slic3r; $|++; @@ -57,27 +58,37 @@ if ($opt{load}) { } # validate command line options +delete $cli_options{$_} for grep !defined $cli_options{$_}, keys %cli_options; Slic3r::Config->validate_cli(\%cli_options); -# apply command line options -Slic3r::Config->set($_ => $cli_options{$_}) - for grep defined $cli_options{$_}, keys %cli_options; +# initialize GUI +my $gui; +if (!@ARGV && !$opt{save} && eval "require Slic3r::GUI; 1") { + $gui = Slic3r::GUI->new; + $gui->{skeinpanel}->load_config($opt{load}[0]) if $opt{load}; +} +die $@ if $@ && $opt{gui}; -# validate configuration +# apply command line options +Slic3r::Config->set($_ => $cli_options{$_}) for keys %cli_options; + +# validate configuration, convert options like --print-center to arrayrefs, init extruders etc. Slic3r::Config->validate; # save configuration Slic3r::Config->save($opt{save}) if $opt{save}; -# start GUI -if (!@ARGV && !$opt{save} && eval "require Slic3r::GUI; 1") { - no warnings 'once'; - my $gui = Slic3r::GUI->new; - $gui->{skeinpanel}->load_config($opt{load}[0]) if $opt{load}; +# apply command line options to GUI as well and start it +if ($gui) { + for my $opt_key (keys %cli_options) { + no warnings 'once'; + ( $Slic3r::GUI::OptionsGroup::reload_callbacks{$opt_key} || sub {} )->(); + my $group = first { $opt_key ~~ @$_ } keys %Slic3r::Groups; + $gui->{skeinpanel}{options_tabs}{$group}->set_dirty(1) if $group; + } $gui->MainLoop; exit; } -die $@ if $@ && $opt{gui}; if (@ARGV) { while (my $input_file = shift @ARGV) { From 23fd8de1f5c4e89a68e4b0789d3d7d4924dcd9b4 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 15 Jul 2012 18:55:01 +0200 Subject: [PATCH 076/106] Warn user if supplied preset name is not valid --- lib/Slic3r/GUI/Tab.pm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 92263833b..b2c0a811e 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -535,8 +535,12 @@ sub new { sub accept { my ($self, $event) = @_; - if (($self->{chosen_name} = $self->{combo}->GetValue) && $self->{chosen_name} =~ /^[a-z0-9 _-]+$/i) { - $self->EndModal(wxID_OK); + if (($self->{chosen_name} = $self->{combo}->GetValue)) { + if ($self->{chosen_name} =~ /^[a-z0-9 _-]+$/i) { + $self->EndModal(wxID_OK); + } else { + Slic3r::GUI::show_error($self, "The supplied name is not valid."); + } } } From 1c6789e042c1edaec7d43dca19bfb040724b9c4e Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 15 Jul 2012 19:36:56 +0200 Subject: [PATCH 077/106] Remove duplicate_mode from options list --- lib/Slic3r/Config.pm | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index e7389306f..f3d7ed78c 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -558,13 +558,6 @@ our $Options = { type => 'i', max => 359, }, - 'duplicate_mode' => { - label => 'Duplicate', - gui_only => 1, - type => 'select', - values => [qw(no autoarrange grid)], - labels => ['No', 'Autoarrange', 'Grid'], - }, 'duplicate' => { label => 'Copies (autoarrange)', cli => 'duplicate=i', From bd77c339197a8892afe5d947cb061c757cd5655d Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 20:05:57 +0200 Subject: [PATCH 078/106] Add sunken border to tree controls. --- lib/Slic3r/GUI/Tab.pm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index b2c0a811e..62df01a4f 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -5,7 +5,7 @@ use utf8; use File::Basename qw(basename); use List::Util qw(first); -use Wx qw(:bookctrl :dialog :icon :id :misc :sizer :treectrl); +use Wx qw(:bookctrl :dialog :icon :id :misc :sizer :treectrl :window); use Wx::Event qw(EVT_BUTTON EVT_CHOICE EVT_TREE_SEL_CHANGED); use base 'Wx::Panel'; @@ -29,9 +29,9 @@ sub new { # left vertical sizer my $left_sizer = Wx::BoxSizer->new(wxVERTICAL); - $self->{sizer}->Add($left_sizer, 0, wxEXPAND); + $self->{sizer}->Add($left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3); - my $left_col_width = 200; + my $left_col_width = 210; # preset chooser { @@ -60,7 +60,7 @@ sub new { } # tree - $self->{treectrl} = Wx::TreeCtrl->new($self, -1, wxDefaultPosition, [$left_col_width, -1], wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES); + $self->{treectrl} = Wx::TreeCtrl->new($self, -1, wxDefaultPosition, [$left_col_width, -1], wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES | wxBORDER_SUNKEN); $left_sizer->Add($self->{treectrl}, 1, wxEXPAND); $self->{icons} = Wx::ImageList->new(16, 16, 1); $self->{treectrl}->AssignImageList($self->{icons}); From 0ab7e7ad7ff65fa3fd877b04a888d2bc3c4ebb35 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 20:11:49 +0200 Subject: [PATCH 079/106] Show icons above text in toolbar. --- lib/Slic3r/GUI/Plater.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index ecf53c7be..d1a79417e 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -54,7 +54,7 @@ sub new { # toolbar for object manipulation if (!&Wx::wxMSW) { Wx::ToolTip::Enable(1); - $self->{htoolbar} = Wx::ToolBar->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxTB_HORZ_TEXT); + $self->{htoolbar} = Wx::ToolBar->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxTB_TEXT); $self->{htoolbar}->AddTool(TB_MORE, "More", Wx::Bitmap->new("$Slic3r::var/add.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_LESS, "Less", Wx::Bitmap->new("$Slic3r::var/delete.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddSeparator; From 8042d5d701e60e401432661f938827cf8ab8654b Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 22:14:34 +0200 Subject: [PATCH 080/106] Add borders to toolbar and list view. --- lib/Slic3r/GUI/Plater.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index d1a79417e..a5b2452ed 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -44,7 +44,7 @@ sub new { $self->{clearance_pen} = Wx::Pen->new(Wx::Colour->new(0,0,200), 1, wxSOLID); $self->{skirt_pen} = Wx::Pen->new(Wx::Colour->new(150,150,150), 1, wxSOLID); - $self->{list} = Wx::ListView->new($self, -1, wxDefaultPosition, [-1, 180], wxLC_SINGLE_SEL | wxLC_REPORT | wxBORDER_DEFAULT); + $self->{list} = Wx::ListView->new($self, -1, wxDefaultPosition, [-1, 180], wxLC_SINGLE_SEL | wxLC_REPORT | wxBORDER_SUNKEN); $self->{list}->InsertColumn(0, "Name", wxLIST_FORMAT_LEFT, 300); $self->{list}->InsertColumn(1, "Copies", wxLIST_FORMAT_CENTER, 50); $self->{list}->InsertColumn(2, "Scale", wxLIST_FORMAT_CENTER, wxLIST_AUTOSIZE_USEHEADER); @@ -54,7 +54,7 @@ sub new { # toolbar for object manipulation if (!&Wx::wxMSW) { Wx::ToolTip::Enable(1); - $self->{htoolbar} = Wx::ToolBar->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxTB_TEXT); + $self->{htoolbar} = Wx::ToolBar->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxTB_TEXT | wxBORDER_SIMPLE); $self->{htoolbar}->AddTool(TB_MORE, "More", Wx::Bitmap->new("$Slic3r::var/add.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_LESS, "Less", Wx::Bitmap->new("$Slic3r::var/delete.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddSeparator; From 314772b3145fde09af48d212c72a4f75e46775f8 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 22:25:04 +0200 Subject: [PATCH 081/106] Improve message dialog texts a bit. --- lib/Slic3r/GUI/SkeinPanel.pm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index a35bd6c89..94a07c59f 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -76,7 +76,7 @@ sub do_slice { $copies = $Slic3r::duplicate if $Slic3r::duplicate > 1; if ($copies > 1) { my $confirmation = Wx::MessageDialog->new($self, "Are you sure you want to slice $copies copies?", - 'Confirm', wxICON_QUESTION | wxOK | wxCANCEL); + 'Multiple Copies', wxICON_QUESTION | wxOK | wxCANCEL); return unless $confirmation->ShowModal == wxID_OK; } @@ -95,13 +95,13 @@ sub do_slice { $last_input_file = $input_file; } else { if (!defined $last_input_file) { - Wx::MessageDialog->new($self, "No previously sliced file", - 'Confirm', wxICON_ERROR | wxOK)->ShowModal(); + Wx::MessageDialog->new($self, "No previously sliced file.", + 'Error', wxICON_ERROR | wxOK)->ShowModal(); return; } if (! -e $last_input_file) { - Wx::MessageDialog->new($self, "Cannot find previously sliced file!", - 'Confirm', wxICON_ERROR | wxOK)->ShowModal(); + Wx::MessageDialog->new($self, "Previously sliced file ($last_input_file) not found.", + 'File Not Found', wxICON_ERROR | wxOK)->ShowModal(); return; } $input_file = $last_input_file; @@ -166,7 +166,7 @@ sub do_slice { } $message .= "."; Slic3r::GUI::notify($message); - Wx::MessageDialog->new($self, $message, 'Done!', + Wx::MessageDialog->new($self, $message, 'Slicing Done!', wxOK | wxICON_INFORMATION)->ShowModal; }; Slic3r::GUI::catch_error($self, sub { $process_dialog->Destroy if $process_dialog }); From 5ef495a601961ea343585a7ee5a5a7e5c9299964 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 22:28:05 +0200 Subject: [PATCH 082/106] Improve repeated quick slice menu item text --- lib/Slic3r/GUI.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 38223c45d..922c60dac 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -70,7 +70,7 @@ sub OnInit { $fileMenu->Append(2, "Export Config…"); $fileMenu->AppendSeparator(); $fileMenu->Append(3, "Quick Slice…"); - $fileMenu->Append(4, "Quick Slice (last file)"); + $fileMenu->Append(4, "Repeat Last Quick Slice"); $fileMenu->Append(5, "Quick Slice and Save As…"); $fileMenu->AppendSeparator(); $fileMenu->Append(6, "Slice to SVG…"); From e01b20ec8e4c4c0449779f10c83e34a80b1b0c84 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 22:38:58 +0200 Subject: [PATCH 083/106] Add shortcuts keys for often used menu items. --- lib/Slic3r/GUI.pm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 922c60dac..79eb8f210 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -66,12 +66,12 @@ sub OnInit { # File menu my $fileMenu = Wx::Menu->new; { - $fileMenu->Append(1, "Load Config…"); - $fileMenu->Append(2, "Export Config…"); + $fileMenu->Append(1, "Load Config…\tCtrl+L"); + $fileMenu->Append(2, "Export Config…\tCtrl+E"); $fileMenu->AppendSeparator(); - $fileMenu->Append(3, "Quick Slice…"); - $fileMenu->Append(4, "Repeat Last Quick Slice"); - $fileMenu->Append(5, "Quick Slice and Save As…"); + $fileMenu->Append(3, "Quick Slice…\tCtrl+U"); + $fileMenu->Append(4, "Repeat Last Quick Slice\tCtrl+Shift+U"); + $fileMenu->Append(5, "Quick Slice and Save As…\tCtrl+Alt+U"); $fileMenu->AppendSeparator(); $fileMenu->Append(6, "Slice to SVG…"); $fileMenu->AppendSeparator(); From c35b57fb0bc06508b719d23b3b1b64a96c19f544 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 22:44:52 +0200 Subject: [PATCH 084/106] Add spacer for correctly aligning top text under wxGTK. --- lib/Slic3r/GUI/SkeinPanel.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 94a07c59f..ba57a625d 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -40,10 +40,12 @@ sub new { $buttons_sizer->Add($slice_button, 0, wxRIGHT, 20); EVT_BUTTON($self, $slice_button, sub { $self->do_slice }); + $buttons_sizer->AddStretchSpacer(1); + my $text = Wx::StaticText->new($self, -1, "Remember to check for updates at http://slic3r.org/\nVersion: $Slic3r::VERSION", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); my $font = Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL); $text->SetFont($font); - $buttons_sizer->Add($text, 1, wxEXPAND | wxALIGN_RIGHT); + $buttons_sizer->Add($text, 0, wxALIGN_RIGHT); } my $sizer = Wx::BoxSizer->new(wxVERTICAL); From 102aea45313ed495761ffa4510c1edc3aadb63c4 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 22:53:32 +0200 Subject: [PATCH 085/106] Sync message dialog title with SkeinPanel.pm changes. --- lib/Slic3r/GUI/Plater.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index a5b2452ed..3cc96adc1 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -553,7 +553,7 @@ sub on_export_completed { $self->statusbar->SetCancelCallback(undef); $self->statusbar->StopBusy; $self->statusbar->SetStatusText("G-code file exported to $self->{output_file}"); - Wx::MessageDialog->new($self, $message, 'Done!', wxOK | wxICON_INFORMATION)->ShowModal; + Wx::MessageDialog->new($self, $message, 'Slicing Done!', wxOK | wxICON_INFORMATION)->ShowModal; } sub on_export_failed { From 9f3031a06943cd291215e885502244b10588e4c1 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 23:06:07 +0200 Subject: [PATCH 086/106] Remove Quick Slice button, move update text to statusbar. --- lib/Slic3r/GUI.pm | 3 ++- lib/Slic3r/GUI/SkeinPanel.pm | 18 ------------------ 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 79eb8f210..817056e31 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -54,13 +54,14 @@ sub OnInit { # application frame Wx::Image::AddHandler(Wx::PNGHandler->new); - my $frame = Wx::Frame->new(undef, -1, 'Slic3r', wxDefaultPosition, [760,520], wxDEFAULT_FRAME_STYLE); + my $frame = Wx::Frame->new(undef, -1, 'Slic3r', wxDefaultPosition, [760, 470], wxDEFAULT_FRAME_STYLE); $frame->SetIcon(Wx::Icon->new("$Slic3r::var/Slic3r_128px.png", wxBITMAP_TYPE_PNG) ); $self->{skeinpanel} = Slic3r::GUI::SkeinPanel->new($frame); $self->SetTopWindow($frame); # status bar $frame->{statusbar} = Slic3r::GUI::ProgressStatusBar->new($frame, -1); + $frame->{statusbar}->SetStatusText("Version $Slic3r::VERSION - Remember to check for updates at http://slic3r.org/"); $frame->SetStatusBar($frame->{statusbar}); # File menu diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index ba57a625d..4b720f61d 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -31,25 +31,7 @@ sub new { $tabpanel->AddPage($self->{options_tabs}{filament}, $self->{options_tabs}{filament}->title); $tabpanel->AddPage($self->{options_tabs}{printer}, $self->{options_tabs}{printer}->title); - my $buttons_sizer; - { - $buttons_sizer = Wx::BoxSizer->new(wxHORIZONTAL); - - my $slice_button = Wx::Button->new($self, -1, "Quick slice…"); - $slice_button->SetDefault(); - $buttons_sizer->Add($slice_button, 0, wxRIGHT, 20); - EVT_BUTTON($self, $slice_button, sub { $self->do_slice }); - - $buttons_sizer->AddStretchSpacer(1); - - my $text = Wx::StaticText->new($self, -1, "Remember to check for updates at http://slic3r.org/\nVersion: $Slic3r::VERSION", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); - my $font = Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL); - $text->SetFont($font); - $buttons_sizer->Add($text, 0, wxALIGN_RIGHT); - } - my $sizer = Wx::BoxSizer->new(wxVERTICAL); - $sizer->Add($buttons_sizer, 0, wxEXPAND | wxALL, 10); $sizer->Add($tabpanel, 1, wxEXPAND); $sizer->SetSizeHints($self); From a2a35f47f6bc5af52bfc8f24f44ba7eba19ffb11 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 23:36:18 +0200 Subject: [PATCH 087/106] Convert Slic3r::GUI::notify() from class method to instance method. --- lib/Slic3r/GUI.pm | 10 +++++----- lib/Slic3r/GUI/Plater.pm | 2 +- lib/Slic3r/GUI/SkeinPanel.pm | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 817056e31..7945678f0 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -15,7 +15,6 @@ use Wx 0.9901 qw(:bitmap :dialog :frame :icon :id :misc :systemsettings); use Wx::Event qw(EVT_CLOSE EVT_MENU); use base 'Wx::App'; -my $growler; our $datadir; our $small_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); @@ -32,8 +31,8 @@ sub OnInit { if (eval "use Growl::GNTP; 1") { # register growl notifications eval { - $growler = Growl::GNTP->new(AppName => 'Slic3r', AppIcon => "$Slic3r::var/Slic3r.png"); - $growler->register([{Name => 'SKEIN_DONE', DisplayName => 'Slicing Done'}]); + $self->{growler} = Growl::GNTP->new(AppName => 'Slic3r', AppIcon => "$Slic3r::var/Slic3r.png"); + $self->{growler}->register([{Name => 'SKEIN_DONE', DisplayName => 'Slicing Done'}]); }; } @@ -170,11 +169,12 @@ sub warning_catcher { } sub notify { + my $self = shift; my ($message) = @_; eval { - $growler->notify(Event => 'SKEIN_DONE', Title => 'Slicing Done!', Message => $message) - if $growler; + $self->{growler}->notify(Event => 'SKEIN_DONE', Title => 'Slicing Done!', Message => $message) + if $self->{growler}; }; } diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 3cc96adc1..9568c9984 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -537,7 +537,7 @@ sub export_gcode2 { $message .= sprintf " %.1f seconds", $print->processing_time - $minutes*60; } $message .= "."; - Slic3r::GUI::notify($message); + &Wx::wxTheApp->notify($message); $params{on_completed}->($message); $print->cleanup; }; diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 4b720f61d..aaf7c5cd1 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -149,7 +149,7 @@ sub do_slice { $message .= sprintf " %.1f seconds", $print->processing_time - $minutes*60; } $message .= "."; - Slic3r::GUI::notify($message); + &Wx::wxTheApp->notify($message); Wx::MessageDialog->new($self, $message, 'Slicing Done!', wxOK | wxICON_INFORMATION)->ShowModal; }; From da7a668c94c29f33b74b4bef01d684128e229f6e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 23:57:31 +0200 Subject: [PATCH 088/106] Remove confirmation dialog on plate slicing done, request user attention instead. #537 --- lib/Slic3r/GUI.pm | 3 +++ lib/Slic3r/GUI/Plater.pm | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 7945678f0..81213242a 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -172,6 +172,9 @@ sub notify { my $self = shift; my ($message) = @_; + my $frame = $self->GetTopWindow; + $frame->RequestUserAttention unless ($frame->IsActive); + eval { $self->{growler}->notify(Event => 'SKEIN_DONE', Title => 'Slicing Done!', Message => $message) if $self->{growler}; diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 9568c9984..b7799c3ae 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -537,7 +537,6 @@ sub export_gcode2 { $message .= sprintf " %.1f seconds", $print->processing_time - $minutes*60; } $message .= "."; - &Wx::wxTheApp->notify($message); $params{on_completed}->($message); $print->cleanup; }; @@ -553,7 +552,7 @@ sub on_export_completed { $self->statusbar->SetCancelCallback(undef); $self->statusbar->StopBusy; $self->statusbar->SetStatusText("G-code file exported to $self->{output_file}"); - Wx::MessageDialog->new($self, $message, 'Slicing Done!', wxOK | wxICON_INFORMATION)->ShowModal; + &Wx::wxTheApp->notify($message); } sub on_export_failed { From b24e0370dd4a1d54a9a2a60929a03b3e4007b2f7 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 15 Jul 2012 23:59:50 +0200 Subject: [PATCH 089/106] Remove unused argument. --- lib/Slic3r/GUI/Plater.pm | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index b7799c3ae..4881ab64f 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -557,7 +557,6 @@ sub on_export_completed { sub on_export_failed { my $self = shift; - my ($message) = @_; $self->{export_thread}->detach if $self->{export_thread}; $self->{export_thread} = undef; From fda21bd6f2fb44ea1b8640cad4cf30623c5d4e92 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 16 Jul 2012 00:28:15 +0200 Subject: [PATCH 090/106] Only set $last_skein_dir from Plater, not $last_skein_file, to avoid interfering with Quick Slice. --- lib/Slic3r/GUI/Plater.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 4881ab64f..1b14df85c 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -236,7 +236,7 @@ sub load_file { my $self = shift; my ($input_file) = @_; - $Slic3r::GUI::SkeinPanel::last_input_file = $input_file; + $Slic3r::GUI::SkeinPanel::last_skein_dir = dirname($input_file); my $process_dialog = Wx::ProgressDialog->new('Loading…', "Processing input file…", 100, $self, 0); $process_dialog->Pulse; From a6da019fc614287a8c924f078d61051885b11211 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 16 Jul 2012 18:34:44 +0200 Subject: [PATCH 091/106] Adhere to various human interface guidelines. --- lib/Slic3r/GUI.pm | 2 +- lib/Slic3r/GUI/ConfigWizard.pm | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 81213242a..744a0e2b2 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -88,7 +88,7 @@ sub OnInit { # Help menu my $helpMenu = Wx::Menu->new; { - $helpMenu->Append(7, "Configuration Wizard…"); + $helpMenu->Append(7, "Configuration $Slic3r::GUI::ConfigWizard::wizard…"); $helpMenu->Append(8, "Slic3r Website"); $helpMenu->Append(wxID_ABOUT, "&About Slic3r"); EVT_MENU($frame, 7, sub { $self->{skeinpanel}->config_wizard }); diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index fcbd2b9d8..fe279ef6c 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -6,10 +6,14 @@ use utf8; use Wx; use base 'Wx::Wizard'; +# adhere to various human interface guidelines +our $wizard = 'Wizard'; +$wizard = 'Assistant' if &Wx::wxMAC || &Wx::wxGTK; + sub new { my $class = shift; my ($parent) = @_; - my $self = $class->SUPER::new($parent, -1, 'Configuration Wizard'); + my $self = $class->SUPER::new($parent, -1, "Configuration $wizard"); # Start from sane defaults $self->{old} = Slic3r::Config->current; @@ -314,10 +318,10 @@ use base 'Slic3r::GUI::ConfigWizard::Page'; sub new { my $class = shift; my ($parent) = @_; - my $self = $class->SUPER::new($parent, 'Welcome to the Slic3r Configuration Wizard', 'Welcome'); + my $self = $class->SUPER::new($parent, "Welcome to the Slic3r Configuration $wizard", 'Welcome'); - $self->append_text('Hello, welcome to Slic3r! This wizard helps you with the initial configuration; just a few settings and you will be ready to print.'); - $self->append_text('To import an existing configuration instead, cancel this wizard and use the Open Config menu item found in the File menu.'); + $self->append_text('Hello, welcome to Slic3r! This '.lc($wizard).' helps you with the initial configuration; just a few settings and you will be ready to print.'); + $self->append_text('To import an existing configuration instead, cancel this '.lc($wizard).' and use the Open Config menu item found in the File menu.'); $self->append_text('To continue, click Next.'); return $self; @@ -408,7 +412,7 @@ sub new { my $self = $class->SUPER::new($parent, 'Extrusion Temperature'); $self->append_text('Enter the temperature needed for extruding your filament, then click Next.'); - $self->append_text('A rule of thumb is 160 to 230 °C for PLA and 215 to 250 °C for ABS.'); + $self->append_text('A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS.'); $self->append_option('temperature'); return $self; @@ -455,9 +459,9 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, 'Congratulations!', 'Finish'); - $self->append_text('You have successfully completed the Slic3r Configuration Wizard. ' . + $self->append_text("You have successfully completed the Slic3r Configuration $wizard. " . 'Slic3r is now configured for your printer and filament.'); - $self->append_text('To close this wizard and apply the newly created configuration, click Finish.'); + $self->append_text('To close this '.lc($wizard).' and apply the newly created configuration, click Finish.'); return $self; } From 225414724c3ae5b53e1c1e2a2b6f0f70470d5c77 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 16 Jul 2012 19:13:35 +0200 Subject: [PATCH 092/106] Add keyboard accelerators to menus. --- lib/Slic3r/GUI.pm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 744a0e2b2..b3af9503c 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -66,14 +66,14 @@ sub OnInit { # File menu my $fileMenu = Wx::Menu->new; { - $fileMenu->Append(1, "Load Config…\tCtrl+L"); - $fileMenu->Append(2, "Export Config…\tCtrl+E"); + $fileMenu->Append(1, "&Load Config…\tCtrl+L"); + $fileMenu->Append(2, "&Export Config…\tCtrl+E"); $fileMenu->AppendSeparator(); - $fileMenu->Append(3, "Quick Slice…\tCtrl+U"); - $fileMenu->Append(4, "Repeat Last Quick Slice\tCtrl+Shift+U"); - $fileMenu->Append(5, "Quick Slice and Save As…\tCtrl+Alt+U"); + $fileMenu->Append(3, "Q&uick Slice…\tCtrl+U"); + $fileMenu->Append(4, "&Repeat Last Quick Slice\tCtrl+Shift+U"); + $fileMenu->Append(5, "Quick Slice and Save &As…\tCtrl+Alt+U"); $fileMenu->AppendSeparator(); - $fileMenu->Append(6, "Slice to SVG…"); + $fileMenu->Append(6, "Slice to SV&G…"); $fileMenu->AppendSeparator(); $fileMenu->Append(wxID_EXIT, "&Quit"); EVT_MENU($frame, 1, sub { $self->{skeinpanel}->load_config }); @@ -88,8 +88,8 @@ sub OnInit { # Help menu my $helpMenu = Wx::Menu->new; { - $helpMenu->Append(7, "Configuration $Slic3r::GUI::ConfigWizard::wizard…"); - $helpMenu->Append(8, "Slic3r Website"); + $helpMenu->Append(7, "&Configuration $Slic3r::GUI::ConfigWizard::wizard…"); + $helpMenu->Append(8, "Slic3r &Website"); $helpMenu->Append(wxID_ABOUT, "&About Slic3r"); EVT_MENU($frame, 7, sub { $self->{skeinpanel}->config_wizard }); EVT_MENU($frame, 8, sub { Wx::LaunchDefaultBrowser('http://slic3r.org/') }); From e80d2813ed6d1c82d1650b4b8676cc415446f036 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 16 Jul 2012 19:23:51 +0200 Subject: [PATCH 093/106] Add keyboard shortcut for SVG slicing. --- lib/Slic3r/GUI.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index b3af9503c..a8b2a8414 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -73,7 +73,7 @@ sub OnInit { $fileMenu->Append(4, "&Repeat Last Quick Slice\tCtrl+Shift+U"); $fileMenu->Append(5, "Quick Slice and Save &As…\tCtrl+Alt+U"); $fileMenu->AppendSeparator(); - $fileMenu->Append(6, "Slice to SV&G…"); + $fileMenu->Append(6, "Slice to SV&G…\tCtrl+G"); $fileMenu->AppendSeparator(); $fileMenu->Append(wxID_EXIT, "&Quit"); EVT_MENU($frame, 1, sub { $self->{skeinpanel}->load_config }); From 5d2fd17715ffca857b3ad4f89c92590fcb4bf7b3 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 16 Jul 2012 20:57:10 +0200 Subject: [PATCH 094/106] Use constants for menu item IDs. --- lib/Slic3r/GUI.pm | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index a8b2a8414..bf73883d4 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -15,6 +15,15 @@ use Wx 0.9901 qw(:bitmap :dialog :frame :icon :id :misc :systemsettings); use Wx::Event qw(EVT_CLOSE EVT_MENU); use base 'Wx::App'; +use constant MI_LOAD_CONF => 1; +use constant MI_EXPORT_CONF => 2; +use constant MI_QUICK_SLICE => 3; +use constant MI_REPEAT_QUICK => 4; +use constant MI_QUICK_SAVE_AS => 5; +use constant MI_SLICE_SVG => 6; +use constant MI_CONF_WIZARD => 7; +use constant MI_WEBSITE => 8; + our $datadir; our $small_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); @@ -66,33 +75,33 @@ sub OnInit { # File menu my $fileMenu = Wx::Menu->new; { - $fileMenu->Append(1, "&Load Config…\tCtrl+L"); - $fileMenu->Append(2, "&Export Config…\tCtrl+E"); + $fileMenu->Append(MI_LOAD_CONF, "&Load Config…\tCtrl+L"); + $fileMenu->Append(MI_EXPORT_CONF, "&Export Config…\tCtrl+E"); $fileMenu->AppendSeparator(); - $fileMenu->Append(3, "Q&uick Slice…\tCtrl+U"); - $fileMenu->Append(4, "&Repeat Last Quick Slice\tCtrl+Shift+U"); - $fileMenu->Append(5, "Quick Slice and Save &As…\tCtrl+Alt+U"); + $fileMenu->Append(MI_QUICK_SLICE, "Q&uick Slice…\tCtrl+U"); + $fileMenu->Append(MI_REPEAT_QUICK, "&Repeat Last Quick Slice\tCtrl+Shift+U"); + $fileMenu->Append(MI_QUICK_SAVE_AS, "Quick Slice and Save &As…\tCtrl+Alt+U"); $fileMenu->AppendSeparator(); - $fileMenu->Append(6, "Slice to SV&G…\tCtrl+G"); + $fileMenu->Append(MI_SLICE_SVG, "Slice to SV&G…\tCtrl+G"); $fileMenu->AppendSeparator(); $fileMenu->Append(wxID_EXIT, "&Quit"); - EVT_MENU($frame, 1, sub { $self->{skeinpanel}->load_config }); - EVT_MENU($frame, 2, sub { $self->{skeinpanel}->save_config }); - EVT_MENU($frame, 3, sub { $self->{skeinpanel}->do_slice }); - EVT_MENU($frame, 4, sub { $self->{skeinpanel}->do_slice(reslice => 1) }); - EVT_MENU($frame, 5, sub { $self->{skeinpanel}->do_slice(save_as => 1) }); - EVT_MENU($frame, 6, sub { $self->{skeinpanel}->do_slice(save_as => 1, export_svg => 1) }); + EVT_MENU($frame, MI_LOAD_CONF, sub { $self->{skeinpanel}->load_config }); + EVT_MENU($frame, MI_EXPORT_CONF, sub { $self->{skeinpanel}->save_config }); + EVT_MENU($frame, MI_QUICK_SLICE, sub { $self->{skeinpanel}->do_slice }); + EVT_MENU($frame, MI_REPEAT_QUICK, sub { $self->{skeinpanel}->do_slice(reslice => 1) }); + EVT_MENU($frame, MI_QUICK_SAVE_AS, sub { $self->{skeinpanel}->do_slice(save_as => 1) }); + EVT_MENU($frame, MI_SLICE_SVG, sub { $self->{skeinpanel}->do_slice(save_as => 1, export_svg => 1) }); EVT_MENU($frame, wxID_EXIT, sub {$_[0]->Close(0)}); } # Help menu my $helpMenu = Wx::Menu->new; { - $helpMenu->Append(7, "&Configuration $Slic3r::GUI::ConfigWizard::wizard…"); - $helpMenu->Append(8, "Slic3r &Website"); + $helpMenu->Append(MI_CONF_WIZARD, "&Configuration $Slic3r::GUI::ConfigWizard::wizard…"); + $helpMenu->Append(MI_WEBSITE, "Slic3r &Website"); $helpMenu->Append(wxID_ABOUT, "&About Slic3r"); - EVT_MENU($frame, 7, sub { $self->{skeinpanel}->config_wizard }); - EVT_MENU($frame, 8, sub { Wx::LaunchDefaultBrowser('http://slic3r.org/') }); + EVT_MENU($frame, MI_CONF_WIZARD, sub { $self->{skeinpanel}->config_wizard }); + EVT_MENU($frame, MI_WEBSITE, sub { Wx::LaunchDefaultBrowser('http://slic3r.org/') }); EVT_MENU($frame, wxID_ABOUT, \&about); } From 99845955b307a42759b69f04f4933e4e45c75a13 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 16 Jul 2012 22:37:31 +0200 Subject: [PATCH 095/106] Add support for libnotify notifications. --- Build.PL | 5 +++-- lib/Slic3r/GUI.pm | 56 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/Build.PL b/Build.PL index 1218f3684..8a74b4711 100644 --- a/Build.PL +++ b/Build.PL @@ -23,8 +23,9 @@ my $build = Module::Build->new( 'Test::More' => '0.10', }, recommends => { - 'Growl::GNTP' => '0.15', - 'Wx' => '0.9901', + 'Growl::GNTP' => '0.15', + 'Gtk2::Notify' => '0.05', + 'Wx' => '0.9901', }, script_files => ['slic3r.pl'], ); diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index bf73883d4..a197487e4 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -37,13 +37,7 @@ sub OnInit { $self->SetAppName('Slic3r'); Slic3r::debugf "wxWidgets version %s\n", &Wx::wxVERSION_STRING; - if (eval "use Growl::GNTP; 1") { - # register growl notifications - eval { - $self->{growler} = Growl::GNTP->new(AppName => 'Slic3r', AppIcon => "$Slic3r::var/Slic3r.png"); - $self->{growler}->register([{Name => 'SKEIN_DONE', DisplayName => 'Slicing Done'}]); - }; - } + $self->{notifier} = Slic3r::GUI::Notifier->new; # locate or create data directory $datadir = Wx::StandardPaths::Get->GetUserDataDir; @@ -184,10 +178,7 @@ sub notify { my $frame = $self->GetTopWindow; $frame->RequestUserAttention unless ($frame->IsActive); - eval { - $self->{growler}->notify(Event => 'SKEIN_DONE', Title => 'Slicing Done!', Message => $message) - if $self->{growler}; - }; + $self->{notifier}->notify($message); } package Slic3r::GUI::ProgressStatusBar; @@ -328,4 +319,47 @@ sub IsBusy { return $self->{_busy}; } +package Slic3r::GUI::Notifier; + +sub new { + my $class = shift; + my $self; + + $self->{icon} = "$Slic3r::var/Slic3r.png"; + + if (eval 'use Growl::GNTP; 1') { + # register with growl + eval { + $self->{growler} = Growl::GNTP->new(AppName => 'Slic3r', AppIcon => $self->{icon}); + $self->{growler}->register([{Name => 'SKEIN_DONE', DisplayName => 'Slicing Done'}]); + }; + } + if (eval 'use Gtk2::Notify; 1') { + # register with libnotify + eval { + Gtk2::Notify->init('Slic3r'); + $self->{libnotify} = 1; + } + } + + bless $self, $class; + + return $self; +} + +sub notify { + my ($self, $message) = @_; + + my $title = 'Slicing Done!'; + + + eval { + $self->{growler}->notify(Event => 'SKEIN_DONE', Title => $title, Message => $message) + if $self->{growler}; + }; + eval { + Gtk2::Notify->new($title, $message, $self->{icon})->show if $self->{libnotify}; + }; +} + 1; From 095607a1665894d43c71ae2e97f5563c20b64906 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 16 Jul 2012 23:09:55 +0200 Subject: [PATCH 096/106] Remove excessive line breaks --- lib/Slic3r/GUI.pm | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index a197487e4..272f04740 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -349,10 +349,8 @@ sub new { sub notify { my ($self, $message) = @_; - my $title = 'Slicing Done!'; - eval { $self->{growler}->notify(Event => 'SKEIN_DONE', Title => $title, Message => $message) if $self->{growler}; From 3690b0798e4d6640d7115a118d122fe2f5eec28a Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 16 Jul 2012 23:43:09 +0200 Subject: [PATCH 097/106] Use Net::DBus instead of Gtk2::Notify due to less dependencies; recommended by @beanz. --- Build.PL | 6 +++--- lib/Slic3r/GUI.pm | 17 ++++++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Build.PL b/Build.PL index 8a74b4711..976e8fa6e 100644 --- a/Build.PL +++ b/Build.PL @@ -23,9 +23,9 @@ my $build = Module::Build->new( 'Test::More' => '0.10', }, recommends => { - 'Growl::GNTP' => '0.15', - 'Gtk2::Notify' => '0.05', - 'Wx' => '0.9901', + 'Growl::GNTP' => '0.15', + 'Net::DBus' => '0', + 'Wx' => '0.9901', }, script_files => ['slic3r.pl'], ); diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 272f04740..df011e910 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -334,13 +334,6 @@ sub new { $self->{growler}->register([{Name => 'SKEIN_DONE', DisplayName => 'Slicing Done'}]); }; } - if (eval 'use Gtk2::Notify; 1') { - # register with libnotify - eval { - Gtk2::Notify->init('Slic3r'); - $self->{libnotify} = 1; - } - } bless $self, $class; @@ -355,8 +348,14 @@ sub notify { $self->{growler}->notify(Event => 'SKEIN_DONE', Title => $title, Message => $message) if $self->{growler}; }; - eval { - Gtk2::Notify->new($title, $message, $self->{icon})->show if $self->{libnotify}; + if (eval 'use Net::DBus; 1') { + eval { + my $session = Net::DBus->session; + my $serv = $session->get_service('org.freedesktop.Notifications'); + my $notifier = $serv->get_object('/org/freedesktop/Notifications', + 'org.freedesktop.Notifications'); + $notifier->Notify('Slic3r', 0, $self->{icon}, $title, $message, [], {}, 5); + } }; } From 19f4036d8af36173baebc2692068b0c5f7cfcca8 Mon Sep 17 00:00:00 2001 From: Ryan Voots Date: Mon, 16 Jul 2012 19:04:25 -0400 Subject: [PATCH 098/106] Time here is in milliseconds, setting it to 1500 to make it stay for at least 1.5 seconds. --- lib/Slic3r/GUI.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index df011e910..5e2bc6fb1 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -354,7 +354,7 @@ sub notify { my $serv = $session->get_service('org.freedesktop.Notifications'); my $notifier = $serv->get_object('/org/freedesktop/Notifications', 'org.freedesktop.Notifications'); - $notifier->Notify('Slic3r', 0, $self->{icon}, $title, $message, [], {}, 5); + $notifier->Notify('Slic3r', 0, $self->{icon}, $title, $message, [], {}, 1500); } }; } From de47f5fe72477146d981799b73a7e3bfdc35270e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 17 Jul 2012 15:38:53 +0200 Subject: [PATCH 099/106] Use default desktop notification timeout. --- lib/Slic3r/GUI.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 5e2bc6fb1..ec1bb5ba0 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -354,7 +354,7 @@ sub notify { my $serv = $session->get_service('org.freedesktop.Notifications'); my $notifier = $serv->get_object('/org/freedesktop/Notifications', 'org.freedesktop.Notifications'); - $notifier->Notify('Slic3r', 0, $self->{icon}, $title, $message, [], {}, 1500); + $notifier->Notify('Slic3r', 0, $self->{icon}, $title, $message, [], {}, -1); } }; } From 82cfc7c3d62f0da8462ac0a7f4bd92fa4d7c25e7 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 17 Jul 2012 23:16:58 +0200 Subject: [PATCH 100/106] Check for unsaved presets before interactively loading an existing config file. --- lib/Slic3r/GUI/SkeinPanel.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index aaf7c5cd1..ed46d7269 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -184,6 +184,7 @@ sub load_config { my ($file) = @_; if (!$file) { + return unless $self->check_unsaved_changes; my $dir = $last_config ? dirname($last_config) : $last_config_dir || $last_skein_dir || ""; my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini", $ini_wildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST); From bd16366d6285a679ef3954e8de4c05f408f33b36 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 17 Jul 2012 23:24:21 +0200 Subject: [PATCH 101/106] Default to "No" when prompting about discarding unsaved changes. --- lib/Slic3r/GUI/SkeinPanel.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index ed46d7269..a31d69bfb 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -214,8 +214,8 @@ sub check_unsaved_changes { if (@dirty) { my $titles = join ', ', @dirty; my $confirm = Wx::MessageDialog->new($self, "You have unsaved changes ($titles). Discard changes and continue anyway?", - 'Unsaved Presets', wxICON_QUESTION | wxOK | wxCANCEL); - return ($confirm->ShowModal == wxID_OK); + 'Unsaved Presets', wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT); + return ($confirm->ShowModal == wxID_YES); } return 1; From c25a31ef98d6f7c6f29d316502486aec1d0e9fcf Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 17 Jul 2012 23:51:57 +0200 Subject: [PATCH 102/106] Avoid SVG slicing interfering with repeating last quick slice. --- lib/Slic3r/GUI/SkeinPanel.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index a31d69bfb..3b7ec4514 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -76,7 +76,7 @@ sub do_slice { } $input_file = $dialog->GetPaths; $dialog->Destroy; - $last_input_file = $input_file; + $last_input_file = $input_file unless $params{export_svg}; } else { if (!defined $last_input_file) { Wx::MessageDialog->new($self, "No previously sliced file.", @@ -110,7 +110,8 @@ sub do_slice { $dlg->Destroy; return; } - $output_file = $last_output_file = $dlg->GetPath; + $output_file = $dlg->GetPath; + $last_output_file = $output_file unless $params{export_svg}; $dlg->Destroy; } From a8d5ee3a74827ee9930798acd919c0ab339e9067 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 17 Jul 2012 23:53:16 +0200 Subject: [PATCH 103/106] Only enable Repeat Last Quick Slice menu item after the first quick slice. --- lib/Slic3r/GUI.pm | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index ec1bb5ba0..c6ce3c3f2 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -73,7 +73,8 @@ sub OnInit { $fileMenu->Append(MI_EXPORT_CONF, "&Export Config…\tCtrl+E"); $fileMenu->AppendSeparator(); $fileMenu->Append(MI_QUICK_SLICE, "Q&uick Slice…\tCtrl+U"); - $fileMenu->Append(MI_REPEAT_QUICK, "&Repeat Last Quick Slice\tCtrl+Shift+U"); + my $repeat = $fileMenu->Append(MI_REPEAT_QUICK, "&Repeat Last Quick Slice\tCtrl+Shift+U"); + $repeat->Enable(0); $fileMenu->Append(MI_QUICK_SAVE_AS, "Quick Slice and Save &As…\tCtrl+Alt+U"); $fileMenu->AppendSeparator(); $fileMenu->Append(MI_SLICE_SVG, "Slice to SV&G…\tCtrl+G"); @@ -81,9 +82,11 @@ sub OnInit { $fileMenu->Append(wxID_EXIT, "&Quit"); EVT_MENU($frame, MI_LOAD_CONF, sub { $self->{skeinpanel}->load_config }); EVT_MENU($frame, MI_EXPORT_CONF, sub { $self->{skeinpanel}->save_config }); - EVT_MENU($frame, MI_QUICK_SLICE, sub { $self->{skeinpanel}->do_slice }); + EVT_MENU($frame, MI_QUICK_SLICE, sub { $self->{skeinpanel}->do_slice; + $repeat->Enable(defined $Slic3r::GUI::SkeinPanel::last_input_file) }); EVT_MENU($frame, MI_REPEAT_QUICK, sub { $self->{skeinpanel}->do_slice(reslice => 1) }); - EVT_MENU($frame, MI_QUICK_SAVE_AS, sub { $self->{skeinpanel}->do_slice(save_as => 1) }); + EVT_MENU($frame, MI_QUICK_SAVE_AS, sub { $self->{skeinpanel}->do_slice(save_as => 1); + $repeat->Enable(defined $Slic3r::GUI::SkeinPanel::last_input_file) }); EVT_MENU($frame, MI_SLICE_SVG, sub { $self->{skeinpanel}->do_slice(save_as => 1, export_svg => 1) }); EVT_MENU($frame, wxID_EXIT, sub {$_[0]->Close(0)}); } From fd88c164d25b640b42382d1cd0665c702598123d Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 17 Jul 2012 23:54:30 +0200 Subject: [PATCH 104/106] Move Repeat Last Quick Slice below other Quick Slice items since it works for both. --- lib/Slic3r/GUI.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index c6ce3c3f2..da25b6208 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -73,9 +73,9 @@ sub OnInit { $fileMenu->Append(MI_EXPORT_CONF, "&Export Config…\tCtrl+E"); $fileMenu->AppendSeparator(); $fileMenu->Append(MI_QUICK_SLICE, "Q&uick Slice…\tCtrl+U"); + $fileMenu->Append(MI_QUICK_SAVE_AS, "Quick Slice and Save &As…\tCtrl+Alt+U"); my $repeat = $fileMenu->Append(MI_REPEAT_QUICK, "&Repeat Last Quick Slice\tCtrl+Shift+U"); $repeat->Enable(0); - $fileMenu->Append(MI_QUICK_SAVE_AS, "Quick Slice and Save &As…\tCtrl+Alt+U"); $fileMenu->AppendSeparator(); $fileMenu->Append(MI_SLICE_SVG, "Slice to SV&G…\tCtrl+G"); $fileMenu->AppendSeparator(); From 42034ecb4037ecb7f000f10d8702f5c6a72af5f2 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 18 Jul 2012 11:54:26 +0200 Subject: [PATCH 105/106] Autosize the main frame to workaround inconsistencies among wxGTK setups --- lib/Slic3r/GUI.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index da25b6208..d8f839658 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -121,6 +121,7 @@ sub OnInit { $event->Skip; }); + $frame->Fit; $frame->SetMinSize($frame->GetSize); $frame->Show; $frame->Layout; From 2d17a94a3842ce7ae3e8a7e31b5a9a8aee028a98 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 18 Jul 2012 12:00:19 +0200 Subject: [PATCH 106/106] Prevent the left treectrl to grow if preset names are too long --- lib/Slic3r/GUI/Tab.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 62df01a4f..66859b0fb 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -31,13 +31,13 @@ sub new { my $left_sizer = Wx::BoxSizer->new(wxVERTICAL); $self->{sizer}->Add($left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3); - my $left_col_width = 210; + my $left_col_width = 150; # preset chooser { # choice menu - $self->{presets_choice} = Wx::Choice->new($self, -1, wxDefaultPosition, wxDefaultSize, []); + $self->{presets_choice} = Wx::Choice->new($self, -1, wxDefaultPosition, [$left_col_width, -1], []); $self->{presets_choice}->SetFont($Slic3r::GUI::small_font); # buttons