2015-12-04 20:25:45 +00:00
# include "GUI.hpp"
2018-03-27 11:44:18 +00:00
# include "WipeTowerDialog.hpp"
2015-12-04 20:25:45 +00:00
2017-11-02 15:21:34 +00:00
# include <assert.h>
2018-04-09 12:41:55 +00:00
# include <cmath>
2017-11-02 15:21:34 +00:00
2018-01-07 17:41:40 +00:00
# include <boost/lexical_cast.hpp>
2018-05-21 20:10:38 +00:00
# include <boost/algorithm/string.hpp>
2018-02-07 10:37:15 +00:00
# include <boost/format.hpp>
2018-02-02 11:38:35 +00:00
2015-12-04 20:25:45 +00:00
# if __APPLE__
# import <IOKit / pwr_mgt / IOPMLib.h>
# elif _WIN32
# include <Windows.h>
2017-12-13 13:45:10 +00:00
// Undefine min/max macros incompatible with the standard library
// For example, std::numeric_limits<std::streamsize>::max()
// produces some weird errors
# ifdef min
# undef min
# endif
# ifdef max
# undef max
# endif
2017-11-02 15:21:34 +00:00
# include "boost/nowide/convert.hpp"
2015-12-04 20:25:45 +00:00
# endif
2017-12-04 09:48:40 +00:00
# include <wx/app.h>
# include <wx/button.h>
2018-02-15 17:13:37 +00:00
# include <wx/dir.h>
# include <wx/filename.h>
2017-12-04 09:48:40 +00:00
# include <wx/frame.h>
# include <wx/menu.h>
# include <wx/notebook.h>
# include <wx/panel.h>
# include <wx/sizer.h>
2018-02-02 11:38:35 +00:00
# include <wx/combo.h>
2017-12-13 13:45:10 +00:00
# include <wx/window.h>
2018-04-16 14:52:11 +00:00
# include <wx/msgdlg.h>
2018-04-09 12:41:55 +00:00
# include <wx/settings.h>
2018-04-25 11:25:34 +00:00
# include <wx/collpane.h>
# include <wx/wupdlock.h>
2018-02-02 11:38:35 +00:00
2018-02-02 12:56:25 +00:00
# include "wxExtensions.hpp"
2017-12-04 09:48:40 +00:00
2018-01-23 10:42:04 +00:00
# include "Tab.hpp"
2018-01-23 10:37:19 +00:00
# include "TabIface.hpp"
2018-04-09 15:03:37 +00:00
# include "AboutDialog.hpp"
2018-01-05 14:11:33 +00:00
# include "AppConfig.hpp"
2018-04-10 14:27:42 +00:00
# include "ConfigSnapshotDialog.hpp"
2018-02-08 09:58:13 +00:00
# include "Utils.hpp"
2018-04-30 12:31:57 +00:00
# include "MsgDialog.hpp"
2018-03-13 11:39:57 +00:00
# include "ConfigWizard.hpp"
2018-02-22 10:12:29 +00:00
# include "Preferences.hpp"
2018-03-09 16:17:51 +00:00
# include "PresetBundle.hpp"
2018-04-27 10:29:18 +00:00
# include "UpdateDialogs.hpp"
2018-05-04 14:04:43 +00:00
# include "FirmwareDialog.hpp"
2017-12-05 14:54:01 +00:00
2018-04-16 14:52:11 +00:00
# include "../Utils/PresetUpdater.hpp"
2018-04-10 14:27:42 +00:00
# include "../Config/Snapshot.hpp"
2017-12-05 14:54:01 +00:00
2018-04-19 08:35:47 +00:00
2015-12-04 20:25:45 +00:00
namespace Slic3r { namespace GUI {
2015-12-05 10:48:24 +00:00
# if __APPLE__
2015-12-04 20:25:45 +00:00
IOPMAssertionID assertionID ;
2015-12-05 10:48:24 +00:00
# endif
2015-12-04 20:25:45 +00:00
2017-10-25 10:53:31 +00:00
void disable_screensaver ( )
2015-12-04 20:25:45 +00:00
{
# if __APPLE__
CFStringRef reasonForActivity = CFSTR ( " Slic3r " ) ;
IOReturn success = IOPMAssertionCreateWithName ( kIOPMAssertionTypeNoDisplaySleep ,
kIOPMAssertionLevelOn , reasonForActivity , & assertionID ) ;
// ignore result: success == kIOReturnSuccess
# elif _WIN32
2015-12-06 10:17:50 +00:00
SetThreadExecutionState ( ES_DISPLAY_REQUIRED | ES_CONTINUOUS ) ;
2015-12-04 20:25:45 +00:00
# endif
}
2017-10-25 10:53:31 +00:00
void enable_screensaver ( )
2015-12-04 20:25:45 +00:00
{
# if __APPLE__
IOReturn success = IOPMAssertionRelease ( assertionID ) ;
# elif _WIN32
2015-12-06 10:17:50 +00:00
SetThreadExecutionState ( ES_CONTINUOUS ) ;
2015-12-04 20:25:45 +00:00
# endif
}
2017-10-25 10:53:31 +00:00
bool debugged ( )
2016-04-13 18:45:44 +00:00
{
2016-04-13 18:51:03 +00:00
# ifdef _WIN32
2016-04-13 18:45:44 +00:00
return IsDebuggerPresent ( ) ;
2016-04-13 18:51:03 +00:00
# else
return false ;
# endif /* _WIN32 */
2016-04-13 18:45:44 +00:00
}
2017-10-25 10:53:31 +00:00
void break_to_debugger ( )
2016-04-13 18:45:44 +00:00
{
# ifdef _WIN32
if ( IsDebuggerPresent ( ) )
DebugBreak ( ) ;
# endif /* _WIN32 */
}
2017-12-04 09:48:40 +00:00
// Passing the wxWidgets GUI classes instantiated by the Perl part to C++.
wxApp * g_wxApp = nullptr ;
wxFrame * g_wxMainFrame = nullptr ;
wxNotebook * g_wxTabPanel = nullptr ;
2018-02-20 07:58:46 +00:00
AppConfig * g_AppConfig = nullptr ;
2018-03-09 16:17:51 +00:00
PresetBundle * g_PresetBundle = nullptr ;
2018-04-16 14:52:11 +00:00
PresetUpdater * g_PresetUpdater = nullptr ;
2018-04-09 12:41:55 +00:00
wxColour g_color_label_modified ;
wxColour g_color_label_sys ;
2018-04-18 11:32:21 +00:00
wxColour g_color_label_default ;
2017-12-04 09:48:40 +00:00
2018-02-09 10:04:34 +00:00
std : : vector < Tab * > g_tabs_list ;
2018-02-12 07:57:32 +00:00
wxLocale * g_wxLocale ;
2018-02-08 09:58:13 +00:00
2018-05-22 14:14:41 +00:00
std : : vector < std : : shared_ptr < ConfigOptionsGroup > > m_optgroups ;
double m_brim_width = 0.0 ;
2018-04-03 20:07:59 +00:00
wxButton * g_wiping_dialog_button = nullptr ;
2018-03-09 16:17:51 +00:00
2018-05-17 08:46:32 +00:00
//showed/hided controls according to the view mode
2018-05-21 12:49:31 +00:00
wxWindow * g_right_panel = nullptr ;
2018-05-17 08:46:32 +00:00
wxBoxSizer * g_frequently_changed_parameters_sizer = nullptr ;
wxBoxSizer * g_expert_mode_part_sizer = nullptr ;
wxBoxSizer * g_scrolled_window_sizer = nullptr ;
wxButton * g_btn_export_stl = nullptr ;
wxButton * g_btn_reslice = nullptr ;
wxButton * g_btn_print = nullptr ;
wxButton * g_btn_send_gcode = nullptr ;
2018-05-18 09:39:49 +00:00
wxStaticBitmap * g_manifold_warning_icon = nullptr ;
2018-05-17 12:07:50 +00:00
bool g_show_print_info = false ;
2018-05-18 09:39:49 +00:00
bool g_show_manifold_warning_icon = false ;
2018-05-17 08:46:32 +00:00
2018-04-09 12:41:55 +00:00
static void init_label_colours ( )
{
auto luma = get_colour_approx_luma ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_WINDOW ) ) ;
if ( luma > = 128 ) {
2018-05-02 11:20:36 +00:00
g_color_label_modified = wxColour ( 252 , 77 , 1 ) ;
2018-04-09 12:41:55 +00:00
g_color_label_sys = wxColour ( 26 , 132 , 57 ) ;
} else {
g_color_label_modified = wxColour ( 253 , 111 , 40 ) ;
g_color_label_sys = wxColour ( 115 , 220 , 103 ) ;
}
2018-04-18 11:32:21 +00:00
g_color_label_default = wxSystemSettings : : GetColour ( wxSYS_COLOUR_WINDOWTEXT ) ;
2018-04-09 12:41:55 +00:00
}
2018-04-30 12:20:33 +00:00
void update_label_colours_from_appconfig ( )
{
if ( g_AppConfig - > has ( " label_clr_sys " ) ) {
auto str = g_AppConfig - > get ( " label_clr_sys " ) ;
if ( str ! = " " )
g_color_label_sys = wxColour ( str ) ;
}
if ( g_AppConfig - > has ( " label_clr_modified " ) ) {
auto str = g_AppConfig - > get ( " label_clr_modified " ) ;
if ( str ! = " " )
g_color_label_modified = wxColour ( str ) ;
}
}
2017-12-04 09:48:40 +00:00
void set_wxapp ( wxApp * app )
{
g_wxApp = app ;
2018-04-09 12:41:55 +00:00
init_label_colours ( ) ;
2017-12-04 09:48:40 +00:00
}
void set_main_frame ( wxFrame * main_frame )
{
g_wxMainFrame = main_frame ;
}
void set_tab_panel ( wxNotebook * tab_panel )
{
g_wxTabPanel = tab_panel ;
}
2018-02-20 07:58:46 +00:00
void set_app_config ( AppConfig * app_config )
{
g_AppConfig = app_config ;
}
2018-03-09 16:17:51 +00:00
void set_preset_bundle ( PresetBundle * preset_bundle )
{
g_PresetBundle = preset_bundle ;
}
2018-04-16 14:52:11 +00:00
void set_preset_updater ( PresetUpdater * updater )
{
g_PresetUpdater = updater ;
}
2018-05-17 12:07:50 +00:00
void set_objects_from_perl ( wxWindow * parent , wxBoxSizer * frequently_changed_parameters_sizer ,
2018-05-17 08:46:32 +00:00
wxBoxSizer * expert_mode_part_sizer , wxBoxSizer * scrolled_window_sizer ,
2018-05-17 12:07:50 +00:00
wxButton * btn_export_stl , wxButton * btn_reslice ,
2018-05-18 09:39:49 +00:00
wxButton * btn_print , wxButton * btn_send_gcode ,
wxStaticBitmap * manifold_warning_icon )
2018-05-17 08:46:32 +00:00
{
2018-05-21 12:49:31 +00:00
g_right_panel = parent ;
2018-05-17 08:46:32 +00:00
g_frequently_changed_parameters_sizer = frequently_changed_parameters_sizer ;
g_expert_mode_part_sizer = expert_mode_part_sizer ;
g_scrolled_window_sizer = scrolled_window_sizer ;
g_btn_export_stl = btn_export_stl ;
g_btn_reslice = btn_reslice ;
g_btn_print = btn_print ;
g_btn_send_gcode = btn_send_gcode ;
2018-05-18 09:39:49 +00:00
g_manifold_warning_icon = manifold_warning_icon ;
2018-05-17 12:07:50 +00:00
}
void set_show_print_info ( bool show )
{
g_show_print_info = show ;
2018-05-17 08:46:32 +00:00
}
2018-05-18 09:39:49 +00:00
void set_show_manifold_warning_icon ( bool show )
{
g_show_manifold_warning_icon = show ;
}
2018-02-09 10:04:34 +00:00
std : : vector < Tab * > & get_tabs_list ( )
2017-12-04 09:48:40 +00:00
{
2018-02-09 10:04:34 +00:00
return g_tabs_list ;
}
bool checked_tab ( Tab * tab )
{
bool ret = true ;
if ( find ( g_tabs_list . begin ( ) , g_tabs_list . end ( ) , tab ) = = g_tabs_list . end ( ) )
ret = false ;
return ret ;
}
void delete_tab_from_list ( Tab * tab )
{
std : : vector < Tab * > : : iterator itr = find ( g_tabs_list . begin ( ) , g_tabs_list . end ( ) , tab ) ;
if ( itr ! = g_tabs_list . end ( ) )
g_tabs_list . erase ( itr ) ;
}
2018-02-08 09:58:13 +00:00
bool select_language ( wxArrayString & names ,
wxArrayLong & identifiers )
{
wxCHECK_MSG ( names . Count ( ) = = identifiers . Count ( ) , false ,
2018-02-23 08:16:35 +00:00
_ ( L ( " Array of language names and identifiers should have the same size. " ) ) ) ;
2018-02-12 07:57:32 +00:00
int init_selection = 0 ;
long current_language = g_wxLocale ? g_wxLocale - > GetLanguage ( ) : wxLANGUAGE_UNKNOWN ;
for ( auto lang : identifiers ) {
if ( lang = = current_language )
break ;
else
+ + init_selection ;
}
if ( init_selection = = identifiers . size ( ) )
init_selection = 0 ;
2018-02-23 08:16:35 +00:00
long index = wxGetSingleChoiceIndex ( _ ( L ( " Select the language " ) ) , _ ( L ( " Language " ) ) ,
2018-02-12 07:57:32 +00:00
names , init_selection ) ;
2018-02-08 09:58:13 +00:00
if ( index ! = - 1 )
{
2018-02-12 07:57:32 +00:00
g_wxLocale = new wxLocale ;
g_wxLocale - > Init ( identifiers [ index ] ) ;
g_wxLocale - > AddCatalogLookupPathPrefix ( wxPathOnly ( localization_dir ( ) ) ) ;
g_wxLocale - > AddCatalog ( g_wxApp - > GetAppName ( ) ) ;
2018-03-06 08:44:53 +00:00
wxSetlocale ( LC_NUMERIC , " C " ) ;
2018-02-08 09:58:13 +00:00
return true ;
}
return false ;
}
bool load_language ( )
{
2018-05-03 07:21:01 +00:00
wxString language = wxEmptyString ;
if ( g_AppConfig - > has ( " translation_language " ) )
language = g_AppConfig - > get ( " translation_language " ) ;
2018-02-20 07:58:46 +00:00
2018-05-03 07:21:01 +00:00
if ( language . IsEmpty ( ) )
2018-02-12 07:57:32 +00:00
return false ;
wxArrayString names ;
wxArrayLong identifiers ;
2018-02-08 09:58:13 +00:00
get_installed_languages ( names , identifiers ) ;
for ( size_t i = 0 ; i < identifiers . Count ( ) ; i + + )
{
2018-05-03 07:21:01 +00:00
if ( wxLocale : : GetLanguageCanonicalName ( identifiers [ i ] ) = = language )
2018-02-08 09:58:13 +00:00
{
2018-02-12 07:57:32 +00:00
g_wxLocale = new wxLocale ;
g_wxLocale - > Init ( identifiers [ i ] ) ;
g_wxLocale - > AddCatalogLookupPathPrefix ( wxPathOnly ( localization_dir ( ) ) ) ;
g_wxLocale - > AddCatalog ( g_wxApp - > GetAppName ( ) ) ;
2018-03-06 08:44:53 +00:00
wxSetlocale ( LC_NUMERIC , " C " ) ;
2018-02-08 09:58:13 +00:00
return true ;
}
}
return false ;
}
2018-02-12 07:57:32 +00:00
void save_language ( )
2018-02-08 09:58:13 +00:00
{
2018-05-03 07:21:01 +00:00
wxString language = wxEmptyString ;
if ( g_wxLocale )
language = g_wxLocale - > GetCanonicalName ( ) ;
g_AppConfig - > set ( " translation_language " , language . ToStdString ( ) ) ;
2018-02-20 07:58:46 +00:00
g_AppConfig - > save ( ) ;
2017-12-04 09:48:40 +00:00
}
2018-02-08 09:58:13 +00:00
void get_installed_languages ( wxArrayString & names ,
wxArrayLong & identifiers )
2017-12-04 09:48:40 +00:00
{
2018-02-08 09:58:13 +00:00
names . Clear ( ) ;
identifiers . Clear ( ) ;
2018-02-12 07:57:32 +00:00
wxDir dir ( wxPathOnly ( localization_dir ( ) ) ) ;
2018-02-08 09:58:13 +00:00
wxString filename ;
const wxLanguageInfo * langinfo ;
wxString name = wxLocale : : GetLanguageName ( wxLANGUAGE_DEFAULT ) ;
if ( ! name . IsEmpty ( ) )
{
2018-02-23 08:16:35 +00:00
names . Add ( _ ( L ( " Default " ) ) ) ;
2018-02-08 09:58:13 +00:00
identifiers . Add ( wxLANGUAGE_DEFAULT ) ;
}
for ( bool cont = dir . GetFirst ( & filename , wxEmptyString , wxDIR_DIRS ) ;
cont ; cont = dir . GetNext ( & filename ) )
{
langinfo = wxLocale : : FindLanguageInfo ( filename ) ;
if ( langinfo ! = NULL )
{
auto full_file_name = dir . GetName ( ) + wxFileName : : GetPathSeparator ( ) +
filename + wxFileName : : GetPathSeparator ( ) +
g_wxApp - > GetAppName ( ) + wxT ( " .mo " ) ;
if ( wxFileExists ( full_file_name ) )
{
names . Add ( langinfo - > Description ) ;
identifiers . Add ( langinfo - > Language ) ;
}
}
}
}
2018-04-09 15:03:37 +00:00
enum ConfigMenuIDs {
ConfigMenuWizard ,
ConfigMenuSnapshots ,
ConfigMenuTakeSnapshot ,
ConfigMenuUpdate ,
ConfigMenuPreferences ,
2018-05-16 12:38:37 +00:00
ConfigMenuModeSimple ,
2018-05-17 08:46:32 +00:00
ConfigMenuModeRegular ,
2018-05-16 12:38:37 +00:00
ConfigMenuModeExpert ,
2018-04-09 15:03:37 +00:00
ConfigMenuLanguage ,
2018-05-21 19:04:03 +00:00
ConfigMenuFlashFirmware ,
2018-04-09 15:03:37 +00:00
ConfigMenuCnt ,
} ;
2018-05-17 08:46:32 +00:00
ConfigMenuIDs get_view_mode ( )
{
if ( ! g_AppConfig - > has ( " view_mode " ) )
return ConfigMenuModeSimple ;
const auto mode = g_AppConfig - > get ( " view_mode " ) ;
return mode = = " expert " ?
ConfigMenuModeExpert :
mode = = " regular " ?
ConfigMenuModeRegular :
ConfigMenuModeSimple ;
}
2018-04-09 15:03:37 +00:00
void add_config_menu ( wxMenuBar * menu , int event_preferences_changed , int event_language_change )
2017-12-04 09:48:40 +00:00
{
2018-02-08 09:58:13 +00:00
auto local_menu = new wxMenu ( ) ;
2018-04-09 15:03:37 +00:00
wxWindowID config_id_base = wxWindow : : NewControlId ( ( int ) ConfigMenuCnt ) ;
2018-04-11 10:21:15 +00:00
2018-04-17 09:54:59 +00:00
const auto config_wizard_tooltip = wxString : : Format ( _ ( L ( " Run %s " ) ) , ConfigWizard : : name ( ) ) ;
2018-04-09 15:03:37 +00:00
// Cmd+, is standard on OS X - what about other operating systems?
2018-05-02 11:20:36 +00:00
local_menu - > Append ( config_id_base + ConfigMenuWizard , ConfigWizard : : name ( ) + " \u2026 " , config_wizard_tooltip ) ;
local_menu - > Append ( config_id_base + ConfigMenuSnapshots , _ ( L ( " Configuration Snapshots " ) ) + " \u2026 " , _ ( L ( " Inspect / activate configuration snapshots " ) ) ) ;
local_menu - > Append ( config_id_base + ConfigMenuTakeSnapshot , _ ( L ( " Take Configuration Snapshot " ) ) , _ ( L ( " Capture a configuration snapshot " ) ) ) ;
2018-05-21 19:04:03 +00:00
// local_menu->Append(config_id_base + ConfigMenuUpdate, _(L("Check for updates")), _(L("Check for configuration updates")));
2018-04-09 15:03:37 +00:00
local_menu - > AppendSeparator ( ) ;
2018-05-02 11:20:36 +00:00
local_menu - > Append ( config_id_base + ConfigMenuPreferences , _ ( L ( " Preferences " ) ) + " \u2026 \t Ctrl+, " , _ ( L ( " Application preferences " ) ) ) ;
2018-05-22 14:14:41 +00:00
local_menu - > AppendSeparator ( ) ;
2018-05-16 12:38:37 +00:00
auto mode_menu = new wxMenu ( ) ;
mode_menu - > AppendRadioItem ( config_id_base + ConfigMenuModeSimple , _ ( L ( " &Simple " ) ) , _ ( L ( " Simple View Mode " ) ) ) ;
2018-05-17 08:46:32 +00:00
mode_menu - > AppendRadioItem ( config_id_base + ConfigMenuModeRegular , _ ( L ( " &Regular " ) ) , _ ( L ( " Regular View Mode " ) ) ) ;
2018-05-16 12:38:37 +00:00
mode_menu - > AppendRadioItem ( config_id_base + ConfigMenuModeExpert , _ ( L ( " &Expert " ) ) , _ ( L ( " Expert View Mode " ) ) ) ;
2018-05-17 08:46:32 +00:00
mode_menu - > Check ( config_id_base + get_view_mode ( ) , true ) ;
2018-05-16 12:38:37 +00:00
local_menu - > AppendSubMenu ( mode_menu , _ ( L ( " &Mode " ) ) , _ ( L ( " Slic3r View Mode " ) ) ) ;
local_menu - > AppendSeparator ( ) ;
local_menu - > Append ( config_id_base + ConfigMenuLanguage , _ ( L ( " Change Application Language " ) ) ) ;
2018-05-22 14:14:41 +00:00
local_menu - > AppendSeparator ( ) ;
local_menu - > Append ( config_id_base + ConfigMenuFlashFirmware , _ ( L ( " Flash printer firmware " ) ) , _ ( L ( " Upload a firmware image into an Arduino based printer " ) ) ) ;
// TODO: for when we're able to flash dictionaries
// local_menu->Append(config_id_base + FirmwareMenuDict, _(L("Flash language file")), _(L("Upload a language dictionary file into a Prusa printer")));
2018-04-09 15:03:37 +00:00
local_menu - > Bind ( wxEVT_MENU , [ config_id_base , event_language_change , event_preferences_changed ] ( wxEvent & event ) {
switch ( event . GetId ( ) - config_id_base ) {
2018-04-11 10:21:15 +00:00
case ConfigMenuWizard :
2018-04-24 16:06:42 +00:00
config_wizard ( ConfigWizard : : RR_USER ) ;
2018-04-11 10:21:15 +00:00
break ;
2018-04-10 14:27:42 +00:00
case ConfigMenuTakeSnapshot :
// Take a configuration snapshot.
2018-04-11 10:21:15 +00:00
if ( check_unsaved_changes ( ) ) {
wxTextEntryDialog dlg ( nullptr , _ ( L ( " Taking configuration snapshot " ) ) , _ ( L ( " Snapshot name " ) ) ) ;
if ( dlg . ShowModal ( ) = = wxID_OK )
2018-04-20 08:26:23 +00:00
g_AppConfig - > set ( " on_snapshot " ,
Slic3r : : GUI : : Config : : SnapshotDB : : singleton ( ) . take_snapshot (
* g_AppConfig , Slic3r : : GUI : : Config : : Snapshot : : SNAPSHOT_USER , dlg . GetValue ( ) . ToUTF8 ( ) . data ( ) ) . id ) ;
2018-04-11 10:21:15 +00:00
}
2018-04-10 14:27:42 +00:00
break ;
case ConfigMenuSnapshots :
2018-04-11 10:21:15 +00:00
if ( check_unsaved_changes ( ) ) {
2018-04-20 08:26:23 +00:00
std : : string on_snapshot ;
if ( Config : : SnapshotDB : : singleton ( ) . is_on_snapshot ( * g_AppConfig ) )
on_snapshot = g_AppConfig - > get ( " on_snapshot " ) ;
ConfigSnapshotDialog dlg ( Slic3r : : GUI : : Config : : SnapshotDB : : singleton ( ) , on_snapshot ) ;
2018-04-11 10:21:15 +00:00
dlg . ShowModal ( ) ;
if ( ! dlg . snapshot_to_activate ( ) . empty ( ) ) {
2018-04-20 08:26:23 +00:00
if ( ! Config : : SnapshotDB : : singleton ( ) . is_on_snapshot ( * g_AppConfig ) )
Config : : SnapshotDB : : singleton ( ) . take_snapshot ( * g_AppConfig , Config : : Snapshot : : SNAPSHOT_BEFORE_ROLLBACK ) ;
g_AppConfig - > set ( " on_snapshot " ,
Config : : SnapshotDB : : singleton ( ) . restore_snapshot ( dlg . snapshot_to_activate ( ) , * g_AppConfig ) . id ) ;
2018-04-11 10:21:15 +00:00
g_PresetBundle - > load_presets ( * g_AppConfig ) ;
// Load the currently selected preset into the GUI, update the preset selection box.
for ( Tab * tab : g_tabs_list )
tab - > load_current_preset ( ) ;
}
}
2018-04-10 14:27:42 +00:00
break ;
2018-04-09 15:03:37 +00:00
case ConfigMenuPreferences :
{
2018-04-11 10:21:15 +00:00
PreferencesDialog dlg ( g_wxMainFrame , event_preferences_changed ) ;
dlg . ShowModal ( ) ;
2018-04-09 15:03:37 +00:00
break ;
}
case ConfigMenuLanguage :
{
wxArrayString names ;
wxArrayLong identifiers ;
get_installed_languages ( names , identifiers ) ;
if ( select_language ( names , identifiers ) ) {
save_language ( ) ;
show_info ( g_wxTabPanel , _ ( L ( " Application will be restarted " ) ) , _ ( L ( " Attention! " ) ) ) ;
if ( event_language_change > 0 ) {
wxCommandEvent event ( event_language_change ) ;
g_wxApp - > ProcessEvent ( event ) ;
}
2018-02-09 10:04:34 +00:00
}
2018-04-09 15:03:37 +00:00
break ;
2018-02-09 10:04:34 +00:00
}
2018-05-21 19:04:03 +00:00
case ConfigMenuFlashFirmware :
2018-05-04 14:04:43 +00:00
FirmwareDialog : : run ( g_wxMainFrame ) ;
break ;
default :
break ;
2018-05-16 12:38:37 +00:00
}
} ) ;
mode_menu - > Bind ( wxEVT_MENU , [ config_id_base ] ( wxEvent & event ) {
std : : string mode = " " ;
switch ( event . GetId ( ) - config_id_base ) {
case ConfigMenuModeExpert :
mode = " expert " ;
break ;
2018-05-17 08:46:32 +00:00
case ConfigMenuModeRegular :
mode = " regular " ;
break ;
2018-05-16 12:38:37 +00:00
case ConfigMenuModeSimple :
mode = " simple " ;
break ;
}
g_AppConfig - > set ( " view_mode " , mode ) ;
g_AppConfig - > save ( ) ;
2018-05-17 08:46:32 +00:00
update_mode ( ) ;
2018-02-08 09:58:13 +00:00
} ) ;
2018-04-09 15:03:37 +00:00
menu - > Append ( local_menu , _ ( L ( " &Configuration " ) ) ) ;
2018-02-22 10:12:29 +00:00
}
2018-05-04 14:04:43 +00:00
void add_menus ( wxMenuBar * menu , int event_preferences_changed , int event_language_change )
{
add_config_menu ( menu , event_language_change , event_language_change ) ;
}
2018-04-11 10:21:15 +00:00
// This is called when closing the application, when loading a config file or when starting the config wizard
// to notify the user whether he is aware that some preset changes will be lost.
bool check_unsaved_changes ( )
{
std : : string dirty ;
for ( Tab * tab : g_tabs_list )
if ( tab - > current_preset_is_dirty ( ) )
if ( dirty . empty ( ) )
dirty = tab - > name ( ) ;
else
dirty + = std : : string ( " , " ) + tab - > name ( ) ;
if ( dirty . empty ( ) )
// No changes, the application may close or reload presets.
return true ;
// Ask the user.
auto dialog = new wxMessageDialog ( g_wxMainFrame ,
_ ( L ( " You have unsaved changes " ) ) + dirty + _ ( L ( " . Discard changes and continue anyway? " ) ) ,
_ ( L ( " Unsaved Presets " ) ) ,
wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT ) ;
return dialog - > ShowModal ( ) = = wxID_YES ;
}
2018-04-24 16:06:42 +00:00
bool config_wizard_startup ( bool app_config_exists )
2018-04-16 14:52:11 +00:00
{
if ( ! app_config_exists | | g_PresetBundle - > has_defauls_only ( ) ) {
2018-04-24 16:06:42 +00:00
config_wizard ( ConfigWizard : : RR_DATA_EMPTY ) ;
return true ;
2018-04-16 14:52:11 +00:00
} else if ( g_AppConfig - > legacy_datadir ( ) ) {
// Looks like user has legacy pre-vendorbundle data directory,
// explain what this is and run the wizard
2018-04-27 10:29:18 +00:00
MsgDataLegacy dlg ;
dlg . ShowModal ( ) ;
2018-04-16 14:52:11 +00:00
2018-04-24 16:06:42 +00:00
config_wizard ( ConfigWizard : : RR_DATA_LEGACY ) ;
return true ;
2018-04-16 14:52:11 +00:00
}
2018-04-24 16:06:42 +00:00
return false ;
2018-04-16 14:52:11 +00:00
}
2018-04-24 16:06:42 +00:00
void config_wizard ( int reason )
2018-03-13 11:39:57 +00:00
{
2018-04-11 10:21:15 +00:00
// Exit wizard if there are unsaved changes and the user cancels the action.
if ( ! check_unsaved_changes ( ) )
2018-04-16 14:52:11 +00:00
return ;
2018-04-11 10:21:15 +00:00
2018-04-24 16:06:42 +00:00
ConfigWizard wizard ( nullptr , static_cast < ConfigWizard : : RunReason > ( reason ) ) ;
2018-04-16 14:52:11 +00:00
wizard . run ( g_PresetBundle , g_PresetUpdater ) ;
2018-04-11 10:21:15 +00:00
// Load the currently selected preset into the GUI, update the preset selection box.
for ( Tab * tab : g_tabs_list )
tab - > load_current_preset ( ) ;
2017-12-04 09:48:40 +00:00
}
2018-02-22 10:12:29 +00:00
void open_preferences_dialog ( int event_preferences )
{
auto dlg = new PreferencesDialog ( g_wxMainFrame , event_preferences ) ;
dlg - > ShowModal ( ) ;
}
2018-03-15 17:06:26 +00:00
void create_preset_tabs ( bool no_controller , int event_value_change , int event_presets_changed )
2018-01-05 14:11:33 +00:00
{
2018-04-30 12:20:33 +00:00
update_label_colours_from_appconfig ( ) ;
2018-03-09 16:17:51 +00:00
add_created_tab ( new TabPrint ( g_wxTabPanel , no_controller ) ) ;
add_created_tab ( new TabFilament ( g_wxTabPanel , no_controller ) ) ;
2018-03-15 17:06:26 +00:00
add_created_tab ( new TabPrinter ( g_wxTabPanel , no_controller ) ) ;
2018-01-21 22:35:00 +00:00
for ( size_t i = 0 ; i < g_wxTabPanel - > GetPageCount ( ) ; + + i ) {
Tab * tab = dynamic_cast < Tab * > ( g_wxTabPanel - > GetPage ( i ) ) ;
if ( ! tab )
continue ;
tab - > set_event_value_change ( wxEventType ( event_value_change ) ) ;
tab - > set_event_presets_changed ( wxEventType ( event_presets_changed ) ) ;
}
2017-12-22 10:50:28 +00:00
}
2018-01-23 10:37:19 +00:00
TabIface * get_preset_tab_iface ( char * name )
{
for ( size_t i = 0 ; i < g_wxTabPanel - > GetPageCount ( ) ; + + i ) {
Tab * tab = dynamic_cast < Tab * > ( g_wxTabPanel - > GetPage ( i ) ) ;
if ( ! tab )
continue ;
2018-01-25 20:44:22 +00:00
if ( tab - > name ( ) = = name ) {
2018-01-23 10:37:19 +00:00
return new TabIface ( tab ) ;
}
}
return new TabIface ( nullptr ) ;
}
2018-02-15 16:30:33 +00:00
// opt_index = 0, by the reason of zero-index in ConfigOptionVector by default (in case only one element)
2018-04-13 10:35:04 +00:00
void change_opt_value ( DynamicPrintConfig & config , const t_config_option_key & opt_key , const boost : : any & value , int opt_index /*= 0*/ )
2018-01-07 17:41:40 +00:00
{
try {
switch ( config . def ( ) - > get ( opt_key ) - > type ) {
2018-01-09 12:52:01 +00:00
case coFloatOrPercent : {
2018-02-20 11:30:13 +00:00
std : : string str = boost : : any_cast < std : : string > ( value ) ;
bool percent = false ;
if ( str . back ( ) = = ' % ' ) {
str . pop_back ( ) ;
percent = true ;
}
double val = stod ( str ) ;
config . set_key_value ( opt_key , new ConfigOptionFloatOrPercent ( val , percent ) ) ;
2018-01-09 12:52:01 +00:00
break ; }
2018-01-07 17:41:40 +00:00
case coPercent :
2018-01-11 09:33:17 +00:00
config . set_key_value ( opt_key , new ConfigOptionPercent ( boost : : any_cast < double > ( value ) ) ) ;
2018-01-09 12:52:01 +00:00
break ;
case coFloat : {
2018-01-07 17:41:40 +00:00
double & val = config . opt_float ( opt_key ) ;
2018-01-09 08:41:07 +00:00
val = boost : : any_cast < double > ( value ) ;
2018-01-07 17:41:40 +00:00
break ;
}
2018-02-26 08:57:08 +00:00
case coPercents : {
ConfigOptionPercents * vec_new = new ConfigOptionPercents { boost : : any_cast < double > ( value ) } ;
config . option < ConfigOptionPercents > ( opt_key ) - > set_at ( vec_new , opt_index , opt_index ) ;
2018-01-09 12:52:01 +00:00
break ;
2018-02-26 08:57:08 +00:00
}
case coFloats : {
ConfigOptionFloats * vec_new = new ConfigOptionFloats { boost : : any_cast < double > ( value ) } ;
config . option < ConfigOptionFloats > ( opt_key ) - > set_at ( vec_new , opt_index , opt_index ) ;
break ;
2018-01-09 12:52:01 +00:00
}
2018-01-07 17:41:40 +00:00
case coString :
2018-01-09 12:52:01 +00:00
config . set_key_value ( opt_key , new ConfigOptionString ( boost : : any_cast < std : : string > ( value ) ) ) ;
2018-01-07 17:41:40 +00:00
break ;
2018-01-12 11:41:13 +00:00
case coStrings : {
2018-04-13 10:35:04 +00:00
if ( opt_key . compare ( " compatible_printers " ) = = 0 ) {
config . option < ConfigOptionStrings > ( opt_key ) - > values =
boost : : any_cast < std : : vector < std : : string > > ( value ) ;
}
else if ( config . def ( ) - > get ( opt_key ) - > gui_flags . compare ( " serialized " ) = = 0 ) {
std : : string str = boost : : any_cast < std : : string > ( value ) ;
if ( str . back ( ) = = ' ; ' ) str . pop_back ( ) ;
// Split a string to multiple strings by a semi - colon.This is the old way of storing multi - string values.
// Currently used for the post_process config value only.
std : : vector < std : : string > values ;
boost : : split ( values , str , boost : : is_any_of ( " ; " ) ) ;
if ( values . size ( ) = = 1 & & values [ 0 ] = = " " )
2018-03-07 14:05:41 +00:00
break ;
2018-03-23 16:27:43 +00:00
config . option < ConfigOptionStrings > ( opt_key ) - > values = values ;
2018-01-12 11:41:13 +00:00
}
else {
2018-01-25 12:46:04 +00:00
ConfigOptionStrings * vec_new = new ConfigOptionStrings { boost : : any_cast < std : : string > ( value ) } ;
2018-03-02 12:41:37 +00:00
config . option < ConfigOptionStrings > ( opt_key ) - > set_at ( vec_new , opt_index , 0 ) ;
2018-01-12 11:41:13 +00:00
}
}
2018-01-07 17:41:40 +00:00
break ;
case coBool :
config . set_key_value ( opt_key , new ConfigOptionBool ( boost : : any_cast < bool > ( value ) ) ) ;
break ;
2018-01-09 12:52:01 +00:00
case coBools : {
2018-03-09 16:17:51 +00:00
ConfigOptionBools * vec_new = new ConfigOptionBools { ( bool ) boost : : any_cast < unsigned char > ( value ) } ;
2018-03-02 12:41:37 +00:00
config . option < ConfigOptionBools > ( opt_key ) - > set_at ( vec_new , opt_index , 0 ) ;
2018-01-09 12:52:01 +00:00
break ; }
2018-01-07 17:41:40 +00:00
case coInt :
config . set_key_value ( opt_key , new ConfigOptionInt ( boost : : any_cast < int > ( value ) ) ) ;
break ;
2018-01-12 11:41:13 +00:00
case coInts : {
ConfigOptionInts * vec_new = new ConfigOptionInts { boost : : any_cast < int > ( value ) } ;
2018-03-02 12:41:37 +00:00
config . option < ConfigOptionInts > ( opt_key ) - > set_at ( vec_new , opt_index , 0 ) ;
2018-01-12 11:41:13 +00:00
}
2018-01-07 17:41:40 +00:00
break ;
2018-01-11 09:33:17 +00:00
case coEnum : {
if ( opt_key . compare ( " external_fill_pattern " ) = = 0 | |
opt_key . compare ( " fill_pattern " ) = = 0 )
config . set_key_value ( opt_key , new ConfigOptionEnum < InfillPattern > ( boost : : any_cast < InfillPattern > ( value ) ) ) ;
else if ( opt_key . compare ( " gcode_flavor " ) = = 0 )
config . set_key_value ( opt_key , new ConfigOptionEnum < GCodeFlavor > ( boost : : any_cast < GCodeFlavor > ( value ) ) ) ;
else if ( opt_key . compare ( " support_material_pattern " ) = = 0 )
config . set_key_value ( opt_key , new ConfigOptionEnum < SupportMaterialPattern > ( boost : : any_cast < SupportMaterialPattern > ( value ) ) ) ;
else if ( opt_key . compare ( " seam_position " ) = = 0 )
config . set_key_value ( opt_key , new ConfigOptionEnum < SeamPosition > ( boost : : any_cast < SeamPosition > ( value ) ) ) ;
}
2018-01-07 17:41:40 +00:00
break ;
2018-01-30 11:10:12 +00:00
case coPoints : {
2018-03-23 16:27:43 +00:00
if ( opt_key . compare ( " bed_shape " ) = = 0 ) {
config . option < ConfigOptionPoints > ( opt_key ) - > values = boost : : any_cast < std : : vector < Pointf > > ( value ) ;
break ;
}
2018-03-08 10:58:06 +00:00
ConfigOptionPoints * vec_new = new ConfigOptionPoints { boost : : any_cast < Pointf > ( value ) } ;
config . option < ConfigOptionPoints > ( opt_key ) - > set_at ( vec_new , opt_index , 0 ) ;
2018-01-30 11:10:12 +00:00
}
2018-01-07 17:41:40 +00:00
break ;
case coNone :
break ;
default :
break ;
}
}
catch ( const std : : exception & e )
{
2018-01-09 12:52:01 +00:00
int i = 0 ; //no reason, just experiment
2018-01-07 17:41:40 +00:00
}
}
2018-03-09 16:17:51 +00:00
void add_created_tab ( Tab * panel )
2017-12-22 10:50:28 +00:00
{
2018-03-09 16:17:51 +00:00
panel - > create_preset_tab ( g_PresetBundle ) ;
2018-01-05 14:11:33 +00:00
2018-01-16 15:28:01 +00:00
// Load the currently selected preset into the GUI, update the preset selection box.
panel - > load_current_preset ( ) ;
2017-12-22 10:50:28 +00:00
g_wxTabPanel - > AddPage ( panel , panel - > title ( ) ) ;
}
2018-04-30 12:31:57 +00:00
void show_error ( wxWindow * parent , const wxString & message ) {
ErrorDialog msg ( parent , message ) ;
msg . ShowModal ( ) ;
}
void show_error_id ( int id , const std : : string & message ) {
auto * parent = id ! = 0 ? wxWindow : : FindWindowById ( id ) : nullptr ;
2018-05-22 12:33:11 +00:00
show_error ( parent , wxString : : FromUTF8 ( message . data ( ) ) ) ;
2017-12-22 10:50:28 +00:00
}
2018-04-13 10:35:04 +00:00
void show_info ( wxWindow * parent , const wxString & message , const wxString & title ) {
2018-04-30 12:31:57 +00:00
wxMessageDialog msg_wingow ( parent , message , title . empty ( ) ? _ ( L ( " Notice " ) ) : title , wxOK | wxICON_INFORMATION ) ;
msg_wingow . ShowModal ( ) ;
2017-12-04 09:48:40 +00:00
}
2018-04-13 10:35:04 +00:00
void warning_catcher ( wxWindow * parent , const wxString & message ) {
2018-05-02 11:20:36 +00:00
if ( message = = " GLUquadricObjPtr | " + _ ( L ( " Attempt to free unreferenced scalar " ) ) )
2018-02-22 10:12:29 +00:00
return ;
2018-04-30 12:31:57 +00:00
wxMessageDialog msg ( parent , message , _ ( L ( " Warning " ) ) , wxOK | wxICON_WARNING ) ;
msg . ShowModal ( ) ;
2018-02-22 10:12:29 +00:00
}
2018-02-05 15:12:16 +00:00
wxApp * get_app ( ) {
return g_wxApp ;
2017-12-04 09:48:40 +00:00
}
2018-04-24 16:06:42 +00:00
PresetBundle * get_preset_bundle ( )
{
return g_PresetBundle ;
}
2018-04-30 12:20:33 +00:00
const wxColour & get_label_clr_modified ( ) {
2018-04-09 12:41:55 +00:00
return g_color_label_modified ;
2018-03-02 08:08:11 +00:00
}
2018-04-30 12:20:33 +00:00
const wxColour & get_label_clr_sys ( ) {
2018-04-09 12:41:55 +00:00
return g_color_label_sys ;
}
2018-04-30 12:20:33 +00:00
void set_label_clr_modified ( const wxColour & clr ) {
g_color_label_modified = clr ;
auto clr_str = wxString : : Format ( wxT ( " #%02X%02X%02X " ) , clr . Red ( ) , clr . Green ( ) , clr . Blue ( ) ) ;
std : : string str = clr_str . ToStdString ( ) ;
g_AppConfig - > set ( " label_clr_modified " , str ) ;
g_AppConfig - > save ( ) ;
}
void set_label_clr_sys ( const wxColour & clr ) {
g_color_label_sys = clr ;
auto clr_str = wxString : : Format ( wxT ( " #%02X%02X%02X " ) , clr . Red ( ) , clr . Green ( ) , clr . Blue ( ) ) ;
std : : string str = clr_str . ToStdString ( ) ;
g_AppConfig - > set ( " label_clr_sys " , str ) ;
g_AppConfig - > save ( ) ;
}
const wxColour & get_label_clr_default ( ) {
2018-04-18 11:32:21 +00:00
return g_color_label_default ;
}
2018-04-09 12:41:55 +00:00
unsigned get_colour_approx_luma ( const wxColour & colour )
{
double r = colour . Red ( ) ;
double g = colour . Green ( ) ;
double b = colour . Blue ( ) ;
2018-04-10 09:43:04 +00:00
return std : : round ( std : : sqrt (
2018-04-09 12:41:55 +00:00
r * r * .241 +
g * g * .691 +
b * b * .068
) ) ;
2018-03-16 11:56:03 +00:00
}
2018-02-02 11:38:35 +00:00
void create_combochecklist ( wxComboCtrl * comboCtrl , std : : string text , std : : string items , bool initial_value )
{
2018-02-06 11:43:25 +00:00
if ( comboCtrl = = nullptr )
return ;
wxCheckListBoxComboPopup * popup = new wxCheckListBoxComboPopup ;
2018-02-02 11:38:35 +00:00
if ( popup ! = nullptr )
{
2018-02-20 14:22:30 +00:00
// FIXME If the following line is removed, the combo box popup list will not react to mouse clicks.
// On the other side, with this line the combo box popup cannot be closed by clicking on the combo button on Windows 10.
comboCtrl - > UseAltPopupWindow ( ) ;
comboCtrl - > EnablePopupAnimation ( false ) ;
2018-02-02 11:38:35 +00:00
comboCtrl - > SetPopupControl ( popup ) ;
2018-02-28 14:39:20 +00:00
popup - > SetStringValue ( from_u8 ( text ) ) ;
2018-02-20 10:40:15 +00:00
popup - > Bind ( wxEVT_CHECKLISTBOX , [ popup ] ( wxCommandEvent & evt ) { popup - > OnCheckListBox ( evt ) ; } ) ;
popup - > Bind ( wxEVT_LISTBOX , [ popup ] ( wxCommandEvent & evt ) { popup - > OnListBoxSelection ( evt ) ; } ) ;
2018-02-20 13:25:40 +00:00
popup - > Bind ( wxEVT_KEY_DOWN , [ popup ] ( wxKeyEvent & evt ) { popup - > OnKeyEvent ( evt ) ; } ) ;
popup - > Bind ( wxEVT_KEY_UP , [ popup ] ( wxKeyEvent & evt ) { popup - > OnKeyEvent ( evt ) ; } ) ;
2018-02-02 11:38:35 +00:00
std : : vector < std : : string > items_str ;
boost : : split ( items_str , items , boost : : is_any_of ( " | " ) , boost : : token_compress_off ) ;
for ( const std : : string & item : items_str )
{
2018-02-26 15:23:44 +00:00
popup - > Append ( from_u8 ( item ) ) ;
2018-02-02 11:38:35 +00:00
}
for ( unsigned int i = 0 ; i < popup - > GetCount ( ) ; + + i )
{
popup - > Check ( i , initial_value ) ;
}
}
}
int combochecklist_get_flags ( wxComboCtrl * comboCtrl )
{
int flags = 0 ;
wxCheckListBoxComboPopup * popup = wxDynamicCast ( comboCtrl - > GetPopupControl ( ) , wxCheckListBoxComboPopup ) ;
if ( popup ! = nullptr )
{
for ( unsigned int i = 0 ; i < popup - > GetCount ( ) ; + + i )
{
if ( popup - > IsChecked ( i ) )
2018-02-13 16:46:23 +00:00
flags | = 1 < < i ;
2018-02-02 11:38:35 +00:00
}
}
return flags ;
}
2018-02-22 10:12:29 +00:00
AppConfig * get_app_config ( )
{
return g_AppConfig ;
}
2018-03-06 08:44:53 +00:00
wxString L_str ( const std : : string & str )
2018-02-22 10:34:41 +00:00
{
2018-02-23 08:16:35 +00:00
//! Explicitly specify that the source string is already in UTF-8 encoding
2018-02-22 10:34:41 +00:00
return wxGetTranslation ( wxString ( str . c_str ( ) , wxConvUTF8 ) ) ;
}
2018-03-06 08:44:53 +00:00
wxString from_u8 ( const std : : string & str )
2018-02-22 10:34:41 +00:00
{
return wxString : : FromUTF8 ( str . c_str ( ) ) ;
}
2018-05-22 06:41:33 +00:00
// add PrusaCollapsiblePane to sizer
void add_prusa_collapsible_pane ( wxWindow * parent , wxBoxSizer * sizer_parent , const wxString & name , std : : function < wxSizer * ( wxWindow * ) > content_function )
2018-03-09 17:34:30 +00:00
{
2018-05-22 06:41:33 +00:00
auto * collpane = new PrusaCollapsiblePane ( parent , wxID_ANY , name ) ;
// add the pane with a zero proportion value to the sizer which contains it
sizer_parent - > Add ( collpane , 0 , wxGROW | wxALL , 0 ) ;
2018-05-09 12:36:20 +00:00
2018-05-22 06:41:33 +00:00
wxWindow * win = collpane - > GetPane ( ) ;
2018-04-25 11:25:34 +00:00
2018-05-22 06:41:33 +00:00
wxSizer * sizer = content_function ( win ) ;
2018-05-17 08:46:32 +00:00
2018-05-22 06:41:33 +00:00
wxSizer * sizer_pane = new wxBoxSizer ( wxVERTICAL ) ;
sizer_pane - > Add ( sizer , 1 , wxGROW | wxEXPAND | wxBOTTOM , 2 ) ;
win - > SetSizer ( sizer_pane ) ;
sizer_pane - > SetSizeHints ( win ) ;
}
2018-05-17 08:46:32 +00:00
2018-05-22 06:41:33 +00:00
wxBoxSizer * content_objects_list ( wxWindow * win )
{
auto objects_ctrl = new wxDataViewCtrl ( win , wxID_ANY , wxDefaultPosition , wxDefaultSize ) ;
objects_ctrl - > SetBestFittingSize ( wxSize ( - 1 , 150 ) ) ; // TODO - Set correct height according to the opened/closed objects
auto objects_sz = new wxBoxSizer ( wxVERTICAL ) ;
2018-05-17 08:46:32 +00:00
objects_sz - > Add ( objects_ctrl , 1 , wxGROW | wxALL , 5 ) ;
auto objects_model = new MyObjectTreeModel ;
objects_ctrl - > AssociateModel ( objects_model ) ;
# if wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
objects_ctrl - > EnableDragSource ( wxDF_UNICODETEXT ) ;
objects_ctrl - > EnableDropTarget ( wxDF_UNICODETEXT ) ;
# endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
// column 0 of the view control:
wxDataViewTextRenderer * tr = new wxDataViewTextRenderer ( " string " , wxDATAVIEW_CELL_INERT ) ;
wxDataViewColumn * column00 = new wxDataViewColumn ( " Name " , tr , 0 , 140 , wxALIGN_LEFT ,
wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE ) ;
objects_ctrl - > AppendColumn ( column00 ) ;
// column 1 of the view control:
tr = new wxDataViewTextRenderer ( " string " , wxDATAVIEW_CELL_INERT ) ;
wxDataViewColumn * column01 = new wxDataViewColumn ( " Copy " , tr , 1 , 75 , wxALIGN_CENTER_HORIZONTAL ,
wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE ) ;
objects_ctrl - > AppendColumn ( column01 ) ;
// column 2 of the view control:
tr = new wxDataViewTextRenderer ( " string " , wxDATAVIEW_CELL_INERT ) ;
wxDataViewColumn * column02 = new wxDataViewColumn ( " Scale " , tr , 2 , 80 , wxALIGN_CENTER_HORIZONTAL ,
wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE ) ;
objects_ctrl - > AppendColumn ( column02 ) ;
2018-05-22 06:41:33 +00:00
return objects_sz ;
}
2018-05-17 08:46:32 +00:00
2018-05-22 06:41:33 +00:00
wxBoxSizer * content_object_settings ( wxWindow * win )
{
2018-05-22 14:14:41 +00:00
DynamicPrintConfig * config = & g_PresetBundle - > prints . get_edited_preset ( ) . config ;
std : : shared_ptr < ConfigOptionsGroup > optgroup = std : : make_shared < ConfigOptionsGroup > ( win , " " , config , false , ogSIDE_OPTIONS_VERTICAL ) ;
optgroup - > label_width = 100 ;
Line line = { _ ( L ( " Position " ) ) , " " } ;
ConfigOptionDef def ;
def . label = L ( " X " ) ;
def . type = coInt ;
def . default_value = new ConfigOptionInt ( 1 ) ;
def . sidetext = L ( " mm " ) ;
Option option = Option ( def , " position_X " ) ;
option . opt . full_width = true ;
line . append_option ( option ) ;
def . label = L ( " Y " ) ;
option = Option ( def , " position_Y " ) ;
line . append_option ( option ) ;
def . label = L ( " Z " ) ;
option = Option ( def , " position_Z " ) ;
line . append_option ( option ) ;
optgroup - > append_line ( line ) ;
m_optgroups . push_back ( optgroup ) ; // ogObjectSettings
2018-05-22 06:41:33 +00:00
auto sizer = new wxBoxSizer ( wxVERTICAL ) ;
2018-05-22 14:14:41 +00:00
sizer - > Add ( optgroup - > sizer , 1 , wxEXPAND | wxBOTTOM , 2 ) ;
2018-05-22 06:41:33 +00:00
return sizer ;
}
2018-05-17 08:46:32 +00:00
2018-05-22 06:41:33 +00:00
wxBoxSizer * content_part_settings ( wxWindow * win )
{
auto sizer = new wxBoxSizer ( wxVERTICAL ) ;
sizer - > Add ( new wxStaticText ( win , wxID_ANY , " Some part text " ) ) ;
return sizer ;
}
2018-05-17 08:46:32 +00:00
2018-05-22 06:41:33 +00:00
void add_expert_mode_part ( wxWindow * parent , wxBoxSizer * sizer )
{
sizer - > SetMinSize ( - 1 , 150 ) ;
auto main_sizer = new wxBoxSizer ( wxVERTICAL ) ;
auto main_page = new wxScrolledWindow ( parent , wxID_ANY , wxDefaultPosition , wxDefaultSize , wxTAB_TRAVERSAL ) ;
main_page - > SetSizer ( main_sizer ) ;
main_page - > SetScrollbars ( 1 , 1 , 1 , 1 ) ;
sizer - > Add ( main_page , 1 , wxEXPAND | wxALL , 1 ) ;
// Experiments with new UI
2018-05-17 08:46:32 +00:00
2018-05-22 06:41:33 +00:00
// *** Objects List ***
add_prusa_collapsible_pane ( main_page , main_sizer , " Objects List: " , content_objects_list ) ;
// *** Object Settings ***
add_prusa_collapsible_pane ( main_page , main_sizer , " Object Settings: " , content_object_settings ) ;
// *** Part Settings ***
add_prusa_collapsible_pane ( main_page , main_sizer , " Part Settings: " , content_part_settings ) ;
2018-05-17 08:46:32 +00:00
2018-05-22 06:41:33 +00:00
// More experiments with UI
// auto listctrl = new wxDataViewListCtrl(main_page, wxID_ANY, wxDefaultPosition, wxSize(-1, 100));
2018-05-17 08:46:32 +00:00
// listctrl->AppendToggleColumn("Toggle");
// listctrl->AppendTextColumn("Text");
// wxVector<wxVariant> data;
// data.push_back(wxVariant(true));
// data.push_back(wxVariant("row 1"));
// listctrl->AppendItem(data);
// data.clear();
// data.push_back(wxVariant(false));
// data.push_back(wxVariant("row 3"));
// listctrl->AppendItem(data);
// data.clear();
// data.push_back(wxVariant(false));
// data.push_back(wxVariant("row 2"));
// listctrl->AppendItem(data);
2018-05-22 06:41:33 +00:00
// main_sizer->Add(listctrl, 0, wxEXPAND | wxALL, 1);
2018-05-17 08:46:32 +00:00
}
void add_frequently_changed_parameters ( wxWindow * parent , wxBoxSizer * sizer , wxFlexGridSizer * preset_sizer )
{
2018-03-09 17:34:30 +00:00
DynamicPrintConfig * config = & g_PresetBundle - > prints . get_edited_preset ( ) . config ;
2018-05-22 14:14:41 +00:00
std : : shared_ptr < ConfigOptionsGroup > optgroup = std : : make_shared < ConfigOptionsGroup > ( parent , " " , config ) ;
2018-05-20 21:39:52 +00:00
const wxArrayInt & ar = preset_sizer - > GetColWidths ( ) ;
2018-05-22 14:14:41 +00:00
optgroup - > label_width = ar . IsEmpty ( ) ? 100 : ar . front ( ) - 4 ; // doesn't work
optgroup - > m_on_change = [ config ] ( t_config_option_key opt_key , boost : : any value ) {
2018-03-12 15:52:21 +00:00
TabPrint * tab_print = nullptr ;
for ( size_t i = 0 ; i < g_wxTabPanel - > GetPageCount ( ) ; + + i ) {
Tab * tab = dynamic_cast < Tab * > ( g_wxTabPanel - > GetPage ( i ) ) ;
if ( ! tab )
continue ;
if ( tab - > name ( ) = = " print " ) {
tab_print = static_cast < TabPrint * > ( tab ) ;
break ;
}
}
if ( tab_print = = nullptr )
return ;
if ( opt_key = = " fill_density " ) {
2018-05-22 14:14:41 +00:00
value = m_optgroups [ ogFrequentlyChangingParameters ] - > get_config_value ( * config , opt_key ) ;
2018-03-12 15:52:21 +00:00
tab_print - > set_value ( opt_key , value ) ;
2018-03-14 09:14:48 +00:00
tab_print - > update ( ) ;
2018-03-12 15:52:21 +00:00
}
2018-03-13 15:14:36 +00:00
else {
DynamicPrintConfig new_conf = * config ;
if ( opt_key = = " brim " ) {
double new_val ;
double brim_width = config - > opt_float ( " brim_width " ) ;
if ( boost : : any_cast < bool > ( value ) = = true )
{
new_val = m_brim_width = = 0.0 ? 10 :
m_brim_width < 0.0 ? m_brim_width * ( - 1 ) :
m_brim_width ;
}
else {
m_brim_width = brim_width * ( - 1 ) ;
new_val = 0 ;
}
new_conf . set_key_value ( " brim_width " , new ConfigOptionFloat ( new_val ) ) ;
}
else { //(opt_key == "support")
const wxString & selection = boost : : any_cast < wxString > ( value ) ;
2018-05-17 08:46:32 +00:00
2018-03-13 15:14:36 +00:00
auto support_material = selection = = _ ( " None " ) ? false : true ;
new_conf . set_key_value ( " support_material " , new ConfigOptionBool ( support_material ) ) ;
if ( selection = = _ ( " Everywhere " ) )
new_conf . set_key_value ( " support_material_buildplate_only " , new ConfigOptionBool ( false ) ) ;
else if ( selection = = _ ( " Support on build plate only " ) )
2018-05-17 08:46:32 +00:00
new_conf . set_key_value ( " support_material_buildplate_only " , new ConfigOptionBool ( true ) ) ;
2018-03-12 15:52:21 +00:00
}
2018-03-13 15:14:36 +00:00
tab_print - > load_config ( new_conf ) ;
2018-03-12 15:52:21 +00:00
}
tab_print - > update_dirty ( ) ;
2018-03-09 17:34:30 +00:00
} ;
2018-03-12 15:52:21 +00:00
2018-05-22 14:14:41 +00:00
Option option = optgroup - > get_option ( " fill_density " ) ;
2018-03-12 15:52:21 +00:00
option . opt . sidetext = " " ;
2018-04-25 09:10:34 +00:00
option . opt . full_width = true ;
2018-05-22 14:14:41 +00:00
optgroup - > append_single_option_line ( option ) ;
2018-03-09 17:34:30 +00:00
ConfigOptionDef def ;
def . label = L ( " Support " ) ;
2018-03-13 15:14:36 +00:00
def . type = coStrings ;
2018-03-09 17:34:30 +00:00
def . gui_type = " select_open " ;
def . tooltip = L ( " Select what kind of support do you need " ) ;
def . enum_labels . push_back ( L ( " None " ) ) ;
def . enum_labels . push_back ( L ( " Support on build plate only " ) ) ;
def . enum_labels . push_back ( L ( " Everywhere " ) ) ;
2018-03-13 15:14:36 +00:00
std : : string selection = ! config - > opt_bool ( " support_material " ) ?
" None " :
config - > opt_bool ( " support_material_buildplate_only " ) ?
" Support on build plate only " :
" Everywhere " ;
def . default_value = new ConfigOptionStrings { selection } ;
2018-03-12 15:52:21 +00:00
option = Option ( def , " support " ) ;
2018-04-25 09:10:34 +00:00
option . opt . full_width = true ;
2018-05-22 14:14:41 +00:00
optgroup - > append_single_option_line ( option ) ;
2018-03-09 17:34:30 +00:00
2018-03-13 15:14:36 +00:00
m_brim_width = config - > opt_float ( " brim_width " ) ;
2018-03-09 17:34:30 +00:00
def . label = L ( " Brim " ) ;
def . type = coBool ;
def . tooltip = L ( " This flag enables the brim that will be printed around each object on the first layer. " ) ;
def . gui_type = " " ;
2018-03-13 15:14:36 +00:00
def . default_value = new ConfigOptionBool { m_brim_width > 0.0 ? true : false } ;
2018-03-09 17:34:30 +00:00
option = Option ( def , " brim " ) ;
2018-05-22 14:14:41 +00:00
optgroup - > append_single_option_line ( option ) ;
2018-03-09 17:34:30 +00:00
2018-03-27 11:44:18 +00:00
2018-05-02 11:20:36 +00:00
Line line = { " " , " " } ;
2018-03-27 11:44:18 +00:00
line . widget = [ config ] ( wxWindow * parent ) {
2018-04-03 20:07:59 +00:00
g_wiping_dialog_button = new wxButton ( parent , wxID_ANY , _ ( L ( " Purging volumes " ) ) + " \u2026 " , wxDefaultPosition , wxDefaultSize , wxBU_EXACTFIT ) ;
2018-03-27 11:44:18 +00:00
auto sizer = new wxBoxSizer ( wxHORIZONTAL ) ;
2018-04-03 20:07:59 +00:00
sizer - > Add ( g_wiping_dialog_button ) ;
2018-04-04 08:18:26 +00:00
g_wiping_dialog_button - > Bind ( wxEVT_BUTTON , ( [ parent ] ( wxCommandEvent & e )
2018-03-27 11:44:18 +00:00
{
2018-04-04 08:18:26 +00:00
auto & config = g_PresetBundle - > project_config ;
std : : vector < double > init_matrix = ( config . option < ConfigOptionFloats > ( " wiping_volumes_matrix " ) ) - > values ;
std : : vector < double > init_extruders = ( config . option < ConfigOptionFloats > ( " wiping_volumes_extruders " ) ) - > values ;
2018-03-27 11:44:18 +00:00
WipingDialog dlg ( parent , std : : vector < float > ( init_matrix . begin ( ) , init_matrix . end ( ) ) , std : : vector < float > ( init_extruders . begin ( ) , init_extruders . end ( ) ) ) ;
if ( dlg . ShowModal ( ) = = wxID_OK ) {
std : : vector < float > matrix = dlg . get_matrix ( ) ;
std : : vector < float > extruders = dlg . get_extruders ( ) ;
2018-04-04 08:18:26 +00:00
( config . option < ConfigOptionFloats > ( " wiping_volumes_matrix " ) ) - > values = std : : vector < double > ( matrix . begin ( ) , matrix . end ( ) ) ;
( config . option < ConfigOptionFloats > ( " wiping_volumes_extruders " ) ) - > values = std : : vector < double > ( extruders . begin ( ) , extruders . end ( ) ) ;
2018-03-27 11:44:18 +00:00
}
} ) ) ;
return sizer ;
} ;
2018-05-22 14:14:41 +00:00
optgroup - > append_line ( line ) ;
sizer - > Add ( optgroup - > sizer , 1 , wxEXPAND | wxBOTTOM , 2 ) ;
2018-03-27 11:44:18 +00:00
2018-05-22 14:14:41 +00:00
m_optgroups . push_back ( optgroup ) ; // ogFrequentlyChangingParameters
2018-05-17 08:46:32 +00:00
}
2018-05-10 14:36:12 +00:00
2018-05-17 12:07:50 +00:00
void show_frequently_changed_parameters ( bool show )
2018-05-17 08:46:32 +00:00
{
2018-05-17 12:07:50 +00:00
g_frequently_changed_parameters_sizer - > Show ( show ) ;
if ( ! show ) return ;
for ( size_t i = 0 ; i < g_wxTabPanel - > GetPageCount ( ) ; + + i ) {
Tab * tab = dynamic_cast < Tab * > ( g_wxTabPanel - > GetPage ( i ) ) ;
if ( ! tab )
continue ;
tab - > update_wiping_button_visibility ( ) ;
break ;
}
}
2018-05-10 14:36:12 +00:00
2018-05-17 12:07:50 +00:00
void show_buttons ( bool show )
{
g_btn_export_stl - > Show ( show ) ;
g_btn_reslice - > Show ( show ) ;
for ( size_t i = 0 ; i < g_wxTabPanel - > GetPageCount ( ) ; + + i ) {
TabPrinter * tab = dynamic_cast < TabPrinter * > ( g_wxTabPanel - > GetPage ( i ) ) ;
if ( ! tab )
continue ;
g_btn_print - > Show ( show & & ! tab - > m_config - > opt_string ( " serial_port " ) . empty ( ) ) ;
g_btn_send_gcode - > Show ( show & & ! tab - > m_config - > opt_string ( " octoprint_host " ) . empty ( ) ) ;
break ;
}
}
void show_scrolled_window_sizer ( bool show )
{
g_scrolled_window_sizer - > Show ( static_cast < size_t > ( 0 ) , show ) ;
g_scrolled_window_sizer - > Show ( 1 , show ) ;
g_scrolled_window_sizer - > Show ( 2 , show & & g_show_print_info ) ;
2018-05-18 09:39:49 +00:00
g_manifold_warning_icon - > Show ( show & & g_show_manifold_warning_icon ) ;
2018-05-17 12:07:50 +00:00
}
void update_mode ( )
{
2018-05-21 12:49:31 +00:00
wxWindowUpdateLocker noUpdates ( g_right_panel ) ;
2018-05-17 12:07:50 +00:00
ConfigMenuIDs mode = get_view_mode ( ) ;
show_frequently_changed_parameters ( mode > = ConfigMenuModeRegular ) ;
g_expert_mode_part_sizer - > Show ( mode = = ConfigMenuModeExpert ) ;
show_scrolled_window_sizer ( mode > = ConfigMenuModeRegular ) ;
show_buttons ( mode > = ConfigMenuModeRegular ) ;
2018-05-21 12:49:31 +00:00
g_right_panel - > Layout ( ) ;
2018-03-09 17:34:30 +00:00
}
2018-05-22 14:14:41 +00:00
ConfigOptionsGroup * get_optgroup ( size_t i )
2018-03-12 15:52:21 +00:00
{
2018-05-22 14:14:41 +00:00
return m_optgroups [ i ] . get ( ) ;
2018-03-12 15:52:21 +00:00
}
2018-04-04 11:06:46 +00:00
2018-04-04 12:41:23 +00:00
wxButton * get_wiping_dialog_button ( )
{
2018-04-03 20:07:59 +00:00
return g_wiping_dialog_button ;
2018-04-04 12:41:23 +00:00
}
2018-04-04 11:06:46 +00:00
2018-03-22 12:49:48 +00:00
wxWindow * export_option_creator ( wxWindow * parent )
{
wxPanel * panel = new wxPanel ( parent , - 1 ) ;
wxSizer * sizer = new wxBoxSizer ( wxHORIZONTAL ) ;
wxCheckBox * cbox = new wxCheckBox ( panel , wxID_HIGHEST + 1 , L ( " Export print config " ) ) ;
2018-04-25 13:31:37 +00:00
cbox - > SetValue ( true ) ;
2018-03-22 12:49:48 +00:00
sizer - > AddSpacer ( 5 ) ;
sizer - > Add ( cbox , 0 , wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL , 5 ) ;
panel - > SetSizer ( sizer ) ;
sizer - > SetSizeHints ( panel ) ;
return panel ;
}
void add_export_option ( wxFileDialog * dlg , const std : : string & format )
{
if ( ( dlg ! = nullptr ) & & ( format = = " AMF " ) | | ( format = = " 3MF " ) )
{
if ( dlg - > SupportsExtraControl ( ) )
dlg - > SetExtraControlCreator ( export_option_creator ) ;
}
}
int get_export_option ( wxFileDialog * dlg )
{
if ( dlg ! = nullptr )
{
wxWindow * wnd = dlg - > GetExtraControl ( ) ;
if ( wnd ! = nullptr )
{
wxPanel * panel = dynamic_cast < wxPanel * > ( wnd ) ;
if ( panel ! = nullptr )
{
wxWindow * child = panel - > FindWindow ( wxID_HIGHEST + 1 ) ;
if ( child ! = nullptr )
{
wxCheckBox * cbox = dynamic_cast < wxCheckBox * > ( child ) ;
if ( cbox ! = nullptr )
return cbox - > IsChecked ( ) ? 1 : 0 ;
}
}
}
}
return 0 ;
2018-04-04 12:41:23 +00:00
2018-03-22 12:49:48 +00:00
}
2018-04-09 15:03:37 +00:00
void about ( )
{
AboutDialog dlg ;
dlg . ShowModal ( ) ;
dlg . Destroy ( ) ;
}
2018-04-04 12:41:23 +00:00
2018-05-21 19:04:03 +00:00
void desktop_open_datadir_folder ( )
{
2018-05-21 20:10:38 +00:00
// Execute command to open a file explorer, platform dependent.
2018-05-21 19:04:03 +00:00
std : : string cmd =
# ifdef _WIN32
" explorer "
# elif __APPLE__
" open "
# else
" xdg-open "
# endif
;
2018-05-21 20:10:38 +00:00
// Escape the path, platform dependent.
std : : string path = data_dir ( ) ;
# ifdef _WIN32
// Enclose the path into double quotes on Windows. A quote character is forbidden in file names,
// therefore it does not need to be escaped.
cmd + = ' " ' ;
cmd + = path ;
cmd + = ' " ' ;
# else
// Enclose the path into single quotes on Unix / OSX. All single quote characters need to be escaped
// inside a file name.
cmd + = ' \' ' ;
2018-05-21 21:40:17 +00:00
boost : : replace_all ( path , " ' " , " \\ ' " ) ;
cmd + = path ;
2018-05-21 20:10:38 +00:00
cmd + = ' \' ' ;
# endif
2018-05-21 19:04:03 +00:00
: : wxExecute ( wxString : : FromUTF8 ( cmd . c_str ( ) ) , wxEXEC_ASYNC , nullptr ) ;
}
2015-12-04 20:25:45 +00:00
} }