mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 12:11:15 -06:00 
			
		
		
		
	Merge remote-tracking branch 'remotes/origin/gui_translate_to_cpp'
This commit is contained in:
		
						commit
						69fc99edbb
					
				
					 26 changed files with 11863 additions and 6374 deletions
				
			
		|  | @ -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; | ||||
|     } | ||||
|      | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv