diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm
index 4ec388c14..88e4745d1 100644
--- a/lib/Slic3r/GUI.pm
+++ b/lib/Slic3r/GUI.pm
@@ -7,7 +7,6 @@ use File::Basename qw(basename);
use FindBin;
use List::Util qw(first);
use Slic3r::GUI::2DBed;
-use Slic3r::GUI::AboutDialog;
use Slic3r::GUI::BedShapeDialog;
use Slic3r::GUI::ConfigWizard;
use Slic3r::GUI::Controller;
@@ -191,13 +190,6 @@ sub recreate_GUI{
}
}
-sub about {
- my ($self) = @_;
- my $about = Slic3r::GUI::AboutDialog->new(undef);
- $about->ShowModal;
- $about->Destroy;
-}
-
sub system_info {
my ($self) = @_;
my $slic3r_info = Slic3r::slic3r_info(format => 'html');
diff --git a/lib/Slic3r/GUI/AboutDialog.pm b/lib/Slic3r/GUI/AboutDialog.pm
deleted file mode 100644
index 0879ea35b..000000000
--- a/lib/Slic3r/GUI/AboutDialog.pm
+++ /dev/null
@@ -1,122 +0,0 @@
-package Slic3r::GUI::AboutDialog;
-use strict;
-use warnings;
-use utf8;
-
-use Wx qw(:font :html :misc :dialog :sizer :systemsettings :frame :id);
-use Wx::Event qw(EVT_HTML_LINK_CLICKED EVT_LEFT_DOWN EVT_BUTTON);
-use Wx::Print;
-use Wx::Html;
-use base 'Wx::Dialog';
-
-sub new {
- my $class = shift;
- my ($parent) = @_;
- my $self = $class->SUPER::new($parent, -1, 'About Slic3r', wxDefaultPosition, [600, 340], wxCAPTION);
-
- $self->SetBackgroundColour(Wx::wxWHITE);
- my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
- $self->SetSizer($hsizer);
-
- # logo
- my $logo = Slic3r::GUI::AboutDialog::Logo->new($self, -1, wxDefaultPosition, wxDefaultSize);
- $logo->SetBackgroundColour(Wx::wxWHITE);
- $hsizer->Add($logo, 0, wxEXPAND | wxLEFT | wxRIGHT, 30);
-
- my $vsizer = Wx::BoxSizer->new(wxVERTICAL);
- $hsizer->Add($vsizer, 1, wxEXPAND, 0);
-
- # title
- my $title = Wx::StaticText->new($self, -1, $Slic3r::FORK_NAME, wxDefaultPosition, wxDefaultSize);
- my $title_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
- $title_font->SetWeight(wxFONTWEIGHT_BOLD);
- $title_font->SetFamily(wxFONTFAMILY_ROMAN);
- $title_font->SetPointSize(24);
- $title->SetFont($title_font);
- $vsizer->Add($title, 0, wxALIGN_LEFT | wxTOP, 30);
-
- # version
- my $version = Wx::StaticText->new($self, -1, "Version $Slic3r::VERSION", wxDefaultPosition, wxDefaultSize);
- my $version_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
- $version_font->SetPointSize(&Wx::wxMSW ? 9 : 11);
- $version->SetFont($version_font);
- $vsizer->Add($version, 0, wxALIGN_LEFT | wxBOTTOM, 10);
-
- # text
- my $text =
- '' .
- '
' .
- '' .
- 'Copyright © 2016 Vojtech Bubnik, Prusa Research.
' .
- 'Copyright © 2011-2016 Alessandro Ranellucci.
' .
- 'Slic3r is licensed under the ' .
- 'GNU Affero General Public License, version 3.' .
- '
' .
- 'Contributions by Henrik Brix Andersen, Nicolas Dandrimont, Mark Hindess, Petr Ledvina, Y. Sapir, Mike Sheldrake and numerous others. ' .
- 'Manual by Gary Hodgson. Inspired by the RepRap community.
' .
- 'Slic3r logo designed by Corey Daniels, Silk Icon Set designed by Mark James. ' .
- '' .
- '' .
- '';
- my $html = Wx::HtmlWindow->new($self, -1, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER);
- my $font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
- my $size = &Wx::wxMSW ? 8 : 10;
- $html->SetFonts($font->GetFaceName, $font->GetFaceName, [$size, $size, $size, $size, $size, $size, $size]);
- $html->SetBorders(2);
- $html->SetPage($text);
- $vsizer->Add($html, 1, wxEXPAND | wxALIGN_LEFT | wxRIGHT | wxBOTTOM, 20);
- EVT_HTML_LINK_CLICKED($self, $html, \&link_clicked);
-
- my $buttons = $self->CreateStdDialogButtonSizer(wxOK);
- $self->SetEscapeId(wxID_CLOSE);
- EVT_BUTTON($self, wxID_CLOSE, sub {
- $self->EndModal(wxID_CLOSE);
- $self->Close;
- });
- $vsizer->Add($buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3);
-
- EVT_LEFT_DOWN($self, sub { $self->Close });
- EVT_LEFT_DOWN($logo, sub { $self->Close });
-
- return $self;
-}
-
-sub link_clicked {
- my ($self, $event) = @_;
-
- Wx::LaunchDefaultBrowser($event->GetLinkInfo->GetHref);
- $event->Skip(0);
-}
-
-package Slic3r::GUI::AboutDialog::Logo;
-use Wx qw(:bitmap :dc);
-use Wx::Event qw(EVT_PAINT);
-use base 'Wx::Panel';
-
-sub new {
- my $class = shift;
- my $self = $class->SUPER::new(@_);
-
- $self->{logo} = Wx::Bitmap->new(Slic3r::var("Slic3r_192px.png"), wxBITMAP_TYPE_PNG);
- $self->SetMinSize(Wx::Size->new($self->{logo}->GetWidth, $self->{logo}->GetHeight));
-
- EVT_PAINT($self, \&repaint);
-
- return $self;
-}
-
-sub repaint {
- my ($self, $event) = @_;
-
- my $dc = Wx::PaintDC->new($self);
- $dc->SetBackgroundMode(wxTRANSPARENT);
-
- my $size = $self->GetSize;
- my $logo_w = $self->{logo}->GetWidth;
- my $logo_h = $self->{logo}->GetHeight;
- $dc->DrawBitmap($self->{logo}, ($size->GetWidth - $logo_w) / 2, ($size->GetHeight - $logo_h) / 2, 1);
-
- $event->Skip;
-}
-
-1;
diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm
index b2f51b9e1..31124e432 100644
--- a/lib/Slic3r/GUI/MainFrame.pm
+++ b/lib/Slic3r/GUI/MainFrame.pm
@@ -237,12 +237,6 @@ sub _init_menubar {
$self->repair_stl;
}, undef, 'wrench.png');
$fileMenu->AppendSeparator();
- # Cmd+, is standard on OS X - what about other operating systems?
- $self->_append_menu_item($fileMenu, L("Preferences…\tCtrl+,"), L('Application preferences'), sub {
- # Opening the C++ preferences dialog.
- Slic3r::GUI::open_preferences_dialog($self->{preferences_event});
- }, wxID_PREFERENCES);
- $fileMenu->AppendSeparator();
$self->_append_menu_item($fileMenu, L("&Quit"), L('Quit Slic3r'), sub {
$self->Close(0);
}, wxID_EXIT);
@@ -348,7 +342,7 @@ sub _init_menubar {
Wx::LaunchDefaultBrowser('http://github.com/prusa3d/slic3r/issues/new');
});
$self->_append_menu_item($helpMenu, L("&About Slic3r"), L('Show about dialog'), sub {
- wxTheApp->about;
+ Slic3r::GUI::about;
});
}
@@ -362,11 +356,9 @@ sub _init_menubar {
$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)
- Slic3r::GUI::add_debug_menu($menubar, $self->{lang_ch_event});
+ # Add a configuration menu.
+ Slic3r::GUI::add_config_menu($menubar, $self->{preferences_event}, $self->{lang_ch_event});
$menubar->Append($helpMenu, L("&Help"));
- # Add an optional debug menu. In production code, the add_debug_menu() call should do nothing.
$self->SetMenuBar($menubar);
}
}
diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt
index 84f169e57..b9a6dbfee 100644
--- a/xs/CMakeLists.txt
+++ b/xs/CMakeLists.txt
@@ -170,6 +170,8 @@ add_library(libslic3r STATIC
)
add_library(libslic3r_gui STATIC
+ ${LIBDIR}/slic3r/GUI/AboutDialog.cpp
+ ${LIBDIR}/slic3r/GUI/AboutDialog.hpp
${LIBDIR}/slic3r/GUI/AppConfig.cpp
${LIBDIR}/slic3r/GUI/AppConfig.hpp
${LIBDIR}/slic3r/GUI/BitmapCache.cpp
@@ -533,13 +535,13 @@ if (SLIC3R_PRUSACONTROL)
set(wxWidgets_UseAlienWx 1)
if (wxWidgets_UseAlienWx)
set(AlienWx_DEBUG 1)
- find_package(AlienWx REQUIRED COMPONENTS base core adv)
+ find_package(AlienWx REQUIRED COMPONENTS base core adv html)
include_directories(${AlienWx_INCLUDE_DIRS})
#add_compile_options(${AlienWx_CXX_FLAGS})
add_definitions(${AlienWx_DEFINITIONS})
set(wxWidgets_LIBRARIES ${AlienWx_LIBRARIES})
else ()
- find_package(wxWidgets REQUIRED COMPONENTS base core adv)
+ find_package(wxWidgets REQUIRED COMPONENTS base core adv html)
include(${wxWidgets_USE_FILE})
endif ()
add_definitions(-DSLIC3R_GUI -DSLIC3R_PRUS)
diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm
index 47a584343..06eb041df 100644
--- a/xs/lib/Slic3r/XS.pm
+++ b/xs/lib/Slic3r/XS.pm
@@ -12,7 +12,7 @@ our $VERSION = '0.01';
BEGIN {
if ($^O eq 'MSWin32') {
eval "use Wx";
-# eval "use Wx::Html";
+ eval "use Wx::Html";
eval "use Wx::Print"; # because of some Wx bug, thread creation fails if we don't have this (looks like Wx::Printout is hard-coded in some thread cleanup code)
}
}
diff --git a/xs/src/libslic3r/FileParserError.hpp b/xs/src/libslic3r/FileParserError.hpp
index 82a6b328e..3f560fa4f 100644
--- a/xs/src/libslic3r/FileParserError.hpp
+++ b/xs/src/libslic3r/FileParserError.hpp
@@ -4,6 +4,7 @@
#include "libslic3r.h"
#include
+#include
#include
namespace Slic3r {
@@ -15,6 +16,9 @@ public:
file_parser_error(const std::string &msg, const std::string &file, unsigned long line = 0) :
std::runtime_error(format_what(msg, file, line)),
m_message(msg), m_filename(file), m_line(line) {}
+ file_parser_error(const std::string &msg, const boost::filesystem::path &file, unsigned long line = 0) :
+ std::runtime_error(format_what(msg, file.string(), line)),
+ m_message(msg), m_filename(file.string()), m_line(line) {}
// gcc 3.4.2 complains about lack of throw specifier on compiler
// generated dtor
~file_parser_error() throw() {}
diff --git a/xs/src/slic3r/Config/Snapshot.cpp b/xs/src/slic3r/Config/Snapshot.cpp
index 559e4c63c..91f02ab25 100644
--- a/xs/src/slic3r/Config/Snapshot.cpp
+++ b/xs/src/slic3r/Config/Snapshot.cpp
@@ -205,6 +205,22 @@ size_t SnapshotDB::load_db()
return m_snapshots.size();
}
+void SnapshotDB::update_slic3r_versions(std::vector &index_db)
+{
+ for (Snapshot &snapshot : m_snapshots) {
+ for (Snapshot::VendorConfig &vendor_config : snapshot.vendor_configs) {
+ auto it = std::find_if(index_db.begin(), index_db.end(), [&vendor_config](const Index &idx) { return idx.vendor() == vendor_config.name; });
+ if (it != index_db.end()) {
+ Index::const_iterator it_version = it->find(vendor_config.version);
+ if (it_version != it->end()) {
+ vendor_config.min_slic3r_version = it_version->min_slic3r_version;
+ vendor_config.max_slic3r_version = it_version->max_slic3r_version;
+ }
+ }
+ }
+ }
+}
+
static void copy_config_dir_single_level(const boost::filesystem::path &path_src, const boost::filesystem::path &path_dst)
{
if (! boost::filesystem::is_directory(path_dst) &&
@@ -303,6 +319,26 @@ boost::filesystem::path SnapshotDB::create_db_dir()
return snapshots_dir;
}
+SnapshotDB& SnapshotDB::singleton()
+{
+ static SnapshotDB instance;
+ bool loaded = false;
+ if (! loaded) {
+ try {
+ loaded = true;
+ // Load the snapshot database.
+ instance.load_db();
+ // Load the vendor specific configuration indices.
+ std::vector index_db = Index::load_db();
+ // Update the min / max slic3r versions compatible with the configurations stored inside the snapshots
+ // based on the min / max slic3r versions defined by the vendor specific config indices.
+ instance.update_slic3r_versions(index_db);
+ } catch (std::exception &ex) {
+ }
+ }
+ return instance;
+}
+
} // namespace Config
} // namespace GUI
} // namespace Slic3r
diff --git a/xs/src/slic3r/Config/Snapshot.hpp b/xs/src/slic3r/Config/Snapshot.hpp
index 358797bf7..1d02c8650 100644
--- a/xs/src/slic3r/Config/Snapshot.hpp
+++ b/xs/src/slic3r/Config/Snapshot.hpp
@@ -6,6 +6,7 @@
#include
+#include "Version.hpp"
#include "../Utils/Semver.hpp"
namespace Slic3r {
@@ -15,6 +16,8 @@ class AppConfig;
namespace GUI {
namespace Config {
+class Version;
+
// A snapshot contains:
// Slic3r.ini
// vendor/
@@ -75,12 +78,16 @@ public:
class SnapshotDB
{
public:
+ // Initialize the SnapshotDB singleton instance. Load the database if it has not been loaded yet.
+ static SnapshotDB& singleton();
+
typedef std::vector::const_iterator const_iterator;
// Load the snapshot database from the snapshots directory.
// If the snapshot directory or its parent does not exist yet, it will be created.
// Returns a number of snapshots loaded.
size_t load_db();
+ void update_slic3r_versions(std::vector &index_db);
// Create a snapshot directory, copy the vendor config bundles, user print/filament/printer profiles,
// create an index.
diff --git a/xs/src/slic3r/Config/Version.cpp b/xs/src/slic3r/Config/Version.cpp
index 1102f3149..cc961829d 100644
--- a/xs/src/slic3r/Config/Version.cpp
+++ b/xs/src/slic3r/Config/Version.cpp
@@ -6,6 +6,8 @@
#include "../../libslic3r/libslic3r.h"
#include "../../libslic3r/Config.hpp"
+#include "../../libslic3r/FileParserError.hpp"
+#include "../../libslic3r/Utils.hpp"
namespace Slic3r {
namespace GUI {
@@ -62,11 +64,12 @@ inline std::string unquote_version_comment(char *value, char *end, const std::st
return svalue;
}
-size_t Index::load(const std::string &path)
+size_t Index::load(const boost::filesystem::path &path)
{
m_configs.clear();
+ m_vendor = path.stem().string();
- boost::nowide::ifstream ifs(path);
+ boost::nowide::ifstream ifs(path.string());
std::string line;
size_t idx_line = 0;
Version ver;
@@ -96,7 +99,7 @@ size_t Index::load(const std::string &path)
if (semver)
throw file_parser_error("Key cannot be a semantic version", path, idx_line);
// Verify validity of the key / value pair.
- std::string svalue = unquote_value(left_trim(++ value), end, path, idx_line);
+ std::string svalue = unquote_value(left_trim(++ value), end, path.string(), idx_line);
if (key == "min_sic3r_version" || key == "max_slic3r_version") {
if (! svalue.empty())
semver = Semver::parse(key);
@@ -113,13 +116,24 @@ size_t Index::load(const std::string &path)
if (! semver)
throw file_parser_error("Invalid semantic version", path, idx_line);
ver.config_version = *semver;
- ver.comment = (end <= key_end) ? "" : unquote_version_comment(value, end, path, idx_line);
+ ver.comment = (end <= key_end) ? "" : unquote_version_comment(value, end, path.string(), idx_line);
m_configs.emplace_back(ver);
}
+ // Sort the configs by their version.
+ std::sort(m_configs.begin(), m_configs.end(), [](const Version &v1, const Version &v2) { return v1.config_version < v2.config_version; });
return m_configs.size();
}
+Index::const_iterator Index::find(const Semver &ver)
+{
+ Version key;
+ key.config_version = ver;
+ auto it = std::lower_bound(m_configs.begin(), m_configs.end(), key,
+ [](const Version &v1, const Version &v2) { return v1.config_version < v2.config_version; });
+ return (it == m_configs.end() || it->config_version == ver) ? it : m_configs.end();
+}
+
Index::const_iterator Index::recommended() const
{
int idx = -1;
@@ -131,6 +145,31 @@ Index::const_iterator Index::recommended() const
return highest;
}
+std::vector Index::load_db()
+{
+ boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir());
+ boost::filesystem::path vendor_dir = data_dir / "vendor";
+
+ std::vector index_db;
+ std::string errors_cummulative;
+ for (auto &dir_entry : boost::filesystem::directory_iterator(vendor_dir))
+ if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".idx")) {
+ Index idx;
+ try {
+ idx.load(dir_entry.path());
+ } catch (const std::runtime_error &err) {
+ errors_cummulative += err.what();
+ errors_cummulative += "\n";
+ continue;
+ }
+ index_db.emplace_back(std::move(idx));
+ }
+
+ if (! errors_cummulative.empty())
+ throw std::runtime_error(errors_cummulative);
+ return index_db;
+}
+
} // namespace Config
} // namespace GUI
} // namespace Slic3r
diff --git a/xs/src/slic3r/Config/Version.hpp b/xs/src/slic3r/Config/Version.hpp
index 7af1d4b5b..43512e82f 100644
--- a/xs/src/slic3r/Config/Version.hpp
+++ b/xs/src/slic3r/Config/Version.hpp
@@ -4,6 +4,8 @@
#include
#include
+#include
+
#include "../../libslic3r/FileParserError.hpp"
#include "../Utils/Semver.hpp"
@@ -54,17 +56,25 @@ public:
typedef std::vector::const_iterator const_iterator;
// Read a config index file in the simple format described in the Index class comment.
// Throws Slic3r::file_parser_error and the standard std file access exceptions.
- size_t load(const std::string &path);
+ size_t load(const boost::filesystem::path &path);
+
+ const std::string& vendor() const { return m_vendor; }
const_iterator begin() const { return m_configs.begin(); }
const_iterator end() const { return m_configs.end(); }
+ const_iterator find(const Semver &ver);
const std::vector& configs() const { return m_configs; }
// Finds a recommended config to be installed for the current Slic3r version.
// Returns configs().end() if such version does not exist in the index. This shall never happen
// if the index is valid.
const_iterator recommended() const;
+ // Load all vendor specific indices.
+ // Throws Slic3r::file_parser_error and the standard std file access exceptions.
+ static std::vector load_db();
+
private:
+ std::string m_vendor;
std::vector m_configs;
};
diff --git a/xs/src/slic3r/GUI/AboutDialog.cpp b/xs/src/slic3r/GUI/AboutDialog.cpp
new file mode 100644
index 000000000..49cfff2bd
--- /dev/null
+++ b/xs/src/slic3r/GUI/AboutDialog.cpp
@@ -0,0 +1,125 @@
+#include "AboutDialog.hpp"
+
+#include "../../libslic3r/Utils.hpp"
+
+namespace Slic3r {
+namespace GUI {
+
+AboutDialogLogo::AboutDialogLogo(wxWindow* parent)
+ : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize)
+{
+ this->SetBackgroundColour(*wxWHITE);
+ this->logo = wxBitmap(from_u8(Slic3r::var("Slic3r_192px.png")), wxBITMAP_TYPE_PNG);
+ this->SetMinSize(this->logo.GetSize());
+
+ this->Bind(wxEVT_PAINT, &AboutDialogLogo::onRepaint, this);
+}
+
+void AboutDialogLogo::onRepaint(wxEvent &event)
+{
+ wxPaintDC dc(this);
+ dc.SetBackgroundMode(wxTRANSPARENT);
+
+ wxSize size = this->GetSize();
+ int logo_w = this->logo.GetWidth();
+ int logo_h = this->logo.GetHeight();
+ dc.DrawBitmap(this->logo, (size.GetWidth() - logo_w)/2, (size.GetHeight() - logo_h)/2, true);
+
+ event.Skip();
+}
+
+AboutDialog::AboutDialog()
+ : wxDialog(NULL, wxID_ANY, _(L("About Slic3r")), wxDefaultPosition, wxSize(600, 340), wxCAPTION)
+{
+ this->SetBackgroundColour(*wxWHITE);
+
+ wxBoxSizer* hsizer = new wxBoxSizer(wxHORIZONTAL);
+ this->SetSizer(hsizer);
+
+ // logo
+ AboutDialogLogo* logo = new AboutDialogLogo(this);
+ hsizer->Add(logo, 0, wxEXPAND | wxLEFT | wxRIGHT, 30);
+
+ wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL);
+ hsizer->Add(vsizer, 1, wxEXPAND, 0);
+
+ // title
+ {
+ wxStaticText* title = new wxStaticText(this, wxID_ANY, "Slic3r Prusa Edition", wxDefaultPosition, wxDefaultSize);
+ wxFont title_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
+ title_font.SetWeight(wxFONTWEIGHT_BOLD);
+ title_font.SetFamily(wxFONTFAMILY_ROMAN);
+ title_font.SetPointSize(24);
+ title->SetFont(title_font);
+ vsizer->Add(title, 0, wxALIGN_LEFT | wxTOP, 30);
+ }
+
+ // version
+ {
+ std::string version_string = _(L("Version ")) + std::string(SLIC3R_VERSION);
+ wxStaticText* version = new wxStaticText(this, wxID_ANY, version_string.c_str(), wxDefaultPosition, wxDefaultSize);
+ wxFont version_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
+ #ifdef __WXMSW__
+ version_font.SetPointSize(9);
+ #else
+ version_font.SetPointSize(11);
+ #endif
+ version->SetFont(version_font);
+ vsizer->Add(version, 0, wxALIGN_LEFT | wxBOTTOM, 10);
+ }
+
+ // text
+ wxHtmlWindow* html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER);
+ {
+ wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
+ #ifdef __WXMSW__
+ int size[] = {8,8,8,8,8,8,8};
+ #else
+ int size[] = {11,11,11,11,11,11,11};
+ #endif
+ html->SetFonts(font.GetFaceName(), font.GetFaceName(), size);
+ html->SetBorders(2);
+ const char* text =
+ ""
+ ""
+ ""
+ "Copyright © 2016-2018 Prusa Research.
"
+ "Copyright © 2011-2017 Alessandro Ranellucci.
"
+ "Slic3r is licensed under the "
+ "GNU Affero General Public License, version 3."
+ "
"
+ "Contributions by Henrik Brix Andersen, Nicolas Dandrimont, Mark Hindess, Petr Ledvina, Joseph Lenox, Y. Sapir, Mike Sheldrake, Vojtech Bubnik and numerous others. "
+ "Manual by Gary Hodgson. Inspired by the RepRap community.
"
+ "Slic3r logo designed by Corey Daniels, Silk Icon Set designed by Mark James. "
+ ""
+ ""
+ "";
+ html->SetPage(text);
+ vsizer->Add(html, 1, wxEXPAND | wxALIGN_LEFT | wxRIGHT | wxBOTTOM, 20);
+ html->Bind(wxEVT_HTML_LINK_CLICKED, &AboutDialog::onLinkClicked, this);
+ }
+
+ wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCLOSE);
+ this->SetEscapeId(wxID_CLOSE);
+ this->Bind(wxEVT_BUTTON, &AboutDialog::onCloseDialog, this, wxID_CLOSE);
+ vsizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3);
+
+ this->Bind(wxEVT_LEFT_DOWN, &AboutDialog::onCloseDialog, this);
+ logo->Bind(wxEVT_LEFT_DOWN, &AboutDialog::onCloseDialog, this);
+ html->Bind(wxEVT_LEFT_DOWN, &AboutDialog::onCloseDialog, this);
+}
+
+void AboutDialog::onLinkClicked(wxHtmlLinkEvent &event)
+{
+ wxLaunchDefaultBrowser(event.GetLinkInfo().GetHref());
+ event.Skip(false);
+}
+
+void AboutDialog::onCloseDialog(wxEvent &)
+{
+ this->EndModal(wxID_CLOSE);
+ this->Close();
+}
+
+} // namespace GUI
+} // namespace Slic3r
diff --git a/xs/src/slic3r/GUI/AboutDialog.hpp b/xs/src/slic3r/GUI/AboutDialog.hpp
new file mode 100644
index 000000000..01f7564c5
--- /dev/null
+++ b/xs/src/slic3r/GUI/AboutDialog.hpp
@@ -0,0 +1,36 @@
+#ifndef slic3r_GUI_AboutDialog_hpp_
+#define slic3r_GUI_AboutDialog_hpp_
+
+#include "GUI.hpp"
+
+#include
+#include
+#include
+
+namespace Slic3r {
+namespace GUI {
+
+class AboutDialogLogo : public wxPanel
+{
+public:
+ AboutDialogLogo(wxWindow* parent);
+
+private:
+ wxBitmap logo;
+ void onRepaint(wxEvent &event);
+};
+
+class AboutDialog : public wxDialog
+{
+public:
+ AboutDialog();
+
+private:
+ void onLinkClicked(wxHtmlLinkEvent &event);
+ void onCloseDialog(wxEvent &);
+};
+
+} // namespace GUI
+} // namespace Slic3r
+
+#endif
diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp
index 3eca4e707..48d56ff11 100644
--- a/xs/src/slic3r/GUI/GUI.cpp
+++ b/xs/src/slic3r/GUI/GUI.cpp
@@ -42,6 +42,7 @@
#include "Tab.hpp"
#include "TabIface.hpp"
+#include "AboutDialog.hpp"
#include "AppConfig.hpp"
#include "Utils.hpp"
#include "Preferences.hpp"
@@ -330,32 +331,56 @@ void get_installed_languages(wxArrayString & names,
}
}
-void add_debug_menu(wxMenuBar *menu, int event_language_change)
+enum ConfigMenuIDs {
+ ConfigMenuWizard,
+ ConfigMenuSnapshots,
+ ConfigMenuTakeSnapshot,
+ ConfigMenuUpdate,
+ ConfigMenuPreferences,
+ ConfigMenuLanguage,
+ ConfigMenuCnt,
+};
+
+void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_language_change)
{
-//#if 0
auto local_menu = new wxMenu();
- local_menu->Append(wxWindow::NewControlId(1), _(L("Change Application Language")));
- local_menu->Bind(wxEVT_MENU, [event_language_change](wxEvent&){
- 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);
+ wxWindowID config_id_base = wxWindow::NewControlId((int)ConfigMenuCnt);
+
+ // Cmd+, is standard on OS X - what about other operating systems?
+ local_menu->Append(config_id_base + ConfigMenuWizard, _(L("Configuration Wizard\u2026")), _(L("Run configuration wizard")));
+ 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")));
+ local_menu->Append(config_id_base + ConfigMenuUpdate, _(L("Check for updates")), _(L("Check for configuration updates")));
+ local_menu->AppendSeparator();
+ local_menu->Append(config_id_base + ConfigMenuPreferences, _(L("Preferences\u2026\tCtrl+,")), _(L("Application preferences")));
+ local_menu->AppendSeparator();
+ local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application Language")));
+ local_menu->Bind(wxEVT_MENU, [config_id_base, event_language_change, event_preferences_changed](wxEvent &event){
+ switch (event.GetId() - config_id_base) {
+ case ConfigMenuPreferences:
+ {
+ auto dlg = new PreferencesDialog(g_wxMainFrame, event_preferences_changed);
+ dlg->ShowModal();
+ 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);
+ }
}
+ break;
+ }
}
});
- menu->Append(local_menu, _(L("&Localization")));
-//#endif
-}
-
-void open_preferences_dialog(int event_preferences)
-{
- auto dlg = new PreferencesDialog(g_wxMainFrame, event_preferences);
- dlg->ShowModal();
+ menu->Append(local_menu, _(L("&Configuration")));
}
void create_preset_tabs(bool no_controller, int event_value_change, int event_presets_changed)
@@ -737,4 +762,11 @@ int get_export_option(wxFileDialog* dlg)
return 0;
}
+void about()
+{
+ AboutDialog dlg;
+ dlg.ShowModal();
+ dlg.Destroy();
+}
+
} }
diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp
index 362b15307..0cbdf8729 100644
--- a/xs/src/slic3r/GUI/GUI.hpp
+++ b/xs/src/slic3r/GUI/GUI.hpp
@@ -82,10 +82,7 @@ wxApp* get_app();
wxColour* get_modified_label_clr();
wxColour* get_sys_label_clr();
-void add_debug_menu(wxMenuBar *menu, int event_language_change);
-
-// Create "Preferences" dialog after selecting menu "Preferences" in Perl part
-void open_preferences_dialog(int event_preferences);
+void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_language_change);
// Create a new preset tab (print, filament and printer),
void create_preset_tabs(bool no_controller, int event_value_change, int event_presets_changed);
@@ -134,7 +131,11 @@ ConfigOptionsGroup* get_optgroup();
void add_export_option(wxFileDialog* dlg, const std::string& format);
int get_export_option(wxFileDialog* dlg);
-}
-}
+
+// Display an About dialog
+void about();
+
+} // namespace GUI
+} // namespace Slic3r
#endif
diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp
index 1376ff164..c8d76adba 100644
--- a/xs/xsp/GUI.xsp
+++ b/xs/xsp/GUI.xsp
@@ -9,6 +9,9 @@
%package{Slic3r::GUI};
+void about()
+ %code{% Slic3r::GUI::about(); %};
+
void disable_screensaver()
%code{% Slic3r::GUI::disable_screensaver(); %};
@@ -32,9 +35,9 @@ void set_main_frame(SV *ui)
void set_tab_panel(SV *ui)
%code%{ Slic3r::GUI::set_tab_panel((wxNotebook*)wxPli_sv_2_object(aTHX_ ui, "Wx::Notebook")); %};
-
-void add_debug_menu(SV *ui, int event_language_change)
- %code%{ Slic3r::GUI::add_debug_menu((wxMenuBar*)wxPli_sv_2_object(aTHX_ ui, "Wx::MenuBar"), event_language_change); %};
+
+void add_config_menu(SV *ui, int event_preferences_changed, int event_language_change)
+ %code%{ Slic3r::GUI::add_config_menu((wxMenuBar*)wxPli_sv_2_object(aTHX_ ui, "Wx::MenuBar"), event_preferences_changed, event_language_change); %};
void create_preset_tabs(bool no_controller, int event_value_change, int event_presets_changed)
%code%{ Slic3r::GUI::create_preset_tabs(no_controller, event_value_change, event_presets_changed); %};
@@ -54,9 +57,6 @@ int combochecklist_get_flags(SV *ui)
void set_app_config(AppConfig *app_config)
%code%{ Slic3r::GUI::set_app_config(app_config); %};
-void open_preferences_dialog(int preferences_event)
- %code%{ Slic3r::GUI::open_preferences_dialog(preferences_event); %};
-
void set_preset_bundle(PresetBundle *preset_bundle)
%code%{ Slic3r::GUI::set_preset_bundle(preset_bundle); %};