Merge remote-tracking branch 'remotes/origin/gui_translate_to_cpp'

This commit is contained in:
bubnikv 2018-02-23 15:32:13 +01:00
commit 69fc99edbb
26 changed files with 11863 additions and 6374 deletions

View File

@ -0,0 +1,45 @@
From the begining you need to have GNUgettext and PoEdit.
GNUgettext package contains a set of tools to extract strings from the source code and
to create the Catalog to translation.
PoEdit provide good interface for the translators.
Those are possible to download here:
GNUgettext - https://sourceforge.net/directory/os:windows/?q=gnu+gettext
PoEdit - https://poedit.net/
When GNUgettext and poEdit are downloaded and installationed, next step is
to add path to gettext/bin directory to your PATH variable.
You can use gettext from cmdline now.
In Slic3rPE we have one macro (L) used to markup strings to localizations.
So, to create Catalog to translation there are next steps:
1. create list of files with this macro (list.txt)
2. create template file(*.POT) with command:
xgettext --keyword=L --from-code=UTF-8 --debug -o Slic3rPE.pot -f list.txt
Use flag --from-code=UTF-8 to specify that the source strings are in UTF-8 encoding
Use flag --debug to correctly extract formated strings(used %d, %s etc.)
3.1 if you start to create PO-file for your projest just open this POT-file in PoEdit.
When you select translation language after first opening of POT-files,
PO-file will be created immediatly.
3.2 if you already have PO-file created before, you have to merge old PO-file with
strings from creaded POT-file. You can do that with command:
msgmerge -N -o new.po old.po new.pot
Use option -N to not using fuzzy matching when an exact match is not found.
3.3 if you already have PO-file created before and new PO-file created from new sourse files
which is not related with first one, you have to concatenate old PO-file with
strings from new PO-file. You can do that with command:
msgcat -o new.po old.po
4. create an English translation catalog with command:
msgen -o new.po old.po
Notice, in this Catalog it will be totally same strings for initial text and translated.
When you have Catalog to translation open POT or PO file in PoEdit and start to translation.
It's very important to keep attention to every gaps and punctuation. Especially with
formated strings. (used %d, %s etc.)

View File

@ -69,7 +69,9 @@ our $grey = Wx::Colour->new(200,200,200);
# Events to be sent from a C++ menu implementation: # Events to be sent from a C++ menu implementation:
# 1) To inform about a change of the application language. # 1) To inform about a change of the application language.
our $LANGUAGE_CHANGE_EVENT = Wx::NewEventType; our $LANGUAGE_CHANGE_EVENT = Wx::NewEventType;
# 2) To inform about a change of Preferences.
our $PREFERENCES_EVENT = Wx::NewEventType;
sub OnInit { sub OnInit {
my ($self) = @_; my ($self) = @_;
@ -84,12 +86,11 @@ sub OnInit {
# Mac: "~/Library/Application Support/Slic3r" # Mac: "~/Library/Application Support/Slic3r"
Slic3r::set_data_dir($datadir || Wx::StandardPaths::Get->GetUserDataDir); Slic3r::set_data_dir($datadir || Wx::StandardPaths::Get->GetUserDataDir);
Slic3r::GUI::set_wxapp($self); Slic3r::GUI::set_wxapp($self);
Slic3r::GUI::load_language();
$self->{notifier} = Slic3r::GUI::Notifier->new; $self->{notifier} = Slic3r::GUI::Notifier->new;
$self->{app_config} = Slic3r::GUI::AppConfig->new; $self->{app_config} = Slic3r::GUI::AppConfig->new;
$self->{preset_bundle} = Slic3r::GUI::PresetBundle->new; $self->{preset_bundle} = Slic3r::GUI::PresetBundle->new;
# just checking for existence of Slic3r::data_dir is not enough: it may be an empty directory # just checking for existence of Slic3r::data_dir is not enough: it may be an empty directory
# supplied as argument to --datadir; in that case we should still run the wizard # supplied as argument to --datadir; in that case we should still run the wizard
eval { $self->{preset_bundle}->setup_directories() }; eval { $self->{preset_bundle}->setup_directories() };
@ -103,6 +104,9 @@ sub OnInit {
$self->{app_config}->set('version', $Slic3r::VERSION); $self->{app_config}->set('version', $Slic3r::VERSION);
$self->{app_config}->save; $self->{app_config}->save;
Slic3r::GUI::set_app_config($self->{app_config});
Slic3r::GUI::load_language();
# Suppress the '- default -' presets. # Suppress the '- default -' presets.
$self->{preset_bundle}->set_default_suppressed($self->{app_config}->get('no_defaults') ? 1 : 0); $self->{preset_bundle}->set_default_suppressed($self->{app_config}->get('no_defaults') ? 1 : 0);
eval { $self->{preset_bundle}->load_presets }; eval { $self->{preset_bundle}->load_presets };
@ -120,6 +124,7 @@ sub OnInit {
no_controller => $self->{app_config}->get('no_controller'), no_controller => $self->{app_config}->get('no_controller'),
no_plater => $no_plater, no_plater => $no_plater,
lang_ch_event => $LANGUAGE_CHANGE_EVENT, lang_ch_event => $LANGUAGE_CHANGE_EVENT,
preferences_event => $PREFERENCES_EVENT,
); );
$self->SetTopWindow($frame); $self->SetTopWindow($frame);
@ -144,6 +149,11 @@ sub OnInit {
EVT_COMMAND($self, -1, $LANGUAGE_CHANGE_EVENT, sub{ EVT_COMMAND($self, -1, $LANGUAGE_CHANGE_EVENT, sub{
$self->recreate_GUI; $self->recreate_GUI;
}); });
# The following event is emited by the C++ menu implementation of preferences change.
EVT_COMMAND($self, -1, $PREFERENCES_EVENT, sub{
$self->update_ui_from_settings;
});
return 1; return 1;
} }
@ -156,6 +166,7 @@ sub recreate_GUI{
no_controller => $self->{app_config}->get('no_controller'), no_controller => $self->{app_config}->get('no_controller'),
no_plater => $no_plater, no_plater => $no_plater,
lang_ch_event => $LANGUAGE_CHANGE_EVENT, lang_ch_event => $LANGUAGE_CHANGE_EVENT,
preferences_event => $PREFERENCES_EVENT,
); );
if($topwindow) if($topwindow)

View File

@ -14,6 +14,8 @@ use Wx qw(:frame :bitmap :id :misc :notebook :panel :sizer :menu :dialog :filedi
use Wx::Event qw(EVT_CLOSE EVT_COMMAND EVT_MENU EVT_NOTEBOOK_PAGE_CHANGED); use Wx::Event qw(EVT_CLOSE EVT_COMMAND EVT_MENU EVT_NOTEBOOK_PAGE_CHANGED);
use base 'Wx::Frame'; use base 'Wx::Frame';
use Wx::Locale gettext => 'L';
our $qs_last_input_file; our $qs_last_input_file;
our $qs_last_output_file; our $qs_last_output_file;
our $last_config; our $last_config;
@ -48,7 +50,8 @@ sub new {
$self->{no_plater} = $params{no_plater}; $self->{no_plater} = $params{no_plater};
$self->{loaded} = 0; $self->{loaded} = 0;
$self->{lang_ch_event} = $params{lang_ch_event}; $self->{lang_ch_event} = $params{lang_ch_event};
$self->{preferences_event} = $params{preferences_event};
# initialize tabpanel and menubar # initialize tabpanel and menubar
$self->_init_tabpanel; $self->_init_tabpanel;
$self->_init_menubar; $self->_init_menubar;
@ -60,7 +63,7 @@ sub new {
# initialize status bar # initialize status bar
$self->{statusbar} = Slic3r::GUI::ProgressStatusBar->new($self, -1); $self->{statusbar} = Slic3r::GUI::ProgressStatusBar->new($self, -1);
$self->{statusbar}->SetStatusText("Version $Slic3r::VERSION - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"); $self->{statusbar}->SetStatusText(L("Version ").$Slic3r::VERSION.L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"));
$self->SetStatusBar($self->{statusbar}); $self->SetStatusBar($self->{statusbar});
$self->{loaded} = 1; $self->{loaded} = 1;
@ -112,9 +115,9 @@ sub _init_tabpanel {
}); });
if (!$self->{no_plater}) { if (!$self->{no_plater}) {
$panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), "Plater"); $panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), L("Plater"));
if (!$self->{no_controller}) { if (!$self->{no_controller}) {
$panel->AddPage($self->{controller} = Slic3r::GUI::Controller->new($panel), "Controller"); $panel->AddPage($self->{controller} = Slic3r::GUI::Controller->new($panel), L("Controller"));
} }
} }
@ -186,7 +189,7 @@ sub _init_tabpanel {
$tab->load_key_value('octoprint_host', $dlg->GetValue . ":" . $dlg->GetPort) $tab->load_key_value('octoprint_host', $dlg->GetValue . ":" . $dlg->GetPort)
if $dlg->ShowModal == wxID_OK; if $dlg->ShowModal == wxID_OK;
} else { } else {
Wx::MessageDialog->new($self, 'No Bonjour device found', 'Device Browser', wxOK | wxICON_INFORMATION)->ShowModal; Wx::MessageDialog->new($self, L('No Bonjour device found'), L('Device Browser'), wxOK | wxICON_INFORMATION)->ShowModal;
} }
}); });
# The following event is emited by the C++ Tab implementation , # The following event is emited by the C++ Tab implementation ,
@ -205,19 +208,19 @@ sub _init_tabpanel {
'X-Api-Key' => $config->octoprint_apikey, 'X-Api-Key' => $config->octoprint_apikey,
); );
if ($res->is_success) { if ($res->is_success) {
Slic3r::GUI::show_info($self, "Connection to OctoPrint works correctly.", "Success!"); Slic3r::GUI::show_info($self, L("Connection to OctoPrint works correctly."), _L("Success!"));
} else { } else {
Slic3r::GUI::show_error($self, Slic3r::GUI::show_error($self,
"I wasn't able to connect to OctoPrint (" . $res->status_line . "). " L("I wasn't able to connect to OctoPrint (") . $res->status_line .
. "Check hostname and OctoPrint version (at least 1.1.0 is required)."); L("). Check hostname and OctoPrint version (at least 1.1.0 is required)."));
} }
}); });
# A variable to inform C++ Tab implementation about disabling of Browse button # A variable to inform C++ Tab implementation about disabling of Browse button
$self->{is_disabled_button_browse} = (!eval "use Net::Bonjour; 1") ? 1 : 0 ; $self->{is_disabled_button_browse} = (!eval "use Net::Bonjour; 1") ? 1 : 0 ;
# A variable to inform C++ Tab implementation about user_agent # A variable to inform C++ Tab implementation about user_agent
$self->{is_user_agent} = (eval "use LWP::UserAgent; 1") ? 1 : 0 ; $self->{is_user_agent} = (eval "use LWP::UserAgent; 1") ? 1 : 0 ;
Slic3r::GUI::create_preset_tabs(wxTheApp->{preset_bundle}, wxTheApp->{app_config}, Slic3r::GUI::create_preset_tabs(wxTheApp->{preset_bundle}, $self->{no_controller},
$self->{no_controller}, $self->{is_disabled_button_browse}, $self->{is_disabled_button_browse},
$self->{is_user_agent}, $self->{is_user_agent},
$VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT, $VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT,
$BUTTON_BROWSE_EVENT, $BUTTON_TEST_EVENT); $BUTTON_BROWSE_EVENT, $BUTTON_TEST_EVENT);
@ -245,59 +248,61 @@ sub _init_menubar {
# File menu # File menu
my $fileMenu = Wx::Menu->new; my $fileMenu = Wx::Menu->new;
{ {
wxTheApp->append_menu_item($fileMenu, "Open STL/OBJ/AMF…\tCtrl+O", 'Open a model', sub { wxTheApp->append_menu_item($fileMenu, L("Open STL/OBJ/AMF…\tCtrl+O"), L('Open a model'), sub {
$self->{plater}->add if $self->{plater}; $self->{plater}->add if $self->{plater};
}, undef, undef); #'brick_add.png'); }, undef, undef); #'brick_add.png');
$self->_append_menu_item($fileMenu, "&Load Config…\tCtrl+L", 'Load exported configuration file', sub { $self->_append_menu_item($fileMenu, L("&Load Config…\tCtrl+L"), L('Load exported configuration file'), sub {
$self->load_config_file; $self->load_config_file;
}, undef, 'plugin_add.png'); }, undef, 'plugin_add.png');
$self->_append_menu_item($fileMenu, "&Export Config…\tCtrl+E", 'Export current configuration to file', sub { $self->_append_menu_item($fileMenu, L("&Export Config…\tCtrl+E"), L('Export current configuration to file'), sub {
$self->export_config; $self->export_config;
}, undef, 'plugin_go.png'); }, undef, 'plugin_go.png');
$self->_append_menu_item($fileMenu, "&Load Config Bundle…", 'Load presets from a bundle', sub { $self->_append_menu_item($fileMenu, L("&Load Config Bundle…"), L('Load presets from a bundle'), sub {
$self->load_configbundle; $self->load_configbundle;
}, undef, 'lorry_add.png'); }, undef, 'lorry_add.png');
$self->_append_menu_item($fileMenu, "&Export Config Bundle…", 'Export all presets to file', sub { $self->_append_menu_item($fileMenu, L("&Export Config Bundle…"), L('Export all presets to file'), sub {
$self->export_configbundle; $self->export_configbundle;
}, undef, 'lorry_go.png'); }, undef, 'lorry_go.png');
$fileMenu->AppendSeparator(); $fileMenu->AppendSeparator();
my $repeat; my $repeat;
$self->_append_menu_item($fileMenu, "Q&uick Slice…\tCtrl+U", 'Slice a file into a G-code', sub { $self->_append_menu_item($fileMenu, L("Q&uick Slice…\tCtrl+U"), L('Slice a file into a G-code'), sub {
wxTheApp->CallAfter(sub { wxTheApp->CallAfter(sub {
$self->quick_slice; $self->quick_slice;
$repeat->Enable(defined $Slic3r::GUI::MainFrame::last_input_file); $repeat->Enable(defined $Slic3r::GUI::MainFrame::last_input_file);
}); });
}, undef, 'cog_go.png'); }, undef, 'cog_go.png');
$self->_append_menu_item($fileMenu, "Quick Slice and Save &As…\tCtrl+Alt+U", 'Slice a file into a G-code, save as', sub { $self->_append_menu_item($fileMenu, L("Quick Slice and Save &As…\tCtrl+Alt+U"), L('Slice a file into a G-code, save as'), sub {
wxTheApp->CallAfter(sub { wxTheApp->CallAfter(sub {
$self->quick_slice(save_as => 1); $self->quick_slice(save_as => 1);
$repeat->Enable(defined $Slic3r::GUI::MainFrame::last_input_file); $repeat->Enable(defined $Slic3r::GUI::MainFrame::last_input_file);
}); });
}, undef, 'cog_go.png'); }, undef, 'cog_go.png');
$repeat = $self->_append_menu_item($fileMenu, "&Repeat Last Quick Slice\tCtrl+Shift+U", 'Repeat last quick slice', sub { $repeat = $self->_append_menu_item($fileMenu, L("&Repeat Last Quick Slice\tCtrl+Shift+U"), L('Repeat last quick slice'), sub {
wxTheApp->CallAfter(sub { wxTheApp->CallAfter(sub {
$self->quick_slice(reslice => 1); $self->quick_slice(reslice => 1);
}); });
}, undef, 'cog_go.png'); }, undef, 'cog_go.png');
$repeat->Enable(0); $repeat->Enable(0);
$fileMenu->AppendSeparator(); $fileMenu->AppendSeparator();
$self->_append_menu_item($fileMenu, "Slice to SV&G…\tCtrl+G", 'Slice file to a multi-layer SVG', sub { $self->_append_menu_item($fileMenu, L("Slice to SV&G…\tCtrl+G"), L('Slice file to a multi-layer SVG'), sub {
$self->quick_slice(save_as => 1, export_svg => 1); $self->quick_slice(save_as => 1, export_svg => 1);
}, undef, 'shape_handles.png'); }, undef, 'shape_handles.png');
$self->{menu_item_reslice_now} = $self->_append_menu_item( $self->{menu_item_reslice_now} = $self->_append_menu_item(
$fileMenu, "(&Re)Slice Now\tCtrl+S", 'Start new slicing process', $fileMenu, L("(&Re)Slice Now\tCtrl+S"), L('Start new slicing process'),
sub { $self->reslice_now; }, undef, 'shape_handles.png'); sub { $self->reslice_now; }, undef, 'shape_handles.png');
$fileMenu->AppendSeparator(); $fileMenu->AppendSeparator();
$self->_append_menu_item($fileMenu, "Repair STL file…", 'Automatically repair an STL file', sub { $self->_append_menu_item($fileMenu, L("Repair STL file…"), L('Automatically repair an STL file'), sub {
$self->repair_stl; $self->repair_stl;
}, undef, 'wrench.png'); }, undef, 'wrench.png');
$fileMenu->AppendSeparator(); $fileMenu->AppendSeparator();
# Cmd+, is standard on OS X - what about other operating systems? # Cmd+, is standard on OS X - what about other operating systems?
$self->_append_menu_item($fileMenu, "Preferences…\tCtrl+,", 'Application preferences', sub { $self->_append_menu_item($fileMenu, L("Preferences…\tCtrl+,"), L('Application preferences'), sub {
Slic3r::GUI::Preferences->new($self)->ShowModal; # Slic3r::GUI::Preferences->new($self)->ShowModal;
# It's in C++ part now
Slic3r::GUI::open_preferences_dialog($self->{preferences_event});
}, wxID_PREFERENCES); }, wxID_PREFERENCES);
$fileMenu->AppendSeparator(); $fileMenu->AppendSeparator();
$self->_append_menu_item($fileMenu, "&Quit", 'Quit Slic3r', sub { $self->_append_menu_item($fileMenu, L("&Quit"), L('Quit Slic3r'), sub {
$self->Close(0); $self->Close(0);
}, wxID_EXIT); }, wxID_EXIT);
} }
@ -307,16 +312,16 @@ sub _init_menubar {
my $plater = $self->{plater}; my $plater = $self->{plater};
$self->{plater_menu} = Wx::Menu->new; $self->{plater_menu} = Wx::Menu->new;
$self->_append_menu_item($self->{plater_menu}, "Export G-code...", 'Export current plate as G-code', sub { $self->_append_menu_item($self->{plater_menu}, L("Export G-code..."), L('Export current plate as G-code'), sub {
$plater->export_gcode; $plater->export_gcode;
}, undef, 'cog_go.png'); }, undef, 'cog_go.png');
$self->_append_menu_item($self->{plater_menu}, "Export plate as STL...", 'Export current plate as STL', sub { $self->_append_menu_item($self->{plater_menu}, L("Export plate as STL..."), L('Export current plate as STL'), sub {
$plater->export_stl; $plater->export_stl;
}, undef, 'brick_go.png'); }, undef, 'brick_go.png');
$self->_append_menu_item($self->{plater_menu}, "Export plate as AMF...", 'Export current plate as AMF', sub { $self->_append_menu_item($self->{plater_menu}, L("Export plate as AMF..."), L('Export current plate as AMF'), sub {
$plater->export_amf; $plater->export_amf;
}, undef, 'brick_go.png'); }, undef, 'brick_go.png');
$self->_append_menu_item($self->{plater_menu}, "Export plate as 3MF...", 'Export current plate as 3MF', sub { $self->_append_menu_item($self->{plater_menu}, L("Export plate as 3MF..."), L('Export current plate as 3MF'), sub {
$plater->export_3mf; $plater->export_3mf;
}, undef, 'brick_go.png'); }, undef, 'brick_go.png');
@ -329,13 +334,13 @@ sub _init_menubar {
{ {
my $tab_offset = 0; my $tab_offset = 0;
if (!$self->{no_plater}) { if (!$self->{no_plater}) {
$self->_append_menu_item($windowMenu, "Select &Plater Tab\tCtrl+1", 'Show the plater', sub { $self->_append_menu_item($windowMenu, L("Select &Plater Tab\tCtrl+1"), L('Show the plater'), sub {
$self->select_tab(0); $self->select_tab(0);
}, undef, 'application_view_tile.png'); }, undef, 'application_view_tile.png');
$tab_offset += 1; $tab_offset += 1;
} }
if (!$self->{no_controller}) { if (!$self->{no_controller}) {
$self->_append_menu_item($windowMenu, "Select &Controller Tab\tCtrl+T", 'Show the printer controller', sub { $self->_append_menu_item($windowMenu, L("Select &Controller Tab\tCtrl+T"), L('Show the printer controller'), sub {
$self->select_tab(1); $self->select_tab(1);
}, undef, 'printer_empty.png'); }, undef, 'printer_empty.png');
$tab_offset += 1; $tab_offset += 1;
@ -343,13 +348,13 @@ sub _init_menubar {
if ($tab_offset > 0) { if ($tab_offset > 0) {
$windowMenu->AppendSeparator(); $windowMenu->AppendSeparator();
} }
$self->_append_menu_item($windowMenu, "Select P&rint Settings Tab\tCtrl+2", 'Show the print settings', sub { $self->_append_menu_item($windowMenu, L("Select P&rint Settings Tab\tCtrl+2"), L('Show the print settings'), sub {
$self->select_tab($tab_offset+0); $self->select_tab($tab_offset+0);
}, undef, 'cog.png'); }, undef, 'cog.png');
$self->_append_menu_item($windowMenu, "Select &Filament Settings Tab\tCtrl+3", 'Show the filament settings', sub { $self->_append_menu_item($windowMenu, L("Select &Filament Settings Tab\tCtrl+3"), L('Show the filament settings'), sub {
$self->select_tab($tab_offset+1); $self->select_tab($tab_offset+1);
}, undef, 'spool.png'); }, undef, 'spool.png');
$self->_append_menu_item($windowMenu, "Select Print&er Settings Tab\tCtrl+4", 'Show the printer settings', sub { $self->_append_menu_item($windowMenu, L("Select Print&er Settings Tab\tCtrl+4"), L('Show the printer settings'), sub {
$self->select_tab($tab_offset+2); $self->select_tab($tab_offset+2);
}, undef, 'printer_empty.png'); }, undef, 'printer_empty.png');
} }
@ -361,47 +366,47 @@ sub _init_menubar {
# as the simple numeric accelerators spoil all numeric data entry. # as the simple numeric accelerators spoil all numeric data entry.
# The camera control accelerators are captured by 3DScene Perl module instead. # The camera control accelerators are captured by 3DScene Perl module instead.
my $accel = ($^O eq 'MSWin32') ? sub { $_[0] . "\t\xA0" . $_[1] } : sub { $_[0] }; my $accel = ($^O eq 'MSWin32') ? sub { $_[0] . "\t\xA0" . $_[1] } : sub { $_[0] };
$self->_append_menu_item($self->{viewMenu}, $accel->('Iso', '0'), 'Iso View' , sub { $self->select_view('iso' ); }); $self->_append_menu_item($self->{viewMenu}, $accel->(L('Iso'), '0'), L('Iso View') , sub { $self->select_view('iso' ); });
$self->_append_menu_item($self->{viewMenu}, $accel->('Top', '1'), 'Top View' , sub { $self->select_view('top' ); }); $self->_append_menu_item($self->{viewMenu}, $accel->(L('Top'), '1'), L('Top View') , sub { $self->select_view('top' ); });
$self->_append_menu_item($self->{viewMenu}, $accel->('Bottom', '2'), 'Bottom View' , sub { $self->select_view('bottom' ); }); $self->_append_menu_item($self->{viewMenu}, $accel->(L('Bottom'), '2'), L('Bottom View') , sub { $self->select_view('bottom' ); });
$self->_append_menu_item($self->{viewMenu}, $accel->('Front', '3'), 'Front View' , sub { $self->select_view('front' ); }); $self->_append_menu_item($self->{viewMenu}, $accel->(L('Front'), '3'), L('Front View') , sub { $self->select_view('front' ); });
$self->_append_menu_item($self->{viewMenu}, $accel->('Rear', '4'), 'Rear View' , sub { $self->select_view('rear' ); }); $self->_append_menu_item($self->{viewMenu}, $accel->(L('Rear'), '4'), L('Rear View') , sub { $self->select_view('rear' ); });
$self->_append_menu_item($self->{viewMenu}, $accel->('Left', '5'), 'Left View' , sub { $self->select_view('left' ); }); $self->_append_menu_item($self->{viewMenu}, $accel->(L('Left'), '5'), L('Left View') , sub { $self->select_view('left' ); });
$self->_append_menu_item($self->{viewMenu}, $accel->('Right', '6'), 'Right View' , sub { $self->select_view('right' ); }); $self->_append_menu_item($self->{viewMenu}, $accel->(L('Right'), '6'), L('Right View') , sub { $self->select_view('right' ); });
} }
# Help menu # Help menu
my $helpMenu = Wx::Menu->new; my $helpMenu = Wx::Menu->new;
{ {
$self->_append_menu_item($helpMenu, "&Configuration $Slic3r::GUI::ConfigWizard::wizard…", "Run Configuration $Slic3r::GUI::ConfigWizard::wizard", sub { $self->_append_menu_item($helpMenu, L("&Configuration ").$Slic3r::GUI::ConfigWizard::wizard."…", L("Run Configuration ").$Slic3r::GUI::ConfigWizard::wizard, sub {
# Run the config wizard, offer the "reset user profile" checkbox. # Run the config wizard, offer the "reset user profile" checkbox.
$self->config_wizard(0); $self->config_wizard(0);
}); });
$helpMenu->AppendSeparator(); $helpMenu->AppendSeparator();
$self->_append_menu_item($helpMenu, "Prusa 3D Drivers", 'Open the Prusa3D drivers download page in your browser', sub { $self->_append_menu_item($helpMenu, L("Prusa 3D Drivers"), L('Open the Prusa3D drivers download page in your browser'), sub {
Wx::LaunchDefaultBrowser('http://www.prusa3d.com/drivers/'); Wx::LaunchDefaultBrowser('http://www.prusa3d.com/drivers/');
}); });
$self->_append_menu_item($helpMenu, "Prusa Edition Releases", 'Open the Prusa Edition releases page in your browser', sub { $self->_append_menu_item($helpMenu, L("Prusa Edition Releases"), L('Open the Prusa Edition releases page in your browser'), sub {
Wx::LaunchDefaultBrowser('http://github.com/prusa3d/slic3r/releases'); Wx::LaunchDefaultBrowser('http://github.com/prusa3d/slic3r/releases');
}); });
# my $versioncheck = $self->_append_menu_item($helpMenu, "Check for &Updates...", 'Check for new Slic3r versions', sub { # my $versioncheck = $self->_append_menu_item($helpMenu, "Check for &Updates...", 'Check for new Slic3r versions', sub {
# wxTheApp->check_version(1); # wxTheApp->check_version(1);
# }); # });
# $versioncheck->Enable(wxTheApp->have_version_check); # $versioncheck->Enable(wxTheApp->have_version_check);
$self->_append_menu_item($helpMenu, "Slic3r &Website", 'Open the Slic3r website in your browser', sub { $self->_append_menu_item($helpMenu, L("Slic3r &Website"), L('Open the Slic3r website in your browser'), sub {
Wx::LaunchDefaultBrowser('http://slic3r.org/'); Wx::LaunchDefaultBrowser('http://slic3r.org/');
}); });
$self->_append_menu_item($helpMenu, "Slic3r &Manual", 'Open the Slic3r manual in your browser', sub { $self->_append_menu_item($helpMenu, L("Slic3r &Manual"), L('Open the Slic3r manual in your browser'), sub {
Wx::LaunchDefaultBrowser('http://manual.slic3r.org/'); Wx::LaunchDefaultBrowser('http://manual.slic3r.org/');
}); });
$helpMenu->AppendSeparator(); $helpMenu->AppendSeparator();
$self->_append_menu_item($helpMenu, "System Info", 'Show system information', sub { $self->_append_menu_item($helpMenu, L("System Info"), L('Show system information'), sub {
wxTheApp->system_info; wxTheApp->system_info;
}); });
$self->_append_menu_item($helpMenu, "Report an Issue", 'Report an issue on the Slic3r Prusa Edition', sub { $self->_append_menu_item($helpMenu, L("Report an Issue"), L('Report an issue on the Slic3r Prusa Edition'), sub {
Wx::LaunchDefaultBrowser('http://github.com/prusa3d/slic3r/issues/new'); Wx::LaunchDefaultBrowser('http://github.com/prusa3d/slic3r/issues/new');
}); });
$self->_append_menu_item($helpMenu, "&About Slic3r", 'Show about dialog', sub { $self->_append_menu_item($helpMenu, L("&About Slic3r"), L('Show about dialog'), sub {
wxTheApp->about; wxTheApp->about;
}); });
} }
@ -411,16 +416,15 @@ sub _init_menubar {
# will not be handled correctly # will not be handled correctly
{ {
my $menubar = Wx::MenuBar->new; my $menubar = Wx::MenuBar->new;
$menubar->Append($fileMenu, "&File"); $menubar->Append($fileMenu, L("&File"));
$menubar->Append($self->{plater_menu}, "&Plater") if $self->{plater_menu}; $menubar->Append($self->{plater_menu}, L("&Plater")) if $self->{plater_menu};
$menubar->Append($self->{object_menu}, "&Object") if $self->{object_menu}; $menubar->Append($self->{object_menu}, L("&Object")) if $self->{object_menu};
$menubar->Append($windowMenu, "&Window"); $menubar->Append($windowMenu, L("&Window"));
$menubar->Append($self->{viewMenu}, "&View") if $self->{viewMenu}; $menubar->Append($self->{viewMenu}, L("&View")) if $self->{viewMenu};
# Add an optional debug menu # Add an optional debug menu
# (Select application language from the list of installed languages) # (Select application language from the list of installed languages)
# In production code, the add_debug_menu() call should do nothing.
Slic3r::GUI::add_debug_menu($menubar, $self->{lang_ch_event}); Slic3r::GUI::add_debug_menu($menubar, $self->{lang_ch_event});
$menubar->Append($helpMenu, "&Help"); $menubar->Append($helpMenu, L("&Help"));
$self->SetMenuBar($menubar); $self->SetMenuBar($menubar);
} }
} }
@ -451,7 +455,7 @@ sub quick_slice {
# select input file # select input file
my $input_file; my $input_file;
if (!$params{reslice}) { if (!$params{reslice}) {
my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):', my $dialog = Wx::FileDialog->new($self, L('Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):'),
wxTheApp->{app_config}->get_last_dir, "", wxTheApp->{app_config}->get_last_dir, "",
&Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); &Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if ($dialog->ShowModal != wxID_OK) { if ($dialog->ShowModal != wxID_OK) {
@ -463,13 +467,13 @@ sub quick_slice {
$qs_last_input_file = $input_file unless $params{export_svg}; $qs_last_input_file = $input_file unless $params{export_svg};
} else { } else {
if (!defined $qs_last_input_file) { if (!defined $qs_last_input_file) {
Wx::MessageDialog->new($self, "No previously sliced file.", Wx::MessageDialog->new($self, L("No previously sliced file."),
'Error', wxICON_ERROR | wxOK)->ShowModal(); L('Error'), wxICON_ERROR | wxOK)->ShowModal();
return; return;
} }
if (! -e $qs_last_input_file) { if (! -e $qs_last_input_file) {
Wx::MessageDialog->new($self, "Previously sliced file ($qs_last_input_file) not found.", Wx::MessageDialog->new($self, L("Previously sliced file (").$qs_last_input_file.L(") not found."),
'File Not Found', wxICON_ERROR | wxOK)->ShowModal(); L('File Not Found'), wxICON_ERROR | wxOK)->ShowModal();
return; return;
} }
$input_file = $qs_last_input_file; $input_file = $qs_last_input_file;
@ -508,7 +512,7 @@ sub quick_slice {
# The following line may die if the output_filename_format template substitution fails. # The following line may die if the output_filename_format template substitution fails.
$output_file = $sprint->output_filepath; $output_file = $sprint->output_filepath;
$output_file =~ s/\.[gG][cC][oO][dD][eE]$/.svg/ if $params{export_svg}; $output_file =~ s/\.[gG][cC][oO][dD][eE]$/.svg/ if $params{export_svg};
my $dlg = Wx::FileDialog->new($self, 'Save ' . ($params{export_svg} ? 'SVG' : 'G-code') . ' file as:', my $dlg = Wx::FileDialog->new($self, L('Save ') . ($params{export_svg} ? L('SVG') : L('G-code')) . L(' file as:'),
wxTheApp->{app_config}->get_last_output_dir(dirname($output_file)), wxTheApp->{app_config}->get_last_output_dir(dirname($output_file)),
basename($output_file), $params{export_svg} ? &Slic3r::GUI::FILE_WILDCARDS->{svg} : &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); basename($output_file), $params{export_svg} ? &Slic3r::GUI::FILE_WILDCARDS->{svg} : &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if ($dlg->ShowModal != wxID_OK) { if ($dlg->ShowModal != wxID_OK) {
@ -522,7 +526,7 @@ sub quick_slice {
} }
# show processbar dialog # show processbar dialog
$progress_dialog = Wx::ProgressDialog->new('Slicing…', "Processing $input_file_basename…", $progress_dialog = Wx::ProgressDialog->new(L('Slicing…'), L("Processing ").$input_file_basename."…",
100, $self, 0); 100, $self, 0);
$progress_dialog->Pulse; $progress_dialog->Pulse;
@ -542,9 +546,9 @@ sub quick_slice {
$progress_dialog->Destroy; $progress_dialog->Destroy;
undef $progress_dialog; undef $progress_dialog;
my $message = "$input_file_basename was successfully sliced."; my $message = $input_file_basename.L(" was successfully sliced.");
wxTheApp->notify($message); wxTheApp->notify($message);
Wx::MessageDialog->new($self, $message, 'Slicing Done!', Wx::MessageDialog->new($self, $message, L('Slicing Done!'),
wxOK | wxICON_INFORMATION)->ShowModal; wxOK | wxICON_INFORMATION)->ShowModal;
}; };
Slic3r::GUI::catch_error($self, sub { $progress_dialog->Destroy if $progress_dialog }); Slic3r::GUI::catch_error($self, sub { $progress_dialog->Destroy if $progress_dialog });
@ -560,7 +564,7 @@ sub repair_stl {
my $input_file; my $input_file;
{ {
my $dialog = Wx::FileDialog->new($self, 'Select the STL file to repair:', my $dialog = Wx::FileDialog->new($self, L('Select the STL file to repair:'),
wxTheApp->{app_config}->get_last_dir, "", wxTheApp->{app_config}->get_last_dir, "",
&Slic3r::GUI::FILE_WILDCARDS->{stl}, wxFD_OPEN | wxFD_FILE_MUST_EXIST); &Slic3r::GUI::FILE_WILDCARDS->{stl}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if ($dialog->ShowModal != wxID_OK) { if ($dialog->ShowModal != wxID_OK) {
@ -574,7 +578,7 @@ sub repair_stl {
my $output_file = $input_file; my $output_file = $input_file;
{ {
$output_file =~ s/\.[sS][tT][lL]$/_fixed.obj/; $output_file =~ s/\.[sS][tT][lL]$/_fixed.obj/;
my $dlg = Wx::FileDialog->new($self, "Save OBJ file (less prone to coordinate errors than STL) as:", dirname($output_file), my $dlg = Wx::FileDialog->new($self, L("Save OBJ file (less prone to coordinate errors than STL) as:"), dirname($output_file),
basename($output_file), &Slic3r::GUI::FILE_WILDCARDS->{obj}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); basename($output_file), &Slic3r::GUI::FILE_WILDCARDS->{obj}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if ($dlg->ShowModal != wxID_OK) { if ($dlg->ShowModal != wxID_OK) {
$dlg->Destroy; $dlg->Destroy;
@ -588,7 +592,7 @@ sub repair_stl {
$tmesh->ReadSTLFile($input_file); $tmesh->ReadSTLFile($input_file);
$tmesh->repair; $tmesh->repair;
$tmesh->WriteOBJFile($output_file); $tmesh->WriteOBJFile($output_file);
Slic3r::GUI::show_info($self, "Your file was repaired.", "Repair"); Slic3r::GUI::show_info($self, L("Your file was repaired."), L("Repair"));
} }
sub export_config { sub export_config {
@ -599,7 +603,7 @@ sub export_config {
eval { $config->validate; }; eval { $config->validate; };
Slic3r::GUI::catch_error($self) and return; Slic3r::GUI::catch_error($self) and return;
# Ask user for the file name for the config file. # Ask user for the file name for the config file.
my $dlg = Wx::FileDialog->new($self, 'Save configuration as:', my $dlg = Wx::FileDialog->new($self, L('Save configuration as:'),
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir, $last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
$last_config ? basename($last_config) : "config.ini", $last_config ? basename($last_config) : "config.ini",
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
@ -617,7 +621,7 @@ sub load_config_file {
my ($self, $file) = @_; my ($self, $file) = @_;
if (!$file) { if (!$file) {
return unless $self->check_unsaved_changes; return unless $self->check_unsaved_changes;
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', my $dlg = Wx::FileDialog->new($self, L('Select configuration to load:'),
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir, $last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
"config.ini", "config.ini",
'INI files (*.ini, *.gcode)|*.ini;*.INI;*.gcode;*.g', wxFD_OPEN | wxFD_FILE_MUST_EXIST); 'INI files (*.ini, *.gcode)|*.ini;*.INI;*.gcode;*.g', wxFD_OPEN | wxFD_FILE_MUST_EXIST);
@ -640,7 +644,7 @@ sub export_configbundle {
eval { wxTheApp->{preset_bundle}->full_config->validate; }; eval { wxTheApp->{preset_bundle}->full_config->validate; };
Slic3r::GUI::catch_error($self) and return; Slic3r::GUI::catch_error($self) and return;
# Ask user for a file name. # Ask user for a file name.
my $dlg = Wx::FileDialog->new($self, 'Save presets bundle as:', my $dlg = Wx::FileDialog->new($self, L('Save presets bundle as:'),
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir, $last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
"Slic3r_config_bundle.ini", "Slic3r_config_bundle.ini",
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
@ -661,7 +665,7 @@ sub load_configbundle {
my ($self, $file, $reset_user_profile) = @_; my ($self, $file, $reset_user_profile) = @_;
return unless $self->check_unsaved_changes; return unless $self->check_unsaved_changes;
if (!$file) { if (!$file) {
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', my $dlg = Wx::FileDialog->new($self, L('Select configuration to load:'),
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir, $last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
"config.ini", "config.ini",
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST); &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
@ -681,7 +685,7 @@ sub load_configbundle {
$tab->load_current_preset; $tab->load_current_preset;
} }
my $message = sprintf "%d presets successfully imported.", $presets_imported; my $message = sprintf L("%d presets successfully imported."), $presets_imported;
Slic3r::GUI::show_info($self, $message); Slic3r::GUI::show_info($self, $message);
} }
@ -743,8 +747,8 @@ sub check_unsaved_changes {
if (@dirty) { if (@dirty) {
my $titles = join ', ', @dirty; my $titles = join ', ', @dirty;
my $confirm = Wx::MessageDialog->new($self, "You have unsaved changes ($titles). Discard changes and continue anyway?", my $confirm = Wx::MessageDialog->new($self, L("You have unsaved changes ").($titles).L(". Discard changes and continue anyway?"),
'Unsaved Presets', wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT); L('Unsaved Presets'), wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT);
return $confirm->ShowModal == wxID_YES; return $confirm->ShowModal == wxID_YES;
} }

View File

@ -33,6 +33,8 @@ use constant TB_CUT => &Wx::NewId;
use constant TB_SETTINGS => &Wx::NewId; use constant TB_SETTINGS => &Wx::NewId;
use constant TB_LAYER_EDITING => &Wx::NewId; use constant TB_LAYER_EDITING => &Wx::NewId;
use Wx::Locale gettext => 'L';
# package variables to avoid passing lexicals to threads # package variables to avoid passing lexicals to threads
our $PROGRESS_BAR_EVENT : shared = Wx::NewEventType; our $PROGRESS_BAR_EVENT : shared = Wx::NewEventType;
our $ERROR_EVENT : shared = Wx::NewEventType; our $ERROR_EVENT : shared = Wx::NewEventType;
@ -99,7 +101,7 @@ sub new {
# Initialize 3D plater # Initialize 3D plater
if ($Slic3r::GUI::have_OpenGL) { if ($Slic3r::GUI::have_OpenGL) {
$self->{canvas3D} = Slic3r::GUI::Plater::3D->new($self->{preview_notebook}, $self->{objects}, $self->{model}, $self->{print}, $self->{config}); $self->{canvas3D} = Slic3r::GUI::Plater::3D->new($self->{preview_notebook}, $self->{objects}, $self->{model}, $self->{print}, $self->{config});
$self->{preview_notebook}->AddPage($self->{canvas3D}, '3D'); $self->{preview_notebook}->AddPage($self->{canvas3D}, L('3D'));
$self->{canvas3D}->set_on_select_object($on_select_object); $self->{canvas3D}->set_on_select_object($on_select_object);
$self->{canvas3D}->set_on_double_click($on_double_click); $self->{canvas3D}->set_on_double_click($on_double_click);
$self->{canvas3D}->set_on_right_click(sub { $on_right_click->($self->{canvas3D}, @_); }); $self->{canvas3D}->set_on_right_click(sub { $on_right_click->($self->{canvas3D}, @_); });
@ -133,7 +135,7 @@ sub new {
# Initialize 2D preview canvas # Initialize 2D preview canvas
$self->{canvas} = Slic3r::GUI::Plater::2D->new($self->{preview_notebook}, wxDefaultSize, $self->{objects}, $self->{model}, $self->{config}); $self->{canvas} = Slic3r::GUI::Plater::2D->new($self->{preview_notebook}, wxDefaultSize, $self->{objects}, $self->{model}, $self->{config});
$self->{preview_notebook}->AddPage($self->{canvas}, '2D'); $self->{preview_notebook}->AddPage($self->{canvas}, L('2D'));
$self->{canvas}->on_select_object($on_select_object); $self->{canvas}->on_select_object($on_select_object);
$self->{canvas}->on_double_click($on_double_click); $self->{canvas}->on_double_click($on_double_click);
$self->{canvas}->on_right_click(sub { $on_right_click->($self->{canvas}, @_); }); $self->{canvas}->on_right_click(sub { $on_right_click->($self->{canvas}, @_); });
@ -145,14 +147,14 @@ sub new {
$self->{preview3D}->canvas->on_viewport_changed(sub { $self->{preview3D}->canvas->on_viewport_changed(sub {
$self->{canvas3D}->set_viewport_from_scene($self->{preview3D}->canvas); $self->{canvas3D}->set_viewport_from_scene($self->{preview3D}->canvas);
}); });
$self->{preview_notebook}->AddPage($self->{preview3D}, 'Preview'); $self->{preview_notebook}->AddPage($self->{preview3D}, L('Preview'));
$self->{preview3D_page_idx} = $self->{preview_notebook}->GetPageCount-1; $self->{preview3D_page_idx} = $self->{preview_notebook}->GetPageCount-1;
} }
# Initialize toolpaths preview # Initialize toolpaths preview
if ($Slic3r::GUI::have_OpenGL) { if ($Slic3r::GUI::have_OpenGL) {
$self->{toolpaths2D} = Slic3r::GUI::Plater::2DToolpaths->new($self->{preview_notebook}, $self->{print}); $self->{toolpaths2D} = Slic3r::GUI::Plater::2DToolpaths->new($self->{preview_notebook}, $self->{print});
$self->{preview_notebook}->AddPage($self->{toolpaths2D}, 'Layers'); $self->{preview_notebook}->AddPage($self->{toolpaths2D}, L('Layers'));
} }
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub { EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub {
@ -172,37 +174,37 @@ sub new {
if (!&Wx::wxMSW) { if (!&Wx::wxMSW) {
Wx::ToolTip::Enable(1); Wx::ToolTip::Enable(1);
$self->{htoolbar} = Wx::ToolBar->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxTB_TEXT | wxBORDER_SIMPLE | wxTAB_TRAVERSAL); $self->{htoolbar} = Wx::ToolBar->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxTB_TEXT | wxBORDER_SIMPLE | wxTAB_TRAVERSAL);
$self->{htoolbar}->AddTool(TB_ADD, "Add…", Wx::Bitmap->new(Slic3r::var("brick_add.png"), wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_ADD, L("Add…"), Wx::Bitmap->new(Slic3r::var("brick_add.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddTool(TB_REMOVE, "Delete", Wx::Bitmap->new(Slic3r::var("brick_delete.png"), wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_REMOVE, L("Delete"), Wx::Bitmap->new(Slic3r::var("brick_delete.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddTool(TB_RESET, "Delete All", Wx::Bitmap->new(Slic3r::var("cross.png"), wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_RESET, L("Delete All"), Wx::Bitmap->new(Slic3r::var("cross.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddTool(TB_ARRANGE, "Arrange", Wx::Bitmap->new(Slic3r::var("bricks.png"), wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_ARRANGE, L("Arrange"), Wx::Bitmap->new(Slic3r::var("bricks.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddSeparator; $self->{htoolbar}->AddSeparator;
$self->{htoolbar}->AddTool(TB_MORE, "More", Wx::Bitmap->new(Slic3r::var("add.png"), wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_MORE, L("More"), Wx::Bitmap->new(Slic3r::var("add.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddTool(TB_FEWER, "Fewer", Wx::Bitmap->new(Slic3r::var("delete.png"), wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_FEWER, L("Fewer"), Wx::Bitmap->new(Slic3r::var("delete.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddSeparator; $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_45CCW, L("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_45CW, L("45° cw"), Wx::Bitmap->new(Slic3r::var("arrow_rotate_clockwise.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddTool(TB_SCALE, "Scale…", Wx::Bitmap->new(Slic3r::var("arrow_out.png"), wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_SCALE, L("Scale…"), Wx::Bitmap->new(Slic3r::var("arrow_out.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddTool(TB_SPLIT, "Split", Wx::Bitmap->new(Slic3r::var("shape_ungroup.png"), wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_SPLIT, L("Split"), Wx::Bitmap->new(Slic3r::var("shape_ungroup.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddTool(TB_CUT, "Cut…", Wx::Bitmap->new(Slic3r::var("package.png"), wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_CUT, L("Cut…"), Wx::Bitmap->new(Slic3r::var("package.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddSeparator; $self->{htoolbar}->AddSeparator;
$self->{htoolbar}->AddTool(TB_SETTINGS, "Settings…", Wx::Bitmap->new(Slic3r::var("cog.png"), wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_SETTINGS, L("Settings…"), Wx::Bitmap->new(Slic3r::var("cog.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddTool(TB_LAYER_EDITING, 'Layer Editing', Wx::Bitmap->new(Slic3r::var("variable_layer_height.png"), wxBITMAP_TYPE_PNG), wxNullBitmap, 1, 0, 'Layer Editing'); $self->{htoolbar}->AddTool(TB_LAYER_EDITING, L('Layer Editing'), Wx::Bitmap->new(Slic3r::var("variable_layer_height.png"), wxBITMAP_TYPE_PNG), wxNullBitmap, 1, 0, 'Layer Editing');
} else { } else {
my %tbar_buttons = ( my %tbar_buttons = (
add => "Add…", add => L("Add…"),
remove => "Delete", remove => L("Delete"),
reset => "Delete All", reset => L("Delete All"),
arrange => "Arrange", arrange => L("Arrange"),
increase => "", increase => "",
decrease => "", decrease => "",
rotate45ccw => "", rotate45ccw => "",
rotate45cw => "", rotate45cw => "",
changescale => "Scale…", changescale => L("Scale…"),
split => "Split", split => L("Split"),
cut => "Cut…", cut => L("Cut…"),
settings => "Settings…", settings => L("Settings…"),
layer_editing => "Layer editing", layer_editing => L("Layer editing"),
); );
$self->{btoolbar} = Wx::BoxSizer->new(wxHORIZONTAL); $self->{btoolbar} = Wx::BoxSizer->new(wxHORIZONTAL);
for (qw(add remove reset arrange increase decrease rotate45ccw rotate45cw changescale split cut settings)) { for (qw(add remove reset arrange increase decrease rotate45ccw rotate45cw changescale split cut settings)) {
@ -215,9 +217,9 @@ sub new {
$self->{list} = Wx::ListView->new($self, -1, wxDefaultPosition, wxDefaultSize, $self->{list} = Wx::ListView->new($self, -1, wxDefaultPosition, wxDefaultSize,
wxLC_SINGLE_SEL | wxLC_REPORT | wxBORDER_SUNKEN | wxTAB_TRAVERSAL | wxWANTS_CHARS ); wxLC_SINGLE_SEL | wxLC_REPORT | wxBORDER_SUNKEN | wxTAB_TRAVERSAL | wxWANTS_CHARS );
$self->{list}->InsertColumn(0, "Name", wxLIST_FORMAT_LEFT, 145); $self->{list}->InsertColumn(0, L("Name"), wxLIST_FORMAT_LEFT, 145);
$self->{list}->InsertColumn(1, "Copies", wxLIST_FORMAT_CENTER, 45); $self->{list}->InsertColumn(1, L("Copies"), wxLIST_FORMAT_CENTER, 45);
$self->{list}->InsertColumn(2, "Scale", wxLIST_FORMAT_CENTER, wxLIST_AUTOSIZE_USEHEADER); $self->{list}->InsertColumn(2, L("Scale"), wxLIST_FORMAT_CENTER, wxLIST_AUTOSIZE_USEHEADER);
EVT_LIST_ITEM_SELECTED($self, $self->{list}, \&list_item_selected); EVT_LIST_ITEM_SELECTED($self, $self->{list}, \&list_item_selected);
EVT_LIST_ITEM_DESELECTED($self, $self->{list}, \&list_item_deselected); EVT_LIST_ITEM_DESELECTED($self, $self->{list}, \&list_item_deselected);
EVT_LIST_ITEM_ACTIVATED($self, $self->{list}, \&list_item_activated); EVT_LIST_ITEM_ACTIVATED($self, $self->{list}, \&list_item_activated);
@ -231,11 +233,11 @@ sub new {
}); });
# right pane buttons # right pane buttons
$self->{btn_export_gcode} = Wx::Button->new($self, -1, "Export G-code…", wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_export_gcode} = Wx::Button->new($self, -1, L("Export G-code…"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
$self->{btn_reslice} = Wx::Button->new($self, -1, "Slice now", wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_reslice} = Wx::Button->new($self, -1, L("Slice now"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
$self->{btn_print} = Wx::Button->new($self, -1, "Print…", wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_print} = Wx::Button->new($self, -1, L("Print…"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
$self->{btn_send_gcode} = Wx::Button->new($self, -1, "Send to printer", wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_send_gcode} = Wx::Button->new($self, -1, L("Send to printer"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
$self->{btn_export_stl} = Wx::Button->new($self, -1, "Export STL…", wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_export_stl} = Wx::Button->new($self, -1, L("Export STL…"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
#$self->{btn_export_gcode}->SetFont($Slic3r::GUI::small_font); #$self->{btn_export_gcode}->SetFont($Slic3r::GUI::small_font);
#$self->{btn_export_stl}->SetFont($Slic3r::GUI::small_font); #$self->{btn_export_stl}->SetFont($Slic3r::GUI::small_font);
$self->{btn_print}->Hide; $self->{btn_print}->Hide;
@ -362,9 +364,9 @@ sub new {
$presets->AddGrowableCol(1, 1); $presets->AddGrowableCol(1, 1);
$presets->SetFlexibleDirection(wxHORIZONTAL); $presets->SetFlexibleDirection(wxHORIZONTAL);
my %group_labels = ( my %group_labels = (
print => 'Print settings', print => L('Print settings'),
filament => 'Filament', filament => L('Filament'),
printer => 'Printer', printer => L('Printer'),
); );
# UI Combo boxes for a print, multiple filaments, and a printer. # UI Combo boxes for a print, multiple filaments, and a printer.
# Initially a single filament combo box is created, but the number of combo boxes for the filament selection may increase, # Initially a single filament combo box is created, but the number of combo boxes for the filament selection may increase,
@ -393,7 +395,7 @@ sub new {
my $object_info_sizer; my $object_info_sizer;
{ {
my $box = Wx::StaticBox->new($self, -1, "Info"); my $box = Wx::StaticBox->new($self, -1, L("Info"));
$object_info_sizer = Wx::StaticBoxSizer->new($box, wxVERTICAL); $object_info_sizer = Wx::StaticBoxSizer->new($box, wxVERTICAL);
$object_info_sizer->SetMinSize([350,-1]); $object_info_sizer->SetMinSize([350,-1]);
my $grid_sizer = Wx::FlexGridSizer->new(3, 4, 5, 5); my $grid_sizer = Wx::FlexGridSizer->new(3, 4, 5, 5);
@ -403,11 +405,11 @@ sub new {
$object_info_sizer->Add($grid_sizer, 0, wxEXPAND); $object_info_sizer->Add($grid_sizer, 0, wxEXPAND);
my @info = ( my @info = (
size => "Size", size => L("Size"),
volume => "Volume", volume => L("Volume"),
facets => "Facets", facets => L("Facets"),
materials => "Materials", materials => L("Materials"),
manifold => "Manifold", manifold => L("Manifold"),
); );
while (my $field = shift @info) { while (my $field = shift @info) {
my $label = shift @info; my $label = shift @info;
@ -433,7 +435,7 @@ sub new {
my $print_info_sizer; my $print_info_sizer;
{ {
my $box = Wx::StaticBox->new($self, -1, "Sliced Info"); my $box = Wx::StaticBox->new($self, -1, L("Sliced Info"));
$print_info_sizer = Wx::StaticBoxSizer->new($box, wxVERTICAL); $print_info_sizer = Wx::StaticBoxSizer->new($box, wxVERTICAL);
$print_info_sizer->SetMinSize([350,-1]); $print_info_sizer->SetMinSize([350,-1]);
my $grid_sizer = Wx::FlexGridSizer->new(2, 2, 5, 5); my $grid_sizer = Wx::FlexGridSizer->new(2, 2, 5, 5);
@ -442,11 +444,11 @@ sub new {
$grid_sizer->AddGrowableCol(3, 1); $grid_sizer->AddGrowableCol(3, 1);
$print_info_sizer->Add($grid_sizer, 0, wxEXPAND); $print_info_sizer->Add($grid_sizer, 0, wxEXPAND);
my @info = ( my @info = (
fil_m => "Used Filament (m)", fil_m => L("Used Filament (m)"),
fil_mm3 => "Used Filament (mm\x{00B3})", fil_mm3 => L("Used Filament (mm³)"),
fil_g => "Used Filament (g)", fil_g => L("Used Filament (g)"),
cost => "Cost", cost => L("Cost"),
time => "Estimated printing time", time => L("Estimated printing time"),
); );
while (my $field = shift @info) { while (my $field = shift @info) {
my $label = shift @info; my $label = shift @info;
@ -624,7 +626,7 @@ sub load_files {
my $one_by_one = (@$nozzle_dmrs <= 1) || (@$input_files == 1) || my $one_by_one = (@$nozzle_dmrs <= 1) || (@$input_files == 1) ||
defined(first { $_ =~ /.[aA][mM][fF]$/ || $_ =~ /.[aA][mM][fF].[xX][mM][lL]$/ || $_ =~ /.[zZ][iI][pP].[aA][mM][fF]$/ || $_ =~ /.3[mM][fF]$/ || $_ =~ /.[pP][rR][uI][sS][aA]$/ } @$input_files); defined(first { $_ =~ /.[aA][mM][fF]$/ || $_ =~ /.[aA][mM][fF].[xX][mM][lL]$/ || $_ =~ /.[zZ][iI][pP].[aA][mM][fF]$/ || $_ =~ /.3[mM][fF]$/ || $_ =~ /.[pP][rR][uI][sS][aA]$/ } @$input_files);
my $process_dialog = Wx::ProgressDialog->new('Loading…', "Processing input file\n" . basename($input_files->[0]), 100, $self, 0); my $process_dialog = Wx::ProgressDialog->new(L('Loading…'), L("Processing input file\n") . basename($input_files->[0]), 100, $self, 0);
$process_dialog->Pulse; $process_dialog->Pulse;
local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self);
@ -638,7 +640,7 @@ sub load_files {
# For all input files. # For all input files.
for (my $i = 0; $i < @$input_files; $i += 1) { for (my $i = 0; $i < @$input_files; $i += 1) {
my $input_file = $input_files->[$i]; my $input_file = $input_files->[$i];
$process_dialog->Update(100. * $i / @$input_files, "Processing input file\n" . basename($input_file)); $process_dialog->Update(100. * $i / @$input_files, L("Processing input file\n") . basename($input_file));
my $model; my $model;
if (($input_file =~ /.3[mM][fF]$/) || ($input_file =~ /.[zZ][iI][pP].[aA][mM][fF]$/)) if (($input_file =~ /.3[mM][fF]$/) || ($input_file =~ /.[zZ][iI][pP].[aA][mM][fF]$/))
@ -658,10 +660,10 @@ sub load_files {
if ($model->looks_like_multipart_object) { if ($model->looks_like_multipart_object) {
my $dialog = Wx::MessageDialog->new($self, my $dialog = Wx::MessageDialog->new($self,
"This file contains several objects positioned at multiple heights. " L("This file contains several objects positioned at multiple heights. "
. "Instead of considering them as multiple objects, should I consider\n" . "Instead of considering them as multiple objects, should I consider\n"
. "this file as a single object having multiple parts?\n", . "this file as a single object having multiple parts?\n"),
'Multi-part object detected', wxICON_WARNING | wxYES | wxNO); L('Multi-part object detected'), wxICON_WARNING | wxYES | wxNO);
$model->convert_multipart_object if $dialog->ShowModal() == wxID_YES; $model->convert_multipart_object if $dialog->ShowModal() == wxID_YES;
} }
@ -675,10 +677,10 @@ sub load_files {
if ($new_model) { if ($new_model) {
my $dialog = Wx::MessageDialog->new($self, my $dialog = Wx::MessageDialog->new($self,
"Multiple objects were loaded for a multi-material printer.\n" L("Multiple objects were loaded for a multi-material printer.\n"
. "Instead of considering them as multiple objects, should I consider\n" . "Instead of considering them as multiple objects, should I consider\n"
. "these files to represent a single object having multiple parts?\n", . "these files to represent a single object having multiple parts?\n"),
'Multi-part object detected', wxICON_WARNING | wxYES | wxNO); L('Multi-part object detected'), wxICON_WARNING | wxYES | wxNO);
$new_model->convert_multipart_object if $dialog->ShowModal() == wxID_YES; $new_model->convert_multipart_object if $dialog->ShowModal() == wxID_YES;
push @obj_idx, $self->load_model_objects(@{$new_model->objects}); push @obj_idx, $self->load_model_objects(@{$new_model->objects});
} }
@ -687,7 +689,7 @@ sub load_files {
wxTheApp->{app_config}->update_skein_dir(dirname($input_files->[-1])); wxTheApp->{app_config}->update_skein_dir(dirname($input_files->[-1]));
$process_dialog->Destroy; $process_dialog->Destroy;
$self->statusbar->SetStatusText("Loaded " . join(',', @loaded_files)); $self->statusbar->SetStatusText(L("Loaded ") . join(',', @loaded_files));
return @obj_idx; return @obj_idx;
} }
@ -739,8 +741,8 @@ sub load_model_objects {
if ($scaled_down) { if ($scaled_down) {
Slic3r::GUI::show_info( Slic3r::GUI::show_info(
$self, $self,
'Your object appears to be too large, so it was automatically scaled down to fit your print bed.', L('Your object appears to be too large, so it was automatically scaled down to fit your print bed.'),
'Object too large?', L('Object too large?'),
); );
} }
@ -895,7 +897,7 @@ sub set_number_of_copies {
my $model_object = $self->{model}->objects->[$obj_idx]; my $model_object = $self->{model}->objects->[$obj_idx];
# prompt user # prompt user
my $copies = Wx::GetNumberFromUser("", "Enter the number of copies of the selected object:", "Copies", $model_object->instances_count, 0, 1000, $self); my $copies = Wx::GetNumberFromUser("", L("Enter the number of copies of the selected object:"), L("Copies"), $model_object->instances_count, 0, 1000, $self);
my $diff = $copies - $model_object->instances_count; my $diff = $copies - $model_object->instances_count;
if ($diff == 0) { if ($diff == 0) {
# no variation # no variation
@ -922,9 +924,9 @@ sub _get_number_from_user {
Wx::MessageBox( Wx::MessageBox(
$error_message . $error_message .
(($only_positive && $value <= 0) ? (($only_positive && $value <= 0) ?
": $value\nNon-positive value." : ": ".$value.L("\nNon-positive value.") :
": $value\nNot a numeric value."), ": ".$value.L("\nNot a numeric value.")),
"Slic3r Error", wxOK | wxICON_EXCLAMATION, $self); L("Slic3r Error"), wxOK | wxICON_EXCLAMATION, $self);
$default = $value; $default = $value;
} }
} }
@ -945,7 +947,7 @@ sub rotate {
if (!defined $angle) { if (!defined $angle) {
my $axis_name = $axis == X ? 'X' : $axis == Y ? 'Y' : 'Z'; my $axis_name = $axis == X ? 'X' : $axis == Y ? 'Y' : 'Z';
my $default = $axis == Z ? rad2deg($model_instance->rotation) : 0; my $default = $axis == Z ? rad2deg($model_instance->rotation) : 0;
$angle = $self->_get_number_from_user("Enter the rotation angle:", "Rotate around $axis_name axis", "Invalid rotation angle entered", $default); $angle = $self->_get_number_from_user(L("Enter the rotation angle:"), L("Rotate around ").$axis_name.(" axis"), L("Invalid rotation angle entered"), $default);
return if $angle eq ''; return if $angle eq '';
} }
@ -1025,12 +1027,12 @@ sub changescale {
if ($tosize) { if ($tosize) {
my $cursize = $object_size->[$axis]; my $cursize = $object_size->[$axis];
my $newsize = $self->_get_number_from_user( my $newsize = $self->_get_number_from_user(
sprintf('Enter the new size for the selected object (print bed: %smm):', unscale($bed_size->[$axis])), sprintf(L('Enter the new size for the selected object (print bed: %smm):'), unscale($bed_size->[$axis])),
"Scale along $axis_name", 'Invalid scaling value entered', $cursize, 1); L("Scale along ").$axis_name, L('Invalid scaling value entered'), $cursize, 1);
return if $newsize eq ''; return if $newsize eq '';
$scale = $newsize / $cursize * 100; $scale = $newsize / $cursize * 100;
} else { } else {
$scale = $self->_get_number_from_user('Enter the scale % for the selected object:', "Scale along $axis_name", 'Invalid scaling value entered', 100, 1); $scale = $self->_get_number_from_user(L('Enter the scale % for the selected object:'), L("Scale along ").$axis_name, L('Invalid scaling value entered'), 100, 1);
return if $scale eq ''; return if $scale eq '';
} }
@ -1051,12 +1053,12 @@ sub changescale {
my $scale; my $scale;
if ($tosize) { if ($tosize) {
my $cursize = max(@$object_size); my $cursize = max(@$object_size);
my $newsize = $self->_get_number_from_user('Enter the new max size for the selected object:', 'Scale', 'Invalid scaling value entered', $cursize, 1); my $newsize = $self->_get_number_from_user(L('Enter the new max size for the selected object:'), L('Scale'), L('Invalid scaling value entered'), $cursize, 1);
return if ! defined($newsize) || $newsize eq ''; return if ! defined($newsize) || $newsize eq '';
$scale = $model_instance->scaling_factor * $newsize / $cursize * 100; $scale = $model_instance->scaling_factor * $newsize / $cursize * 100;
} else { } else {
# max scale factor should be above 2540 to allow importing files exported in inches # max scale factor should be above 2540 to allow importing files exported in inches
$scale = $self->_get_number_from_user('Enter the scale % for the selected object:', 'Scale', 'Invalid scaling value entered', $model_instance->scaling_factor*100, 1); $scale = $self->_get_number_from_user(L('Enter the scale % for the selected object:'), L('Scale'), L('Invalid scaling value entered'), $model_instance->scaling_factor*100, 1);
return if ! defined($scale) || $scale eq ''; return if ! defined($scale) || $scale eq '';
} }
@ -1107,7 +1109,7 @@ sub split_object {
my $current_model_object = $new_model->get_object($obj_idx); my $current_model_object = $new_model->get_object($obj_idx);
if ($current_model_object->volumes_count > 1) { if ($current_model_object->volumes_count > 1) {
Slic3r::GUI::warning_catcher($self)->("The selected object can't be split because it contains more than one volume/material."); Slic3r::GUI::warning_catcher($self)->(L("The selected object can't be split because it contains more than one volume/material."));
return; return;
} }
@ -1116,7 +1118,7 @@ sub split_object {
my @model_objects = @{$current_model_object->split_object}; my @model_objects = @{$current_model_object->split_object};
if (@model_objects == 1) { if (@model_objects == 1) {
$self->resume_background_process; $self->resume_background_process;
Slic3r::GUI::warning_catcher($self)->("The selected object couldn't be split because it contains only one part."); Slic3r::GUI::warning_catcher($self)->(L("The selected object couldn't be split because it contains only one part."));
$self->resume_background_process; $self->resume_background_process;
return; return;
} }
@ -1281,7 +1283,7 @@ sub reslice {
$self->async_apply_config; $self->async_apply_config;
$self->statusbar->SetCancelCallback(sub { $self->statusbar->SetCancelCallback(sub {
$self->stop_background_process; $self->stop_background_process;
$self->statusbar->SetStatusText("Slicing cancelled"); $self->statusbar->SetStatusText(L("Slicing cancelled"));
# this updates buttons status # this updates buttons status
$self->object_list_changed; $self->object_list_changed;
}); });
@ -1295,7 +1297,7 @@ sub export_gcode {
return if !@{$self->{objects}}; return if !@{$self->{objects}};
if ($self->{export_gcode_output_file}) { if ($self->{export_gcode_output_file}) {
Wx::MessageDialog->new($self, "Another export job is currently running.", 'Error', wxOK | wxICON_ERROR)->ShowModal; Wx::MessageDialog->new($self, L("Another export job is currently running."), L('Error'), wxOK | wxICON_ERROR)->ShowModal;
return; return;
} }
@ -1326,7 +1328,7 @@ sub export_gcode {
} else { } else {
my $default_output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') }; my $default_output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') };
Slic3r::GUI::catch_error($self) and return; Slic3r::GUI::catch_error($self) and return;
my $dlg = Wx::FileDialog->new($self, 'Save G-code file as:', my $dlg = Wx::FileDialog->new($self, L('Save G-code file as:'),
wxTheApp->{app_config}->get_last_output_dir(dirname($default_output_file)), wxTheApp->{app_config}->get_last_output_dir(dirname($default_output_file)),
basename($default_output_file), &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); basename($default_output_file), &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if ($dlg->ShowModal != wxID_OK) { if ($dlg->ShowModal != wxID_OK) {
@ -1343,7 +1345,7 @@ sub export_gcode {
$self->statusbar->SetCancelCallback(sub { $self->statusbar->SetCancelCallback(sub {
$self->stop_background_process; $self->stop_background_process;
$self->statusbar->SetStatusText("Export cancelled"); $self->statusbar->SetStatusText(L("Export cancelled"));
$self->{export_gcode_output_file} = undef; $self->{export_gcode_output_file} = undef;
$self->{send_gcode_file} = undef; $self->{send_gcode_file} = undef;
@ -1440,16 +1442,16 @@ sub on_export_completed {
if ($result) { if ($result) {
# G-code file exported successfully. # G-code file exported successfully.
if ($self->{print_file}) { if ($self->{print_file}) {
$message = "File added to print queue"; $message = L("File added to print queue");
$do_print = 1; $do_print = 1;
} elsif ($self->{send_gcode_file}) { } elsif ($self->{send_gcode_file}) {
$message = "Sending G-code file to the OctoPrint server..."; $message = L("Sending G-code file to the OctoPrint server...");
$send_gcode = 1; $send_gcode = 1;
} else { } else {
$message = "G-code file exported to " . $self->{export_gcode_output_file}; $message = L("G-code file exported to ") . $self->{export_gcode_output_file};
} }
} else { } else {
$message = "Export failed"; $message = L("Export failed");
} }
$self->{export_gcode_output_file} = undef; $self->{export_gcode_output_file} = undef;
$self->statusbar->SetStatusText($message); $self->statusbar->SetStatusText($message);
@ -1519,9 +1521,9 @@ sub send_gcode {
$self->statusbar->StopBusy; $self->statusbar->StopBusy;
if ($res->is_success) { if ($res->is_success) {
$self->statusbar->SetStatusText("G-code file successfully uploaded to the OctoPrint server"); $self->statusbar->SetStatusText(L("G-code file successfully uploaded to the OctoPrint server"));
} else { } else {
my $message = "Error while uploading to the OctoPrint server: " . $res->status_line; my $message = L("Error while uploading to the OctoPrint server: ") . $res->status_line;
Slic3r::GUI::show_error($self, $message); Slic3r::GUI::show_error($self, $message);
$self->statusbar->SetStatusText($message); $self->statusbar->SetStatusText($message);
} }
@ -1534,7 +1536,7 @@ sub export_stl {
my $output_file = $self->_get_export_file('STL') or return; my $output_file = $self->_get_export_file('STL') or return;
# Store a binary STL. # Store a binary STL.
$self->{model}->store_stl($output_file, 1); $self->{model}->store_stl($output_file, 1);
$self->statusbar->SetStatusText("STL file exported to $output_file"); $self->statusbar->SetStatusText(L("STL file exported to ").$output_file);
} }
sub reload_from_disk { sub reload_from_disk {
@ -1576,7 +1578,7 @@ sub export_object_stl {
# Ask user for a file name to write into. # Ask user for a file name to write into.
my $output_file = $self->_get_export_file('STL') or return; my $output_file = $self->_get_export_file('STL') or return;
$model_object->mesh->write_binary($output_file); $model_object->mesh->write_binary($output_file);
$self->statusbar->SetStatusText("STL file exported to $output_file"); $self->statusbar->SetStatusText(L("STL file exported to ").$output_file);
} }
sub export_amf { sub export_amf {
@ -1587,11 +1589,11 @@ sub export_amf {
my $res = $self->{model}->store_amf($output_file, $self->{print}); my $res = $self->{model}->store_amf($output_file, $self->{print});
if ($res) if ($res)
{ {
$self->statusbar->SetStatusText("AMF file exported to $output_file"); $self->statusbar->SetStatusText(L("AMF file exported to ").$output_file);
} }
else else
{ {
$self->statusbar->SetStatusText("Error exporting AMF file $output_file"); $self->statusbar->SetStatusText(L("Error exporting AMF file ").$output_file);
} }
} }
@ -1603,11 +1605,11 @@ sub export_3mf {
my $res = $self->{model}->store_3mf($output_file, $self->{print}); my $res = $self->{model}->store_3mf($output_file, $self->{print});
if ($res) if ($res)
{ {
$self->statusbar->SetStatusText("3MF file exported to $output_file"); $self->statusbar->SetStatusText(L("3MF file exported to ").$output_file);
} }
else else
{ {
$self->statusbar->SetStatusText("Error exporting 3MF file $output_file"); $self->statusbar->SetStatusText(L("Error exporting 3MF file ").$output_file);
} }
} }
@ -1640,7 +1642,7 @@ sub _get_export_file {
my $output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') }; my $output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') };
Slic3r::GUI::catch_error($self) and return undef; Slic3r::GUI::catch_error($self) and return undef;
$output_file =~ s/\.[gG][cC][oO][dD][eE]$/$suffix/; $output_file =~ s/\.[gG][cC][oO][dD][eE]$/$suffix/;
my $dlg = Wx::FileDialog->new($self, "Save $format file as:", dirname($output_file), my $dlg = Wx::FileDialog->new($self, L("Save ").$format.L(" file as:"), dirname($output_file),
basename($output_file), &Slic3r::GUI::FILE_WILDCARDS->{$wildcard}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); basename($output_file), &Slic3r::GUI::FILE_WILDCARDS->{$wildcard}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if ($dlg->ShowModal != wxID_OK) { if ($dlg->ShowModal != wxID_OK) {
$dlg->Destroy; $dlg->Destroy;
@ -1843,7 +1845,7 @@ sub object_cut_dialog {
} }
if (!$Slic3r::GUI::have_OpenGL) { if (!$Slic3r::GUI::have_OpenGL) {
Slic3r::GUI::show_error($self, "Please install the OpenGL modules to use this feature (see build instructions)."); Slic3r::GUI::show_error($self, L("Please install the OpenGL modules to use this feature (see build instructions)."));
return; return;
} }
@ -1953,19 +1955,19 @@ sub selection_changed {
if (my $stats = $model_object->mesh_stats) { if (my $stats = $model_object->mesh_stats) {
$self->{object_info_volume}->SetLabel(sprintf('%.2f', $stats->{volume} * ($model_instance->scaling_factor**3))); $self->{object_info_volume}->SetLabel(sprintf('%.2f', $stats->{volume} * ($model_instance->scaling_factor**3)));
$self->{object_info_facets}->SetLabel(sprintf('%d (%d shells)', $model_object->facets_count, $stats->{number_of_parts})); $self->{object_info_facets}->SetLabel(sprintf(L('%d (%d shells)'), $model_object->facets_count, $stats->{number_of_parts}));
if (my $errors = sum(@$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)})) { if (my $errors = sum(@$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)})) {
$self->{object_info_manifold}->SetLabel(sprintf("Auto-repaired (%d errors)", $errors)); $self->{object_info_manifold}->SetLabel(sprintf(L("Auto-repaired (%d errors)"), $errors));
$self->{object_info_manifold_warning_icon}->Show; $self->{object_info_manifold_warning_icon}->Show;
# we don't show normals_fixed because we never provide normals # we don't show normals_fixed because we never provide normals
# to admesh, so it generates normals for all facets # to admesh, so it generates normals for all facets
my $message = sprintf '%d degenerate facets, %d edges fixed, %d facets removed, %d facets added, %d facets reversed, %d backwards edges', my $message = sprintf L('%d degenerate facets, %d edges fixed, %d facets removed, %d facets added, %d facets reversed, %d backwards edges'),
@$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)}; @$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)};
$self->{object_info_manifold}->SetToolTipString($message); $self->{object_info_manifold}->SetToolTipString($message);
$self->{object_info_manifold_warning_icon}->SetToolTipString($message); $self->{object_info_manifold_warning_icon}->SetToolTipString($message);
} else { } else {
$self->{object_info_manifold}->SetLabel("Yes"); $self->{object_info_manifold}->SetLabel(L("Yes"));
} }
} else { } else {
$self->{object_info_facets}->SetLabel($object->facets); $self->{object_info_facets}->SetLabel($object->facets);
@ -2016,99 +2018,99 @@ sub object_menu {
my $frame = $self->GetFrame; my $frame = $self->GetFrame;
my $menu = Wx::Menu->new; my $menu = Wx::Menu->new;
my $accel = ($^O eq 'MSWin32') ? sub { $_[0] . "\t\xA0" . $_[1] } : sub { $_[0] }; my $accel = ($^O eq 'MSWin32') ? sub { $_[0] . "\t\xA0" . $_[1] } : sub { $_[0] };
$frame->_append_menu_item($menu, $accel->('Delete', 'Del'), 'Remove the selected object', sub { $frame->_append_menu_item($menu, $accel->(L('Delete'), 'Del'), L('Remove the selected object'), sub {
$self->remove; $self->remove;
}, undef, 'brick_delete.png'); }, undef, 'brick_delete.png');
$frame->_append_menu_item($menu, $accel->('Increase copies', '+'), 'Place one more copy of the selected object', sub { $frame->_append_menu_item($menu, $accel->(L('Increase copies'), '+'), L('Place one more copy of the selected object'), sub {
$self->increase; $self->increase;
}, undef, 'add.png'); }, undef, 'add.png');
$frame->_append_menu_item($menu, $accel->('Decrease copies', '-'), 'Remove one copy of the selected object', sub { $frame->_append_menu_item($menu, $accel->(L('Decrease copies'), '-'), L('Remove one copy of the selected object'), sub {
$self->decrease; $self->decrease;
}, undef, 'delete.png'); }, undef, 'delete.png');
$frame->_append_menu_item($menu, "Set number of copies…", 'Change the number of copies of the selected object', sub { $frame->_append_menu_item($menu, L("Set number of copies…"), L('Change the number of copies of the selected object'), sub {
$self->set_number_of_copies; $self->set_number_of_copies;
}, undef, 'textfield.png'); }, undef, 'textfield.png');
$menu->AppendSeparator(); $menu->AppendSeparator();
$frame->_append_menu_item($menu, $accel->('Rotate 45° clockwise', 'l'), 'Rotate the selected object by 45° clockwise', sub { $frame->_append_menu_item($menu, $accel->(L('Rotate 45° clockwise'), 'l'), L('Rotate the selected object by 45° clockwise'), sub {
$self->rotate(-45, Z, 'relative'); $self->rotate(-45, Z, 'relative');
}, undef, 'arrow_rotate_clockwise.png'); }, undef, 'arrow_rotate_clockwise.png');
$frame->_append_menu_item($menu, $accel->('Rotate 45° counter-clockwise', 'r'), 'Rotate the selected object by 45° counter-clockwise', sub { $frame->_append_menu_item($menu, $accel->(L('Rotate 45° counter-clockwise'), 'r'), L('Rotate the selected object by 45° counter-clockwise'), sub {
$self->rotate(+45, Z, 'relative'); $self->rotate(+45, Z, 'relative');
}, undef, 'arrow_rotate_anticlockwise.png'); }, undef, 'arrow_rotate_anticlockwise.png');
my $rotateMenu = Wx::Menu->new; my $rotateMenu = Wx::Menu->new;
my $rotateMenuItem = $menu->AppendSubMenu($rotateMenu, "Rotate", 'Rotate the selected object by an arbitrary angle'); my $rotateMenuItem = $menu->AppendSubMenu($rotateMenu, L("Rotate"), L('Rotate the selected object by an arbitrary angle'));
$frame->_set_menu_item_icon($rotateMenuItem, 'textfield.png'); $frame->_set_menu_item_icon($rotateMenuItem, 'textfield.png');
$frame->_append_menu_item($rotateMenu, "Around X axis…", 'Rotate the selected object by an arbitrary angle around X axis', sub { $frame->_append_menu_item($rotateMenu, L("Around X axis…"), L('Rotate the selected object by an arbitrary angle around X axis'), sub {
$self->rotate(undef, X); $self->rotate(undef, X);
}, undef, 'bullet_red.png'); }, undef, 'bullet_red.png');
$frame->_append_menu_item($rotateMenu, "Around Y axis…", 'Rotate the selected object by an arbitrary angle around Y axis', sub { $frame->_append_menu_item($rotateMenu, L("Around Y axis…"), L('Rotate the selected object by an arbitrary angle around Y axis'), sub {
$self->rotate(undef, Y); $self->rotate(undef, Y);
}, undef, 'bullet_green.png'); }, undef, 'bullet_green.png');
$frame->_append_menu_item($rotateMenu, "Around Z axis…", 'Rotate the selected object by an arbitrary angle around Z axis', sub { $frame->_append_menu_item($rotateMenu, L("Around Z axis…"), L('Rotate the selected object by an arbitrary angle around Z axis'), sub {
$self->rotate(undef, Z); $self->rotate(undef, Z);
}, undef, 'bullet_blue.png'); }, undef, 'bullet_blue.png');
my $mirrorMenu = Wx::Menu->new; my $mirrorMenu = Wx::Menu->new;
my $mirrorMenuItem = $menu->AppendSubMenu($mirrorMenu, "Mirror", 'Mirror the selected object'); my $mirrorMenuItem = $menu->AppendSubMenu($mirrorMenu, L("Mirror"), L('Mirror the selected object'));
$frame->_set_menu_item_icon($mirrorMenuItem, 'shape_flip_horizontal.png'); $frame->_set_menu_item_icon($mirrorMenuItem, 'shape_flip_horizontal.png');
$frame->_append_menu_item($mirrorMenu, "Along X axis…", 'Mirror the selected object along the X axis', sub { $frame->_append_menu_item($mirrorMenu, L("Along X axis…"), L('Mirror the selected object along the X axis'), sub {
$self->mirror(X); $self->mirror(X);
}, undef, 'bullet_red.png'); }, undef, 'bullet_red.png');
$frame->_append_menu_item($mirrorMenu, "Along Y axis…", 'Mirror the selected object along the Y axis', sub { $frame->_append_menu_item($mirrorMenu, L("Along Y axis…"), L('Mirror the selected object along the Y axis'), sub {
$self->mirror(Y); $self->mirror(Y);
}, undef, 'bullet_green.png'); }, undef, 'bullet_green.png');
$frame->_append_menu_item($mirrorMenu, "Along Z axis…", 'Mirror the selected object along the Z axis', sub { $frame->_append_menu_item($mirrorMenu, L("Along Z axis…"), L('Mirror the selected object along the Z axis'), sub {
$self->mirror(Z); $self->mirror(Z);
}, undef, 'bullet_blue.png'); }, undef, 'bullet_blue.png');
my $scaleMenu = Wx::Menu->new; my $scaleMenu = Wx::Menu->new;
my $scaleMenuItem = $menu->AppendSubMenu($scaleMenu, "Scale", 'Scale the selected object along a single axis'); my $scaleMenuItem = $menu->AppendSubMenu($scaleMenu, L("Scale"), L('Scale the selected object along a single axis'));
$frame->_set_menu_item_icon($scaleMenuItem, 'arrow_out.png'); $frame->_set_menu_item_icon($scaleMenuItem, 'arrow_out.png');
$frame->_append_menu_item($scaleMenu, $accel->('Uniformly…', 's'), 'Scale the selected object along the XYZ axes', sub { $frame->_append_menu_item($scaleMenu, $accel->(L('Uniformly…'), 's'), L('Scale the selected object along the XYZ axes'), sub {
$self->changescale(undef); $self->changescale(undef);
}); });
$frame->_append_menu_item($scaleMenu, "Along X axis…", 'Scale the selected object along the X axis', sub { $frame->_append_menu_item($scaleMenu, L("Along X axis…"), L('Scale the selected object along the X axis'), sub {
$self->changescale(X); $self->changescale(X);
}, undef, 'bullet_red.png'); }, undef, 'bullet_red.png');
$frame->_append_menu_item($scaleMenu, "Along Y axis…", 'Scale the selected object along the Y axis', sub { $frame->_append_menu_item($scaleMenu, L("Along Y axis…"), L('Scale the selected object along the Y axis'), sub {
$self->changescale(Y); $self->changescale(Y);
}, undef, 'bullet_green.png'); }, undef, 'bullet_green.png');
$frame->_append_menu_item($scaleMenu, "Along Z axis…", 'Scale the selected object along the Z axis', sub { $frame->_append_menu_item($scaleMenu, L("Along Z axis…"), L('Scale the selected object along the Z axis'), sub {
$self->changescale(Z); $self->changescale(Z);
}, undef, 'bullet_blue.png'); }, undef, 'bullet_blue.png');
my $scaleToSizeMenu = Wx::Menu->new; my $scaleToSizeMenu = Wx::Menu->new;
my $scaleToSizeMenuItem = $menu->AppendSubMenu($scaleToSizeMenu, "Scale to size", 'Scale the selected object along a single axis'); my $scaleToSizeMenuItem = $menu->AppendSubMenu($scaleToSizeMenu, L("Scale to size"), L('Scale the selected object along a single axis'));
$frame->_set_menu_item_icon($scaleToSizeMenuItem, 'arrow_out.png'); $frame->_set_menu_item_icon($scaleToSizeMenuItem, 'arrow_out.png');
$frame->_append_menu_item($scaleToSizeMenu, "Uniformly…", 'Scale the selected object along the XYZ axes', sub { $frame->_append_menu_item($scaleToSizeMenu, L("Uniformly…"), L('Scale the selected object along the XYZ axes'), sub {
$self->changescale(undef, 1); $self->changescale(undef, 1);
}); });
$frame->_append_menu_item($scaleToSizeMenu, "Along X axis…", 'Scale the selected object along the X axis', sub { $frame->_append_menu_item($scaleToSizeMenu, L("Along X axis…"), L('Scale the selected object along the X axis'), sub {
$self->changescale(X, 1); $self->changescale(X, 1);
}, undef, 'bullet_red.png'); }, undef, 'bullet_red.png');
$frame->_append_menu_item($scaleToSizeMenu, "Along Y axis…", 'Scale the selected object along the Y axis', sub { $frame->_append_menu_item($scaleToSizeMenu, L("Along Y axis…"), L('Scale the selected object along the Y axis'), sub {
$self->changescale(Y, 1); $self->changescale(Y, 1);
}, undef, 'bullet_green.png'); }, undef, 'bullet_green.png');
$frame->_append_menu_item($scaleToSizeMenu, "Along Z axis…", 'Scale the selected object along the Z axis', sub { $frame->_append_menu_item($scaleToSizeMenu, L("Along Z axis…"), L('Scale the selected object along the Z axis'), sub {
$self->changescale(Z, 1); $self->changescale(Z, 1);
}, undef, 'bullet_blue.png'); }, undef, 'bullet_blue.png');
$frame->_append_menu_item($menu, "Split", 'Split the selected object into individual parts', sub { $frame->_append_menu_item($menu, L("Split"), L('Split the selected object into individual parts'), sub {
$self->split_object; $self->split_object;
}, undef, 'shape_ungroup.png'); }, undef, 'shape_ungroup.png');
$frame->_append_menu_item($menu, "Cut…", 'Open the 3D cutting tool', sub { $frame->_append_menu_item($menu, L("Cut…"), L('Open the 3D cutting tool'), sub {
$self->object_cut_dialog; $self->object_cut_dialog;
}, undef, 'package.png'); }, undef, 'package.png');
$menu->AppendSeparator(); $menu->AppendSeparator();
$frame->_append_menu_item($menu, "Settings…", 'Open the object editor dialog', sub { $frame->_append_menu_item($menu, L("Settings…"), L('Open the object editor dialog'), sub {
$self->object_settings_dialog; $self->object_settings_dialog;
}, undef, 'cog.png'); }, undef, 'cog.png');
$menu->AppendSeparator(); $menu->AppendSeparator();
$frame->_append_menu_item($menu, "Reload from Disk", 'Reload the selected file from Disk', sub { $frame->_append_menu_item($menu, L("Reload from Disk"), L('Reload the selected file from Disk'), sub {
$self->reload_from_disk; $self->reload_from_disk;
}, undef, 'arrow_refresh.png'); }, undef, 'arrow_refresh.png');
$frame->_append_menu_item($menu, "Export object as STL…", 'Export this single object as STL file', sub { $frame->_append_menu_item($menu, L("Export object as STL…"), L('Export this single object as STL file'), sub {
$self->export_object_stl; $self->export_object_stl;
}, undef, 'brick_go.png'); }, undef, 'brick_go.png');
@ -2119,8 +2121,8 @@ sub object_menu {
sub select_view { sub select_view {
my ($self, $direction) = @_; my ($self, $direction) = @_;
my $idx_page = $self->{preview_notebook}->GetSelection; my $idx_page = $self->{preview_notebook}->GetSelection;
my $page = ($idx_page == &Wx::wxNOT_FOUND) ? '3D' : $self->{preview_notebook}->GetPageText($idx_page); my $page = ($idx_page == &Wx::wxNOT_FOUND) ? L('3D') : $self->{preview_notebook}->GetPageText($idx_page);
if ($page eq 'Preview') { if ($page eq L('Preview')) {
$self->{preview3D}->canvas->select_view($direction); $self->{preview3D}->canvas->select_view($direction);
$self->{canvas3D}->set_viewport_from_scene($self->{preview3D}->canvas); $self->{canvas3D}->set_viewport_from_scene($self->{preview3D}->canvas);
} else { } else {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -36,43 +36,43 @@ void BedShapePanel::build_panel(ConfigOptionPoints* default_pt)
{ {
// on_change(nullptr); // on_change(nullptr);
auto box = new wxStaticBox(this, wxID_ANY, _L("Shape")); auto box = new wxStaticBox(this, wxID_ANY, _(L("Shape")));
auto sbsizer = new wxStaticBoxSizer(box, wxVERTICAL); auto sbsizer = new wxStaticBoxSizer(box, wxVERTICAL);
// shape options // shape options
m_shape_options_book = new wxChoicebook(this, wxID_ANY, wxDefaultPosition, wxSize(300, -1), wxCHB_TOP); m_shape_options_book = new wxChoicebook(this, wxID_ANY, wxDefaultPosition, wxSize(300, -1), wxCHB_TOP);
sbsizer->Add(m_shape_options_book); sbsizer->Add(m_shape_options_book);
auto optgroup = init_shape_options_page(_L("Rectangular")); auto optgroup = init_shape_options_page(_(L("Rectangular")));
ConfigOptionDef def; ConfigOptionDef def;
def.type = coPoints; def.type = coPoints;
def.default_value = new ConfigOptionPoints{ Pointf(200, 200) }; def.default_value = new ConfigOptionPoints{ Pointf(200, 200) };
def.label = _LU8("Size"); def.label = L("Size");
def.tooltip = _LU8("Size in X and Y of the rectangular plate."); def.tooltip = L("Size in X and Y of the rectangular plate.");
Option option(def, "rect_size"); Option option(def, "rect_size");
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
def.type = coPoints; def.type = coPoints;
def.default_value = new ConfigOptionPoints{ Pointf(0, 0) }; def.default_value = new ConfigOptionPoints{ Pointf(0, 0) };
def.label = _LU8("Origin"); def.label = L("Origin");
def.tooltip = _LU8("Distance of the 0,0 G-code coordinate from the front left corner of the rectangle."); def.tooltip = L("Distance of the 0,0 G-code coordinate from the front left corner of the rectangle.");
option = Option(def, "rect_origin"); option = Option(def, "rect_origin");
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
optgroup = init_shape_options_page(_L("Circular")); optgroup = init_shape_options_page(_(L("Circular")));
def.type = coFloat; def.type = coFloat;
def.default_value = new ConfigOptionFloat(200); def.default_value = new ConfigOptionFloat(200);
def.sidetext = _LU8("mm"); def.sidetext = L("mm");
def.label = _LU8("Diameter"); def.label = L("Diameter");
def.tooltip = _LU8("Diameter of the print bed. It is assumed that origin (0,0) is located in the center."); def.tooltip = L("Diameter of the print bed. It is assumed that origin (0,0) is located in the center.");
option = Option(def, "diameter"); option = Option(def, "diameter");
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
optgroup = init_shape_options_page(_L("Custom")); optgroup = init_shape_options_page(_(L("Custom")));
Line line{ "", "" }; Line line{ "", "" };
line.full_width = 1; line.full_width = 1;
line.widget = [this](wxWindow* parent) { line.widget = [this](wxWindow* parent) {
auto btn = new wxButton(parent, wxID_ANY, _L("Load shape from STL..."), wxDefaultPosition, wxDefaultSize); auto btn = new wxButton(parent, wxID_ANY, _(L("Load shape from STL...")), wxDefaultPosition, wxDefaultSize);
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn); sizer->Add(btn);
@ -117,7 +117,7 @@ ConfigOptionsGroupShp BedShapePanel::init_shape_options_page(wxString title){
auto panel = new wxPanel(m_shape_options_book); auto panel = new wxPanel(m_shape_options_book);
ConfigOptionsGroupShp optgroup; ConfigOptionsGroupShp optgroup;
optgroup = std::make_shared<ConfigOptionsGroup>(panel, _L("Settings")); optgroup = std::make_shared<ConfigOptionsGroup>(panel, _(L("Settings")));
optgroup->label_width = 100; optgroup->label_width = 100;
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
@ -295,8 +295,8 @@ void BedShapePanel::load_stl()
for (auto file_type: file_types) for (auto file_type: file_types)
MODEL_WILDCARD += vec_FILE_WILDCARDS.at(file_type) + "|"; MODEL_WILDCARD += vec_FILE_WILDCARDS.at(file_type) + "|";
auto dialog = new wxFileDialog(this, _L("Choose a file to import bed shape from (STL/OBJ/AMF/3MF/PRUSA):"), "", "", auto dialog = new wxFileDialog(this, _(L("Choose a file to import bed shape from (STL/OBJ/AMF/3MF/PRUSA):")), "", "",
MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (dialog->ShowModal() != wxID_OK) { if (dialog->ShowModal() != wxID_OK) {
dialog->Destroy(); dialog->Destroy();
return; return;
@ -312,7 +312,7 @@ void BedShapePanel::load_stl()
model = Model::read_from_file(file_name); model = Model::read_from_file(file_name);
} }
catch (std::exception &e) { catch (std::exception &e) {
auto msg = _L("Error! ") + file_name + " : " + e.what() + "."; auto msg = _(L("Error! ")) + file_name + " : " + e.what() + ".";
show_error(this, msg); show_error(this, msg);
exit(1); exit(1);
} }
@ -321,11 +321,11 @@ void BedShapePanel::load_stl()
auto expolygons = mesh.horizontal_projection(); auto expolygons = mesh.horizontal_projection();
if (expolygons.size() == 0) { if (expolygons.size() == 0) {
show_error(this, _L("The selected file contains no geometry.")); show_error(this, _(L("The selected file contains no geometry.")));
return; return;
} }
if (expolygons.size() > 1) { if (expolygons.size() > 1) {
show_error(this, _L("The selected file contains several disjoint areas. This is not supported.")); show_error(this, _(L("The selected file contains several disjoint areas. This is not supported.")));
return; return;
} }

View File

@ -39,7 +39,7 @@ class BedShapeDialog : public wxDialog
{ {
BedShapePanel* m_panel; BedShapePanel* m_panel;
public: public:
BedShapeDialog(wxWindow* parent) : wxDialog(parent, wxID_ANY, _L("Bed Shape"), BedShapeDialog(wxWindow* parent) : wxDialog(parent, wxID_ANY, _(L("Bed Shape")),
wxDefaultPosition, wxSize(350, 700), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER){} wxDefaultPosition, wxSize(350, 700), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER){}
~BedShapeDialog(){ } ~BedShapeDialog(){ }

View File

@ -10,6 +10,14 @@
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
wxString double_to_string(double const value)
{
int precision = 10 * value - int(10 * value) == 0 ? 1 : 2;
return value - int(value) == 0 ?
wxString::Format(_T("%i"), int(value)) :
wxNumberFormatter::ToString(value, precision, wxNumberFormatter::Style_None);
}
void Field::on_kill_focus(wxEvent& event) { void Field::on_kill_focus(wxEvent& event) {
// Without this, there will be nasty focus bugs on Windows. // Without this, there will be nasty focus bugs on Windows.
// Also, docs for wxEvent::Skip() say "In general, it is recommended to skip all // Also, docs for wxEvent::Skip() say "In general, it is recommended to skip all
@ -30,9 +38,9 @@ namespace Slic3r { namespace GUI {
wxString Field::get_tooltip_text(const wxString& default_string) wxString Field::get_tooltip_text(const wxString& default_string)
{ {
wxString tooltip_text(""); wxString tooltip_text("");
wxString tooltip = wxString::FromUTF8(m_opt.tooltip.c_str()); wxString tooltip = L_str(m_opt.tooltip);
if (tooltip.length() > 0) if (tooltip.length() > 0)
tooltip_text = tooltip + "(" + _L("default") + ": " + tooltip_text = tooltip + "(" + _(L("default")) + ": " +
(boost::iends_with(m_opt_id, "_gcode") ? "\n" : "") + (boost::iends_with(m_opt_id, "_gcode") ? "\n" : "") +
default_string + ")"; default_string + ")";
@ -45,7 +53,7 @@ namespace Slic3r { namespace GUI {
return std::regex_match(string, regex_pattern); return std::regex_match(string, regex_pattern);
} }
boost::any Field::get_value_by_opt_type(wxString str, ConfigOptionType type) boost::any Field::get_value_by_opt_type(wxString str)
{ {
boost::any ret_val; boost::any ret_val;
switch (m_opt.type){ switch (m_opt.type){
@ -56,23 +64,17 @@ namespace Slic3r { namespace GUI {
case coPercents: case coPercents:
case coFloats: case coFloats:
case coFloat:{ case coFloat:{
if (m_opt.type == coPercent) str.RemoveLast(); if (m_opt.type == coPercent && str.Last() == '%')
str.RemoveLast();
double val; double val;
str.ToCDouble(&val); str.ToCDouble(&val);
ret_val = val; ret_val = val;
break; } break; }
case coString: case coString:
case coStrings: case coStrings:
case coFloatOrPercent:
ret_val = str.ToStdString(); ret_val = str.ToStdString();
break; break;
case coFloatOrPercent:{
if (str.Last() == '%')
str.RemoveLast();
double val;
str.ToCDouble(&val);
ret_val = val;
break;
}
default: default:
break; break;
} }
@ -90,13 +92,9 @@ namespace Slic3r { namespace GUI {
switch (m_opt.type) { switch (m_opt.type) {
case coFloatOrPercent: case coFloatOrPercent:
{ {
if (static_cast<const ConfigOptionFloatOrPercent*>(m_opt.default_value)->percent) text_value = double_to_string(m_opt.default_value->getFloat());
{ if (static_cast<const ConfigOptionFloatOrPercent*>(m_opt.default_value)->percent)
text_value = wxString::Format(_T("%i"), int(m_opt.default_value->getFloat())); text_value += "%";
text_value += "%";
}
else
text_value = wxNumberFormatter::ToString(m_opt.default_value->getFloat(), 2);
break; break;
} }
case coPercent: case coPercent:
@ -106,29 +104,15 @@ namespace Slic3r { namespace GUI {
break; break;
} }
case coPercents: case coPercents:
{ case coFloats:
const ConfigOptionPercents *vec = static_cast<const ConfigOptionPercents*>(m_opt.default_value);
if (vec == nullptr || vec->empty()) break;
if (vec->size() > 1)
break;
double val = vec->get_at(0);
text_value = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None);
break;
}
case coFloat: case coFloat:
{ {
double val = m_opt.default_value->getFloat(); double val = m_opt.type == coFloats ?
text_value = (val - int(val)) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None); static_cast<const ConfigOptionFloats*>(m_opt.default_value)->get_at(0) :
break; m_opt.type == coFloat ?
} m_opt.default_value->getFloat() :
case coFloats: static_cast<const ConfigOptionPercents*>(m_opt.default_value)->get_at(0);
{ text_value = double_to_string(val);
const ConfigOptionFloats *vec = static_cast<const ConfigOptionFloats*>(m_opt.default_value);
if (vec == nullptr || vec->empty()) break;
if (vec->size() > 1)
break;
double val = vec->get_at(0);
text_value = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None);
break; break;
} }
case coString: case coString:
@ -174,7 +158,7 @@ namespace Slic3r { namespace GUI {
boost::any TextCtrl::get_value() boost::any TextCtrl::get_value()
{ {
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue(); wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
boost::any ret_val = get_value_by_opt_type(ret_str, m_opt.type); boost::any ret_val = get_value_by_opt_type(ret_str);
return ret_val; return ret_val;
} }
@ -303,7 +287,7 @@ void Choice::set_selection()
break; break;
++idx; ++idx;
} }
if (m_opt.type == coPercent) text_value += "%"; // if (m_opt.type == coPercent) text_value += "%";
idx == m_opt.enum_values.size() ? idx == m_opt.enum_values.size() ?
dynamic_cast<wxComboBox*>(window)->SetValue(text_value) : dynamic_cast<wxComboBox*>(window)->SetValue(text_value) :
dynamic_cast<wxComboBox*>(window)->SetSelection(idx); dynamic_cast<wxComboBox*>(window)->SetSelection(idx);
@ -387,7 +371,7 @@ void Choice::set_value(boost::any value)
break; break;
++idx; ++idx;
} }
if (m_opt.type == coPercent) text_value += "%"; // if (m_opt.type == coPercent) text_value += "%";
idx == m_opt.enum_values.size() ? idx == m_opt.enum_values.size() ?
dynamic_cast<wxComboBox*>(window)->SetValue(text_value) : dynamic_cast<wxComboBox*>(window)->SetValue(text_value) :
dynamic_cast<wxComboBox*>(window)->SetSelection(idx); dynamic_cast<wxComboBox*>(window)->SetSelection(idx);
@ -429,7 +413,7 @@ boost::any Choice::get_value()
wxString ret_str = static_cast<wxComboBox*>(window)->GetValue(); wxString ret_str = static_cast<wxComboBox*>(window)->GetValue();
if (m_opt.type != coEnum) if (m_opt.type != coEnum)
ret_val = get_value_by_opt_type(ret_str, m_opt.type); ret_val = get_value_by_opt_type(ret_str);
else else
{ {
int ret_enum = static_cast<wxComboBox*>(window)->GetSelection(); int ret_enum = static_cast<wxComboBox*>(window)->GetSelection();
@ -535,21 +519,29 @@ void PointCtrl::set_value(const Pointf value)
void PointCtrl::set_value(boost::any value) void PointCtrl::set_value(boost::any value)
{ {
Pointf pt; Pointf pt;
try Pointf *ptf = boost::any_cast<Pointf>(&value);
if (!ptf)
{ {
pt = boost::any_cast<ConfigOptionPoints*>(value)->values.at(0); ConfigOptionPoints* pts = boost::any_cast<ConfigOptionPoints*>(value);
pt = pts->values.at(0);
} }
catch (const std::exception &e) else
{ pt = *ptf;
try{ // try
pt = boost::any_cast<Pointf>(value); // {
} // pt = boost::any_cast<ConfigOptionPoints*>(value)->values.at(0);
catch (const std::exception &e) // }
{ // catch (const std::exception &e)
std::cerr << "Error! Can't cast PointCtrl value" << m_opt_id << "\n"; // {
return; // try{
} // pt = boost::any_cast<Pointf>(value);
} // }
// catch (const std::exception &e)
// {
// std::cerr << "Error! Can't cast PointCtrl value" << m_opt_id << "\n";
// return;
// }
// }
set_value(pt); set_value(pt);
} }

View File

@ -26,6 +26,8 @@ using t_field = std::unique_ptr<Field>;
using t_kill_focus = std::function<void()>; using t_kill_focus = std::function<void()>;
using t_change = std::function<void(t_config_option_key, boost::any)>; using t_change = std::function<void(t_config_option_key, boost::any)>;
wxString double_to_string(double const value);
class Field { class Field {
protected: protected:
// factory function to defer and enforce creation of derived type. // factory function to defer and enforce creation of derived type.
@ -83,7 +85,7 @@ public:
virtual wxWindow* getWindow() { return nullptr; } virtual wxWindow* getWindow() { return nullptr; }
bool is_matched(std::string string, std::string pattern); bool is_matched(std::string string, std::string pattern);
boost::any get_value_by_opt_type(wxString str, ConfigOptionType type); boost::any get_value_by_opt_type(wxString str);
/// Factory method for generating new derived classes. /// Factory method for generating new derived classes.
template<class T> template<class T>

View File

@ -28,7 +28,6 @@
#include <wx/app.h> #include <wx/app.h>
#include <wx/button.h> #include <wx/button.h>
#include <wx/config.h>
#include <wx/dir.h> #include <wx/dir.h>
#include <wx/filename.h> #include <wx/filename.h>
#include <wx/frame.h> #include <wx/frame.h>
@ -45,6 +44,7 @@
#include "TabIface.hpp" #include "TabIface.hpp"
#include "AppConfig.hpp" #include "AppConfig.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "Preferences.hpp"
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
@ -171,6 +171,7 @@ void break_to_debugger()
wxApp *g_wxApp = nullptr; wxApp *g_wxApp = nullptr;
wxFrame *g_wxMainFrame = nullptr; wxFrame *g_wxMainFrame = nullptr;
wxNotebook *g_wxTabPanel = nullptr; wxNotebook *g_wxTabPanel = nullptr;
AppConfig *g_AppConfig = nullptr;
std::vector<Tab *> g_tabs_list; std::vector<Tab *> g_tabs_list;
@ -191,6 +192,11 @@ void set_tab_panel(wxNotebook *tab_panel)
g_wxTabPanel = tab_panel; g_wxTabPanel = tab_panel;
} }
void set_app_config(AppConfig *app_config)
{
g_AppConfig = app_config;
}
std::vector<Tab *>& get_tabs_list() std::vector<Tab *>& get_tabs_list()
{ {
return g_tabs_list; return g_tabs_list;
@ -215,7 +221,7 @@ bool select_language(wxArrayString & names,
wxArrayLong & identifiers) wxArrayLong & identifiers)
{ {
wxCHECK_MSG(names.Count() == identifiers.Count(), false, wxCHECK_MSG(names.Count() == identifiers.Count(), false,
_L("Array of language names and identifiers should have the same size.")); _(L("Array of language names and identifiers should have the same size.")));
int init_selection = 0; int init_selection = 0;
long current_language = g_wxLocale ? g_wxLocale->GetLanguage() : wxLANGUAGE_UNKNOWN; long current_language = g_wxLocale ? g_wxLocale->GetLanguage() : wxLANGUAGE_UNKNOWN;
for (auto lang : identifiers){ for (auto lang : identifiers){
@ -226,7 +232,7 @@ bool select_language(wxArrayString & names,
} }
if (init_selection == identifiers.size()) if (init_selection == identifiers.size())
init_selection = 0; init_selection = 0;
long index = wxGetSingleChoiceIndex(_L("Select the language"), _L("Language"), long index = wxGetSingleChoiceIndex(_(L("Select the language")), _(L("Language")),
names, init_selection); names, init_selection);
if (index != -1) if (index != -1)
{ {
@ -241,13 +247,14 @@ bool select_language(wxArrayString & names,
bool load_language() bool load_language()
{ {
wxConfig config(g_wxApp->GetAppName());
long language; long language;
if (!config.Read(wxT("wxTranslation_Language"), if (!g_AppConfig->has("translation_language"))
&language, wxLANGUAGE_UNKNOWN))
{
language = wxLANGUAGE_UNKNOWN; language = wxLANGUAGE_UNKNOWN;
else {
auto str_language = g_AppConfig->get("translation_language");
language = str_language != "" ? stol(str_language) : wxLANGUAGE_UNKNOWN;
} }
if (language == wxLANGUAGE_UNKNOWN) if (language == wxLANGUAGE_UNKNOWN)
return false; return false;
wxArrayString names; wxArrayString names;
@ -269,13 +276,13 @@ bool load_language()
void save_language() void save_language()
{ {
wxConfig config(g_wxApp->GetAppName());
long language = wxLANGUAGE_UNKNOWN; long language = wxLANGUAGE_UNKNOWN;
if (g_wxLocale) { if (g_wxLocale) {
language = g_wxLocale->GetLanguage(); language = g_wxLocale->GetLanguage();
} }
config.Write(wxT("wxTranslation_Language"), language); std::string str_language = std::to_string(language);
config.Flush(); g_AppConfig->set("translation_language", str_language);
g_AppConfig->save();
} }
void get_installed_languages(wxArrayString & names, void get_installed_languages(wxArrayString & names,
@ -290,15 +297,12 @@ void get_installed_languages(wxArrayString & names,
wxString name = wxLocale::GetLanguageName(wxLANGUAGE_DEFAULT); wxString name = wxLocale::GetLanguageName(wxLANGUAGE_DEFAULT);
if (!name.IsEmpty()) if (!name.IsEmpty())
{ {
names.Add(_L("Default")); names.Add(_(L("Default")));
identifiers.Add(wxLANGUAGE_DEFAULT); identifiers.Add(wxLANGUAGE_DEFAULT);
} }
for (bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_DIRS); for (bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_DIRS);
cont; cont = dir.GetNext(&filename)) cont; cont = dir.GetNext(&filename))
{ {
wxLogTrace(wxTraceMask(),
"L10n: Directory found = \"%s\"",
filename.GetData());
langinfo = wxLocale::FindLanguageInfo(filename); langinfo = wxLocale::FindLanguageInfo(filename);
if (langinfo != NULL) if (langinfo != NULL)
{ {
@ -318,14 +322,14 @@ void add_debug_menu(wxMenuBar *menu, int event_language_change)
{ {
//#if 0 //#if 0
auto local_menu = new wxMenu(); auto local_menu = new wxMenu();
local_menu->Append(wxWindow::NewControlId(1), _L("Change Application Language")); local_menu->Append(wxWindow::NewControlId(1), _(L("Change Application Language")));
local_menu->Bind(wxEVT_MENU, [event_language_change](wxEvent&){ local_menu->Bind(wxEVT_MENU, [event_language_change](wxEvent&){
wxArrayString names; wxArrayString names;
wxArrayLong identifiers; wxArrayLong identifiers;
get_installed_languages(names, identifiers); get_installed_languages(names, identifiers);
if (select_language(names, identifiers)){ if (select_language(names, identifiers)){
save_language(); save_language();
show_info(g_wxTabPanel, "Application will be restarted", "Attention!"); show_info(g_wxTabPanel, _(L("Application will be restarted")), _(L("Attention!")));
if (event_language_change > 0) { if (event_language_change > 0) {
wxCommandEvent event(event_language_change); wxCommandEvent event(event_language_change);
g_wxApp->ProcessEvent(event); g_wxApp->ProcessEvent(event);
@ -336,15 +340,21 @@ void add_debug_menu(wxMenuBar *menu, int event_language_change)
//#endif //#endif
} }
void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config, void open_preferences_dialog(int event_preferences)
{
auto dlg = new PreferencesDialog(g_wxMainFrame, event_preferences);
dlg->ShowModal();
}
void create_preset_tabs(PresetBundle *preset_bundle,
bool no_controller, bool is_disabled_button_browse, bool is_user_agent, bool no_controller, bool is_disabled_button_browse, bool is_user_agent,
int event_value_change, int event_presets_changed, int event_value_change, int event_presets_changed,
int event_button_browse, int event_button_test) int event_button_browse, int event_button_test)
{ {
add_created_tab(new TabPrint (g_wxTabPanel, no_controller), preset_bundle, app_config); add_created_tab(new TabPrint (g_wxTabPanel, no_controller), preset_bundle);
add_created_tab(new TabFilament (g_wxTabPanel, no_controller), preset_bundle, app_config); add_created_tab(new TabFilament (g_wxTabPanel, no_controller), preset_bundle);
add_created_tab(new TabPrinter (g_wxTabPanel, no_controller, is_disabled_button_browse, is_user_agent), add_created_tab(new TabPrinter (g_wxTabPanel, no_controller, is_disabled_button_browse, is_user_agent),
preset_bundle, app_config); preset_bundle);
for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++ i) { for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++ i) {
Tab *tab = dynamic_cast<Tab*>(g_wxTabPanel->GetPage(i)); Tab *tab = dynamic_cast<Tab*>(g_wxTabPanel->GetPage(i));
if (! tab) if (! tab)
@ -378,8 +388,14 @@ void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, b
try{ try{
switch (config.def()->get(opt_key)->type){ switch (config.def()->get(opt_key)->type){
case coFloatOrPercent:{ case coFloatOrPercent:{
const auto &val = *config.option<ConfigOptionFloatOrPercent>(opt_key); std::string str = boost::any_cast<std::string>(value);
config.set_key_value(opt_key, new ConfigOptionFloatOrPercent(boost::any_cast<double>(value), val.percent)); bool percent = false;
if (str.back() == '%'){
str.pop_back();
percent = true;
}
double val = stod(str);
config.set_key_value(opt_key, new ConfigOptionFloatOrPercent(val, percent));
break;} break;}
case coPercent: case coPercent:
config.set_key_value(opt_key, new ConfigOptionPercent(boost::any_cast<double>(value))); config.set_key_value(opt_key, new ConfigOptionPercent(boost::any_cast<double>(value)));
@ -455,9 +471,9 @@ void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, b
} }
} }
void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_config) void add_created_tab(Tab* panel, PresetBundle *preset_bundle)
{ {
panel->m_show_btn_incompatible_presets = app_config->get("show_incompatible_presets").empty(); panel->m_show_btn_incompatible_presets = g_AppConfig->get("show_incompatible_presets").empty();
panel->create_preset_tab(preset_bundle); panel->create_preset_tab(preset_bundle);
// Load the currently selected preset into the GUI, update the preset selection box. // Load the currently selected preset into the GUI, update the preset selection box.
@ -466,15 +482,22 @@ void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_con
} }
void show_error(wxWindow* parent, wxString message){ void show_error(wxWindow* parent, wxString message){
auto msg_wingow = new wxMessageDialog(parent, message, _L("Error"), wxOK | wxICON_ERROR); auto msg_wingow = new wxMessageDialog(parent, message, _(L("Error")), wxOK | wxICON_ERROR);
msg_wingow->ShowModal(); msg_wingow->ShowModal();
} }
void show_info(wxWindow* parent, wxString message, wxString title){ void show_info(wxWindow* parent, wxString message, wxString title){
auto msg_wingow = new wxMessageDialog(parent, message, title.empty() ? _L("Notice") : title, wxOK | wxICON_INFORMATION); auto msg_wingow = new wxMessageDialog(parent, message, title.empty() ? _(L("Notice")) : title, wxOK | wxICON_INFORMATION);
msg_wingow->ShowModal(); msg_wingow->ShowModal();
} }
void warning_catcher(wxWindow* parent, wxString message){
if (message == _(L("GLUquadricObjPtr | Attempt to free unreferenced scalar")) )
return;
auto msg = new wxMessageDialog(parent, message, _(L("Warning")), wxOK | wxICON_WARNING);
msg->ShowModal();
}
wxApp* get_app(){ wxApp* get_app(){
return g_wxApp; return g_wxApp;
} }
@ -531,4 +554,20 @@ int combochecklist_get_flags(wxComboCtrl* comboCtrl)
return flags; return flags;
} }
AppConfig* get_app_config()
{
return g_AppConfig;
}
wxString L_str(std::string str)
{
//! Explicitly specify that the source string is already in UTF-8 encoding
return wxGetTranslation(wxString(str.c_str(), wxConvUTF8));
}
wxString from_u8(std::string str)
{
return wxString::FromUTF8(str.c_str());
}
} } } }

View File

@ -23,10 +23,16 @@ class AppConfig;
class DynamicPrintConfig; class DynamicPrintConfig;
class TabIface; class TabIface;
//! macro used to localization, return wxString // !!! If you needed to translate some wxString,
#define _L(s) wxGetTranslation(s) // !!! please use _(L(string))
//! macro used to localization, return const CharType * // !!! _() - is a standard wxWidgets macro to translate
#define _LU8(s) wxGetTranslation(s).ToUTF8().data() // !!! L() is used only for marking localizable string
// !!! It will be used in "xgettext" to create a Locating Message Catalog.
#define L(s) s
//! macro used to localization, return wxScopedCharBuffer
//! With wxConvUTF8 explicitly specify that the source string is already in UTF-8 encoding
#define _CHB(s) wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str()
namespace GUI { namespace GUI {
@ -59,22 +65,31 @@ void break_to_debugger();
void set_wxapp(wxApp *app); void set_wxapp(wxApp *app);
void set_main_frame(wxFrame *main_frame); void set_main_frame(wxFrame *main_frame);
void set_tab_panel(wxNotebook *tab_panel); void set_tab_panel(wxNotebook *tab_panel);
void set_app_config(AppConfig *app_config);
AppConfig* get_app_config();
wxApp* get_app();
void add_debug_menu(wxMenuBar *menu, int event_language_change); void add_debug_menu(wxMenuBar *menu, int event_language_change);
// Create "Preferences" dialog after selecting menu "Preferences" in Perl part
void open_preferences_dialog(int event_preferences);
// Create a new preset tab (print, filament and printer), // Create a new preset tab (print, filament and printer),
void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config, void create_preset_tabs(PresetBundle *preset_bundle,
bool no_controller, bool is_disabled_button_browse, bool is_user_agent, bool no_controller, bool is_disabled_button_browse, bool is_user_agent,
int event_value_change, int event_presets_changed, int event_value_change, int event_presets_changed,
int event_button_browse, int event_button_test); int event_button_browse, int event_button_test);
TabIface* get_preset_tab_iface(char *name); TabIface* get_preset_tab_iface(char *name);
// add it at the end of the tab panel. // add it at the end of the tab panel.
void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_config); void add_created_tab(Tab* panel, PresetBundle *preset_bundle);
// Change option value in config // Change option value in config
void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, boost::any value, int opt_index = 0); void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, boost::any value, int opt_index = 0);
void show_error(wxWindow* parent, wxString message); void show_error(wxWindow* parent, wxString message);
void show_info(wxWindow* parent, wxString message, wxString title); void show_info(wxWindow* parent, wxString message, wxString title);
void warning_catcher(wxWindow* parent, wxString message);
// load language saved at application config // load language saved at application config
bool load_language(); bool load_language();
@ -98,6 +113,11 @@ void create_combochecklist(wxComboCtrl* comboCtrl, std::string text, std::string
// encoded inside an int. // encoded inside an int.
int combochecklist_get_flags(wxComboCtrl* comboCtrl); int combochecklist_get_flags(wxComboCtrl* comboCtrl);
// Return translated std::string as a wxString
wxString L_str(std::string str);
// Return wxString from std::string in UTF8
wxString from_u8(std::string str);
} }
} }

View File

@ -2,7 +2,6 @@
#include "ConfigExceptions.hpp" #include "ConfigExceptions.hpp"
#include <utility> #include <utility>
#include <wx/tooltip.h>
#include <wx/numformatter.h> #include <wx/numformatter.h>
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
@ -122,13 +121,13 @@ void OptionsGroup::append_line(const Line& line) {
} }
// If there's a widget, build it and add the result to the sizer. // If there's a widget, build it and add the result to the sizer.
if (line.widget != nullptr) { if (line.widget != nullptr) {
auto wgt = line.widget(parent()); auto wgt = line.widget(parent());
grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, wxOSX ? 0 : 5); grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, wxOSX ? 0 : 5);
return; return;
} }
// if we have a single option with no sidetext just add it directly to the grid sizer // if we have a single option with no sidetext just add it directly to the grid sizer
if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 && if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 &&
option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) { option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) {
const auto& option = option_set.front(); const auto& option = option_set.front();
@ -152,7 +151,7 @@ void OptionsGroup::append_line(const Line& line) {
ConfigOptionDef option = opt.opt; ConfigOptionDef option = opt.opt;
// add label if any // add label if any
if (option.label != "") { if (option.label != "") {
auto field_label = new wxStaticText(parent(), wxID_ANY, wxString::FromUTF8(option.label.c_str()) + ":", wxDefaultPosition, wxDefaultSize); auto field_label = new wxStaticText(parent(), wxID_ANY, L_str(option.label) + ":", wxDefaultPosition, wxDefaultSize);
field_label->SetFont(label_font); field_label->SetFont(label_font);
sizer->Add(field_label, 0, wxALIGN_CENTER_VERTICAL, 0); sizer->Add(field_label, 0, wxALIGN_CENTER_VERTICAL, 0);
} }
@ -166,7 +165,7 @@ void OptionsGroup::append_line(const Line& line) {
// add sidetext if any // add sidetext if any
if (option.sidetext != "") { if (option.sidetext != "") {
auto sidetext = new wxStaticText(parent(), wxID_ANY, wxString::FromUTF8(option.sidetext.c_str()), wxDefaultPosition, wxDefaultSize); auto sidetext = new wxStaticText(parent(), wxID_ANY, L_str(option.sidetext), wxDefaultPosition, wxDefaultSize);
sidetext->SetFont(sidetext_font); sidetext->SetFont(sidetext_font);
sizer->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4); sizer->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4);
} }
@ -188,7 +187,7 @@ void OptionsGroup::append_line(const Line& line) {
} }
Line OptionsGroup::create_single_option_line(const Option& option) const { Line OptionsGroup::create_single_option_line(const Option& option) const {
Line retval{ wxString::FromUTF8(option.opt.label.c_str()), wxString::FromUTF8(option.opt.tooltip.c_str()) }; Line retval{ L_str(option.opt.label), L_str(option.opt.tooltip) };
Option tmp(option); Option tmp(option);
tmp.opt.label = std::string(""); tmp.opt.label = std::string("");
retval.append_option(tmp); retval.append_option(tmp);
@ -203,7 +202,7 @@ void OptionsGroup::on_change_OG(t_config_option_key id, /*config_value*/boost::a
Option ConfigOptionsGroup::get_option(const std::string opt_key, int opt_index /*= -1*/) Option ConfigOptionsGroup::get_option(const std::string opt_key, int opt_index /*= -1*/)
{ {
if (!m_config->has(opt_key)) { if (!m_config->has(opt_key)) {
//! exception ("No $opt_key in ConfigOptionsGroup config"); std::cerr << "No " << opt_key << " in ConfigOptionsGroup config.";
} }
std::string opt_id = opt_index == -1 ? opt_key : opt_key + "#" + std::to_string(opt_index); std::string opt_id = opt_index == -1 ? opt_key : opt_key + "#" + std::to_string(opt_index);
@ -287,14 +286,6 @@ boost::any ConfigOptionsGroup::config_value(std::string opt_key, int opt_index,
} }
} }
wxString double_to_string(double const value)
{
int precision = 10 * value - int(10 * value) == 0 ? 1 : 2;
return value - int(value) == 0 ?
wxString::Format(_T("%i"), int(value)) :
wxNumberFormatter::ToString(value, precision, wxNumberFormatter::Style_None);
}
boost::any ConfigOptionsGroup::get_config_value(DynamicPrintConfig& config, std::string opt_key, int opt_index/* = -1*/) boost::any ConfigOptionsGroup::get_config_value(DynamicPrintConfig& config, std::string opt_key, int opt_index/* = -1*/)
{ {
size_t idx = opt_index == -1 ? 0 : opt_index; size_t idx = opt_index == -1 ? 0 : opt_index;
@ -325,9 +316,9 @@ boost::any ConfigOptionsGroup::get_config_value(DynamicPrintConfig& config, std:
case coFloats: case coFloats:
case coFloat:{ case coFloat:{
double val = opt->type == coFloats ? double val = opt->type == coFloats ?
config.opt_float(opt_key, idx/*0opt_index*/) : config.opt_float(opt_key, idx) :
opt->type == coFloat ? config.opt_float(opt_key) : opt->type == coFloat ? config.opt_float(opt_key) :
config.option<ConfigOptionPercents>(opt_key)->values.at(idx/*0*/); config.option<ConfigOptionPercents>(opt_key)->values.at(idx);
ret = double_to_string(val); ret = double_to_string(val);
} }
break; break;
@ -338,19 +329,19 @@ boost::any ConfigOptionsGroup::get_config_value(DynamicPrintConfig& config, std:
if (config.option<ConfigOptionStrings>(opt_key)->values.empty()) if (config.option<ConfigOptionStrings>(opt_key)->values.empty())
ret = text_value; ret = text_value;
else else
ret = static_cast<wxString>(config.opt_string(opt_key, static_cast<unsigned int>(idx/*0*/)/*opt_index*/)); ret = static_cast<wxString>(config.opt_string(opt_key, static_cast<unsigned int>(idx)));
break; break;
case coBool: case coBool:
ret = config.opt_bool(opt_key); ret = config.opt_bool(opt_key);
break; break;
case coBools: case coBools:
ret = config.opt_bool(opt_key, idx/*0opt_index*/); ret = config.opt_bool(opt_key, idx);
break; break;
case coInt: case coInt:
ret = config.opt_int(opt_key); ret = config.opt_int(opt_key);
break; break;
case coInts: case coInts:
ret = config.opt_int(opt_key, idx/*0/*opt_index*/); ret = config.opt_int(opt_key, idx);
break; break;
case coEnum:{ case coEnum:{
if (opt_key.compare("external_fill_pattern") == 0 || if (opt_key.compare("external_fill_pattern") == 0 ||
@ -369,7 +360,7 @@ boost::any ConfigOptionsGroup::get_config_value(DynamicPrintConfig& config, std:
break; break;
case coPoints:{ case coPoints:{
const auto &value = *config.option<ConfigOptionPoints>(opt_key); const auto &value = *config.option<ConfigOptionPoints>(opt_key);
ret = value.values.at(idx/*0*/); ret = value.values.at(idx);
} }
break; break;
case coNone: case coNone:
@ -397,14 +388,5 @@ void ogStaticText::SetText(wxString value)
GetParent()->Layout(); GetParent()->Layout();
} }
void Option::translate()
{
opt.label = _LU8(opt.label);
opt.tooltip = _LU8(opt.tooltip);
opt.sidetext = _LU8(opt.sidetext);
opt.full_label = _LU8(opt.full_label);
opt.category = _LU8(opt.category);
}
} // GUI } // GUI
} // Slic3r } // Slic3r

View File

@ -35,8 +35,7 @@ struct Option {
bool readonly {false}; bool readonly {false};
Option(const ConfigOptionDef& _opt, t_config_option_key id) : Option(const ConfigOptionDef& _opt, t_config_option_key id) :
opt(_opt), opt_id(id) { translate(); } opt(_opt), opt_id(id) {}
void translate();
}; };
using t_option = std::unique_ptr<Option>; //! using t_option = std::unique_ptr<Option>; //!
@ -90,9 +89,22 @@ public:
void append_single_option_line(const Option& option) { append_line(create_single_option_line(option)); } void append_single_option_line(const Option& option) { append_line(create_single_option_line(option)); }
// return a non-owning pointer reference // return a non-owning pointer reference
inline /*const*/ Field* get_field(t_config_option_key id) const { try { return m_fields.at(id).get(); } catch (std::out_of_range e) { return nullptr; } } inline Field* get_field(t_config_option_key id) const{
bool set_value(t_config_option_key id, boost::any value) { try { m_fields.at(id)->set_value(value); return true; } catch (std::out_of_range e) { return false; } } if (m_fields.find(id) == m_fields.end()) return nullptr;
boost::any get_value(t_config_option_key id) { boost::any out; try { out = m_fields.at(id)->get_value(); } catch (std::out_of_range e) { ; } return out; } return m_fields.at(id).get();
}
bool set_value(t_config_option_key id, boost::any value) {
if (m_fields.find(id) == m_fields.end()) return false;
m_fields.at(id)->set_value(value);
return true;
}
boost::any get_value(t_config_option_key id) {
boost::any out;
if (m_fields.find(id) == m_fields.end()) ;
else
out = m_fields.at(id)->get_value();
return out;
}
inline void enable() { for (auto& field : m_fields) field.second->enable(); } inline void enable() { for (auto& field : m_fields) field.second->enable(); }
inline void disable() { for (auto& field : m_fields) field.second->disable(); } inline void disable() { for (auto& field : m_fields) field.second->disable(); }

View File

@ -0,0 +1,120 @@
#include "Preferences.hpp"
#include "AppConfig.hpp"
#include "OptionsGroup.hpp"
namespace Slic3r {
namespace GUI {
void PreferencesDialog::build()
{
auto app_config = get_app_config();
m_optgroup = std::make_shared<ConfigOptionsGroup>(this, _(L("General")));
m_optgroup->label_width = 200;
m_optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
m_values[opt_key] = boost::any_cast<bool>(value) ? "1" : "0";
};
// $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
// opt_id = > 'version_check',
// type = > 'bool',
// label = > 'Check for updates',
// tooltip = > 'If this is enabled, Slic3r will check for updates daily and display a reminder if a newer version is available.',
// default = > $app_config->get("version_check") // 1,
// readonly = > !wxTheApp->have_version_check,
// ));
ConfigOptionDef def;
def.label = L("Remember output directory");
def.type = coBool;
def.tooltip = L("If this is enabled, Slic3r will prompt the last output directory "
"instead of the one containing the input files.");
def.default_value = new ConfigOptionBool{ app_config->get("remember_output_path")[0] == '1' }; // 1;
Option option(def, "remember_output_path");
m_optgroup->append_single_option_line(option);
def.label = L("Auto-center parts");
def.type = coBool;
def.tooltip = L("If this is enabled, Slic3r will auto-center objects "
"around the print bed center.");
def.default_value = new ConfigOptionBool{ app_config->get("autocenter")[0] == '1' }; // 1;
option = Option (def,"autocenter");
m_optgroup->append_single_option_line(option);
def.label = L("Background processing");
def.type = coBool;
def.tooltip = L("If this is enabled, Slic3r will pre-process objects as soon "
"as they\'re loaded in order to save time when exporting G-code.");
def.default_value = new ConfigOptionBool{ app_config->get("background_processing")[0] == '1' }; // 1;
option = Option (def,"background_processing");
m_optgroup->append_single_option_line(option);
def.label = L("Disable USB/serial connection");
def.type = coBool;
def.tooltip = L("Disable communication with the printer over a serial / USB cable. "
"This simplifies the user interface in case the printer is never attached to the computer.");
def.default_value = new ConfigOptionBool{ app_config->get("no_controller")[0] == '1' }; // 1;
option = Option (def,"no_controller");
m_optgroup->append_single_option_line(option);
def.label = L("Suppress \" - default - \" presets");
def.type = coBool;
def.tooltip = L("Suppress \" - default - \" presets in the Print / Filament / Printer "
"selections once there are any other valid presets available.");
def.default_value = new ConfigOptionBool{ app_config->get("no_defaults")[0] == '1' }; // 1;
option = Option (def,"no_defaults");
m_optgroup->append_single_option_line(option);
def.label = L("Show incompatible print and filament presets");
def.type = coBool;
def.tooltip = L("When checked, the print and filament presets are shown in the preset editor "
"even if they are marked as incompatible with the active printer");
def.default_value = new ConfigOptionBool{ app_config->get("show_incompatible_presets")[0] == '1' }; // 1;
option = Option (def,"show_incompatible_presets");
m_optgroup->append_single_option_line(option);
def.label = L("Use legacy OpenGL 1.1 rendering");
def.type = coBool;
def.tooltip = L("If you have rendering issues caused by a buggy OpenGL 2.0 driver, "
"you may try to check this checkbox. This will disable the layer height "
"editing and anti aliasing, so it is likely better to upgrade your graphics driver.");
def.default_value = new ConfigOptionBool{ app_config->get("use_legacy_opengl")[0] == '1' }; // 1;
option = Option (def,"use_legacy_opengl");
m_optgroup->append_single_option_line(option);
auto sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(m_optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
wxButton* btn = static_cast<wxButton*>(FindWindowById(wxID_OK, this));
btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { accept(); });
sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10);
SetSizer(sizer);
sizer->SetSizeHints(this);
}
void PreferencesDialog::accept()
{
if (m_values.find("no_controller") != m_values.end()||
m_values.find("no_defaults") != m_values.end()||
m_values.find("use_legacy_opengl")!= m_values.end()) {
warning_catcher(this, _(L("You need to restart Slic3r to make the changes effective.")));
}
auto app_config = get_app_config();
for (std::map<std::string, std::string>::iterator it = m_values.begin(); it != m_values.end(); ++it) {
app_config->set(it->first, it->second);
}
EndModal(wxID_OK);
Close(); // needed on Linux
// Nothify the UI to update itself from the ini file.
if (m_event_preferences > 0) {
wxCommandEvent event(m_event_preferences);
get_app()->ProcessEvent(event);
}
}
} // GUI
} // Slic3r

View File

@ -0,0 +1,27 @@
#include "GUI.hpp"
#include <wx/dialog.h>
#include <map>
namespace Slic3r {
namespace GUI {
class ConfigOptionsGroup;
class PreferencesDialog : public wxDialog
{
std::map<std::string, std::string> m_values;
std::shared_ptr<ConfigOptionsGroup> m_optgroup;
int m_event_preferences;
public:
PreferencesDialog(wxWindow* parent, int event_preferences) : wxDialog(parent, wxID_ANY, _(L("Preferences")),
wxDefaultPosition, wxDefaultSize), m_event_preferences(event_preferences) { build(); }
~PreferencesDialog(){ }
void build();
void accept();
};
} // GUI
} // Slic3r

View File

@ -6,8 +6,10 @@
#include "Flow.hpp" #include "Flow.hpp"
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <wx/intl.h>
#include "../../libslic3r/libslic3r.h" #include "../../libslic3r/libslic3r.h"
#include "GUI.hpp"
namespace Slic3r { namespace Slic3r {
@ -21,31 +23,31 @@ std::string PresetHints::cooling_description(const Preset &preset)
int max_fan_speed = preset.config.opt_int("max_fan_speed", 0); int max_fan_speed = preset.config.opt_int("max_fan_speed", 0);
int min_print_speed = int(preset.config.opt_float("min_print_speed", 0) + 0.5); int min_print_speed = int(preset.config.opt_float("min_print_speed", 0) + 0.5);
int fan_below_layer_time = preset.config.opt_int("fan_below_layer_time", 0); int fan_below_layer_time = preset.config.opt_int("fan_below_layer_time", 0);
sprintf(buf, "If estimated layer time is below ~%ds, fan will run at %d%% and print speed will be reduced so that no less than %ds are spent on that layer (however, speed will never be reduced below %dmm/s).", sprintf(buf, _CHB(L("If estimated layer time is below ~%ds, fan will run at %d%% and print speed will be reduced so that no less than %ds are spent on that layer (however, speed will never be reduced below %dmm/s).")),
slowdown_below_layer_time, max_fan_speed, slowdown_below_layer_time, min_print_speed); slowdown_below_layer_time, max_fan_speed, slowdown_below_layer_time, min_print_speed);
out += buf; out += buf;
if (fan_below_layer_time > slowdown_below_layer_time) { if (fan_below_layer_time > slowdown_below_layer_time) {
sprintf(buf, "\nIf estimated layer time is greater, but still below ~%ds, fan will run at a proportionally decreasing speed between %d%% and %d%%.", sprintf(buf, _CHB(L("\nIf estimated layer time is greater, but still below ~%ds, fan will run at a proportionally decreasing speed between %d%% and %d%%.")),
fan_below_layer_time, max_fan_speed, min_fan_speed); fan_below_layer_time, max_fan_speed, min_fan_speed);
out += buf; out += buf;
} }
out += "\nDuring the other layers, fan "; out += _CHB(L("\nDuring the other layers, fan "));
} else { } else {
out = "Fan "; out = _CHB(L("Fan "));
} }
if (preset.config.opt_bool("fan_always_on", 0)) { if (preset.config.opt_bool("fan_always_on", 0)) {
int disable_fan_first_layers = preset.config.opt_int("disable_fan_first_layers", 0); int disable_fan_first_layers = preset.config.opt_int("disable_fan_first_layers", 0);
int min_fan_speed = preset.config.opt_int("min_fan_speed", 0); int min_fan_speed = preset.config.opt_int("min_fan_speed", 0);
sprintf(buf, "will always run at %d%% ", min_fan_speed); sprintf(buf, _CHB(L("will always run at %d%% ")), min_fan_speed);
out += buf; out += buf;
if (disable_fan_first_layers > 1) { if (disable_fan_first_layers > 1) {
sprintf(buf, "except for the first %d layers", disable_fan_first_layers); sprintf(buf, _CHB(L("except for the first %d layers")), disable_fan_first_layers);
out += buf; out += buf;
} }
else if (disable_fan_first_layers == 1) else if (disable_fan_first_layers == 1)
out += "except for the first layer"; out += _CHB(L("except for the first layer"));
} else } else
out += "will be turned off."; out += _CHB(L("will be turned off."));
return out; return out;
} }
@ -146,7 +148,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle
limit_by_first_layer_speed(std::max(external_perimeter_speed, small_perimeter_speed), max_print_speed)); limit_by_first_layer_speed(std::max(external_perimeter_speed, small_perimeter_speed), max_print_speed));
if (max_flow < external_perimeter_rate) { if (max_flow < external_perimeter_rate) {
max_flow = external_perimeter_rate; max_flow = external_perimeter_rate;
max_flow_extrusion_type = "external perimeters"; max_flow_extrusion_type = _CHB(L("external perimeters"));
} }
double perimeter_rate = Flow::new_from_config_width(frPerimeter, double perimeter_rate = Flow::new_from_config_width(frPerimeter,
first_positive(first_layer_extrusion_width_ptr, perimeter_extrusion_width, extrusion_width), first_positive(first_layer_extrusion_width_ptr, perimeter_extrusion_width, extrusion_width),
@ -155,7 +157,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle
limit_by_first_layer_speed(std::max(perimeter_speed, small_perimeter_speed), max_print_speed)); limit_by_first_layer_speed(std::max(perimeter_speed, small_perimeter_speed), max_print_speed));
if (max_flow < perimeter_rate) { if (max_flow < perimeter_rate) {
max_flow = perimeter_rate; max_flow = perimeter_rate;
max_flow_extrusion_type = "perimeters"; max_flow_extrusion_type = _CHB(L("perimeters"));
} }
} }
if (! bridging && infill_extruder_active) { if (! bridging && infill_extruder_active) {
@ -164,7 +166,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle
nozzle_diameter, lh, bfr).mm3_per_mm() * limit_by_first_layer_speed(infill_speed, max_print_speed); nozzle_diameter, lh, bfr).mm3_per_mm() * limit_by_first_layer_speed(infill_speed, max_print_speed);
if (max_flow < infill_rate) { if (max_flow < infill_rate) {
max_flow = infill_rate; max_flow = infill_rate;
max_flow_extrusion_type = "infill"; max_flow_extrusion_type = _CHB(L("infill"));
} }
} }
if (solid_infill_extruder_active) { if (solid_infill_extruder_active) {
@ -174,7 +176,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle
(bridging ? bridge_speed : limit_by_first_layer_speed(solid_infill_speed, max_print_speed)); (bridging ? bridge_speed : limit_by_first_layer_speed(solid_infill_speed, max_print_speed));
if (max_flow < solid_infill_rate) { if (max_flow < solid_infill_rate) {
max_flow = solid_infill_rate; max_flow = solid_infill_rate;
max_flow_extrusion_type = "solid infill"; max_flow_extrusion_type = _CHB(L("solid infill"));
} }
if (! bridging) { if (! bridging) {
double top_solid_infill_rate = Flow::new_from_config_width(frInfill, double top_solid_infill_rate = Flow::new_from_config_width(frInfill,
@ -182,7 +184,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle
nozzle_diameter, lh, bfr).mm3_per_mm() * limit_by_first_layer_speed(top_solid_infill_speed, max_print_speed); nozzle_diameter, lh, bfr).mm3_per_mm() * limit_by_first_layer_speed(top_solid_infill_speed, max_print_speed);
if (max_flow < top_solid_infill_rate) { if (max_flow < top_solid_infill_rate) {
max_flow = top_solid_infill_rate; max_flow = top_solid_infill_rate;
max_flow_extrusion_type = "top solid infill"; max_flow_extrusion_type = _CHB(L("top solid infill"));
} }
} }
} }
@ -193,7 +195,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle
(bridging ? bridge_speed : limit_by_first_layer_speed(support_material_speed, max_print_speed)); (bridging ? bridge_speed : limit_by_first_layer_speed(support_material_speed, max_print_speed));
if (max_flow < support_material_rate) { if (max_flow < support_material_rate) {
max_flow = support_material_rate; max_flow = support_material_rate;
max_flow_extrusion_type = "support"; max_flow_extrusion_type = _CHB(L("support"));
} }
} }
if (support_material_interface_extruder_active) { if (support_material_interface_extruder_active) {
@ -203,25 +205,25 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle
(bridging ? bridge_speed : limit_by_first_layer_speed(support_material_interface_speed, max_print_speed)); (bridging ? bridge_speed : limit_by_first_layer_speed(support_material_interface_speed, max_print_speed));
if (max_flow < support_material_interface_rate) { if (max_flow < support_material_interface_rate) {
max_flow = support_material_interface_rate; max_flow = support_material_interface_rate;
max_flow_extrusion_type = "support interface"; max_flow_extrusion_type = _CHB(L("support interface"));
} }
} }
//FIXME handle gap_fill_speed //FIXME handle gap_fill_speed
if (! out.empty()) if (! out.empty())
out += "\n"; out += "\n";
out += (first_layer ? "First layer volumetric" : (bridging ? "Bridging volumetric" : "Volumetric")); out += (first_layer ? _CHB(L("First layer volumetric")) : (bridging ? _CHB(L("Bridging volumetric")) : _CHB(L("Volumetric"))));
out += " flow rate is maximized "; out += _CHB(L(" flow rate is maximized "));
bool limited_by_max_volumetric_speed = max_volumetric_speed > 0 && max_volumetric_speed < max_flow; bool limited_by_max_volumetric_speed = max_volumetric_speed > 0 && max_volumetric_speed < max_flow;
out += (limited_by_max_volumetric_speed ? out += (limited_by_max_volumetric_speed ?
"by the print profile maximum" : _CHB(L("by the print profile maximum")) :
("when printing " + max_flow_extrusion_type)) (_CHB(L("when printing ")) + max_flow_extrusion_type))
+ " with a volumetric rate "; + _CHB(L(" with a volumetric rate "));
if (limited_by_max_volumetric_speed) if (limited_by_max_volumetric_speed)
max_flow = max_volumetric_speed; max_flow = max_volumetric_speed;
char buf[2048]; char buf[2048];
sprintf(buf, "%3.2f mm³/s", max_flow); sprintf(buf, _CHB(L("%3.2f mm³/s")), max_flow);
out += buf; out += buf;
sprintf(buf, " at filament speed %3.2f mm/s.", max_flow / filament_crossection); sprintf(buf, _CHB(L(" at filament speed %3.2f mm/s.")), max_flow / filament_crossection);
out += buf; out += buf;
} }
@ -238,8 +240,11 @@ std::string PresetHints::recommended_thin_wall_thickness(const PresetBundle &pre
bool thin_walls = print_config.opt_bool("thin_walls"); bool thin_walls = print_config.opt_bool("thin_walls");
float nozzle_diameter = float(printer_config.opt_float("nozzle_diameter", 0)); float nozzle_diameter = float(printer_config.opt_float("nozzle_diameter", 0));
if (layer_height <= 0.f) std::string out;
return "Recommended object thin wall thickness: Not available due to invalid layer height."; if (layer_height <= 0.f){
out += _CHB(L("Recommended object thin wall thickness: Not available due to invalid layer height."));
return out;
}
Flow external_perimeter_flow = Flow::new_from_config_width( Flow external_perimeter_flow = Flow::new_from_config_width(
frExternalPerimeter, frExternalPerimeter,
@ -250,18 +255,18 @@ std::string PresetHints::recommended_thin_wall_thickness(const PresetBundle &pre
*print_config.opt<ConfigOptionFloatOrPercent>("perimeter_extrusion_width"), *print_config.opt<ConfigOptionFloatOrPercent>("perimeter_extrusion_width"),
nozzle_diameter, layer_height, false); nozzle_diameter, layer_height, false);
std::string out;
if (num_perimeters > 0) { if (num_perimeters > 0) {
int num_lines = std::min(num_perimeters * 2, 10); int num_lines = std::min(num_perimeters * 2, 10);
char buf[256]; char buf[256];
sprintf(buf, "Recommended object thin wall thickness for layer height %.2f and ", layer_height); sprintf(buf, _CHB(L("Recommended object thin wall thickness for layer height %.2f and ")), layer_height);
out += buf; out += buf;
// Start with the width of two closely spaced // Start with the width of two closely spaced
double width = external_perimeter_flow.width + external_perimeter_flow.spacing(); double width = external_perimeter_flow.width + external_perimeter_flow.spacing();
for (int i = 2; i <= num_lines; thin_walls ? ++ i : i += 2) { for (int i = 2; i <= num_lines; thin_walls ? ++ i : i += 2) {
if (i > 2) if (i > 2)
out += ", "; out += ", ";
sprintf(buf, "%d lines: %.2lf mm", i, width); sprintf(buf, _CHB(L("%d lines: %.2lf mm")), i, width);
out += buf; out += buf;
width += perimeter_flow.spacing() * (thin_walls ? 1.f : 2.f); width += perimeter_flow.spacing() * (thin_walls ? 1.f : 2.f);
} }

View File

@ -33,22 +33,22 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
// preset chooser // preset chooser
m_presets_choice = new wxBitmapComboBox(panel, wxID_ANY, "", wxDefaultPosition, wxSize(270, -1), 0, 0,wxCB_READONLY); m_presets_choice = new wxBitmapComboBox(panel, wxID_ANY, "", wxDefaultPosition, wxSize(270, -1), 0, 0,wxCB_READONLY);
const wxBitmap* bmp = new wxBitmap(wxString::FromUTF8(Slic3r::var("flag-green-icon.png").c_str()), wxBITMAP_TYPE_PNG); const wxBitmap* bmp = new wxBitmap(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG);
//buttons //buttons
wxBitmap bmpMenu; wxBitmap bmpMenu;
bmpMenu = wxBitmap(wxString::FromUTF8(Slic3r::var("disk.png").c_str()), wxBITMAP_TYPE_PNG); bmpMenu = wxBitmap(from_u8(Slic3r::var("disk.png")), wxBITMAP_TYPE_PNG);
m_btn_save_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); m_btn_save_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
bmpMenu = wxBitmap(wxString::FromUTF8(Slic3r::var("delete.png").c_str()), wxBITMAP_TYPE_PNG); bmpMenu = wxBitmap(from_u8(Slic3r::var("delete.png")), wxBITMAP_TYPE_PNG);
m_btn_delete_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); m_btn_delete_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
m_show_incompatible_presets = false; m_show_incompatible_presets = false;
m_bmp_show_incompatible_presets = new wxBitmap(wxString::FromUTF8(Slic3r::var("flag-red-icon.png").c_str()), wxBITMAP_TYPE_PNG); m_bmp_show_incompatible_presets = new wxBitmap(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG);
m_bmp_hide_incompatible_presets = new wxBitmap(wxString::FromUTF8(Slic3r::var("flag-green-icon.png").c_str()), wxBITMAP_TYPE_PNG); m_bmp_hide_incompatible_presets = new wxBitmap(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG);
m_btn_hide_incompatible_presets = new wxBitmapButton(panel, wxID_ANY, *m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); m_btn_hide_incompatible_presets = new wxBitmapButton(panel, wxID_ANY, *m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
m_btn_save_preset->SetToolTip(_L("Save current ") + m_title); m_btn_save_preset->SetToolTip(_(L("Save current ")) + m_title);
m_btn_delete_preset->SetToolTip(_L("Delete this preset")); m_btn_delete_preset->SetToolTip(_(L("Delete this preset")));
m_btn_delete_preset->Disable(); m_btn_delete_preset->Disable();
m_hsizer = new wxBoxSizer(wxHORIZONTAL); m_hsizer = new wxBoxSizer(wxHORIZONTAL);
@ -113,11 +113,11 @@ PageShp Tab::add_options_page(wxString title, std::string icon, bool is_extruder
// Index of icon in an icon list $self->{icons}. // Index of icon in an icon list $self->{icons}.
auto icon_idx = 0; auto icon_idx = 0;
if (!icon.empty()) { if (!icon.empty()) {
try { icon_idx = m_icon_index.at(icon);} if (m_icon_index.find(icon) == m_icon_index.end())
catch (std::out_of_range e) { icon_idx = -1; } icon_idx = -1;
if (icon_idx == -1) { if (icon_idx == -1) {
// Add a new icon to the icon list. // Add a new icon to the icon list.
const auto img_icon = new wxIcon(wxString::FromUTF8(Slic3r::var(icon).c_str()), wxBITMAP_TYPE_PNG); const auto img_icon = new wxIcon(from_u8(Slic3r::var(icon)), wxBITMAP_TYPE_PNG);
m_icons->Add(*img_icon); m_icons->Add(*img_icon);
icon_idx = ++m_icon_count; icon_idx = ++m_icon_count;
m_icon_index[icon] = icon_idx; m_icon_index[icon] = icon_idx;
@ -311,12 +311,12 @@ void TabPrint::build()
m_presets = &m_preset_bundle->prints; m_presets = &m_preset_bundle->prints;
m_config = &m_presets->get_edited_preset().config; m_config = &m_presets->get_edited_preset().config;
auto page = add_options_page(_L("Layers and perimeters"), "layers.png"); auto page = add_options_page(_(L("Layers and perimeters")), "layers.png");
auto optgroup = page->new_optgroup(_L("Layer height")); auto optgroup = page->new_optgroup(_(L("Layer height")));
optgroup->append_single_option_line("layer_height"); optgroup->append_single_option_line("layer_height");
optgroup->append_single_option_line("first_layer_height"); optgroup->append_single_option_line("first_layer_height");
optgroup = page->new_optgroup(_L("Vertical shells")); optgroup = page->new_optgroup(_(L("Vertical shells")));
optgroup->append_single_option_line("perimeters"); optgroup->append_single_option_line("perimeters");
optgroup->append_single_option_line("spiral_vase"); optgroup->append_single_option_line("spiral_vase");
@ -327,34 +327,34 @@ void TabPrint::build()
}; };
optgroup->append_line(line); optgroup->append_line(line);
optgroup = page->new_optgroup(_L("Horizontal shells")); optgroup = page->new_optgroup(_(L("Horizontal shells")));
line = { _L("Solid layers"), "" }; line = { _(L("Solid layers")), "" };
line.append_option(optgroup->get_option("top_solid_layers")); line.append_option(optgroup->get_option("top_solid_layers"));
line.append_option(optgroup->get_option("bottom_solid_layers")); line.append_option(optgroup->get_option("bottom_solid_layers"));
optgroup->append_line(line); optgroup->append_line(line);
optgroup = page->new_optgroup(_L("Quality (slower slicing)")); optgroup = page->new_optgroup(_(L("Quality (slower slicing)")));
optgroup->append_single_option_line("extra_perimeters"); optgroup->append_single_option_line("extra_perimeters");
optgroup->append_single_option_line("ensure_vertical_shell_thickness"); optgroup->append_single_option_line("ensure_vertical_shell_thickness");
optgroup->append_single_option_line("avoid_crossing_perimeters"); optgroup->append_single_option_line("avoid_crossing_perimeters");
optgroup->append_single_option_line("thin_walls"); optgroup->append_single_option_line("thin_walls");
optgroup->append_single_option_line("overhangs"); optgroup->append_single_option_line("overhangs");
optgroup = page->new_optgroup(_L("Advanced")); optgroup = page->new_optgroup(_(L("Advanced")));
optgroup->append_single_option_line("seam_position"); optgroup->append_single_option_line("seam_position");
optgroup->append_single_option_line("external_perimeters_first"); optgroup->append_single_option_line("external_perimeters_first");
page = add_options_page(_L("Infill"), "infill.png"); page = add_options_page(_(L("Infill")), "infill.png");
optgroup = page->new_optgroup(_L("Infill")); optgroup = page->new_optgroup(_(L("Infill")));
optgroup->append_single_option_line("fill_density"); optgroup->append_single_option_line("fill_density");
optgroup->append_single_option_line("fill_pattern"); optgroup->append_single_option_line("fill_pattern");
optgroup->append_single_option_line("external_fill_pattern"); optgroup->append_single_option_line("external_fill_pattern");
optgroup = page->new_optgroup(_L("Reducing printing time")); optgroup = page->new_optgroup(_(L("Reducing printing time")));
optgroup->append_single_option_line("infill_every_layers"); optgroup->append_single_option_line("infill_every_layers");
optgroup->append_single_option_line("infill_only_where_needed"); optgroup->append_single_option_line("infill_only_where_needed");
optgroup = page->new_optgroup(_L("Advanced")); optgroup = page->new_optgroup(_(L("Advanced")));
optgroup->append_single_option_line("solid_infill_every_layers"); optgroup->append_single_option_line("solid_infill_every_layers");
optgroup->append_single_option_line("fill_angle"); optgroup->append_single_option_line("fill_angle");
optgroup->append_single_option_line("solid_infill_below_area"); optgroup->append_single_option_line("solid_infill_below_area");
@ -362,27 +362,27 @@ void TabPrint::build()
optgroup->append_single_option_line("only_retract_when_crossing_perimeters"); optgroup->append_single_option_line("only_retract_when_crossing_perimeters");
optgroup->append_single_option_line("infill_first"); optgroup->append_single_option_line("infill_first");
page = add_options_page(_L("Skirt and brim"), "box.png"); page = add_options_page(_(L("Skirt and brim")), "box.png");
optgroup = page->new_optgroup(_L("Skirt")); optgroup = page->new_optgroup(_(L("Skirt")));
optgroup->append_single_option_line("skirts"); optgroup->append_single_option_line("skirts");
optgroup->append_single_option_line("skirt_distance"); optgroup->append_single_option_line("skirt_distance");
optgroup->append_single_option_line("skirt_height"); optgroup->append_single_option_line("skirt_height");
optgroup->append_single_option_line("min_skirt_length"); optgroup->append_single_option_line("min_skirt_length");
optgroup = page->new_optgroup(_L("Brim")); optgroup = page->new_optgroup(_(L("Brim")));
optgroup->append_single_option_line("brim_width"); optgroup->append_single_option_line("brim_width");
page = add_options_page(_L("Support material"), "building.png"); page = add_options_page(_(L("Support material")), "building.png");
optgroup = page->new_optgroup(_L("Support material")); optgroup = page->new_optgroup(_(L("Support material")));
optgroup->append_single_option_line("support_material"); optgroup->append_single_option_line("support_material");
optgroup->append_single_option_line("support_material_threshold"); optgroup->append_single_option_line("support_material_threshold");
optgroup->append_single_option_line("support_material_enforce_layers"); optgroup->append_single_option_line("support_material_enforce_layers");
optgroup = page->new_optgroup(_L("Raft")); optgroup = page->new_optgroup(_(L("Raft")));
optgroup->append_single_option_line("raft_layers"); optgroup->append_single_option_line("raft_layers");
// # optgroup->append_single_option_line(get_option_("raft_contact_distance"); // # optgroup->append_single_option_line(get_option_("raft_contact_distance");
optgroup = page->new_optgroup(_L("Options for support material and raft")); optgroup = page->new_optgroup(_(L("Options for support material and raft")));
optgroup->append_single_option_line("support_material_contact_distance"); optgroup->append_single_option_line("support_material_contact_distance");
optgroup->append_single_option_line("support_material_pattern"); optgroup->append_single_option_line("support_material_pattern");
optgroup->append_single_option_line("support_material_with_sheath"); optgroup->append_single_option_line("support_material_with_sheath");
@ -396,8 +396,8 @@ void TabPrint::build()
optgroup->append_single_option_line("dont_support_bridges"); optgroup->append_single_option_line("dont_support_bridges");
optgroup->append_single_option_line("support_material_synchronize_layers"); optgroup->append_single_option_line("support_material_synchronize_layers");
page = add_options_page(_L("Speed"), "time.png"); page = add_options_page(_(L("Speed")), "time.png");
optgroup = page->new_optgroup(_L("Speed for print moves")); optgroup = page->new_optgroup(_(L("Speed for print moves")));
optgroup->append_single_option_line("perimeter_speed"); optgroup->append_single_option_line("perimeter_speed");
optgroup->append_single_option_line("small_perimeter_speed"); optgroup->append_single_option_line("small_perimeter_speed");
optgroup->append_single_option_line("external_perimeter_speed"); optgroup->append_single_option_line("external_perimeter_speed");
@ -409,49 +409,49 @@ void TabPrint::build()
optgroup->append_single_option_line("bridge_speed"); optgroup->append_single_option_line("bridge_speed");
optgroup->append_single_option_line("gap_fill_speed"); optgroup->append_single_option_line("gap_fill_speed");
optgroup = page->new_optgroup(_L("Speed for non-print moves")); optgroup = page->new_optgroup(_(L("Speed for non-print moves")));
optgroup->append_single_option_line("travel_speed"); optgroup->append_single_option_line("travel_speed");
optgroup = page->new_optgroup(_L("Modifiers")); optgroup = page->new_optgroup(_(L("Modifiers")));
optgroup->append_single_option_line("first_layer_speed"); optgroup->append_single_option_line("first_layer_speed");
optgroup = page->new_optgroup(_L("Acceleration control (advanced)")); optgroup = page->new_optgroup(_(L("Acceleration control (advanced)")));
optgroup->append_single_option_line("perimeter_acceleration"); optgroup->append_single_option_line("perimeter_acceleration");
optgroup->append_single_option_line("infill_acceleration"); optgroup->append_single_option_line("infill_acceleration");
optgroup->append_single_option_line("bridge_acceleration"); optgroup->append_single_option_line("bridge_acceleration");
optgroup->append_single_option_line("first_layer_acceleration"); optgroup->append_single_option_line("first_layer_acceleration");
optgroup->append_single_option_line("default_acceleration"); optgroup->append_single_option_line("default_acceleration");
optgroup = page->new_optgroup(_L("Autospeed (advanced)")); optgroup = page->new_optgroup(_(L("Autospeed (advanced)")));
optgroup->append_single_option_line("max_print_speed"); optgroup->append_single_option_line("max_print_speed");
optgroup->append_single_option_line("max_volumetric_speed"); optgroup->append_single_option_line("max_volumetric_speed");
optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_positive"); optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_positive");
optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_negative"); optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_negative");
page = add_options_page(_L("Multiple Extruders"), "funnel.png"); page = add_options_page(_(L("Multiple Extruders")), "funnel.png");
optgroup = page->new_optgroup(_L("Extruders")); optgroup = page->new_optgroup(_(L("Extruders")));
optgroup->append_single_option_line("perimeter_extruder"); optgroup->append_single_option_line("perimeter_extruder");
optgroup->append_single_option_line("infill_extruder"); optgroup->append_single_option_line("infill_extruder");
optgroup->append_single_option_line("solid_infill_extruder"); optgroup->append_single_option_line("solid_infill_extruder");
optgroup->append_single_option_line("support_material_extruder"); optgroup->append_single_option_line("support_material_extruder");
optgroup->append_single_option_line("support_material_interface_extruder"); optgroup->append_single_option_line("support_material_interface_extruder");
optgroup = page->new_optgroup(_L("Ooze prevention")); optgroup = page->new_optgroup(_(L("Ooze prevention")));
optgroup->append_single_option_line("ooze_prevention"); optgroup->append_single_option_line("ooze_prevention");
optgroup->append_single_option_line("standby_temperature_delta"); optgroup->append_single_option_line("standby_temperature_delta");
optgroup = page->new_optgroup(_L("Wipe tower")); optgroup = page->new_optgroup(_(L("Wipe tower")));
optgroup->append_single_option_line("wipe_tower"); optgroup->append_single_option_line("wipe_tower");
optgroup->append_single_option_line("wipe_tower_x"); optgroup->append_single_option_line("wipe_tower_x");
optgroup->append_single_option_line("wipe_tower_y"); optgroup->append_single_option_line("wipe_tower_y");
optgroup->append_single_option_line("wipe_tower_width"); optgroup->append_single_option_line("wipe_tower_width");
optgroup->append_single_option_line("wipe_tower_per_color_wipe"); optgroup->append_single_option_line("wipe_tower_per_color_wipe");
optgroup = page->new_optgroup(_L("Advanced")); optgroup = page->new_optgroup(_(L("Advanced")));
optgroup->append_single_option_line("interface_shells"); optgroup->append_single_option_line("interface_shells");
page = add_options_page(_L("Advanced"), "wrench.png"); page = add_options_page(_(L("Advanced")), "wrench.png");
optgroup = page->new_optgroup(_L("Extrusion width"), 180); optgroup = page->new_optgroup(_(L("Extrusion width")), 180);
optgroup->append_single_option_line("extrusion_width"); optgroup->append_single_option_line("extrusion_width");
optgroup->append_single_option_line("first_layer_extrusion_width"); optgroup->append_single_option_line("first_layer_extrusion_width");
optgroup->append_single_option_line("perimeter_extrusion_width"); optgroup->append_single_option_line("perimeter_extrusion_width");
@ -461,23 +461,23 @@ void TabPrint::build()
optgroup->append_single_option_line("top_infill_extrusion_width"); optgroup->append_single_option_line("top_infill_extrusion_width");
optgroup->append_single_option_line("support_material_extrusion_width"); optgroup->append_single_option_line("support_material_extrusion_width");
optgroup = page->new_optgroup(_L("Overlap")); optgroup = page->new_optgroup(_(L("Overlap")));
optgroup->append_single_option_line("infill_overlap"); optgroup->append_single_option_line("infill_overlap");
optgroup = page->new_optgroup(_L("Flow")); optgroup = page->new_optgroup(_(L("Flow")));
optgroup->append_single_option_line("bridge_flow_ratio"); optgroup->append_single_option_line("bridge_flow_ratio");
optgroup = page->new_optgroup(_L("Other")); optgroup = page->new_optgroup(_(L("Other")));
optgroup->append_single_option_line("clip_multipart_objects"); optgroup->append_single_option_line("clip_multipart_objects");
optgroup->append_single_option_line("elefant_foot_compensation"); optgroup->append_single_option_line("elefant_foot_compensation");
optgroup->append_single_option_line("xy_size_compensation"); optgroup->append_single_option_line("xy_size_compensation");
// # optgroup->append_single_option_line("threads"); // # optgroup->append_single_option_line("threads");
optgroup->append_single_option_line("resolution"); optgroup->append_single_option_line("resolution");
page = add_options_page(_L("Output options"), "page_white_go.png"); page = add_options_page(_(L("Output options")), "page_white_go.png");
optgroup = page->new_optgroup(_L("Sequential printing")); optgroup = page->new_optgroup(_(L("Sequential printing")));
optgroup->append_single_option_line("complete_objects"); optgroup->append_single_option_line("complete_objects");
line = { _L("Extruder clearance (mm)"), "" }; line = { _(L("Extruder clearance (mm)")), "" };
Option option = optgroup->get_option("extruder_clearance_radius"); Option option = optgroup->get_option("extruder_clearance_radius");
option.opt.width = 60; option.opt.width = 60;
line.append_option(option); line.append_option(option);
@ -486,28 +486,28 @@ void TabPrint::build()
line.append_option(option); line.append_option(option);
optgroup->append_line(line); optgroup->append_line(line);
optgroup = page->new_optgroup(_L("Output file")); optgroup = page->new_optgroup(_(L("Output file")));
optgroup->append_single_option_line("gcode_comments"); optgroup->append_single_option_line("gcode_comments");
option = optgroup->get_option("output_filename_format"); option = optgroup->get_option("output_filename_format");
option.opt.full_width = true; option.opt.full_width = true;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(_L("Post-processing scripts"), 0); optgroup = page->new_optgroup(_(L("Post-processing scripts")), 0);
option = optgroup->get_option("post_process"); option = optgroup->get_option("post_process");
option.opt.full_width = true; option.opt.full_width = true;
option.opt.height = 50; option.opt.height = 50;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
page = add_options_page(_L("Notes"), "note.png"); page = add_options_page(_(L("Notes")), "note.png");
optgroup = page->new_optgroup(_L("Notes"), 0); optgroup = page->new_optgroup(_(L("Notes")), 0);
option = optgroup->get_option("notes"); option = optgroup->get_option("notes");
option.opt.full_width = true; option.opt.full_width = true;
option.opt.height = 250; option.opt.height = 250;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
page = add_options_page(_L("Dependencies"), "wrench.png"); page = add_options_page(_(L("Dependencies")), "wrench.png");
optgroup = page->new_optgroup(_L("Profile dependencies")); optgroup = page->new_optgroup(_(L("Profile dependencies")));
line = { _L("Compatible printers"), "" }; line = { _(L("Compatible printers")), "" };
line.widget = [this](wxWindow* parent){ line.widget = [this](wxWindow* parent){
return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn); return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn);
}; };
@ -528,78 +528,79 @@ void TabPrint::update()
{ {
Freeze(); Freeze();
if ( m_config->opt_bool("spiral_vase") && if (m_config->opt_bool("spiral_vase") &&
!(m_config->opt_int("perimeters") == 1 && m_config->opt_int("top_solid_layers") == 0 && !(m_config->opt_int("perimeters") == 1 && m_config->opt_int("top_solid_layers") == 0 &&
m_config->option<ConfigOptionPercent>("fill_density")->value == 0)) { m_config->option<ConfigOptionPercent>("fill_density")->value == 0)) {
wxString msg_text = _L("The Spiral Vase mode requires:\n" wxString msg_text = _(L("The Spiral Vase mode requires:\n"
"- one perimeter\n" "- one perimeter\n"
"- no top solid layers\n" "- no top solid layers\n"
"- 0% fill density\n" "- 0% fill density\n"
"- no support material\n" "- no support material\n"
"- no ensure_vertical_shell_thickness\n" "- no ensure_vertical_shell_thickness\n"
"\nShall I adjust those settings in order to enable Spiral Vase?"); "\nShall I adjust those settings in order to enable Spiral Vase?"));
auto dialog = new wxMessageDialog(parent(), msg_text, _L("Spiral Vase"), wxICON_WARNING | wxYES | wxNO); auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Spiral Vase")), wxICON_WARNING | wxYES | wxNO);
DynamicPrintConfig new_conf = *m_config; DynamicPrintConfig new_conf = *m_config;
if (dialog->ShowModal() == wxID_YES) { if (dialog->ShowModal() == wxID_YES) {
new_conf.set_key_value("perimeters", new ConfigOptionInt(1)); new_conf.set_key_value("perimeters", new ConfigOptionInt(1));
new_conf.set_key_value("top_solid_layers", new ConfigOptionInt(0)); new_conf.set_key_value("top_solid_layers", new ConfigOptionInt(0));
new_conf.set_key_value("fill_density", new ConfigOptionPercent(0)); new_conf.set_key_value("fill_density", new ConfigOptionPercent(0));
new_conf.set_key_value("support_material", new ConfigOptionBool(false)); new_conf.set_key_value("support_material", new ConfigOptionBool(false));
new_conf.set_key_value("support_material_enforce_layers", new ConfigOptionInt(0));
new_conf.set_key_value("ensure_vertical_shell_thickness", new ConfigOptionBool(false)); new_conf.set_key_value("ensure_vertical_shell_thickness", new ConfigOptionBool(false));
} }
else { else {
new_conf.set_key_value("spiral_vase", new ConfigOptionBool(false)); new_conf.set_key_value("spiral_vase", new ConfigOptionBool(false));
} }
load_config(new_conf); load_config(new_conf);
} }
auto first_layer_height = m_config->option<ConfigOptionFloatOrPercent>("first_layer_height")->value; auto first_layer_height = m_config->option<ConfigOptionFloatOrPercent>("first_layer_height")->value;
auto layer_height = m_config->opt_float("layer_height"); auto layer_height = m_config->opt_float("layer_height");
if (m_config->opt_bool("wipe_tower") && if (m_config->opt_bool("wipe_tower") &&
( first_layer_height != 0.2 || layer_height < 0.15 || layer_height > 0.35)) { (first_layer_height != 0.2 || layer_height < 0.15 || layer_height > 0.35)) {
wxString msg_text = _L("The Wipe Tower currently supports only:\n" wxString msg_text = _(L("The Wipe Tower currently supports only:\n"
"- first layer height 0.2mm\n" "- first layer height 0.2mm\n"
"- layer height from 0.15mm to 0.35mm\n" "- layer height from 0.15mm to 0.35mm\n"
"\nShall I adjust those settings in order to enable the Wipe Tower?"); "\nShall I adjust those settings in order to enable the Wipe Tower?"));
auto dialog = new wxMessageDialog(parent(), msg_text, _L("Wipe Tower"), wxICON_WARNING | wxYES | wxNO); auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Wipe Tower")), wxICON_WARNING | wxYES | wxNO);
DynamicPrintConfig new_conf = *m_config; DynamicPrintConfig new_conf = *m_config;
if (dialog->ShowModal() == wxID_YES) { if (dialog->ShowModal() == wxID_YES) {
const auto &val = *m_config->option<ConfigOptionFloatOrPercent>("first_layer_height"); const auto &val = *m_config->option<ConfigOptionFloatOrPercent>("first_layer_height");
new_conf.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.2, val.percent)); new_conf.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.2, val.percent));
if (m_config->opt_float("layer_height") < 0.15) new_conf.set_key_value("layer_height", new ConfigOptionFloat(0.15)) ; if (m_config->opt_float("layer_height") < 0.15) new_conf.set_key_value("layer_height", new ConfigOptionFloat(0.15));
if (m_config->opt_float("layer_height") > 0.35) new_conf.set_key_value("layer_height", new ConfigOptionFloat(0.35)); if (m_config->opt_float("layer_height") > 0.35) new_conf.set_key_value("layer_height", new ConfigOptionFloat(0.35));
} }
else else
new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false)); new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false));
load_config(new_conf); load_config(new_conf);
} }
if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") && if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") &&
m_config->opt_float("support_material_contact_distance") > 0. && m_config->opt_float("support_material_contact_distance") > 0. &&
(m_config->opt_int("support_material_extruder") != 0 || m_config->opt_int("support_material_interface_extruder") != 0)) { (m_config->opt_int("support_material_extruder") != 0 || m_config->opt_int("support_material_interface_extruder") != 0)) {
wxString msg_text = _L("The Wipe Tower currently supports the non-soluble supports only\n" wxString msg_text = _(L("The Wipe Tower currently supports the non-soluble supports only\n"
"if they are printed with the current extruder without triggering a tool change.\n" "if they are printed with the current extruder without triggering a tool change.\n"
"(both support_material_extruder and support_material_interface_extruder need to be set to 0).\n" "(both support_material_extruder and support_material_interface_extruder need to be set to 0).\n"
"\nShall I adjust those settings in order to enable the Wipe Tower?"); "\nShall I adjust those settings in order to enable the Wipe Tower?"));
auto dialog = new wxMessageDialog(parent(), msg_text, _L("Wipe Tower"), wxICON_WARNING | wxYES | wxNO); auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Wipe Tower")), wxICON_WARNING | wxYES | wxNO);
DynamicPrintConfig new_conf = *m_config; DynamicPrintConfig new_conf = *m_config;
if (dialog->ShowModal() == wxID_YES) { if (dialog->ShowModal() == wxID_YES) {
new_conf.set_key_value("support_material_extruder", new ConfigOptionInt(0)); new_conf.set_key_value("support_material_extruder", new ConfigOptionInt(0));
new_conf.set_key_value("support_material_interface_extruder", new ConfigOptionInt(0)); new_conf.set_key_value("support_material_interface_extruder", new ConfigOptionInt(0));
} }
else else
new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false)); new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false));
load_config(new_conf); load_config(new_conf);
} }
if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") && if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") &&
m_config->opt_float("support_material_contact_distance") == 0 && m_config->opt_float("support_material_contact_distance") == 0 &&
!m_config->opt_bool("support_material_synchronize_layers")) { !m_config->opt_bool("support_material_synchronize_layers")) {
wxString msg_text = _L("For the Wipe Tower to work with the soluble supports, the support layers\n" wxString msg_text = _(L("For the Wipe Tower to work with the soluble supports, the support layers\n"
"need to be synchronized with the object layers.\n" "need to be synchronized with the object layers.\n"
"\nShall I synchronize support layers in order to enable the Wipe Tower?"); "\nShall I synchronize support layers in order to enable the Wipe Tower?"));
auto dialog = new wxMessageDialog(parent(), msg_text, _L("Wipe Tower"), wxICON_WARNING | wxYES | wxNO); auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Wipe Tower")), wxICON_WARNING | wxYES | wxNO);
DynamicPrintConfig new_conf = *m_config; DynamicPrintConfig new_conf = *m_config;
if (dialog->ShowModal() == wxID_YES) { if (dialog->ShowModal() == wxID_YES) {
new_conf.set_key_value("support_material_synchronize_layers", new ConfigOptionBool(true)); new_conf.set_key_value("support_material_synchronize_layers", new ConfigOptionBool(true));
@ -614,18 +615,18 @@ void TabPrint::update()
if (!m_support_material_overhangs_queried) { if (!m_support_material_overhangs_queried) {
m_support_material_overhangs_queried = true; m_support_material_overhangs_queried = true;
if (!m_config->opt_bool("overhangs")/* != 1*/) { if (!m_config->opt_bool("overhangs")/* != 1*/) {
wxString msg_text = _L("Supports work better, if the following feature is enabled:\n" wxString msg_text = _(L("Supports work better, if the following feature is enabled:\n"
"- Detect bridging perimeters\n" "- Detect bridging perimeters\n"
"\nShall I adjust those settings for supports?"); "\nShall I adjust those settings for supports?"));
auto dialog = new wxMessageDialog(parent(), msg_text, _L("Support Generator"), wxICON_WARNING | wxYES | wxNO | wxCANCEL); auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Support Generator")), wxICON_WARNING | wxYES | wxNO | wxCANCEL);
DynamicPrintConfig new_conf = *m_config; DynamicPrintConfig new_conf = *m_config;
auto answer = dialog->ShowModal(); auto answer = dialog->ShowModal();
if (answer == wxID_YES) { if (answer == wxID_YES) {
// Enable "detect bridging perimeters". // Enable "detect bridging perimeters".
new_conf.set_key_value("overhangs", new ConfigOptionBool(true)); new_conf.set_key_value("overhangs", new ConfigOptionBool(true));
} else if(answer == wxID_NO) { } else if (answer == wxID_NO) {
// Do nothing, leave supports on and "detect bridging perimeters" off. // Do nothing, leave supports on and "detect bridging perimeters" off.
} else if(answer == wxID_CANCEL) { } else if (answer == wxID_CANCEL) {
// Disable supports. // Disable supports.
new_conf.set_key_value("support_material", new ConfigOptionBool(false)); new_conf.set_key_value("support_material", new ConfigOptionBool(false));
m_support_material_overhangs_queried = false; m_support_material_overhangs_queried = false;
@ -642,7 +643,7 @@ void TabPrint::update()
auto fill_pattern = m_config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->value; auto fill_pattern = m_config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->value;
std::string str_fill_pattern = ""; std::string str_fill_pattern = "";
t_config_enum_values map_names = m_config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->get_enum_values(); t_config_enum_values map_names = m_config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->get_enum_values();
for (auto it:map_names) { for (auto it : map_names) {
if (fill_pattern == it.second) { if (fill_pattern == it.second) {
str_fill_pattern = it.first; str_fill_pattern = it.first;
break; break;
@ -659,9 +660,9 @@ void TabPrint::update()
// get fill_pattern name from enum_labels for using this one at dialog_msg // get fill_pattern name from enum_labels for using this one at dialog_msg
str_fill_pattern = m_config->def()->get("fill_pattern")->enum_labels[fill_pattern]; str_fill_pattern = m_config->def()->get("fill_pattern")->enum_labels[fill_pattern];
if (!correct_100p_fill){ if (!correct_100p_fill){
wxString msg_text = _L("The ") + str_fill_pattern + _L(" infill pattern is not supposed to work at 100% density.\n" wxString msg_text = _(L("The ")) + str_fill_pattern + _(L(" infill pattern is not supposed to work at 100% density.\n"
"\nShall I switch to rectilinear fill pattern?"); "\nShall I switch to rectilinear fill pattern?"));
auto dialog = new wxMessageDialog(parent(), msg_text, _L("Infill"), wxICON_WARNING | wxYES | wxNO); auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Infill")), wxICON_WARNING | wxYES | wxNO);
DynamicPrintConfig new_conf = *m_config; DynamicPrintConfig new_conf = *m_config;
if (dialog->ShowModal() == wxID_YES) { if (dialog->ShowModal() == wxID_YES) {
new_conf.set_key_value("fill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinear)); new_conf.set_key_value("fill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinear));
@ -675,7 +676,7 @@ void TabPrint::update()
} }
bool have_perimeters = m_config->opt_int("perimeters") > 0; bool have_perimeters = m_config->opt_int("perimeters") > 0;
std::vector<std::string> vec_enable = { "extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs", std::vector<std::string> vec_enable = { "extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs",
"seam_position", "external_perimeters_first", "external_perimeter_extrusion_width", "seam_position", "external_perimeters_first", "external_perimeter_extrusion_width",
"perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" }; "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" };
for (auto el : vec_enable) for (auto el : vec_enable)
@ -683,22 +684,22 @@ void TabPrint::update()
bool have_infill = m_config->option<ConfigOptionPercent>("fill_density")->value > 0; bool have_infill = m_config->option<ConfigOptionPercent>("fill_density")->value > 0;
vec_enable.resize(0); vec_enable.resize(0);
vec_enable = { "fill_pattern", "infill_every_layers", "infill_only_where_needed", vec_enable = { "fill_pattern", "infill_every_layers", "infill_only_where_needed",
"solid_infill_every_layers", "solid_infill_below_area", "infill_extruder"}; "solid_infill_every_layers", "solid_infill_below_area", "infill_extruder" };
// infill_extruder uses the same logic as in Print::extruders() // infill_extruder uses the same logic as in Print::extruders()
for (auto el : vec_enable) for (auto el : vec_enable)
get_field(el)->toggle(have_infill); get_field(el)->toggle(have_infill);
bool have_solid_infill = m_config->opt_int("top_solid_layers") > 0 || m_config->opt_int("bottom_solid_layers") > 0; bool have_solid_infill = m_config->opt_int("top_solid_layers") > 0 || m_config->opt_int("bottom_solid_layers") > 0;
vec_enable.resize(0); vec_enable.resize(0);
vec_enable = { "external_fill_pattern", "infill_first", "solid_infill_extruder", vec_enable = { "external_fill_pattern", "infill_first", "solid_infill_extruder",
"solid_infill_extrusion_width", "solid_infill_speed" }; "solid_infill_extrusion_width", "solid_infill_speed" };
// solid_infill_extruder uses the same logic as in Print::extruders() // solid_infill_extruder uses the same logic as in Print::extruders()
for (auto el : vec_enable) for (auto el : vec_enable)
get_field(el)->toggle(have_solid_infill); get_field(el)->toggle(have_solid_infill);
vec_enable.resize(0); vec_enable.resize(0);
vec_enable = { "fill_angle", "bridge_angle", "infill_extrusion_width", vec_enable = { "fill_angle", "bridge_angle", "infill_extrusion_width",
"infill_speed", "bridge_speed" }; "infill_speed", "bridge_speed" };
for (auto el : vec_enable) for (auto el : vec_enable)
get_field(el)->toggle(have_infill || have_solid_infill); get_field(el)->toggle(have_infill || have_solid_infill);
@ -713,14 +714,14 @@ void TabPrint::update()
bool have_default_acceleration = m_config->opt_float("default_acceleration") > 0; bool have_default_acceleration = m_config->opt_float("default_acceleration") > 0;
vec_enable.resize(0); vec_enable.resize(0);
vec_enable = { "perimeter_acceleration", "infill_acceleration", vec_enable = { "perimeter_acceleration", "infill_acceleration",
"bridge_acceleration", "first_layer_acceleration"}; "bridge_acceleration", "first_layer_acceleration" };
for (auto el : vec_enable) for (auto el : vec_enable)
get_field(el)->toggle(have_default_acceleration); get_field(el)->toggle(have_default_acceleration);
bool have_skirt = m_config->opt_int("skirts") > 0 || m_config->opt_float("min_skirt_length") > 0; bool have_skirt = m_config->opt_int("skirts") > 0 || m_config->opt_float("min_skirt_length") > 0;
vec_enable.resize(0); vec_enable.resize(0);
vec_enable = { "skirt_distance", "skirt_height"}; vec_enable = { "skirt_distance", "skirt_height" };
for (auto el : vec_enable) for (auto el : vec_enable)
get_field(el)->toggle(have_skirt); get_field(el)->toggle(have_skirt);
@ -734,15 +735,15 @@ void TabPrint::update()
bool have_support_soluble = have_support_material && m_config->opt_float("support_material_contact_distance") == 0; bool have_support_soluble = have_support_material && m_config->opt_float("support_material_contact_distance") == 0;
vec_enable.resize(0); vec_enable.resize(0);
vec_enable = { "support_material_threshold", "support_material_pattern", "support_material_with_sheath", vec_enable = { "support_material_threshold", "support_material_pattern", "support_material_with_sheath",
"support_material_spacing", "support_material_angle", "support_material_interface_layers", "support_material_spacing", "support_material_angle", "support_material_interface_layers",
"dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance", "dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance",
"support_material_xy_spacing"}; "support_material_xy_spacing" };
for (auto el : vec_enable) for (auto el : vec_enable)
get_field(el)->toggle(have_support_material); get_field(el)->toggle(have_support_material);
vec_enable.resize(0); vec_enable.resize(0);
vec_enable = { "support_material_interface_spacing", "support_material_interface_extruder", vec_enable = { "support_material_interface_spacing", "support_material_interface_extruder",
"support_material_interface_speed", "support_material_interface_contact_loops"}; "support_material_interface_speed", "support_material_interface_contact_loops" };
for (auto el : vec_enable) for (auto el : vec_enable)
get_field(el)->toggle(have_support_material && have_support_interface); get_field(el)->toggle(have_support_material && have_support_interface);
get_field("support_material_synchronize_layers")->toggle(have_support_soluble); get_field("support_material_synchronize_layers")->toggle(have_support_soluble);
@ -753,7 +754,7 @@ void TabPrint::update()
bool have_sequential_printing = m_config->opt_bool("complete_objects"); bool have_sequential_printing = m_config->opt_bool("complete_objects");
vec_enable.resize(0); vec_enable.resize(0);
vec_enable = { "extruder_clearance_radius", "extruder_clearance_height"}; vec_enable = { "extruder_clearance_radius", "extruder_clearance_height" };
for (auto el : vec_enable) for (auto el : vec_enable)
get_field(el)->toggle(have_sequential_printing); get_field(el)->toggle(have_sequential_printing);
@ -762,7 +763,7 @@ void TabPrint::update()
bool have_wipe_tower = m_config->opt_bool("wipe_tower"); bool have_wipe_tower = m_config->opt_bool("wipe_tower");
vec_enable.resize(0); vec_enable.resize(0);
vec_enable = { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe"}; vec_enable = { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe" };
for (auto el : vec_enable) for (auto el : vec_enable)
get_field(el)->toggle(have_wipe_tower); get_field(el)->toggle(have_wipe_tower);
@ -782,39 +783,39 @@ void TabFilament::build()
m_presets = &m_preset_bundle->filaments; m_presets = &m_preset_bundle->filaments;
m_config = &m_preset_bundle->filaments.get_edited_preset().config; m_config = &m_preset_bundle->filaments.get_edited_preset().config;
auto page = add_options_page(_L("Filament"), "spool.png"); auto page = add_options_page(_(L("Filament")), "spool.png");
auto optgroup = page->new_optgroup(_L("Filament")); auto optgroup = page->new_optgroup(_(L("Filament")));
optgroup->append_single_option_line("filament_colour"); optgroup->append_single_option_line("filament_colour");
optgroup->append_single_option_line("filament_diameter"); optgroup->append_single_option_line("filament_diameter");
optgroup->append_single_option_line("extrusion_multiplier"); optgroup->append_single_option_line("extrusion_multiplier");
optgroup->append_single_option_line("filament_density"); optgroup->append_single_option_line("filament_density");
optgroup->append_single_option_line("filament_cost"); optgroup->append_single_option_line("filament_cost");
optgroup = page->new_optgroup(_L("Temperature") +" (\u00B0C)"); // degree sign optgroup = page->new_optgroup(_(L("Temperature ")) +" (\u00B0C)"); // degree sign
Line line = { _L("Extruder"), "" }; Line line = { _(L("Extruder")), "" };
line.append_option(optgroup->get_option("first_layer_temperature")); line.append_option(optgroup->get_option("first_layer_temperature"));
line.append_option(optgroup->get_option("temperature")); line.append_option(optgroup->get_option("temperature"));
optgroup->append_line(line); optgroup->append_line(line);
line = { _L("Bed"), "" }; line = { _(L("Bed")), "" };
line.append_option(optgroup->get_option("first_layer_bed_temperature")); line.append_option(optgroup->get_option("first_layer_bed_temperature"));
line.append_option(optgroup->get_option("bed_temperature")); line.append_option(optgroup->get_option("bed_temperature"));
optgroup->append_line(line); optgroup->append_line(line);
page = add_options_page(_L("Cooling"), "hourglass.png"); page = add_options_page(_(L("Cooling")), "hourglass.png");
optgroup = page->new_optgroup(_L("Enable")); optgroup = page->new_optgroup(_(L("Enable")));
optgroup->append_single_option_line("fan_always_on"); optgroup->append_single_option_line("fan_always_on");
optgroup->append_single_option_line("cooling"); optgroup->append_single_option_line("cooling");
line = { "", "" }; line = { "", "" };
line.full_width = 1; line.full_width = 1;
line.widget = [this](wxWindow* parent) { line.widget = [this](wxWindow* parent) {
return description_line_widget(parent, &m_cooling_description_line); return description_line_widget(parent, &m_cooling_description_line);
}; };
optgroup->append_line(line); optgroup->append_line(line);
optgroup = page->new_optgroup(_L("Fan settings")); optgroup = page->new_optgroup(_(L("Fan settings")));
line = {_L("Fan speed"),""}; line = { _(L("Fan speed")), "" };
line.append_option(optgroup->get_option("min_fan_speed")); line.append_option(optgroup->get_option("min_fan_speed"));
line.append_option(optgroup->get_option("max_fan_speed")); line.append_option(optgroup->get_option("max_fan_speed"));
optgroup->append_line(line); optgroup->append_line(line);
@ -822,50 +823,50 @@ void TabFilament::build()
optgroup->append_single_option_line("bridge_fan_speed"); optgroup->append_single_option_line("bridge_fan_speed");
optgroup->append_single_option_line("disable_fan_first_layers"); optgroup->append_single_option_line("disable_fan_first_layers");
optgroup = page->new_optgroup(_L("Cooling thresholds"), 250); optgroup = page->new_optgroup(_(L("Cooling thresholds")), 250);
optgroup->append_single_option_line("fan_below_layer_time"); optgroup->append_single_option_line("fan_below_layer_time");
optgroup->append_single_option_line("slowdown_below_layer_time"); optgroup->append_single_option_line("slowdown_below_layer_time");
optgroup->append_single_option_line("min_print_speed"); optgroup->append_single_option_line("min_print_speed");
page = add_options_page(_L("Advanced"), "wrench.png"); page = add_options_page(_(L("Advanced")), "wrench.png");
optgroup = page->new_optgroup(_L("Filament properties")); optgroup = page->new_optgroup(_(L("Filament properties")));
optgroup->append_single_option_line("filament_type"); optgroup->append_single_option_line("filament_type");
optgroup->append_single_option_line("filament_soluble"); optgroup->append_single_option_line("filament_soluble");
optgroup = page->new_optgroup(_L("Print speed override")); optgroup = page->new_optgroup(_(L("Print speed override")));
optgroup->append_single_option_line("filament_max_volumetric_speed"); optgroup->append_single_option_line("filament_max_volumetric_speed");
line = {"",""}; line = { "", "" };
line.full_width = 1; line.full_width = 1;
line.widget = [this](wxWindow* parent) { line.widget = [this](wxWindow* parent) {
return description_line_widget(parent, &m_volumetric_speed_description_line); return description_line_widget(parent, &m_volumetric_speed_description_line);
}; };
optgroup->append_line(line); optgroup->append_line(line);
page = add_options_page(_L("Custom G-code"), "cog.png"); page = add_options_page(_(L("Custom G-code")), "cog.png");
optgroup = page->new_optgroup(_L("Start G-code"), 0); optgroup = page->new_optgroup(_(L("Start G-code")), 0);
Option option = optgroup->get_option("start_filament_gcode"); Option option = optgroup->get_option("start_filament_gcode");
option.opt.full_width = true; option.opt.full_width = true;
option.opt.height = 150; option.opt.height = 150;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(_L("End G-code"), 0); optgroup = page->new_optgroup(_(L("End G-code")), 0);
option = optgroup->get_option("end_filament_gcode"); option = optgroup->get_option("end_filament_gcode");
option.opt.full_width = true; option.opt.full_width = true;
option.opt.height = 150; option.opt.height = 150;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
page = add_options_page(_L("Notes"), "note.png"); page = add_options_page(_(L("Notes")), "note.png");
optgroup = page->new_optgroup(_L("Notes"), 0); optgroup = page->new_optgroup(_(L("Notes")), 0);
optgroup->label_width = 0; optgroup->label_width = 0;
option = optgroup->get_option("filament_notes"); option = optgroup->get_option("filament_notes");
option.opt.full_width = true; option.opt.full_width = true;
option.opt.height = 250; option.opt.height = 250;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
page = add_options_page(_L("Dependencies"), "wrench.png"); page = add_options_page(_(L("Dependencies")), "wrench.png");
optgroup = page->new_optgroup(_L("Profile dependencies")); optgroup = page->new_optgroup(_(L("Profile dependencies")));
line = {_L("Compatible printers"), ""}; line = { _(L("Compatible printers")), "" };
line.widget = [this](wxWindow* parent){ line.widget = [this](wxWindow* parent){
return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn); return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn);
}; };
@ -884,9 +885,9 @@ void TabFilament::reload_config(){
void TabFilament::update() void TabFilament::update()
{ {
wxString text = wxString::FromUTF8(PresetHints::cooling_description(m_presets->get_edited_preset()).c_str()); wxString text = from_u8(PresetHints::cooling_description(m_presets->get_edited_preset()));
m_cooling_description_line->SetText(text); m_cooling_description_line->SetText(text);
text = wxString::FromUTF8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle).c_str()); text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle));
m_volumetric_speed_description_line->SetText(text); m_volumetric_speed_description_line->SetText(text);
bool cooling = m_config->opt_bool("cooling", 0); bool cooling = m_config->opt_bool("cooling", 0);
@ -904,7 +905,7 @@ void TabFilament::update()
void TabFilament::OnActivate() void TabFilament::OnActivate()
{ {
m_volumetric_speed_description_line->SetText(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle)); m_volumetric_speed_description_line->SetText(from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle)));
} }
wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticText) wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticText)
@ -933,14 +934,14 @@ void TabPrinter::build()
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter")); auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter"));
m_extruders_count = nozzle_diameter->values.size(); m_extruders_count = nozzle_diameter->values.size();
auto page = add_options_page(_L("General"), "printer_empty.png"); auto page = add_options_page(_(L("General")), "printer_empty.png");
auto optgroup = page->new_optgroup(_L("Size and coordinates")); auto optgroup = page->new_optgroup(_(L("Size and coordinates")));
Line line{ _L("Bed shape"), "" }; Line line{ _(L("Bed shape")), "" };
line.widget = [this](wxWindow* parent){ line.widget = [this](wxWindow* parent){
auto btn = new wxButton(parent, wxID_ANY, _L("Set")+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); auto btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
// btn->SetFont(Slic3r::GUI::small_font); // btn->SetFont(Slic3r::GUI::small_font);
btn->SetBitmap(wxBitmap(wxString::FromUTF8(Slic3r::var("printer_empty.png").c_str()), wxBITMAP_TYPE_PNG)); btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("printer_empty.png")), wxBITMAP_TYPE_PNG));
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn); sizer->Add(btn);
@ -958,12 +959,12 @@ void TabPrinter::build()
optgroup->append_line(line); optgroup->append_line(line);
optgroup->append_single_option_line("z_offset"); optgroup->append_single_option_line("z_offset");
optgroup = page->new_optgroup(_L("Capabilities")); optgroup = page->new_optgroup(_(L("Capabilities")));
ConfigOptionDef def; ConfigOptionDef def;
def.type = coInt, def.type = coInt,
def.default_value = new ConfigOptionInt(1); def.default_value = new ConfigOptionInt(1);
def.label = _LU8("Extruders"); def.label = L("Extruders");
def.tooltip = _LU8("Number of extruders of the printer."); def.tooltip = L("Number of extruders of the printer.");
def.min = 1; def.min = 1;
Option option(def, "extruders_count"); Option option(def, "extruders_count");
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
@ -985,13 +986,13 @@ void TabPrinter::build()
if (!m_no_controller) if (!m_no_controller)
{ {
optgroup = page->new_optgroup(_L("USB/Serial connection")); optgroup = page->new_optgroup(_(L("USB/Serial connection")));
line = {_L("Serial port"), ""}; line = {_(L("Serial port")), ""};
Option serial_port = optgroup->get_option("serial_port"); Option serial_port = optgroup->get_option("serial_port");
serial_port.side_widget = ([this](wxWindow* parent){ serial_port.side_widget = ([this](wxWindow* parent){
auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(wxString::FromUTF8(Slic3r::var("arrow_rotate_clockwise.png").c_str()), wxBITMAP_TYPE_PNG), auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(from_u8(Slic3r::var("arrow_rotate_clockwise.png")), wxBITMAP_TYPE_PNG),
wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
btn->SetToolTip(_L("Rescan serial ports")); btn->SetToolTip(_(L("Rescan serial ports")));
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn); sizer->Add(btn);
@ -1000,9 +1001,9 @@ void TabPrinter::build()
}); });
auto serial_test = [this](wxWindow* parent){ auto serial_test = [this](wxWindow* parent){
auto btn = m_serial_test_btn = new wxButton(parent, wxID_ANY, auto btn = m_serial_test_btn = new wxButton(parent, wxID_ANY,
_L("Test"), wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); _(L("Test")), wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
// btn->SetFont($Slic3r::GUI::small_font); // btn->SetFont($Slic3r::GUI::small_font);
btn->SetBitmap(wxBitmap(wxString::FromUTF8(Slic3r::var("wrench.png").c_str()), wxBITMAP_TYPE_PNG)); btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("wrench.png")), wxBITMAP_TYPE_PNG));
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn); sizer->Add(btn);
@ -1013,10 +1014,10 @@ void TabPrinter::build()
m_config->opt_int("serial_speed") m_config->opt_int("serial_speed")
); );
if (res && sender->wait_connected()) { if (res && sender->wait_connected()) {
show_info(parent, _L("Connection to printer works correctly."), _L("Success!")); show_info(parent, _(L("Connection to printer works correctly.")), _(L("Success!")));
} }
else { else {
show_error(parent, _L("Connection failed.")); show_error(parent, _(L("Connection failed.")));
} }
}); });
return sizer; return sizer;
@ -1028,12 +1029,12 @@ void TabPrinter::build()
optgroup->append_line(line); optgroup->append_line(line);
} }
optgroup = page->new_optgroup(_L("OctoPrint upload")); optgroup = page->new_optgroup(_(L("OctoPrint upload")));
// # append two buttons to the Host line // # append two buttons to the Host line
auto octoprint_host_browse = [this] (wxWindow* parent) { auto octoprint_host_browse = [this] (wxWindow* parent) {
auto btn = new wxButton(parent, wxID_ANY, _L("Browse")+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT); auto btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
// btn->SetFont($Slic3r::GUI::small_font); // btn->SetFont($Slic3r::GUI::small_font);
btn->SetBitmap(wxBitmap(wxString::FromUTF8(Slic3r::var("zoom.png").c_str()), wxBITMAP_TYPE_PNG)); btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("zoom.png")), wxBITMAP_TYPE_PNG));
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn); sizer->Add(btn);
@ -1043,7 +1044,7 @@ void TabPrinter::build()
btn->Bind(wxEVT_BUTTON, [this, parent](wxCommandEvent e){ btn->Bind(wxEVT_BUTTON, [this, parent](wxCommandEvent e){
if (m_event_button_browse > 0){ if (m_event_button_browse > 0){
wxCommandEvent event(m_event_button_browse); wxCommandEvent event(m_event_button_browse);
event.SetString(_L("Button BROWSE was clicked!")); event.SetString(_(L("Button BROWSE was clicked!")));
g_wxMainFrame->ProcessWindowEvent(event); g_wxMainFrame->ProcessWindowEvent(event);
} }
// // # look for devices // // # look for devices
@ -1068,17 +1069,17 @@ void TabPrinter::build()
}; };
auto octoprint_host_test = [this](wxWindow* parent) { auto octoprint_host_test = [this](wxWindow* parent) {
auto btn = m_octoprint_host_test_btn = new wxButton(parent, wxID_ANY, _L("Test"), auto btn = m_octoprint_host_test_btn = new wxButton(parent, wxID_ANY, _(L("Test")),
wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
// btn->SetFont($Slic3r::GUI::small_font); // btn->SetFont($Slic3r::GUI::small_font);
btn->SetBitmap(wxBitmap(wxString::FromUTF8(Slic3r::var("wrench.png").c_str()), wxBITMAP_TYPE_PNG)); btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("wrench.png")), wxBITMAP_TYPE_PNG));
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn); sizer->Add(btn);
btn->Bind(wxEVT_BUTTON, [this, parent](wxCommandEvent e) { btn->Bind(wxEVT_BUTTON, [this, parent](wxCommandEvent e) {
if (m_event_button_test > 0){ if (m_event_button_test > 0){
wxCommandEvent event(m_event_button_test); wxCommandEvent event(m_event_button_test);
event.SetString(_L("Button TEST was clicked!")); event.SetString(_(L("Button TEST was clicked!")));
g_wxMainFrame->ProcessWindowEvent(event); g_wxMainFrame->ProcessWindowEvent(event);
} }
// my $ua = LWP::UserAgent->new; // my $ua = LWP::UserAgent->new;
@ -1106,54 +1107,54 @@ void TabPrinter::build()
optgroup->append_line(host_line); optgroup->append_line(host_line);
optgroup->append_single_option_line("octoprint_apikey"); optgroup->append_single_option_line("octoprint_apikey");
optgroup = page->new_optgroup(_L("Firmware")); optgroup = page->new_optgroup(_(L("Firmware")));
optgroup->append_single_option_line("gcode_flavor"); optgroup->append_single_option_line("gcode_flavor");
optgroup = page->new_optgroup(_L("Advanced")); optgroup = page->new_optgroup(_(L("Advanced")));
optgroup->append_single_option_line("use_relative_e_distances"); optgroup->append_single_option_line("use_relative_e_distances");
optgroup->append_single_option_line("use_firmware_retraction"); optgroup->append_single_option_line("use_firmware_retraction");
optgroup->append_single_option_line("use_volumetric_e"); optgroup->append_single_option_line("use_volumetric_e");
optgroup->append_single_option_line("variable_layer_height"); optgroup->append_single_option_line("variable_layer_height");
page = add_options_page(_L("Custom G-code"), "cog.png"); page = add_options_page(_(L("Custom G-code")), "cog.png");
optgroup = page->new_optgroup(_L("Start G-code"), 0); optgroup = page->new_optgroup(_(L("Start G-code")), 0);
option = optgroup->get_option("start_gcode"); option = optgroup->get_option("start_gcode");
option.opt.full_width = true; option.opt.full_width = true;
option.opt.height = 150; option.opt.height = 150;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(_L("End G-code"), 0); optgroup = page->new_optgroup(_(L("End G-code")), 0);
option = optgroup->get_option("end_gcode"); option = optgroup->get_option("end_gcode");
option.opt.full_width = true; option.opt.full_width = true;
option.opt.height = 150; option.opt.height = 150;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(_L("Before layer change G-code"), 0); optgroup = page->new_optgroup(_(L("Before layer change G-code")), 0);
option = optgroup->get_option("before_layer_gcode"); option = optgroup->get_option("before_layer_gcode");
option.opt.full_width = true; option.opt.full_width = true;
option.opt.height = 150; option.opt.height = 150;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(_L("After layer change G-code"), 0); optgroup = page->new_optgroup(_(L("After layer change G-code")), 0);
option = optgroup->get_option("layer_gcode"); option = optgroup->get_option("layer_gcode");
option.opt.full_width = true; option.opt.full_width = true;
option.opt.height = 150; option.opt.height = 150;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(_L("Tool change G-code"), 0); optgroup = page->new_optgroup(_(L("Tool change G-code")), 0);
option = optgroup->get_option("toolchange_gcode"); option = optgroup->get_option("toolchange_gcode");
option.opt.full_width = true; option.opt.full_width = true;
option.opt.height = 150; option.opt.height = 150;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(_L("Between objects G-code (for sequential printing)"), 0); optgroup = page->new_optgroup(_(L("Between objects G-code (for sequential printing)")), 0);
option = optgroup->get_option("between_objects_gcode"); option = optgroup->get_option("between_objects_gcode");
option.opt.full_width = true; option.opt.full_width = true;
option.opt.height = 150; option.opt.height = 150;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
page = add_options_page(_L("Notes"), "note.png"); page = add_options_page(_(L("Notes")), "note.png");
optgroup = page->new_optgroup(_L("Notes"), 0); optgroup = page->new_optgroup(_(L("Notes")), 0);
option = optgroup->get_option("printer_notes"); option = optgroup->get_option("printer_notes");
option.opt.full_width = true; option.opt.full_width = true;
option.opt.height = 250; option.opt.height = 250;
@ -1182,24 +1183,24 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){
void TabPrinter::build_extruder_pages(){ void TabPrinter::build_extruder_pages(){
for (auto extruder_idx = m_extruder_pages.size(); extruder_idx < m_extruders_count; ++extruder_idx){ for (auto extruder_idx = m_extruder_pages.size(); extruder_idx < m_extruders_count; ++extruder_idx){
//# build page //# build page
auto page = add_options_page(_L("Extruder ") + wxString::Format(_T("%i"), extruder_idx + 1), "funnel.png", true); auto page = add_options_page(_(L("Extruder ")) + wxString::Format(_T("%i"), extruder_idx + 1), "funnel.png", true);
m_extruder_pages.push_back(page); m_extruder_pages.push_back(page);
auto optgroup = page->new_optgroup(_L("Size")); auto optgroup = page->new_optgroup(_(L("Size")));
optgroup->append_single_option_line("nozzle_diameter", extruder_idx); optgroup->append_single_option_line("nozzle_diameter", extruder_idx);
optgroup = page->new_optgroup(_L("Layer height limits")); optgroup = page->new_optgroup(_(L("Layer height limits")));
optgroup->append_single_option_line("min_layer_height", extruder_idx); optgroup->append_single_option_line("min_layer_height", extruder_idx);
optgroup->append_single_option_line("max_layer_height", extruder_idx); optgroup->append_single_option_line("max_layer_height", extruder_idx);
optgroup = page->new_optgroup(_L("Position (for multi-extruder printers)")); optgroup = page->new_optgroup(_(L("Position (for multi-extruder printers)")));
optgroup->append_single_option_line("extruder_offset", extruder_idx); optgroup->append_single_option_line("extruder_offset", extruder_idx);
optgroup = page->new_optgroup(_L("Retraction")); optgroup = page->new_optgroup(_(L("Retraction")));
optgroup->append_single_option_line("retract_length", extruder_idx); optgroup->append_single_option_line("retract_length", extruder_idx);
optgroup->append_single_option_line("retract_lift", extruder_idx); optgroup->append_single_option_line("retract_lift", extruder_idx);
Line line = { _L("Only lift Z"), "" }; Line line = { _(L("Only lift Z")), "" };
line.append_option(optgroup->get_option("retract_lift_above", extruder_idx)); line.append_option(optgroup->get_option("retract_lift_above", extruder_idx));
line.append_option(optgroup->get_option("retract_lift_below", extruder_idx)); line.append_option(optgroup->get_option("retract_lift_below", extruder_idx));
optgroup->append_line(line); optgroup->append_line(line);
@ -1212,11 +1213,11 @@ void TabPrinter::build_extruder_pages(){
optgroup->append_single_option_line("wipe", extruder_idx); optgroup->append_single_option_line("wipe", extruder_idx);
optgroup->append_single_option_line("retract_before_wipe", extruder_idx); optgroup->append_single_option_line("retract_before_wipe", extruder_idx);
optgroup = page->new_optgroup(_L("Retraction when tool is disabled (advanced settings for multi-extruder setups)")); optgroup = page->new_optgroup(_(L("Retraction when tool is disabled (advanced settings for multi-extruder setups)")));
optgroup->append_single_option_line("retract_length_toolchange", extruder_idx); optgroup->append_single_option_line("retract_length_toolchange", extruder_idx);
optgroup->append_single_option_line("retract_restart_extra_toolchange", extruder_idx); optgroup->append_single_option_line("retract_restart_extra_toolchange", extruder_idx);
optgroup = page->new_optgroup(_L("Preview")); optgroup = page->new_optgroup(_(L("Preview")));
optgroup->append_single_option_line("extruder_colour", extruder_idx); optgroup->append_single_option_line("extruder_colour", extruder_idx);
} }
@ -1228,7 +1229,7 @@ void TabPrinter::build_extruder_pages(){
// # rebuild page list // # rebuild page list
PageShp page_note = m_pages.back(); PageShp page_note = m_pages.back();
m_pages.pop_back(); m_pages.pop_back();
while (m_pages.back()->title().find(_L("Extruder")) != std::string::npos) while (m_pages.back()->title().find(_(L("Extruder"))) != std::string::npos)
m_pages.pop_back(); m_pages.pop_back();
for (auto page_extruder : m_extruder_pages) for (auto page_extruder : m_extruder_pages)
m_pages.push_back(page_extruder); m_pages.push_back(page_extruder);
@ -1306,9 +1307,9 @@ void TabPrinter::update(){
if (use_firmware_retraction && wipe) { if (use_firmware_retraction && wipe) {
auto dialog = new wxMessageDialog(parent(), auto dialog = new wxMessageDialog(parent(),
_L("The Wipe option is not available when using the Firmware Retraction mode.\n" _(L("The Wipe option is not available when using the Firmware Retraction mode.\n"
"\nShall I disable it in order to enable Firmware Retraction?"), "\nShall I disable it in order to enable Firmware Retraction?")),
_L("Firmware Retraction"), wxICON_WARNING | wxYES | wxNO); _(L("Firmware Retraction")), wxICON_WARNING | wxYES | wxNO);
DynamicPrintConfig new_conf = *m_config; DynamicPrintConfig new_conf = *m_config;
if (dialog->ShowModal() == wxID_YES) { if (dialog->ShowModal() == wxID_YES) {
@ -1463,8 +1464,8 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr
auto type_name = presets->name(); auto type_name = presets->name();
auto tab = " "; auto tab = " ";
auto name = old_preset.is_default ? auto name = old_preset.is_default ?
_L("Default ") + type_name + _L(" preset") : _(L("Default ")) + type_name + _(L(" preset")) :
(type_name + _L(" preset\n") + tab + old_preset.name); (type_name + _(L(" preset\n")) + tab + old_preset.name);
// Collect descriptions of the dirty options. // Collect descriptions of the dirty options.
std::vector<std::string> option_names; std::vector<std::string> option_names;
for(auto opt_key: presets->current_dirty_options()) { for(auto opt_key: presets->current_dirty_options()) {
@ -1482,11 +1483,11 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr
for (auto changed_name : option_names) for (auto changed_name : option_names)
changes += tab + changed_name + "\n"; changes += tab + changed_name + "\n";
auto message = (!new_printer_name.empty()) ? auto message = (!new_printer_name.empty()) ?
name + _L("\n\nis not compatible with printer\n") +tab + new_printer_name+ _L("\n\nand it has the following unsaved changes:") : name + _(L("\n\nis not compatible with printer\n")) +tab + new_printer_name+ _(L("\n\nand it has the following unsaved changes:")) :
name + _L("\n\nhas the following unsaved changes:"); name + _(L("\n\nhas the following unsaved changes:"));
auto confirm = new wxMessageDialog(parent(), auto confirm = new wxMessageDialog(parent(),
message + "\n" +changes +_L("\n\nDiscard changes and continue anyway?"), message + "\n" +changes +_(L("\n\nDiscard changes and continue anyway?")),
_L("Unsaved Changes"), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); _(L("Unsaved Changes")), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
return confirm->ShowModal() == wxID_YES; return confirm->ShowModal() == wxID_YES;
} }
@ -1554,21 +1555,13 @@ void Tab::save_preset(std::string name /*= ""*/)
return; return;
name = dlg->get_name(); name = dlg->get_name();
if (name == ""){ if (name == ""){
show_error(this, _L("The supplied name is empty. It can't be saved.")); show_error(this, _(L("The supplied name is empty. It can't be saved.")));
return; return;
} }
} }
try
{
// Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini
m_presets->save_current_preset(name);
}
catch (const std::exception &e)
{
show_error(this, _L("Something is wrong. It can't be saved."));
return;
}
// Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini
m_presets->save_current_preset(name);
// Mark the print & filament enabled if they are compatible with the currently selected preset. // Mark the print & filament enabled if they are compatible with the currently selected preset.
m_preset_bundle->update_compatible_with_printer(false); m_preset_bundle->update_compatible_with_printer(false);
// Add the new item into the UI component, remove dirty flags and activate the saved item. // Add the new item into the UI component, remove dirty flags and activate the saved item.
@ -1582,10 +1575,10 @@ void Tab::delete_preset()
{ {
auto current_preset = m_presets->get_selected_preset(); auto current_preset = m_presets->get_selected_preset();
// Don't let the user delete the ' - default - ' configuration. // Don't let the user delete the ' - default - ' configuration.
wxString action = current_preset.is_external ? _L("remove") : _L("delete"); wxString action = current_preset.is_external ? _(L("remove")) : _(L("delete"));
wxString msg = _L("Are you sure you want to ") + action + _L(" the selected preset?"); wxString msg = _(L("Are you sure you want to ")) + action + _(L(" the selected preset?"));
action = current_preset.is_external ? _L("Remove") : _L("Delete"); action = current_preset.is_external ? _(L("Remove")) : _(L("Delete"));
wxString title = action + _L(" Preset"); wxString title = action + _(L(" Preset"));
if (current_preset.is_default || if (current_preset.is_default ||
wxID_YES != wxMessageDialog(parent(), msg, title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal()) wxID_YES != wxMessageDialog(parent(), msg, title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal())
return; return;
@ -1637,10 +1630,10 @@ void Tab::update_ui_from_settings()
// Return a callback to create a Tab widget to mark the preferences as compatible / incompatible to the current printer. // Return a callback to create a Tab widget to mark the preferences as compatible / incompatible to the current printer.
wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn) wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn)
{ {
*checkbox = new wxCheckBox(parent, wxID_ANY, _L("All")); *checkbox = new wxCheckBox(parent, wxID_ANY, _(L("All")));
*btn = new wxButton(parent, wxID_ANY, _L("Set")+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); *btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
(*btn)->SetBitmap(wxBitmap(wxString::FromUTF8(Slic3r::var("printer_empty.png").c_str()), wxBITMAP_TYPE_PNG)); (*btn)->SetBitmap(wxBitmap(from_u8(Slic3r::var("printer_empty.png")), wxBITMAP_TYPE_PNG));
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add((*checkbox), 0, wxALIGN_CENTER_VERTICAL); sizer->Add((*checkbox), 0, wxALIGN_CENTER_VERTICAL);
@ -1668,8 +1661,8 @@ wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox
} }
auto dlg = new wxMultiChoiceDialog(parent, auto dlg = new wxMultiChoiceDialog(parent,
_L("Select the printers this profile is compatible with."), _(L("Select the printers this profile is compatible with.")),
_L("Compatible printers"), presets); _(L("Compatible printers")), presets);
// # Collect and set indices of printers marked as compatible. // # Collect and set indices of printers marked as compatible.
wxArrayInt selections; wxArrayInt selections;
auto *compatible_printers = dynamic_cast<const ConfigOptionStrings*>(m_config->option("compatible_printers")); auto *compatible_printers = dynamic_cast<const ConfigOptionStrings*>(m_config->option("compatible_printers"));
@ -1752,12 +1745,12 @@ ConfigOptionsGroupShp Page::new_optgroup(wxString title, int noncommon_label_wid
void SavePresetWindow::build(wxString title, std::string default_name, std::vector<std::string> &values) void SavePresetWindow::build(wxString title, std::string default_name, std::vector<std::string> &values)
{ {
auto text = new wxStaticText(this, wxID_ANY, _L("Save ") + title + _L(" as:"), auto text = new wxStaticText(this, wxID_ANY, _(L("Save ")) + title + _(L(" as:")),
wxDefaultPosition, wxDefaultSize); wxDefaultPosition, wxDefaultSize);
m_combo = new wxComboBox(this, wxID_ANY, wxString::FromUTF8(default_name.c_str()), m_combo = new wxComboBox(this, wxID_ANY, from_u8(default_name),
wxDefaultPosition, wxDefaultSize, 0, 0, wxTE_PROCESS_ENTER); wxDefaultPosition, wxDefaultSize, 0, 0, wxTE_PROCESS_ENTER);
for (auto value : values) for (auto value : values)
m_combo->Append(wxString::FromUTF8(value.c_str())); m_combo->Append(from_u8(value));
auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL); auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
auto sizer = new wxBoxSizer(wxVERTICAL); auto sizer = new wxBoxSizer(wxVERTICAL);
@ -1786,10 +1779,10 @@ void SavePresetWindow::accept()
} }
} }
if (is_unusable_symbol) { if (is_unusable_symbol) {
show_error(this, _L("The supplied name is not valid; the following characters are not allowed:")+" <>:/\\|?*\""); show_error(this, _(L("The supplied name is not valid; the following characters are not allowed:"))+" <>:/\\|?*\"");
} }
else if (m_chosen_name.compare("- default -") == 0) { else if (m_chosen_name.compare("- default -") == 0) {
show_error(this, _L("The supplied name is not available.")); show_error(this, _(L("The supplied name is not available.")));
} }
else { else {
EndModal(wxID_OK); EndModal(wxID_OK);

View File

@ -179,7 +179,7 @@ class TabPrint : public Tab
public: public:
TabPrint() {} TabPrint() {}
TabPrint(wxNotebook* parent, bool no_controller) : TabPrint(wxNotebook* parent, bool no_controller) :
Tab(parent, _L("Print Settings"), "print", no_controller) {} Tab(parent, _(L("Print Settings")), "print", no_controller) {}
~TabPrint(){} ~TabPrint(){}
ogStaticText* m_recommended_thin_wall_thickness_description_line; ogStaticText* m_recommended_thin_wall_thickness_description_line;
@ -199,7 +199,7 @@ class TabFilament : public Tab
public: public:
TabFilament() {} TabFilament() {}
TabFilament(wxNotebook* parent, bool no_controller) : TabFilament(wxNotebook* parent, bool no_controller) :
Tab(parent, _L("Filament Settings"), "filament", no_controller) {} Tab(parent, _(L("Filament Settings")), "filament", no_controller) {}
~TabFilament(){} ~TabFilament(){}
void build() override; void build() override;
@ -225,7 +225,7 @@ public:
TabPrinter() {} TabPrinter() {}
TabPrinter(wxNotebook* parent, bool no_controller, bool is_disabled_btn_browse, bool is_user_agent) : TabPrinter(wxNotebook* parent, bool no_controller, bool is_disabled_btn_browse, bool is_user_agent) :
Tab(parent, _L("Printer Settings"), "printer", no_controller), Tab(parent, _(L("Printer Settings")), "printer", no_controller),
m_is_disabled_button_browse(is_disabled_btn_browse), m_is_disabled_button_browse(is_disabled_btn_browse),
m_is_user_agent(is_user_agent) {} m_is_user_agent(is_user_agent) {}
~TabPrinter(){} ~TabPrinter(){}
@ -245,7 +245,7 @@ public:
class SavePresetWindow :public wxDialog class SavePresetWindow :public wxDialog
{ {
public: public:
SavePresetWindow(wxWindow* parent) :wxDialog(parent, wxID_ANY, _L("Save preset")){} SavePresetWindow(wxWindow* parent) :wxDialog(parent, wxID_ANY, _(L("Save preset"))){}
~SavePresetWindow(){} ~SavePresetWindow(){}
std::string m_chosen_name; std::string m_chosen_name;

View File

@ -11,7 +11,7 @@ void TabIface::load_config(DynamicPrintConfig* config) { m_tab->load_config(*con
void TabIface::load_key_value(char* opt_key, char* value){ m_tab->load_key_value(opt_key, static_cast<std::string>(value)); } void TabIface::load_key_value(char* opt_key, char* value){ m_tab->load_key_value(opt_key, static_cast<std::string>(value)); }
bool TabIface::current_preset_is_dirty() { return m_tab->current_preset_is_dirty();} bool TabIface::current_preset_is_dirty() { return m_tab->current_preset_is_dirty();}
void TabIface::OnActivate() { return m_tab->OnActivate();} void TabIface::OnActivate() { return m_tab->OnActivate();}
std::string TabIface::title() { return m_tab->title().ToStdString();} std::string TabIface::title() { return m_tab->title().ToUTF8().data(); }
DynamicPrintConfig* TabIface::get_config() { return m_tab->get_config(); } DynamicPrintConfig* TabIface::get_config() { return m_tab->get_config(); }
PresetCollection* TabIface::get_presets() { return m_tab!=nullptr ? m_tab->get_presets() : nullptr; } PresetCollection* TabIface::get_presets() { return m_tab!=nullptr ? m_tab->get_presets() : nullptr; }
std::vector<std::string> TabIface::get_dependent_tabs() { return m_tab->get_dependent_tabs(); } std::vector<std::string> TabIface::get_dependent_tabs() { return m_tab->get_dependent_tabs(); }

View File

@ -35,11 +35,11 @@ void set_tab_panel(SV *ui)
void add_debug_menu(SV *ui, int event_language_change) void add_debug_menu(SV *ui, int event_language_change)
%code%{ Slic3r::GUI::add_debug_menu((wxMenuBar*)wxPli_sv_2_object(aTHX_ ui, "Wx::MenuBar"), event_language_change); %}; %code%{ Slic3r::GUI::add_debug_menu((wxMenuBar*)wxPli_sv_2_object(aTHX_ ui, "Wx::MenuBar"), event_language_change); %};
void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config, void create_preset_tabs(PresetBundle *preset_bundle, bool no_controller,
bool no_controller, bool is_disabled_button_browse, bool is_user_agent, bool is_disabled_button_browse, bool is_user_agent,
int event_value_change, int event_presets_changed, int event_value_change, int event_presets_changed,
int event_button_browse, int event_button_test) int event_button_browse, int event_button_test)
%code%{ Slic3r::GUI::create_preset_tabs(preset_bundle, app_config, no_controller, %code%{ Slic3r::GUI::create_preset_tabs(preset_bundle, no_controller,
is_disabled_button_browse, is_user_agent, is_disabled_button_browse, is_user_agent,
event_value_change, event_presets_changed, event_value_change, event_presets_changed,
event_button_browse, event_button_test); %}; event_button_browse, event_button_test); %};
@ -55,3 +55,9 @@ void create_combochecklist(SV *ui, std::string text, std::string items, bool ini
int combochecklist_get_flags(SV *ui) int combochecklist_get_flags(SV *ui)
%code%{ RETVAL=Slic3r::GUI::combochecklist_get_flags((wxComboCtrl*)wxPli_sv_2_object(aTHX_ ui, "Wx::ComboCtrl")); %}; %code%{ RETVAL=Slic3r::GUI::combochecklist_get_flags((wxComboCtrl*)wxPli_sv_2_object(aTHX_ ui, "Wx::ComboCtrl")); %};
void set_app_config(AppConfig *app_config)
%code%{ Slic3r::GUI::set_app_config(app_config); %};
void open_preferences_dialog(int preferences_event)
%code%{ Slic3r::GUI::open_preferences_dialog(preferences_event); %};