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

@ -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 base 'Wx::Frame';
use Wx::Locale gettext => 'L';
our $qs_last_input_file;
our $qs_last_output_file;
our $last_config;
@ -48,7 +50,8 @@ sub new {
$self->{no_plater} = $params{no_plater};
$self->{loaded} = 0;
$self->{lang_ch_event} = $params{lang_ch_event};
$self->{preferences_event} = $params{preferences_event};
# initialize tabpanel and menubar
$self->_init_tabpanel;
$self->_init_menubar;
@ -60,7 +63,7 @@ sub new {
# initialize status bar
$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->{loaded} = 1;
@ -112,9 +115,9 @@ sub _init_tabpanel {
});
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}) {
$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)
if $dlg->ShowModal == wxID_OK;
} 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 ,
@ -205,19 +208,19 @@ sub _init_tabpanel {
'X-Api-Key' => $config->octoprint_apikey,
);
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 {
Slic3r::GUI::show_error($self,
"I wasn't able to connect to OctoPrint (" . $res->status_line . "). "
. "Check hostname and OctoPrint version (at least 1.1.0 is required).");
L("I wasn't able to connect to OctoPrint (") . $res->status_line .
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
$self->{is_disabled_button_browse} = (!eval "use Net::Bonjour; 1") ? 1 : 0 ;
# A variable to inform C++ Tab implementation about user_agent
$self->{is_user_agent} = (eval "use LWP::UserAgent; 1") ? 1 : 0 ;
Slic3r::GUI::create_preset_tabs(wxTheApp->{preset_bundle}, wxTheApp->{app_config},
$self->{no_controller}, $self->{is_disabled_button_browse},
Slic3r::GUI::create_preset_tabs(wxTheApp->{preset_bundle}, $self->{no_controller},
$self->{is_disabled_button_browse},
$self->{is_user_agent},
$VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT,
$BUTTON_BROWSE_EVENT, $BUTTON_TEST_EVENT);
@ -245,59 +248,61 @@ sub _init_menubar {
# File menu
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};
}, 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;
}, 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;
}, 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;
}, 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;
}, undef, 'lorry_go.png');
$fileMenu->AppendSeparator();
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 {
$self->quick_slice;
$repeat->Enable(defined $Slic3r::GUI::MainFrame::last_input_file);
});
}, 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 {
$self->quick_slice(save_as => 1);
$repeat->Enable(defined $Slic3r::GUI::MainFrame::last_input_file);
});
}, 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 {
$self->quick_slice(reslice => 1);
});
}, undef, 'cog_go.png');
$repeat->Enable(0);
$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);
}, undef, 'shape_handles.png');
$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');
$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;
}, undef, 'wrench.png');
$fileMenu->AppendSeparator();
# Cmd+, is standard on OS X - what about other operating systems?
$self->_append_menu_item($fileMenu, "Preferences…\tCtrl+,", 'Application preferences', sub {
Slic3r::GUI::Preferences->new($self)->ShowModal;
$self->_append_menu_item($fileMenu, L("Preferences…\tCtrl+,"), L('Application preferences'), sub {
# Slic3r::GUI::Preferences->new($self)->ShowModal;
# It's in C++ part now
Slic3r::GUI::open_preferences_dialog($self->{preferences_event});
}, wxID_PREFERENCES);
$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);
}, wxID_EXIT);
}
@ -307,16 +312,16 @@ sub _init_menubar {
my $plater = $self->{plater};
$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;
}, 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;
}, 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;
}, 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;
}, undef, 'brick_go.png');
@ -329,13 +334,13 @@ sub _init_menubar {
{
my $tab_offset = 0;
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);
}, undef, 'application_view_tile.png');
$tab_offset += 1;
}
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);
}, undef, 'printer_empty.png');
$tab_offset += 1;
@ -343,13 +348,13 @@ sub _init_menubar {
if ($tab_offset > 0) {
$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);
}, 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);
}, 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);
}, undef, 'printer_empty.png');
}
@ -361,47 +366,47 @@ sub _init_menubar {
# as the simple numeric accelerators spoil all numeric data entry.
# The camera control accelerators are captured by 3DScene Perl module instead.
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->('Top', '1'), '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->('Front', '3'), '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->('Left', '5'), '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('Iso'), '0'), L('Iso View') , sub { $self->select_view('iso' ); });
$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->(L('Bottom'), '2'), L('Bottom View') , sub { $self->select_view('bottom' ); });
$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->(L('Rear'), '4'), L('Rear View') , sub { $self->select_view('rear' ); });
$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->(L('Right'), '6'), L('Right View') , sub { $self->select_view('right' ); });
}
# Help menu
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.
$self->config_wizard(0);
});
$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/');
});
$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');
});
# my $versioncheck = $self->_append_menu_item($helpMenu, "Check for &Updates...", 'Check for new Slic3r versions', sub {
# wxTheApp->check_version(1);
# });
# $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/');
});
$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/');
});
$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;
});
$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');
});
$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;
});
}
@ -411,16 +416,15 @@ sub _init_menubar {
# will not be handled correctly
{
my $menubar = Wx::MenuBar->new;
$menubar->Append($fileMenu, "&File");
$menubar->Append($self->{plater_menu}, "&Plater") if $self->{plater_menu};
$menubar->Append($self->{object_menu}, "&Object") if $self->{object_menu};
$menubar->Append($windowMenu, "&Window");
$menubar->Append($self->{viewMenu}, "&View") if $self->{viewMenu};
$menubar->Append($fileMenu, L("&File"));
$menubar->Append($self->{plater_menu}, L("&Plater")) if $self->{plater_menu};
$menubar->Append($self->{object_menu}, L("&Object")) if $self->{object_menu};
$menubar->Append($windowMenu, L("&Window"));
$menubar->Append($self->{viewMenu}, L("&View")) if $self->{viewMenu};
# Add an optional debug menu
# (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});
$menubar->Append($helpMenu, "&Help");
$menubar->Append($helpMenu, L("&Help"));
$self->SetMenuBar($menubar);
}
}
@ -451,7 +455,7 @@ sub quick_slice {
# select input file
my $input_file;
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, "",
&Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if ($dialog->ShowModal != wxID_OK) {
@ -463,13 +467,13 @@ sub quick_slice {
$qs_last_input_file = $input_file unless $params{export_svg};
} else {
if (!defined $qs_last_input_file) {
Wx::MessageDialog->new($self, "No previously sliced file.",
'Error', wxICON_ERROR | wxOK)->ShowModal();
Wx::MessageDialog->new($self, L("No previously sliced file."),
L('Error'), wxICON_ERROR | wxOK)->ShowModal();
return;
}
if (! -e $qs_last_input_file) {
Wx::MessageDialog->new($self, "Previously sliced file ($qs_last_input_file) not found.",
'File Not Found', wxICON_ERROR | wxOK)->ShowModal();
Wx::MessageDialog->new($self, L("Previously sliced file (").$qs_last_input_file.L(") not found."),
L('File Not Found'), wxICON_ERROR | wxOK)->ShowModal();
return;
}
$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.
$output_file = $sprint->output_filepath;
$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)),
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) {
@ -522,7 +526,7 @@ sub quick_slice {
}
# 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);
$progress_dialog->Pulse;
@ -542,9 +546,9 @@ sub quick_slice {
$progress_dialog->Destroy;
undef $progress_dialog;
my $message = "$input_file_basename was successfully sliced.";
my $message = $input_file_basename.L(" was successfully sliced.");
wxTheApp->notify($message);
Wx::MessageDialog->new($self, $message, 'Slicing Done!',
Wx::MessageDialog->new($self, $message, L('Slicing Done!'),
wxOK | wxICON_INFORMATION)->ShowModal;
};
Slic3r::GUI::catch_error($self, sub { $progress_dialog->Destroy if $progress_dialog });
@ -560,7 +564,7 @@ sub repair_stl {
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, "",
&Slic3r::GUI::FILE_WILDCARDS->{stl}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if ($dialog->ShowModal != wxID_OK) {
@ -574,7 +578,7 @@ sub repair_stl {
my $output_file = $input_file;
{
$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);
if ($dlg->ShowModal != wxID_OK) {
$dlg->Destroy;
@ -588,7 +592,7 @@ sub repair_stl {
$tmesh->ReadSTLFile($input_file);
$tmesh->repair;
$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 {
@ -599,7 +603,7 @@ sub export_config {
eval { $config->validate; };
Slic3r::GUI::catch_error($self) and return;
# 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 ? basename($last_config) : "config.ini",
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
@ -617,7 +621,7 @@ sub load_config_file {
my ($self, $file) = @_;
if (!$file) {
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,
"config.ini",
'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; };
Slic3r::GUI::catch_error($self) and return;
# 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,
"Slic3r_config_bundle.ini",
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
@ -661,7 +665,7 @@ sub load_configbundle {
my ($self, $file, $reset_user_profile) = @_;
return unless $self->check_unsaved_changes;
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,
"config.ini",
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
@ -681,7 +685,7 @@ sub load_configbundle {
$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);
}
@ -743,8 +747,8 @@ sub check_unsaved_changes {
if (@dirty) {
my $titles = join ', ', @dirty;
my $confirm = Wx::MessageDialog->new($self, "You have unsaved changes ($titles). Discard changes and continue anyway?",
'Unsaved Presets', wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT);
my $confirm = Wx::MessageDialog->new($self, L("You have unsaved changes ").($titles).L(". Discard changes and continue anyway?"),
L('Unsaved Presets'), wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT);
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_LAYER_EDITING => &Wx::NewId;
use Wx::Locale gettext => 'L';
# package variables to avoid passing lexicals to threads
our $PROGRESS_BAR_EVENT : shared = Wx::NewEventType;
our $ERROR_EVENT : shared = Wx::NewEventType;
@ -99,7 +101,7 @@ sub new {
# Initialize 3D plater
if ($Slic3r::GUI::have_OpenGL) {
$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_double_click($on_double_click);
$self->{canvas3D}->set_on_right_click(sub { $on_right_click->($self->{canvas3D}, @_); });
@ -133,7 +135,7 @@ sub new {
# Initialize 2D preview canvas
$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_double_click($on_double_click);
$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->{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;
}
# Initialize toolpaths preview
if ($Slic3r::GUI::have_OpenGL) {
$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 {
@ -172,37 +174,37 @@ sub new {
if (!&Wx::wxMSW) {
Wx::ToolTip::Enable(1);
$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_REMOVE, "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_ARRANGE, "Arrange", Wx::Bitmap->new(Slic3r::var("bricks.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, L("Delete"), Wx::Bitmap->new(Slic3r::var("brick_delete.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, L("Arrange"), Wx::Bitmap->new(Slic3r::var("bricks.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddSeparator;
$self->{htoolbar}->AddTool(TB_MORE, "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_MORE, L("More"), Wx::Bitmap->new(Slic3r::var("add.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}->AddTool(TB_45CCW, "45° ccw", Wx::Bitmap->new(Slic3r::var("arrow_rotate_anticlockwise.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddTool(TB_45CW, "45° cw", Wx::Bitmap->new(Slic3r::var("arrow_rotate_clockwise.png"), wxBITMAP_TYPE_PNG), '');
$self->{htoolbar}->AddTool(TB_SCALE, "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_CUT, "Cut…", Wx::Bitmap->new(Slic3r::var("package.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, L("45° cw"), Wx::Bitmap->new(Slic3r::var("arrow_rotate_clockwise.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, L("Split"), Wx::Bitmap->new(Slic3r::var("shape_ungroup.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}->AddTool(TB_SETTINGS, "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_SETTINGS, L("Settings…"), Wx::Bitmap->new(Slic3r::var("cog.png"), wxBITMAP_TYPE_PNG), '');
$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 {
my %tbar_buttons = (
add => "Add…",
remove => "Delete",
reset => "Delete All",
arrange => "Arrange",
add => L("Add…"),
remove => L("Delete"),
reset => L("Delete All"),
arrange => L("Arrange"),
increase => "",
decrease => "",
rotate45ccw => "",
rotate45cw => "",
changescale => "Scale…",
split => "Split",
cut => "Cut…",
settings => "Settings…",
layer_editing => "Layer editing",
changescale => L("Scale…"),
split => L("Split"),
cut => L("Cut…"),
settings => L("Settings…"),
layer_editing => L("Layer editing"),
);
$self->{btoolbar} = Wx::BoxSizer->new(wxHORIZONTAL);
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,
wxLC_SINGLE_SEL | wxLC_REPORT | wxBORDER_SUNKEN | wxTAB_TRAVERSAL | wxWANTS_CHARS );
$self->{list}->InsertColumn(0, "Name", wxLIST_FORMAT_LEFT, 145);
$self->{list}->InsertColumn(1, "Copies", wxLIST_FORMAT_CENTER, 45);
$self->{list}->InsertColumn(2, "Scale", wxLIST_FORMAT_CENTER, wxLIST_AUTOSIZE_USEHEADER);
$self->{list}->InsertColumn(0, L("Name"), wxLIST_FORMAT_LEFT, 145);
$self->{list}->InsertColumn(1, L("Copies"), wxLIST_FORMAT_CENTER, 45);
$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_DESELECTED($self, $self->{list}, \&list_item_deselected);
EVT_LIST_ITEM_ACTIVATED($self, $self->{list}, \&list_item_activated);
@ -231,11 +233,11 @@ sub new {
});
# right pane buttons
$self->{btn_export_gcode} = Wx::Button->new($self, -1, "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_print} = Wx::Button->new($self, -1, "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_export_stl} = Wx::Button->new($self, -1, "Export STL…", 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, L("Slice now"), 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, L("Send to printer"), 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_stl}->SetFont($Slic3r::GUI::small_font);
$self->{btn_print}->Hide;
@ -362,9 +364,9 @@ sub new {
$presets->AddGrowableCol(1, 1);
$presets->SetFlexibleDirection(wxHORIZONTAL);
my %group_labels = (
print => 'Print settings',
filament => 'Filament',
printer => 'Printer',
print => L('Print settings'),
filament => L('Filament'),
printer => L('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,
@ -393,7 +395,7 @@ sub new {
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->SetMinSize([350,-1]);
my $grid_sizer = Wx::FlexGridSizer->new(3, 4, 5, 5);
@ -403,11 +405,11 @@ sub new {
$object_info_sizer->Add($grid_sizer, 0, wxEXPAND);
my @info = (
size => "Size",
volume => "Volume",
facets => "Facets",
materials => "Materials",
manifold => "Manifold",
size => L("Size"),
volume => L("Volume"),
facets => L("Facets"),
materials => L("Materials"),
manifold => L("Manifold"),
);
while (my $field = shift @info) {
my $label = shift @info;
@ -433,7 +435,7 @@ sub new {
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->SetMinSize([350,-1]);
my $grid_sizer = Wx::FlexGridSizer->new(2, 2, 5, 5);
@ -442,11 +444,11 @@ sub new {
$grid_sizer->AddGrowableCol(3, 1);
$print_info_sizer->Add($grid_sizer, 0, wxEXPAND);
my @info = (
fil_m => "Used Filament (m)",
fil_mm3 => "Used Filament (mm\x{00B3})",
fil_g => "Used Filament (g)",
cost => "Cost",
time => "Estimated printing time",
fil_m => L("Used Filament (m)"),
fil_mm3 => L("Used Filament (mm³)"),
fil_g => L("Used Filament (g)"),
cost => L("Cost"),
time => L("Estimated printing time"),
);
while (my $field = shift @info) {
my $label = shift @info;
@ -624,7 +626,7 @@ sub load_files {
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);
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;
local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self);
@ -638,7 +640,7 @@ sub load_files {
# For all input files.
for (my $i = 0; $i < @$input_files; $i += 1) {
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;
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) {
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"
. "this file as a single object having multiple parts?\n",
'Multi-part object detected', wxICON_WARNING | wxYES | wxNO);
. "this file as a single object having multiple parts?\n"),
L('Multi-part object detected'), wxICON_WARNING | wxYES | wxNO);
$model->convert_multipart_object if $dialog->ShowModal() == wxID_YES;
}
@ -675,10 +677,10 @@ sub load_files {
if ($new_model) {
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"
. "these files to represent a single object having multiple parts?\n",
'Multi-part object detected', wxICON_WARNING | wxYES | wxNO);
. "these files to represent a single object having multiple parts?\n"),
L('Multi-part object detected'), wxICON_WARNING | wxYES | wxNO);
$new_model->convert_multipart_object if $dialog->ShowModal() == wxID_YES;
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]));
$process_dialog->Destroy;
$self->statusbar->SetStatusText("Loaded " . join(',', @loaded_files));
$self->statusbar->SetStatusText(L("Loaded ") . join(',', @loaded_files));
return @obj_idx;
}
@ -739,8 +741,8 @@ sub load_model_objects {
if ($scaled_down) {
Slic3r::GUI::show_info(
$self,
'Your object appears to be too large, so it was automatically scaled down to fit your print bed.',
'Object too large?',
L('Your object appears to be too large, so it was automatically scaled down to fit your print bed.'),
L('Object too large?'),
);
}
@ -895,7 +897,7 @@ sub set_number_of_copies {
my $model_object = $self->{model}->objects->[$obj_idx];
# 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;
if ($diff == 0) {
# no variation
@ -922,9 +924,9 @@ sub _get_number_from_user {
Wx::MessageBox(
$error_message .
(($only_positive && $value <= 0) ?
": $value\nNon-positive value." :
": $value\nNot a numeric value."),
"Slic3r Error", wxOK | wxICON_EXCLAMATION, $self);
": ".$value.L("\nNon-positive value.") :
": ".$value.L("\nNot a numeric value.")),
L("Slic3r Error"), wxOK | wxICON_EXCLAMATION, $self);
$default = $value;
}
}
@ -945,7 +947,7 @@ sub rotate {
if (!defined $angle) {
my $axis_name = $axis == X ? 'X' : $axis == Y ? 'Y' : 'Z';
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 '';
}
@ -1025,12 +1027,12 @@ sub changescale {
if ($tosize) {
my $cursize = $object_size->[$axis];
my $newsize = $self->_get_number_from_user(
sprintf('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);
sprintf(L('Enter the new size for the selected object (print bed: %smm):'), unscale($bed_size->[$axis])),
L("Scale along ").$axis_name, L('Invalid scaling value entered'), $cursize, 1);
return if $newsize eq '';
$scale = $newsize / $cursize * 100;
} 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 '';
}
@ -1051,12 +1053,12 @@ sub changescale {
my $scale;
if ($tosize) {
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 '';
$scale = $model_instance->scaling_factor * $newsize / $cursize * 100;
} else {
# 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 '';
}
@ -1107,7 +1109,7 @@ sub split_object {
my $current_model_object = $new_model->get_object($obj_idx);
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;
}
@ -1116,7 +1118,7 @@ sub split_object {
my @model_objects = @{$current_model_object->split_object};
if (@model_objects == 1) {
$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;
return;
}
@ -1281,7 +1283,7 @@ sub reslice {
$self->async_apply_config;
$self->statusbar->SetCancelCallback(sub {
$self->stop_background_process;
$self->statusbar->SetStatusText("Slicing cancelled");
$self->statusbar->SetStatusText(L("Slicing cancelled"));
# this updates buttons status
$self->object_list_changed;
});
@ -1295,7 +1297,7 @@ sub export_gcode {
return if !@{$self->{objects}};
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;
}
@ -1326,7 +1328,7 @@ sub export_gcode {
} else {
my $default_output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') };
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)),
basename($default_output_file), &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if ($dlg->ShowModal != wxID_OK) {
@ -1343,7 +1345,7 @@ sub export_gcode {
$self->statusbar->SetCancelCallback(sub {
$self->stop_background_process;
$self->statusbar->SetStatusText("Export cancelled");
$self->statusbar->SetStatusText(L("Export cancelled"));
$self->{export_gcode_output_file} = undef;
$self->{send_gcode_file} = undef;
@ -1440,16 +1442,16 @@ sub on_export_completed {
if ($result) {
# G-code file exported successfully.
if ($self->{print_file}) {
$message = "File added to print queue";
$message = L("File added to print queue");
$do_print = 1;
} 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;
} 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 {
$message = "Export failed";
$message = L("Export failed");
}
$self->{export_gcode_output_file} = undef;
$self->statusbar->SetStatusText($message);
@ -1519,9 +1521,9 @@ sub send_gcode {
$self->statusbar->StopBusy;
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 {
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);
$self->statusbar->SetStatusText($message);
}
@ -1534,7 +1536,7 @@ sub export_stl {
my $output_file = $self->_get_export_file('STL') or return;
# Store a binary STL.
$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 {
@ -1576,7 +1578,7 @@ sub export_object_stl {
# Ask user for a file name to write into.
my $output_file = $self->_get_export_file('STL') or return;
$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 {
@ -1587,11 +1589,11 @@ sub export_amf {
my $res = $self->{model}->store_amf($output_file, $self->{print});
if ($res)
{
$self->statusbar->SetStatusText("AMF file exported to $output_file");
$self->statusbar->SetStatusText(L("AMF file exported to ").$output_file);
}
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});
if ($res)
{
$self->statusbar->SetStatusText("3MF file exported to $output_file");
$self->statusbar->SetStatusText(L("3MF file exported to ").$output_file);
}
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} // '') };
Slic3r::GUI::catch_error($self) and return undef;
$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);
if ($dlg->ShowModal != wxID_OK) {
$dlg->Destroy;
@ -1843,7 +1845,7 @@ sub object_cut_dialog {
}
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;
}
@ -1953,19 +1955,19 @@ sub selection_changed {
if (my $stats = $model_object->mesh_stats) {
$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)})) {
$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;
# we don't show normals_fixed because we never provide normals
# 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)};
$self->{object_info_manifold}->SetToolTipString($message);
$self->{object_info_manifold_warning_icon}->SetToolTipString($message);
} else {
$self->{object_info_manifold}->SetLabel("Yes");
$self->{object_info_manifold}->SetLabel(L("Yes"));
}
} else {
$self->{object_info_facets}->SetLabel($object->facets);
@ -2016,99 +2018,99 @@ sub object_menu {
my $frame = $self->GetFrame;
my $menu = Wx::Menu->new;
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;
}, 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;
}, 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;
}, 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;
}, undef, 'textfield.png');
$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');
}, 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');
}, undef, 'arrow_rotate_anticlockwise.png');
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->_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);
}, 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);
}, 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);
}, undef, 'bullet_blue.png');
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->_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);
}, 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);
}, 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);
}, undef, 'bullet_blue.png');
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->_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);
});
$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);
}, 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);
}, 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);
}, undef, 'bullet_blue.png');
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->_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);
});
$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);
}, 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);
}, 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);
}, 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;
}, 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;
}, undef, 'package.png');
$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;
}, undef, 'cog.png');
$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;
}, 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;
}, undef, 'brick_go.png');
@ -2119,8 +2121,8 @@ sub object_menu {
sub select_view {
my ($self, $direction) = @_;
my $idx_page = $self->{preview_notebook}->GetSelection;
my $page = ($idx_page == &Wx::wxNOT_FOUND) ? '3D' : $self->{preview_notebook}->GetPageText($idx_page);
if ($page eq 'Preview') {
my $page = ($idx_page == &Wx::wxNOT_FOUND) ? L('3D') : $self->{preview_notebook}->GetPageText($idx_page);
if ($page eq L('Preview')) {
$self->{preview3D}->canvas->select_view($direction);
$self->{canvas3D}->set_viewport_from_scene($self->{preview3D}->canvas);
} else {