diff --git a/.travis.yml b/.travis.yml index f76e6822f..738368ffc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,12 +5,13 @@ install: - export BOOST_DIR=$HOME/boost_1_63_0 - export SLIC3R_STATIC=1 - export CXX=g++-4.9 -- export CC=g++-4.9 +- export CC=gcc-4.9 - source $HOME/perl5/perlbrew/etc/bashrc script: - bash package/linux/travis-setup.sh - perlbrew switch slic3r-perl -- perl ./Build.PL +- cmake -DBOOST_ROOT=$BOOST_DIR src/ +- make after_success: - eval $(perl -Mlocal::lib=$TRAVIS_BUILD_DIR/local-lib) - LD_LIBRARY_PATH=$WXDIR/lib package/linux/make_archive.sh linux-x64 @@ -22,6 +23,7 @@ branches: only: - master - xsgui + - cppgui cache: apt: true directories: @@ -36,6 +38,10 @@ addons: - libgtk2.0-0 - libgtk2.0-dev - freeglut3 + - cmake + - wx3.0-headers + - libwxgtk3.0-dev + - wx-common ssh_known_hosts: dl.slic3r.org notifications: irc: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb34b5ae8..bd8f28ffb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.8) +cmake_minimum_required (VERSION 3.9) project (slic3r) # only on newer GCCs: -ftemplate-backtrace-limit=0 @@ -17,14 +17,17 @@ IF(CMAKE_HOST_APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_NO_CXX11_RVALUE_REFERENCES -DBOOST_THREAD_USES_MOVE") set(CMAKE_EXE_LINKER_FLAGS "-framework IOKit -framework CoreFoundation -lc++") ELSE(CMAKE_HOST_APPLE) - set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") +# set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -L.") ENDIF(CMAKE_HOST_APPLE) -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_STATIC_RUNTIME ON) -set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") + +set(Boost_USE_STATIC_LIBS OFF) +set(Boost_USE_STATIC_RUNTIME OFF) +find_package(Threads REQUIRED) + find_package(Boost COMPONENTS system thread filesystem) set(LIBDIR ${CMAKE_CURRENT_SOURCE_DIR}/../xs/src/) +set(GUI_LIBDIR ${CMAKE_CURRENT_SOURCE_DIR}/GUI/) include_directories(${LIBDIR}) include_directories(${LIBDIR}/libslic3r) @@ -53,6 +56,7 @@ add_library(libslic3r STATIC ${LIBDIR}/libslic3r/Fill/FillHoneycomb.cpp ${LIBDIR}/libslic3r/Fill/FillPlanePath.cpp ${LIBDIR}/libslic3r/Fill/FillRectilinear.cpp + ${LIBDIR}/libslic3r/Fill/FillGyroid.cpp ${LIBDIR}/libslic3r/Flow.cpp ${LIBDIR}/libslic3r/GCode.cpp ${LIBDIR}/libslic3r/GCode/CoolingBuffer.cpp @@ -122,29 +126,29 @@ add_library(poly2tri STATIC ) add_executable(slic3r slic3r.cpp) -set_target_properties(slic3r PROPERTIES LINK_SEARCH_START_STATIC 1) -set_target_properties(slic3r PROPERTIES LINK_SEARCH_END_STATIC 1) +#set_target_properties(slic3r PROPERTIES LINK_SEARCH_START_STATIC 1) +#set_target_properties(slic3r PROPERTIES LINK_SEARCH_END_STATIC 1) -add_executable(extrude-tin utils/extrude-tin.cpp) -set_target_properties(extrude-tin PROPERTIES LINK_SEARCH_START_STATIC 1) -set_target_properties(extrude-tin PROPERTIES LINK_SEARCH_END_STATIC 1) +#add_executable(extrude-tin utils/extrude-tin.cpp) +#set_target_properties(extrude-tin PROPERTIES LINK_SEARCH_START_STATIC 1) +#set_target_properties(extrude-tin PROPERTIES LINK_SEARCH_END_STATIC 1) -set(wxWidgets_USE_STATIC) -SET(wxWidgets_USE_LIBS) +set(Boost_USE_STATIC_LIBS OFF) +set(Boost_USE_STATIC_RUNTIME OFF) -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_STATIC_RUNTIME ON) -set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") find_library(bsystem_l boost_system) -add_library(bsystem STATIC IMPORTED) +add_library(bsystem SHARED IMPORTED) set_target_properties(bsystem PROPERTIES IMPORTED_LOCATION ${bsystem_l}) find_library(bthread_l boost_thread) -add_library(bthread STATIC IMPORTED) +add_library(bthread SHARED IMPORTED) set_target_properties(bthread PROPERTIES IMPORTED_LOCATION ${bthread_l}) include_directories(${Boost_INCLUDE_DIRS}) -#find_package(wxWidgets) -#disable wx for the time being - we're not building any of the gui yet +set(wxWidgets_USE_STATIC OFF) +set(wxWidgets_USE_UNICODE ON) + +find_package(wxWidgets COMPONENTS base aui core) + IF(CMAKE_HOST_UNIX) #set(Boost_LIBRARIES bsystem bthread bfilesystem) ENDIF(CMAKE_HOST_UNIX) @@ -154,9 +158,16 @@ target_link_libraries (slic3r libslic3r admesh BSpline clipper expat polypartiti IF(wxWidgets_FOUND) MESSAGE("wx found!") INCLUDE("${wxWidgets_USE_FILE}") - add_library(slic3r_gui STATIC ${LIBDIR}/slic3r/GUI/3DScene.cpp ${LIBDIR}/slic3r/GUI/GUI.cpp) + include_directories(${GUI_LIBDIR}) + include_directories(${wxWidgets_INCLUDE}) + + add_library(slic3r_gui STATIC + ${GUI_LIBDIR}/MainFrame.cpp + ${GUI_LIBDIR}/GUI.cpp + ${GUI_LIBDIR}/misc_ui.cpp + ) #only build GUI lib if building with wx - target_link_libraries (slic3r slic3r-gui ${wxWidgets_LIBRARIES}) + target_link_libraries (slic3r slic3r_gui ${wxWidgets_LIBRARIES}) ELSE(wxWidgets_FOUND) # For convenience. When we cannot continue, inform the user MESSAGE("wx not found!") @@ -169,8 +180,8 @@ IF (WIN32) ${LIBDIR}/boost/nowide/iostream.cpp ) - target_link_libraries(slic3r boost-nowide) - target_link_libraries(extrude-tin boost-nowide) + target_link_libraries(slic3r STATIC boost-nowide) +# target_link_libraries(extrude-tin boost-nowide) ENDIF(WIN32) -target_link_libraries (extrude-tin libslic3r admesh BSpline clipper expat polypartition poly2tri ${Boost_LIBRARIES}) +#target_link_libraries (extrude-tin libslic3r admesh BSpline clipper expat polypartition poly2tri ${Boost_LIBRARIES}) diff --git a/src/GUI/Controller.hpp b/src/GUI/Controller.hpp new file mode 100644 index 000000000..ef3650886 --- /dev/null +++ b/src/GUI/Controller.hpp @@ -0,0 +1,15 @@ +#ifndef CONTROLLER_UI_HPP +#define CONTROLLER_UI_HPP + +namespace Slic3r { namespace GUI { + +class Controller : public wxPanel { +public: + Controller(wxWindow* parent, const wxString& title) : + wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, title) + { } +}; + +}} // Namespace Slic3r::GUI + +#endif // CONTROLLER_UI_HPP diff --git a/src/GUI/GUI.cpp b/src/GUI/GUI.cpp new file mode 100644 index 000000000..b2a1e280b --- /dev/null +++ b/src/GUI/GUI.cpp @@ -0,0 +1,26 @@ +#include +#ifndef WX_PRECOMP + #include +#endif + +#include "MainFrame.hpp" +#include "GUI.hpp" + +namespace Slic3r { namespace GUI { + +enum +{ + ID_Hello = 1 +}; +bool App::OnInit() +{ + MainFrame *frame = new MainFrame( "Slic3r", wxDefaultPosition, wxDefaultSize, this->gui_config); + + frame->Show( true ); + + this->SetAppName("Slic3r"); + + return true; +} + +}} // namespace Slic3r::GUI diff --git a/src/GUI/GUI.hpp b/src/GUI/GUI.hpp new file mode 100644 index 000000000..82d6de746 --- /dev/null +++ b/src/GUI/GUI.hpp @@ -0,0 +1,33 @@ +#ifndef GUI_HPP +#define GUI_HPP +#include "MainFrame.hpp" +#include "Notifier.hpp" +#include +#include + +namespace Slic3r { namespace GUI { + +// Friendly indices for the preset lists. +enum class PresetID { + PRINT = 0, + FILAMENT = 1, + PRINTER = 2 +}; +using preset_list = std::vector; + +class App: public wxApp +{ +public: + virtual bool OnInit(); + App(std::shared_ptr config) : wxApp(), gui_config(config) {} + + void check_version(bool manual) { /* stub */} + +private: + std::shared_ptr gui_config; // GUI-specific configuration options + Notifier* notifier; + std::vector presets { preset_list(), preset_list(), preset_list() }; +}; + +}} // namespace Slic3r::GUI +#endif // GUI_HPP diff --git a/src/GUI/MainFrame.cpp b/src/GUI/MainFrame.cpp new file mode 100644 index 000000000..f006423b1 --- /dev/null +++ b/src/GUI/MainFrame.cpp @@ -0,0 +1,171 @@ +#include "MainFrame.hpp" +#include "misc_ui.hpp" +#include +#include + +namespace Slic3r { namespace GUI { + +wxBEGIN_EVENT_TABLE(MainFrame, wxFrame) +wxEND_EVENT_TABLE() + +MainFrame::MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size) + : MainFrame(title, pos, size, nullptr) {} +MainFrame::MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, std::shared_ptr config) + : wxFrame(NULL, wxID_ANY, title, pos, size), loaded(false), + tabpanel(nullptr), controller(nullptr), plater(nullptr), gui_config(config), preset_editor_tabs(std::map()) +{ + // Set icon to either the .ico if windows or png for everything else. + if (the_os == OS::Windows) + this->SetIcon(wxIcon(var("Slic3r.ico"), wxBITMAP_TYPE_ICO)); + else + this->SetIcon(wxIcon(var("Slic3r_128px.png"), wxBITMAP_TYPE_PNG)); + + + this->init_tabpanel(); + this->init_menubar(); + + wxToolTip::SetAutoPop(TOOLTIP_TIMER); + + // STUB: Initialize status bar with text. + /* # initialize status bar + $self->{statusbar} = Slic3r::GUI::ProgressStatusBar->new($self, -1); + $self->{statusbar}->SetStatusText("Version $Slic3r::VERSION - Remember to check for updates at http://slic3r.org/"); + $self->SetStatusBar($self->{statusbar}); */ + + this->loaded = 1; + + // Initialize layout + { + wxSizer* sizer = new wxBoxSizer(wxVERTICAL); + sizer->Add(this->tabpanel, 1, wxEXPAND); + sizer->SetSizeHints(this); + this->Fit(); + this->SetMinSize(wxSize(760, 490)); + this->SetSize(this->GetMinSize()); + wxTheApp->SetTopWindow(this); + this->Show(); + this->Layout(); + } +/* + # declare events + EVT_CLOSE($self, sub { + my (undef, $event) = @_; + + if ($event->CanVeto) { + if (!$self->{plater}->prompt_unsaved_changes) { + $event->Veto; + return; + } + + if ($self->{controller} && $self->{controller}->printing) { + my $confirm = Wx::MessageDialog->new($self, "You are currently printing. Do you want to stop printing and continue anyway?", + 'Unfinished Print', wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT); + if ($confirm->ShowModal == wxID_NO) { + $event->Veto; + return; + } + } + } + + # save window size + wxTheApp->save_window_pos($self, "main_frame"); + + # propagate event + $event->Skip; + }); +*/ +} + +/// Private initialization function for the main frame tab panel. +void MainFrame::init_tabpanel() +{ + this->tabpanel = new wxAuiNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP); + auto panel = this->tabpanel; + + panel->Bind(wxEVT_AUINOTEBOOK_PAGE_CHANGED, ([=](wxAuiNotebookEvent& e) + { + auto tabpanel = this->tabpanel; + // TODO: trigger processing for activation event + if (tabpanel->GetSelection() > 1) { + tabpanel->SetWindowStyle(tabpanel->GetWindowStyleFlag() | wxAUI_NB_CLOSE_ON_ACTIVE_TAB); + } else if (this->gui_config->show_host == false && tabpanel->GetSelection() == 1) { + tabpanel->SetWindowStyle(tabpanel->GetWindowStyleFlag() | wxAUI_NB_CLOSE_ON_ACTIVE_TAB); + } else { + tabpanel->SetWindowStyle(tabpanel->GetWindowStyleFlag() | ~wxAUI_NB_CLOSE_ON_ACTIVE_TAB); + } + }), panel->GetId()); + + panel->Bind(wxEVT_AUINOTEBOOK_PAGE_CLOSE, ([=](wxAuiNotebookEvent& e) + { + if (typeid(panel) == typeid(Slic3r::GUI::PresetEditor)) { + wxDELETE(this->preset_editor_tabs[panel->GetId()]); + } + wxTheApp->CallAfter([=] { this->tabpanel->SetSelection(0); }); + }), panel->GetId()); + + this->plater = new Slic3r::GUI::Plater(panel, _("Plater")); + this->controller = new Slic3r::GUI::Controller(panel, _("Controller")); + + panel->AddPage(this->plater, this->plater->GetName()); + if (this->gui_config->show_host) panel->AddPage(this->controller, this->controller->GetName()); + +} + +void MainFrame::init_menubar() +{ + + wxMenu* menuFile = new wxMenu(); + { + } + + wxMenu* menuPlater = new wxMenu(); + { + } + wxMenu* menuObject = new wxMenu(); + { + } + wxMenu* menuSettings = new wxMenu(); + { + } + wxMenu* menuView = new wxMenu(); + { + } + wxMenu* menuWindow = new wxMenu(); + { + } + wxMenu* menuHelp = new wxMenu(); + { + // TODO: Reimplement config wizard + //menuHelp->AppendSeparator(); + append_menu_item(menuHelp, _("Slic3r &Website"), _("Open the Slic3r website in your browser"), [=](wxCommandEvent& e) + { + wxLaunchDefaultBrowser("http://www.slic3r.org"); + }); + append_menu_item(menuHelp, _("Check for &Updates..."), _("Check for new Slic3r versions"), [=](wxCommandEvent& e) + { + check_version(true); + }); + append_menu_item(menuHelp, _("Slic3r &Manual"), _("Open the Slic3r manual in your browser"), [=](wxCommandEvent& e) + { + wxLaunchDefaultBrowser("http://manual.slic3r.org/"); + }); + append_menu_item(menuHelp, _("&About Slic3r"), _("Show about dialog"), [=](wxCommandEvent& e) + { + }, wxID_ABOUT); + + } + + wxMenuBar* menubar = new wxMenuBar(); + menubar->Append(menuFile, _("&File")); + menubar->Append(menuPlater, _("&Plater")); + menubar->Append(menuObject, _("&Object")); + menubar->Append(menuSettings, _("&Settings")); + menubar->Append(menuView, _("&View")); + menubar->Append(menuWindow, _("&Window")); + menubar->Append(menuHelp, _("&Help")); + + this->SetMenuBar(menubar); + +} + +}} // Namespace Slic3r::GUI diff --git a/src/GUI/MainFrame.hpp b/src/GUI/MainFrame.hpp new file mode 100644 index 000000000..e4014a27c --- /dev/null +++ b/src/GUI/MainFrame.hpp @@ -0,0 +1,62 @@ + +#ifndef MAINFRAME_HPP +#define MAINFRAME_HPP +#include +#ifndef WX_PRECOMP + #include +#endif +#include +#include + +#include +#include + + +#include "Controller.hpp" +#include "Plater.hpp" +#include "PresetEditor.hpp" +#include "Settings.hpp" +#include "GUI.hpp" + +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; + +class MainFrame: public wxFrame +{ +public: + MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size); + MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, std::shared_ptr gui_config); +private: + wxDECLARE_EVENT_TABLE(); + + void init_menubar(); //< Routine to intialize all top-level menu items. + void init_tabpanel(); //< Routine to initialize all of the tabs. + + bool loaded; //< Main frame itself has finished loading. + // STUB: preset editor tabs storage + // STUB: Statusbar reference + + wxAuiNotebook* tabpanel; + Controller* controller; + Plater* plater; + + + std::shared_ptr gui_config; + std::map preset_editor_tabs; + +}; + +}} // Namespace Slic3r::GUI +#endif // MAINFRAME_HPP diff --git a/src/GUI/Notifier.hpp b/src/GUI/Notifier.hpp new file mode 100644 index 000000000..f7a9c0d92 --- /dev/null +++ b/src/GUI/Notifier.hpp @@ -0,0 +1,15 @@ +#ifndef NOTIFIER_HPP +#define NOTIFIER_HPP + +namespace Slic3r { namespace GUI { + +/// Class to perform window manager notifications using Growl and/or DBus XWindow + +class Notifier { +public: + Notifier() { } +}; + +}} // Namespace Slic3r::GUI + +#endif // NOTIFIER_HPP diff --git a/src/GUI/Plater.hpp b/src/GUI/Plater.hpp new file mode 100644 index 000000000..bf7aa917a --- /dev/null +++ b/src/GUI/Plater.hpp @@ -0,0 +1,17 @@ +#ifndef PLATER_HPP +#define PLATER_HPP + +namespace Slic3r { namespace GUI { + +class Plater : public wxPanel +{ +public: + Plater(wxWindow* parent, const wxString& title) : + wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, title) + { } + +}; + +} } // Namespace Slic3r::GUI + +#endif // PLATER_HPP diff --git a/src/GUI/PresetEditor.hpp b/src/GUI/PresetEditor.hpp new file mode 100644 index 000000000..8d6359eab --- /dev/null +++ b/src/GUI/PresetEditor.hpp @@ -0,0 +1,11 @@ +#ifndef PRESETEDITOR_HPP +#define PRESETEDITOR_HPP + +namespace Slic3r { namespace GUI { + +class PresetEditor : public wxPanel { + +}; + +}} // namespace Slic3r::GUI +#endif // PRESETEDITOR_HPP diff --git a/src/GUI/Settings.hpp b/src/GUI/Settings.hpp new file mode 100644 index 000000000..07e219406 --- /dev/null +++ b/src/GUI/Settings.hpp @@ -0,0 +1,15 @@ +#ifndef SETTINGS_HPP +#define SETTINGS_HPP +namespace Slic3r { namespace GUI { + +/// 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 +}; + +}} //namespace Slic3r::GUI + +#endif // SETTINGS_HPP diff --git a/src/GUI/misc_ui.cpp b/src/GUI/misc_ui.cpp new file mode 100644 index 000000000..278f6e4d7 --- /dev/null +++ b/src/GUI/misc_ui.cpp @@ -0,0 +1,30 @@ +#include "misc_ui.hpp" +namespace Slic3r { namespace GUI { + + +#ifdef SLIC3R_DEV +void check_version(bool manual) { +} +#else +void check_version(bool manual) { +} + +#endif + +const wxString var(const wxString& in) { + wxFileName f(wxStandardPaths::Get().GetExecutablePath()); + wxString appPath(f.GetPath()); + + // replace center string with path to VAR in actual distribution later + return appPath + "/../var/" + in; +} + +/// Returns the path to Slic3r's default user data directory. +const wxString home(const wxString& in) { + if (the_os == OS::Windows) + return wxGetHomeDir() + "/" + in + "/"; + return wxGetHomeDir() + "/." + in + "/"; +} + +}} // namespace Slic3r::GUI + diff --git a/src/GUI/misc_ui.hpp b/src/GUI/misc_ui.hpp new file mode 100644 index 000000000..cc92e5a03 --- /dev/null +++ b/src/GUI/misc_ui.hpp @@ -0,0 +1,44 @@ +#ifndef MISC_UI_HPP +#define MISC_UI_HPP + +#include +#ifndef WX_PRECOMP + #include +#endif + +#include +#include + +/// Common static (that is, free-standing) functions, not part of an object hierarchy. + +namespace Slic3r { namespace GUI { + +enum class OS { Linux, Mac, Windows } ; +// constants to reduce the proliferation of macros in the rest of the code +#ifdef __WIN32 +constexpr OS the_os = OS::Windows; +#elif __APPLE__ +constexpr OS the_os = OS::Mac; +#elif __linux__ +constexpr OS the_os = OS::Linux; +#endif + +#ifdef SLIC3R_DEV +constexpr bool isDev = true; +#else +constexpr bool isDev = false; +#endif + +/// Performs a check via the Internet for a new version of Slic3r. +/// If this version of Slic3r was compiled with -DSLIC3R_DEV, check the development +/// space instead of release. +void check_version(bool manual = false); + +const wxString var(const wxString& in); + +/// Always returns path to home directory. +const wxString home(const wxString& in = "Slic3r"); + +}} // namespace Slic3r::GUI + +#endif // MISC_UI_HPP diff --git a/src/slic3r.cpp b/src/slic3r.cpp index bf2fb2be7..82a04a1f1 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -13,6 +13,7 @@ #include #include #include +#include "GUI/GUI.hpp" using namespace Slic3r; @@ -39,6 +40,15 @@ main(int argc, char **argv) cli_config.apply(config, true); DynamicPrintConfig print_config; + + std::shared_ptr gui_config = std::make_shared(); + + GUI::App *gui = new GUI::App(gui_config); + + gui_config->show_host = true; + + GUI::App::SetInstance(gui); + wxEntry(argc, argv); // load config files supplied via --load for (const std::string &file : cli_config.load.values) {