diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bd8f28ffb..15382d8b8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -136,7 +136,7 @@ add_executable(slic3r slic3r.cpp) set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_STATIC_RUNTIME OFF) -find_library(bsystem_l boost_system) +find_library(bsystem_l boost_system log) add_library(bsystem SHARED IMPORTED) set_target_properties(bsystem PROPERTIES IMPORTED_LOCATION ${bsystem_l}) find_library(bthread_l boost_thread) @@ -164,6 +164,7 @@ IF(wxWidgets_FOUND) add_library(slic3r_gui STATIC ${GUI_LIBDIR}/MainFrame.cpp ${GUI_LIBDIR}/GUI.cpp + ${GUI_LIBDIR}/Settings.cpp ${GUI_LIBDIR}/misc_ui.cpp ) #only build GUI lib if building with wx diff --git a/src/GUI/GUI.cpp b/src/GUI/GUI.cpp index b2a1e280b..67d5485c1 100644 --- a/src/GUI/GUI.cpp +++ b/src/GUI/GUI.cpp @@ -2,9 +2,13 @@ #ifndef WX_PRECOMP #include #endif +#include + #include "MainFrame.hpp" #include "GUI.hpp" +#include "misc_ui.hpp" +#include "Preset.hpp" namespace Slic3r { namespace GUI { @@ -14,13 +18,142 @@ enum }; bool App::OnInit() { - MainFrame *frame = new MainFrame( "Slic3r", wxDefaultPosition, wxDefaultSize, this->gui_config); - frame->Show( true ); this->SetAppName("Slic3r"); + // TODO: Call a logging function with channel GUI, severity info + + this->notifier = std::unique_ptr(); + + wxString datadir {decode_path(wxStandardPaths::Get().GetUserDataDir())}; + wxString enc_datadir = encode_path(datadir); + std::cerr << datadir << "\n"; + + // TODO: Call a logging function with channel GUI, severity info for datadir path + + /* Check to make sure if datadir exists + * + */ + + // Load settings + this->gui_config->save_settings(); + this->load_presets(); + + + wxImage::AddHandler(new wxPNGHandler()); + MainFrame *frame = new MainFrame( "Slic3r", wxDefaultPosition, wxDefaultSize, this->gui_config); + this->SetTopWindow(frame); + frame->Show( true ); + + // Load init bundle + // + + // Run the wizard if we don't have an initial config + /* + $self->check_version + if $self->have_version_check + && ($Settings->{_}{version_check} // 1) + && (!$Settings->{_}{last_version_check} || (time - $Settings->{_}{last_version_check}) >= 86400); + */ + + // run callback functions during idle + /* + EVT_IDLE($frame, sub { + while (my $cb = shift @cb) { + $cb->(); + } + }); + */ + + // Handle custom version check event + /* + EVT_COMMAND($self, -1, $VERSION_CHECK_EVENT, sub { + my ($self, $event) = @_; + my ($success, $response, $manual_check) = @{$event->GetData}; + + if ($success) { + if ($response =~ /^obsolete ?= ?([a-z0-9.-]+,)*\Q$Slic3r::VERSION\E(?:,|$)/) { + my $res = Wx::MessageDialog->new(undef, "A new version is available. Do you want to open the Slic3r website now?", + 'Update', wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_INFORMATION | wxICON_ERROR)->ShowModal; + Wx::LaunchDefaultBrowser('http://slic3r.org/') if $res == wxID_YES; + } else { + Slic3r::GUI::show_info(undef, "You're using the latest version. No updates are available.") if $manual_check; + } + $Settings->{_}{last_version_check} = time(); + $self->save_settings; + } else { + Slic3r::GUI::show_error(undef, "Failed to check for updates. Try later.") if $manual_check; + } + }); + */ return true; } +void App::save_window_pos(const wxTopLevelWindow* window, const wxString& name ) { + this->gui_config->window_pos[name] = + std::make_tuple( + window->GetScreenPosition(), + window->GetSize(), + window->IsMaximized()); + + this->gui_config->save_settings(); +} + +void App::restore_window_pos(wxTopLevelWindow* window, const wxString& name ) { + try { + auto tmp = gui_config->window_pos[name]; + const auto& size = std::get<1>(tmp); + const auto& pos = std::get<0>(tmp); + window->SetSize(size); + + auto display = wxDisplay().GetClientArea(); + if (((pos.x + size.x / 2) < display.GetRight()) && (pos.y + size.y/2 < display.GetBottom())) + window->Move(pos); + + window->Maximize(std::get<2>(tmp)); + } + catch (std::out_of_range e) { + // config was empty + } +} + +void App::load_presets() { +/* + for my $group (qw(printer filament print)) { + my $presets = $self->{presets}{$group}; + + # keep external or dirty presets + @$presets = grep { ($_->external && $_->file_exists) || $_->dirty } @$presets; + + my $dir = "$Slic3r::GUI::datadir/$group"; + opendir my $dh, Slic3r::encode_path($dir) + or die "Failed to read directory $dir (errno: $!)\n"; + foreach my $file (grep /\.ini$/i, readdir $dh) { + $file = Slic3r::decode_path($file); + my $name = basename($file); + $name =~ s/\.ini$//i; + + # skip if we already have it + next if any { $_->name eq $name } @$presets; + + push @$presets, Slic3r::GUI::Preset->new( + group => $group, + name => $name, + file => "$dir/$file", + ); + } + closedir $dh; + + @$presets = sort { $a->name cmp $b->name } @$presets; + + unshift @$presets, Slic3r::GUI::Preset->new( + group => $group, + default => 1, + name => '- default -', + ); + } +*/ +} + }} // namespace Slic3r::GUI diff --git a/src/GUI/GUI.hpp b/src/GUI/GUI.hpp index 82d6de746..219970806 100644 --- a/src/GUI/GUI.hpp +++ b/src/GUI/GUI.hpp @@ -1,9 +1,11 @@ #ifndef GUI_HPP #define GUI_HPP +#include #include "MainFrame.hpp" #include "Notifier.hpp" #include -#include +#include + namespace Slic3r { namespace GUI { @@ -21,12 +23,19 @@ public: virtual bool OnInit(); App(std::shared_ptr config) : wxApp(), gui_config(config) {} - void check_version(bool manual) { /* stub */} + /// Save position, size, and maximize state for a TopLevelWindow (includes Frames) by name in Settings. + void save_window_pos(const wxTopLevelWindow* window, const wxString& name ); + + /// Move/resize a named TopLevelWindow (includes Frames) from Settings + void restore_window_pos(wxTopLevelWindow* window, const wxString& name ); private: std::shared_ptr gui_config; // GUI-specific configuration options - Notifier* notifier; + std::unique_ptr notifier {nullptr}; std::vector presets { preset_list(), preset_list(), preset_list() }; + + void load_presets(); + }; }} // namespace Slic3r::GUI diff --git a/src/GUI/MainFrame.hpp b/src/GUI/MainFrame.hpp index e4014a27c..085cc3922 100644 --- a/src/GUI/MainFrame.hpp +++ b/src/GUI/MainFrame.hpp @@ -20,16 +20,7 @@ namespace Slic3r { namespace GUI { -template -void append_menu_item(wxMenu* menu, const wxString& name,const wxString& help, T lambda, int id = wxID_ANY, const wxBitmap& icon = wxBitmap(), const wxString& accel = "") { - wxMenuItem* tmp = menu->Append(wxID_ANY, name, help); - wxAcceleratorEntry* a = new wxAcceleratorEntry(); - if (a->FromString(accel)) - tmp->SetAccel(a); // set the accelerator if and only if the accelerator is fine - tmp->SetHelp(help); - menu->Bind(wxEVT_MENU, lambda, tmp->GetId(), tmp->GetId()); -} constexpr unsigned int TOOLTIP_TIMER = 32767; diff --git a/src/GUI/Preset.hpp b/src/GUI/Preset.hpp new file mode 100644 index 000000000..e169c4827 --- /dev/null +++ b/src/GUI/Preset.hpp @@ -0,0 +1,17 @@ +#ifndef PRESET_HPP +#define PRESET_HPP + +#include "PrintConfig.hpp" + +namespace Slic3r { namespace GUI { + +class Preset { + +private: + Slic3r::DynamicPrintConfig config { Slic3r::DynamicPrintConfig() }; + +}; + +}} // namespace Slic3r::GUI + +#endif // PRESET_HPP diff --git a/src/GUI/Settings.cpp b/src/GUI/Settings.cpp new file mode 100644 index 000000000..8affa6886 --- /dev/null +++ b/src/GUI/Settings.cpp @@ -0,0 +1,15 @@ +#include "Settings.hpp" + +namespace Slic3r { namespace GUI { + +void Settings::save_settings() { +/* +sub save_settings { + my ($self) = @_; + Slic3r::Config->write_ini("$datadir/slic3r.ini", $Settings); +} + +*/ +} + +}} // namespace Slic3r::GUI diff --git a/src/GUI/Settings.hpp b/src/GUI/Settings.hpp index 07e219406..9c135cec3 100644 --- a/src/GUI/Settings.hpp +++ b/src/GUI/Settings.hpp @@ -1,13 +1,58 @@ #ifndef SETTINGS_HPP #define SETTINGS_HPP + +#include +#ifndef WX_PRECOMP + #include +#endif +#include +#include + +#include "libslic3r.h" + namespace Slic3r { namespace GUI { +enum class PathColor { + role +}; + +enum class ColorScheme { + solarized, slic3r +}; + +enum class ReloadBehavior { + all, copy, discard +}; + /// Stub class to hold onto GUI-specific settings options. /// TODO: Incorporate a copy of Slic3r::Config class Settings { public: - bool show_host; - Settings(): show_host(false) {} //< Show host/controller tab + bool show_host {false}; + bool version_check {true}; + bool autocenter {true}; + bool autoalignz {true}; + bool invert_zoom {false}; + bool background_processing {false}; + + bool preset_editor_tabs {false}; + + bool hide_reload_dialog {false}; + + ReloadBehavior reload {ReloadBehavior::all}; + ColorScheme color {ColorScheme::slic3r}; + PathColor color_toolpaths_by {PathColor::role}; + + float nudge {1.0}; //< 2D plater nudge amount in mm + + unsigned int threads {1}; //< Number of threads to use when slicing + + const wxString version { wxString(SLIC3R_VERSION) }; + + void save_settings(); + + /// Storage for window positions + std::map > window_pos { std::map >() }; }; }} //namespace Slic3r::GUI diff --git a/src/GUI/misc_ui.cpp b/src/GUI/misc_ui.cpp index 278f6e4d7..ef00fa2d3 100644 --- a/src/GUI/misc_ui.cpp +++ b/src/GUI/misc_ui.cpp @@ -1,4 +1,6 @@ #include "misc_ui.hpp" +#include + namespace Slic3r { namespace GUI { @@ -26,5 +28,62 @@ const wxString home(const wxString& in) { return wxGetHomeDir() + "/." + in + "/"; } + +wxString decode_path(const wxString& in) { + // TODO Stub + return in; +} + +wxString encode_path(const wxString& in) { + // TODO Stub + return in; +} +/* +sub append_submenu { + my ($self, $menu, $string, $description, $submenu, $id, $icon) = @_; + + $id //= &Wx::NewId(); + my $item = Wx::MenuItem->new($menu, $id, $string, $description // ''); + $self->set_menu_item_icon($item, $icon); + $item->SetSubMenu($submenu); + $menu->Append($item); + + return $item; +} +*/ + +/* +sub scan_serial_ports { + my ($self) = @_; + + my @ports = (); + + if ($^O eq 'MSWin32') { + # Windows + if (eval "use Win32::TieRegistry; 1") { + my $ts = Win32::TieRegistry->new("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM", + { Access => 'KEY_READ' }); + if ($ts) { + # when no serial ports are available, the registry key doesn't exist and + # TieRegistry->new returns undef + $ts->Tie(\my %reg); + push @ports, sort values %reg; + } + } + } else { + # UNIX and OS X + push @ports, glob '/dev/{ttyUSB,ttyACM,tty.,cu.,rfcomm}*'; + } + + return grep !/Bluetooth|FireFly/, @ports; +} +*/ +/* +sub show_error { + my ($parent, $message) = @_; + Wx::MessageDialog->new($parent, $message, 'Error', wxOK | wxICON_ERROR)->ShowModal; +} +*/ + }} // namespace Slic3r::GUI diff --git a/src/GUI/misc_ui.hpp b/src/GUI/misc_ui.hpp index cc92e5a03..5276a3f8c 100644 --- a/src/GUI/misc_ui.hpp +++ b/src/GUI/misc_ui.hpp @@ -39,6 +39,31 @@ const wxString var(const wxString& in); /// Always returns path to home directory. const wxString home(const wxString& in = "Slic3r"); +template +void append_menu_item(wxMenu* menu, const wxString& name,const wxString& help, T lambda, int id = wxID_ANY, const wxString& icon = "", const wxString& accel = "") { + wxMenuItem* tmp = menu->Append(wxID_ANY, name, help); + wxAcceleratorEntry* a = new wxAcceleratorEntry(); + if (!accel.IsEmpty()) { + a->FromString(accel); + tmp->SetAccel(a); // set the accelerator if and only if the accelerator is fine + } + tmp->SetHelp(help); + if (!icon.IsEmpty()) + tmp->SetBitmap(wxBitmap(var(icon))); + + menu->Bind(wxEVT_MENU, lambda, tmp->GetId(), tmp->GetId()); +} + +/* +sub CallAfter { + my ($self, $cb) = @_; + push @cb, $cb; +} +*/ + +wxString decode_path(const wxString& in); +wxString encode_path(const wxString& in); + }} // namespace Slic3r::GUI #endif // MISC_UI_HPP