2012-06-17 22:27:05 +02:00
package Slic3r::GUI::Tab ;
use strict ;
use warnings ;
use utf8 ;
2012-06-19 14:47:02 +02:00
use File::Basename qw(basename) ;
2012-06-18 22:27:57 +02:00
use List::Util qw(first) ;
2012-07-15 20:05:57 +02:00
use Wx qw(:bookctrl :dialog :icon :id :misc :sizer :treectrl :window) ;
2012-07-01 19:24:06 +02:00
use Wx::Event qw(EVT_BUTTON EVT_CHOICE EVT_TREE_SEL_CHANGED) ;
2012-06-18 16:46:43 +02:00
use base 'Wx::Panel' ;
2012-06-17 22:27:05 +02:00
sub new {
my $class = shift ;
2012-07-18 20:36:34 +02:00
my ( $parent , %params ) = @_ ;
2012-07-03 01:20:30 +02:00
my $self = $class -> SUPER:: new ( $parent , - 1 , wxDefaultPosition , wxDefaultSize , wxBK_LEFT );
2012-06-17 22:54:08 +02:00
2012-06-19 17:23:10 +02:00
$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 ;
});
2012-06-18 22:27:57 +02:00
# horizontal sizer
2012-07-01 19:24:06 +02:00
$self -> { sizer } = Wx::BoxSizer -> new ( wxHORIZONTAL );
2012-06-18 16:46:43 +02:00
$self -> { sizer } -> SetSizeHints ( $self );
$self -> SetSizer ( $self -> { sizer });
2012-06-18 22:27:57 +02:00
# left vertical sizer
2012-07-01 19:24:06 +02:00
my $left_sizer = Wx::BoxSizer -> new ( wxVERTICAL );
2012-07-15 20:05:57 +02:00
$self -> { sizer } -> Add ( $left_sizer , 0 , wxEXPAND | wxLEFT | wxTOP | wxBOTTOM , 3 );
2012-06-18 16:46:43 +02:00
2012-07-18 12:00:19 +02:00
my $left_col_width = 150 ;
2012-06-18 22:27:57 +02:00
# preset chooser
{
# choice menu
2012-07-18 12:00:19 +02:00
$self -> { presets_choice } = Wx::Choice -> new ( $self , - 1 , wxDefaultPosition , [ $left_col_width , - 1 ], [] );
2012-06-19 17:23:10 +02:00
$self -> { presets_choice } -> SetFont ( $ Slic3r::GUI:: small_font );
2012-06-18 22:27:57 +02:00
# buttons
2012-07-01 19:24:06 +02:00
$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 ));
2012-07-18 20:36:34 +02:00
$self -> { btn_save_preset } -> SetToolTipString ( "Save current " . lc ( $self -> title ));
2012-06-18 22:27:57 +02:00
$self -> { btn_delete_preset } -> SetToolTipString ( "Delete this preset" );
$self -> { btn_delete_preset } -> Disable ;
2012-06-20 17:08:38 +02:00
### These cause GTK warnings:
2012-07-03 01:20:30 +02:00
###my $box = Wx::StaticBox->new($self, -1, "Presets:", wxDefaultPosition, [$left_col_width, 50]);
2012-07-01 19:24:06 +02:00
###my $hsizer = Wx::StaticBoxSizer->new($box, wxHORIZONTAL);
2012-06-20 17:08:38 +02:00
2012-07-01 19:24:06 +02:00
my $hsizer = Wx::BoxSizer -> new ( wxHORIZONTAL );
2012-06-20 17:08:38 +02:00
2012-07-01 19:24:06 +02:00
$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 );
2012-06-18 22:27:57 +02:00
}
# tree
2012-07-15 20:05:57 +02:00
$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 );
2012-07-01 19:24:06 +02:00
$left_sizer -> Add ( $self -> { treectrl }, 1 , wxEXPAND );
2012-06-18 16:46:43 +02:00
$self -> { icons } = Wx::ImageList -> new ( 16 , 16 , 1 );
$self -> { treectrl } -> AssignImageList ( $self -> { icons });
$self -> { iconcount } = - 1 ;
$self -> { treectrl } -> AddRoot ( "root" );
2012-07-18 20:36:34 +02:00
$self -> { pages } = [] ;
2012-06-18 16:46:43 +02:00
$self -> { treectrl } -> SetIndent ( 0 );
EVT_TREE_SEL_CHANGED ( $parent , $self -> { treectrl }, sub {
2012-07-18 20:36:34 +02:00
my $page = first { $_ -> { title } eq $self -> { treectrl } -> GetItemText ( $self -> { treectrl } -> GetSelection ) } @ { $self -> { pages }}
or return ;
$_ -> Hide for @ { $self -> { pages }};
2012-07-24 00:34:07 +02:00
$self -> { sizer } -> Detach ( 1 );
2012-07-01 19:24:06 +02:00
$self -> { sizer } -> Add ( $page , 1 , wxEXPAND | wxLEFT , 5 );
2012-07-24 00:34:57 +02:00
$page -> Show ;
2012-06-18 16:46:43 +02:00
$self -> { sizer } -> Layout ;
2012-07-18 19:19:07 +02:00
$self -> Refresh ;
2012-06-18 16:46:43 +02:00
});
2012-06-17 22:54:08 +02:00
2012-06-18 22:27:57 +02:00
EVT_CHOICE ( $parent , $self -> { presets_choice }, sub {
2012-06-19 17:23:10 +02:00
$self -> on_select_preset ;
$self -> sync_presets ;
2012-06-18 22:27:57 +02:00
});
EVT_BUTTON ( $self , $self -> { btn_save_preset }, sub {
2012-07-15 17:54:57 +02:00
my $preset = $self -> current_preset ;
my $default_name = $preset -> { default } ? 'Untitled' : basename ( $preset -> { name });
2012-07-15 18:37:00 +02:00
$default_name =~ s/\.ini$//i ;
2012-06-18 22:27:57 +02:00
my $dlg = Slic3r::GUI::SavePresetWindow -> new ( $self ,
2012-07-18 20:36:34 +02:00
title => lc ( $self -> title ),
2012-07-15 17:54:57 +02:00
default => $default_name ,
2012-07-15 18:37:00 +02:00
values => [ map { my $name = $_ -> { name }; $name =~ s/\.ini$//i ; $name } @ { $self -> { presets }} ],
2012-06-18 22:27:57 +02:00
);
2012-07-01 19:24:06 +02:00
return unless $dlg -> ShowModal == wxID_OK ;
2012-06-18 22:27:57 +02:00
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 ;
2012-07-15 18:37:00 +02:00
$self -> { presets_choice } -> SetSelection ( first { basename ( $self -> { presets }[ $_ ]{ file }) eq $dlg -> get_name . ".ini" } 1 .. $# { $self -> { presets }});
2012-06-19 18:11:51 +02:00
$self -> on_select_preset ;
2012-06-19 17:23:10 +02:00
$self -> sync_presets ;
2012-06-18 22:27:57 +02:00
});
2012-06-19 17:47:48 +02:00
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
2012-07-01 19:24:06 +02:00
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 ;
2012-07-18 16:17:23 +02:00
if ( - e $self -> { presets }[ $i ]{ file }) {
unlink $self -> { presets }[ $i ]{ file };
2012-06-19 17:47:48 +02:00
}
2012-07-18 16:17:23 +02:00
splice @ { $self -> { presets }}, $i , 1 ;
2012-06-19 17:47:48 +02:00
$self -> { presets_choice } -> Delete ( $i );
$self -> { presets_choice } -> SetSelection ( 0 );
$self -> on_select_preset ;
$self -> sync_presets ;
});
2012-07-18 20:36:34 +02:00
$self -> build ;
2012-06-17 22:27:05 +02:00
return $self ;
}
2012-07-15 17:54:57 +02:00
sub current_preset {
my $self = shift ;
return $self -> { presets }[ $self -> { presets_choice } -> GetSelection ];
}
2012-07-18 20:36:34 +02:00
sub on_value_change {}
sub on_preset_loaded {}
2012-06-19 17:23:10 +02:00
sub on_select_preset {
my $self = shift ;
if ( defined $self -> { dirty }) {
# TODO: prompt user?
$self -> set_dirty ( 0 );
}
2012-07-15 17:54:57 +02:00
my $preset = $self -> current_preset ;
if ( $preset -> { default }) {
# default settings: disable the delete button
2012-06-19 17:23:10 +02:00
Slic3r::Config -> load_hash ( $ Slic3r:: Defaults , $self -> { presets_group }, 1 );
$self -> { btn_delete_preset } -> Disable ;
} else {
2012-07-15 17:54:57 +02:00
if ( !- e $preset -> { file }) {
Slic3r::GUI:: show_error ( $self , "The selected preset does not exist anymore ($preset->{file})." );
2012-06-19 17:23:10 +02:00
return ;
}
2012-07-15 17:54:57 +02:00
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 ;
2012-06-19 17:23:10 +02:00
}
2012-07-18 20:36:34 +02:00
$self -> on_preset_loaded ;
2012-06-19 17:23:10 +02:00
$_ -> () for @ Slic3r::GUI::OptionsGroup:: reload_callbacks { @ { $ Slic3r::Config:: Groups { $self -> { presets_group }}}};
$self -> set_dirty ( 0 );
2012-07-15 17:54:57 +02:00
$ Slic3r:: Settings -> { presets }{ $self -> { presets_group }} = $preset -> { file } ? basename ( $preset -> { file }) : '' ;
2012-06-19 18:11:51 +02:00
Slic3r::Config -> save_settings ( "$Slic3r::GUI::datadir/slic3r.ini" );
2012-06-19 17:23:10 +02:00
}
2012-06-18 22:27:57 +02:00
sub add_options_page {
2012-06-17 22:27:05 +02:00
my $self = shift ;
2012-07-18 20:36:34 +02:00
my ( $title , $icon , %params ) = @_ ;
2012-06-17 22:54:08 +02:00
2012-07-18 20:36:34 +02:00
if ( $icon ) {
my $bitmap = Wx::Bitmap -> new ( "$Slic3r::var/$icon" , wxBITMAP_TYPE_PNG );
2012-06-18 16:46:43 +02:00
$self -> { icons } -> Add ( $bitmap );
$self -> { iconcount } ++ ;
2012-06-17 22:54:08 +02:00
}
2012-07-18 20:36:34 +02:00
my $page = Slic3r::GUI::Tab::Page -> new ( $self , $title , $self -> { iconcount }, %params , on_change => sub {
$self -> on_value_change ( @_ );
$self -> set_dirty ( 1 );
$self -> sync_presets ;
});
2012-06-18 16:46:43 +02:00
$page -> Hide ;
2012-07-18 20:36:34 +02:00
push @ { $self -> { pages }}, $page ;
$self -> update_tree ;
return $page ;
}
sub update_tree {
my $self = shift ;
my ( $select ) = @_ ;
$select // = 0 ; #/
my $rootItem = $self -> { treectrl } -> GetRootItem ;
$self -> { treectrl } -> DeleteChildren ( $rootItem );
foreach my $page ( @ { $self -> { pages }}) {
my $itemId = $self -> { treectrl } -> AppendItem ( $rootItem , $page -> { title }, $page -> { iconID });
$self -> { treectrl } -> SelectItem ( $itemId ) if $self -> { treectrl } -> GetChildrenCount ( $rootItem ) == $select + 1 ;
2012-06-18 22:27:57 +02:00
}
}
sub set_dirty {
my $self = shift ;
my ( $dirty ) = @_ ;
my $i = $self -> { dirty } // $self -> { presets_choice } -> GetSelection ; #/
my $text = $self -> { presets_choice } -> GetString ( $i );
2012-07-15 17:54:57 +02:00
2012-06-18 22:27:57 +02:00
if ( $dirty ) {
$self -> { dirty } = $i ;
if ( $text !~ / \(modified\)$/ ) {
$self -> { presets_choice } -> SetString ( $i , "$text (modified)" );
2012-06-20 21:43:06 +02:00
$self -> { presets_choice } -> SetSelection ( $i ); # wxMSW needs this after every SetString()
2012-06-18 22:27:57 +02:00
}
} else {
$self -> { dirty } = undef ;
$text =~ s/ \(modified\)$// ;
$self -> { presets_choice } -> SetString ( $i , $text );
2012-06-20 21:43:06 +02:00
$self -> { presets_choice } -> SetSelection ( $i ); # wxMSW needs this after every SetString()
2012-06-18 22:27:57 +02:00
}
2012-06-19 17:23:10 +02:00
$self -> sync_presets ;
2012-06-18 22:27:57 +02:00
}
2012-06-23 17:38:19 +02:00
sub is_dirty {
my $self = shift ;
2012-06-30 22:34:13 +02:00
return ( defined $self -> { dirty });
2012-06-23 17:38:19 +02:00
}
2012-06-18 22:27:57 +02:00
sub load_presets {
my $self = shift ;
my ( $group ) = @_ ;
$self -> { presets_group } ||= $group ;
2012-07-15 17:54:57 +02:00
$self -> { presets } = [{
default => 1 ,
name => '- default -' ,
}];
2012-06-18 22:27:57 +02:00
opendir my $dh , "$Slic3r::GUI::datadir/$self->{presets_group}" or die "Failed to read directory $Slic3r::GUI::datadir/$self->{presets_group} (errno: $!)\n" ;
2012-07-15 17:54:57 +02:00
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 ,
};
}
2012-06-18 22:27:57 +02:00
closedir $dh ;
$self -> { presets_choice } -> Clear ;
2012-07-15 17:54:57 +02:00
$self -> { presets_choice } -> Append ( $_ -> { name }) for @ { $self -> { presets }};
2012-06-19 18:11:51 +02:00
{
2012-07-15 17:54:57 +02:00
# 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 );
2012-06-20 17:17:07 +02:00
$self -> on_select_preset ;
2012-06-19 18:11:51 +02:00
}
2012-06-19 17:23:10 +02:00
$self -> sync_presets ;
2012-06-17 22:27:05 +02:00
}
2012-07-18 20:36:34 +02:00
sub load_external_config {
2012-06-19 14:47:02 +02:00
my $self = shift ;
my ( $file ) = @_ ;
# look for the loaded config among the existing menu items
2012-07-15 17:54:57 +02:00
my $i = first { $self -> { presets }[ $_ ]{ file } eq $file && $self -> { presets }[ $_ ]{ external } } 1 .. $# { $self -> { presets }};
2012-06-19 14:47:02 +02:00
if ( ! $i ) {
2012-07-15 17:54:57 +02:00
my $preset_name = basename ( $file ); # keep the .ini suffix
push @ { $self -> { presets }}, {
file => $file ,
name => $preset_name ,
external => 1 ,
};
2012-06-19 14:47:02 +02:00
$self -> { presets_choice } -> Append ( $preset_name );
$i = $# { $self -> { presets }};
}
2012-07-15 17:54:57 +02:00
$self -> { presets_choice } -> SetSelection ( $i );
$self -> on_select_preset ;
2012-06-19 17:23:10 +02:00
$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 );
2012-06-19 14:47:02 +02:00
}
2012-06-17 22:27:05 +02:00
package Slic3r::GUI::Tab::Print ;
use base 'Slic3r::GUI::Tab' ;
2012-07-18 20:36:34 +02:00
sub title { 'Print Settings' }
sub build {
my $self = shift ;
2012-06-17 22:27:05 +02:00
2012-06-18 22:27:57 +02:00
$self -> add_options_page ( 'Layers and perimeters' , 'layers.png' , optgroups => [
2012-06-17 22:27:05 +02:00
{
title => 'Layer height' ,
options => [ qw(layer_height first_layer_height) ],
},
{
title => 'Vertical shells' ,
2012-07-18 15:48:04 +02:00
options => [ qw(perimeters randomize_start extra_perimeters) ],
2012-06-17 22:27:05 +02:00
},
{
title => 'Horizontal shells' ,
options => [ qw(solid_layers) ],
},
]);
2012-06-18 22:27:57 +02:00
$self -> add_options_page ( 'Infill' , 'shading.png' , optgroups => [
2012-06-17 22:27:05 +02:00
{
title => 'Infill' ,
2012-06-18 10:19:24 +02:00
options => [ qw(fill_density fill_angle fill_pattern solid_fill_pattern infill_every_layers) ],
2012-06-17 22:27:05 +02:00
},
]);
2012-06-18 22:27:57 +02:00
$self -> add_options_page ( 'Speed' , 'time.png' , optgroups => [
2012-06-17 22:27:05 +02:00
{
title => 'Speed for print moves' ,
2012-07-23 09:43:59 +02:00
options => [ qw(perimeter_speed small_perimeter_speed external_perimeter_speed infill_speed solid_infill_speed top_solid_infill_speed bridge_speed) ],
2012-06-17 22:27:05 +02:00
},
{
title => 'Speed for non-print moves' ,
options => [ qw(travel_speed) ],
},
{
2012-06-18 10:19:24 +02:00
title => 'Modifiers' ,
2012-06-17 22:27:05 +02:00
options => [ qw(first_layer_speed) ],
},
]);
2012-07-18 15:48:04 +02:00
$self -> add_options_page ( 'Skirt and brim' , 'box.png' , optgroups => [
2012-06-17 22:27:05 +02:00
{
title => 'Skirt' ,
options => [ qw(skirts skirt_distance skirt_height) ],
},
2012-07-18 15:48:04 +02:00
{
title => 'Brim' ,
options => [ qw(brim_width) ],
},
2012-06-17 22:27:05 +02:00
]);
2012-06-18 22:27:57 +02:00
$self -> add_options_page ( 'Support material' , 'building.png' , optgroups => [
2012-06-17 22:27:05 +02:00
{
title => 'Support material' ,
2012-07-18 15:48:04 +02:00
options => [ qw(support_material support_material_threshold support_material_pattern support_material_spacing support_material_angle) ],
2012-06-17 22:27:05 +02:00
},
]);
2012-06-18 22:27:57 +02:00
$self -> add_options_page ( 'Notes' , 'note.png' , optgroups => [
2012-06-17 22:27:05 +02:00
{
title => 'Notes' ,
2012-06-17 23:24:10 +02:00
no_labels => 1 ,
2012-06-17 22:27:05 +02:00
options => [ qw(notes) ],
},
]);
2012-06-18 22:27:57 +02:00
$self -> add_options_page ( 'Output options' , 'page_white_go.png' , optgroups => [
2012-06-17 22:27:05 +02:00
{
title => 'Sequential printing' ,
options => [ qw(complete_objects extruder_clearance_radius extruder_clearance_height) ],
},
{
title => 'Output file' ,
options => [ qw(gcode_comments output_filename_format) ],
},
{
2012-06-17 23:24:10 +02:00
title => 'Post-processing scripts' ,
no_labels => 1 ,
2012-06-18 11:26:21 +02:00
options => [ qw(post_process) ],
2012-06-17 22:27:05 +02:00
},
]);
2012-06-18 22:27:57 +02:00
$self -> add_options_page ( 'Advanced' , 'wrench.png' , optgroups => [
2012-06-17 22:27:05 +02:00
{
title => 'Extrusion width' ,
2012-06-18 14:29:47 +02:00
label_width => 180 ,
2012-07-18 18:14:32 +02:00
options => [ qw(extrusion_width first_layer_extrusion_width perimeter_extrusion_width infill_extrusion_width support_material_extrusion_width) ],
2012-06-17 22:27:05 +02:00
},
{
title => 'Flow' ,
options => [ qw(bridge_flow_ratio) ],
},
2012-06-18 11:26:21 +02:00
{
title => 'Other' ,
2012-07-18 15:48:04 +02:00
options => [ qw(duplicate_distance) , ( $ Slic3r:: have_threads ? qw(threads) : ())],
2012-06-18 11:26:21 +02:00
},
2012-06-17 22:27:05 +02:00
]);
2012-06-18 22:27:57 +02:00
$self -> load_presets ( 'print' );
2012-06-17 22:27:05 +02:00
}
2012-06-18 14:29:47 +02:00
package Slic3r::GUI::Tab::Filament ;
use base 'Slic3r::GUI::Tab' ;
2012-07-18 20:36:34 +02:00
sub title { 'Filament Settings' }
sub build {
my $self = shift ;
2012-06-18 14:29:47 +02:00
2012-06-18 22:27:57 +02:00
$self -> add_options_page ( 'Filament' , 'spool.png' , optgroups => [
2012-06-18 14:29:47 +02:00
{
title => 'Filament' ,
2012-07-18 15:48:04 +02:00
options => [ 'filament_diameter#0' , 'extrusion_multiplier#0' ],
2012-06-18 14:29:47 +02:00
},
{
title => 'Temperature' ,
2012-07-18 15:48:04 +02:00
options => [ 'temperature#0' , 'first_layer_temperature#0' , qw(bed_temperature first_layer_bed_temperature) ],
2012-06-18 14:29:47 +02:00
},
]);
2012-06-18 22:27:57 +02:00
$self -> add_options_page ( 'Cooling' , 'hourglass.png' , optgroups => [
2012-06-18 14:29:47 +02:00
{
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) ],
},
]);
2012-06-18 22:27:57 +02:00
$self -> load_presets ( 'filament' );
2012-06-18 14:29:47 +02:00
}
2012-06-17 22:27:05 +02:00
package Slic3r::GUI::Tab::Printer ;
use base 'Slic3r::GUI::Tab' ;
2012-07-18 20:36:34 +02:00
sub title { 'Printer Settings' }
sub build {
my $self = shift ;
2012-06-17 22:27:05 +02:00
2012-06-18 22:27:57 +02:00
$self -> add_options_page ( 'General' , 'printer_empty.png' , optgroups => [
2012-06-17 22:27:05 +02:00
{
title => 'Size and coordinates' ,
options => [ qw(bed_size print_center z_offset) ],
},
{
title => 'Firmware' ,
options => [ qw(gcode_flavor use_relative_e_distances) ],
},
{
2012-07-18 20:36:34 +02:00
title => 'Capabilities' ,
options => [ qw(extruders_count) ],
2012-06-17 22:27:05 +02:00
},
]);
2012-06-18 22:27:57 +02:00
$self -> add_options_page ( 'Custom G-code' , 'cog.png' , optgroups => [
2012-06-17 22:27:05 +02:00
{
2012-06-17 23:24:10 +02:00
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) ],
2012-06-17 22:27:05 +02:00
},
]);
2012-07-18 20:36:34 +02:00
$self -> { extruder_pages } = [] ;
$self -> build_extruder_pages ;
2012-06-18 22:27:57 +02:00
2012-07-18 20:36:34 +02:00
$self -> load_presets ( 'printer' );
}
sub extruder_options { qw(nozzle_diameter) }
sub build_extruder_pages {
my $self = shift ;
foreach my $extruder_idx ( 0 .. $ Slic3r:: extruders_count - 1 ) {
# set default values
for my $opt_key ( $self -> extruder_options ) {
Slic3r::Config -> get_raw ( $opt_key ) -> [ $extruder_idx ] // = Slic3r::Config -> get_raw ( $opt_key ) -> [ 0 ]; #/
}
# build page if it doesn't exist
$self -> { extruder_pages }[ $extruder_idx ] ||= $self -> add_options_page ( "Extruder " . ( $extruder_idx + 1 ), 'funnel.png' , optgroups => [
{
title => 'Size' ,
options => [ 'nozzle_diameter#' . $extruder_idx ],
},
{
title => 'Retraction' ,
options => [ qw(retract_length retract_lift retract_speed retract_restart_extra retract_before_travel) ],
},
]);
$self -> { extruder_pages }[ $extruder_idx ]{ disabled } = 0 ;
}
# rebuild page list
@ { $self -> { pages }} = (
( grep $_ -> { title } !~ /^Extruder \d+/ , @ { $self -> { pages }}),
@ { $self -> { extruder_pages }}[ 0 .. $ Slic3r:: extruders_count - 1 ],
);
}
sub on_value_change {
my $self = shift ;
my ( $opt_key ) = @_ ;
$self -> SUPER:: on_value_change ( @_ );
if ( $opt_key eq 'extruders_count' ) {
# remove unused pages from list
my @unused_pages = @ { $self -> { extruder_pages } }[ $ Slic3r:: extruders_count .. $# { $self -> { extruder_pages }}];
for my $page ( @unused_pages ) {
@ { $self -> { pages }} = grep $_ ne $page , @ { $self -> { pages }};
$page -> { disabled } = 1 ;
}
# delete values for unused extruders
for my $opt_key ( $self -> extruder_options ) {
my $values = Slic3r::Config -> get_raw ( $opt_key );
splice @$values , $ Slic3r:: extruders_count if $ Slic3r:: extruders_count <= $#$values ;
}
# add extra pages
$self -> build_extruder_pages ;
# update page list and select first page (General)
$self -> update_tree ( 0 );
}
}
# this gets executed after preset is loaded in repository and before GUI fields are updated
sub on_preset_loaded {
my $self = shift ;
# update the extruders count field
2012-07-20 14:41:27 +02:00
{
2012-07-18 20:36:34 +02:00
# set value in repository according to the number of nozzle diameters supplied
Slic3r::Config -> set ( 'extruders_count' , scalar @ { Slic3r::Config -> get_raw ( 'nozzle_diameter' ) });
# update the GUI field
$ Slic3r::GUI::OptionsGroup:: reload_callbacks { extruders_count } -> ();
# update extruder page list
$self -> on_value_change ( 'extruders_count' );
}
2012-06-17 22:27:05 +02:00
}
package Slic3r::GUI::Tab::Page ;
2012-07-01 19:24:06 +02:00
use Wx qw(:sizer) ;
2012-06-18 11:26:21 +02:00
use base 'Wx::ScrolledWindow' ;
2012-06-17 22:27:05 +02:00
sub new {
my $class = shift ;
2012-07-18 20:36:34 +02:00
my ( $parent , $title , $iconID , %params ) = @_ ;
2012-06-17 22:27:05 +02:00
my $self = $class -> SUPER:: new ( $parent , - 1 );
2012-07-18 20:36:34 +02:00
$self -> { opt_keys } = [] ;
$self -> { title } = $title ;
$self -> { iconID } = $iconID ;
2012-06-17 22:27:05 +02:00
2012-06-18 11:26:21 +02:00
$self -> SetScrollbars ( 1 , 1 , 1 , 1 );
2012-07-01 19:24:06 +02:00
$self -> { vsizer } = Wx::BoxSizer -> new ( wxVERTICAL );
2012-06-17 22:27:05 +02:00
$self -> SetSizer ( $self -> { vsizer });
if ( $params { optgroups }) {
2012-06-18 22:27:57 +02:00
$self -> append_optgroup ( %$_ , on_change => $params { on_change }) for @ { $params { optgroups }};
2012-06-17 22:27:05 +02:00
}
return $self ;
}
sub append_optgroup {
my $self = shift ;
2012-07-18 20:36:34 +02:00
my %params = @_ ;
2012-06-17 22:27:05 +02:00
2012-07-18 20:36:34 +02:00
my $optgroup = Slic3r::GUI::OptionsGroup -> new ( $self , label_width => 200 , %params );
2012-06-17 22:27:05 +02:00
$self -> { vsizer } -> Add ( $optgroup , 0 , wxEXPAND | wxALL , 5 );
}
2012-06-18 22:27:57 +02:00
package Slic3r::GUI::SavePresetWindow ;
2012-07-03 01:20:30 +02:00
use Wx qw(:combobox :dialog :id :misc :sizer) ;
2012-06-21 13:01:59 +02:00
use Wx::Event qw(EVT_BUTTON EVT_TEXT_ENTER) ;
2012-06-18 22:27:57 +02:00
use base 'Wx::Dialog' ;
sub new {
my $class = shift ;
my ( $parent , %params ) = @_ ;
2012-07-03 01:20:30 +02:00
my $self = $class -> SUPER:: new ( $parent , - 1 , "Save preset" , wxDefaultPosition , wxDefaultSize );
2012-06-18 22:27:57 +02:00
2012-07-03 01:20:30 +02:00
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 },
2012-07-01 19:24:06 +02:00
wxTE_PROCESS_ENTER );
my $buttons = $self -> CreateStdDialogButtonSizer ( wxOK | wxCANCEL );
2012-06-18 22:27:57 +02:00
my $sizer = Wx::BoxSizer -> new ( wxVERTICAL );
$sizer -> Add ( $text , 0 , wxEXPAND | wxTOP | wxLEFT | wxRIGHT , 10 );
2012-06-21 13:01:59 +02:00
$sizer -> Add ( $self -> { combo }, 0 , wxEXPAND | wxLEFT | wxRIGHT , 10 );
2012-06-18 22:27:57 +02:00
$sizer -> Add ( $buttons , 0 , wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT , 10 );
2012-07-01 19:24:06 +02:00
EVT_BUTTON ( $self , wxID_OK , \& accept );
2012-06-21 13:01:59 +02:00
EVT_TEXT_ENTER ( $self , $self -> { combo }, \& accept );
2012-06-18 22:27:57 +02:00
$self -> SetSizer ( $sizer );
$sizer -> SetSizeHints ( $self );
return $self ;
}
2012-06-21 13:01:59 +02:00
sub accept {
my ( $self , $event ) = @_ ;
2012-07-15 18:55:01 +02:00
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." );
}
2012-06-21 13:01:59 +02:00
}
}
2012-06-18 22:27:57 +02:00
sub get_name {
my $self = shift ;
return $self -> { chosen_name };
}
2012-06-17 22:27:05 +02:00
1 ;