Merge branch 'master' into amf_activate_existing_presets

This commit is contained in:
bubnikv 2018-06-28 22:00:10 +02:00
commit 6b3c24359b
22 changed files with 135 additions and 236 deletions

View File

@ -110,6 +110,10 @@ sub _init_tabpanel {
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{tabpanel}, sub { EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{tabpanel}, sub {
my $panel = $self->{tabpanel}->GetCurrentPage; my $panel = $self->{tabpanel}->GetCurrentPage;
$panel->OnActivate if $panel->can('OnActivate'); $panel->OnActivate if $panel->can('OnActivate');
for my $tab_name (qw(print filament printer)) {
Slic3r::GUI::get_preset_tab("$tab_name")->OnActivate if ("$tab_name" eq $panel->GetName);
}
}); });
if (!$self->{no_plater}) { if (!$self->{no_plater}) {

View File

@ -186,7 +186,6 @@ sub new {
# Initialize 3D toolpaths preview # Initialize 3D toolpaths preview
if ($Slic3r::GUI::have_OpenGL) { if ($Slic3r::GUI::have_OpenGL) {
$self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self->{preview_notebook}, $self->{print}, $self->{gcode_preview_data}, $self->{config}); $self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self->{preview_notebook}, $self->{print}, $self->{gcode_preview_data}, $self->{config});
Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
Slic3r::GUI::_3DScene::enable_legend_texture($self->{preview3D}->canvas, 1); Slic3r::GUI::_3DScene::enable_legend_texture($self->{preview3D}->canvas, 1);
Slic3r::GUI::_3DScene::register_on_viewport_changed_callback($self->{preview3D}->canvas, sub { Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{canvas3D}, $self->{preview3D}->canvas); }); Slic3r::GUI::_3DScene::register_on_viewport_changed_callback($self->{preview3D}->canvas, sub { Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{canvas3D}, $self->{preview3D}->canvas); });
$self->{preview_notebook}->AddPage($self->{preview3D}, L('Preview')); $self->{preview_notebook}->AddPage($self->{preview3D}, L('Preview'));
@ -202,19 +201,12 @@ sub new {
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub { EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub {
my $preview = $self->{preview_notebook}->GetCurrentPage; my $preview = $self->{preview_notebook}->GetCurrentPage;
if (($preview != $self->{preview3D}) && ($preview != $self->{canvas3D})) { if (($preview != $self->{preview3D}) && ($preview != $self->{canvas3D})) {
Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 0);
Slic3r::GUI::_3DScene::reset_current_canvas();
$preview->OnActivate if $preview->can('OnActivate'); $preview->OnActivate if $preview->can('OnActivate');
} elsif ($preview == $self->{preview3D}) { } elsif ($preview == $self->{preview3D}) {
Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 1);
Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 0);
$self->{preview3D}->load_print; $self->{preview3D}->load_print;
# sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably) # sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably)
Slic3r::GUI::_3DScene::set_as_dirty($self->{preview3D}->canvas); Slic3r::GUI::_3DScene::set_as_dirty($self->{preview3D}->canvas);
} elsif ($preview == $self->{canvas3D}) { } elsif ($preview == $self->{canvas3D}) {
Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 1);
Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
if (Slic3r::GUI::_3DScene::is_reload_delayed($self->{canvas3D})) { if (Slic3r::GUI::_3DScene::is_reload_delayed($self->{canvas3D})) {
my $selections = $self->collect_selections; my $selections = $self->collect_selections;
Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections); Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);

View File

@ -279,7 +279,6 @@ sub reload_print {
my ($self, $force) = @_; my ($self, $force) = @_;
Slic3r::GUI::_3DScene::reset_volumes($self->canvas); Slic3r::GUI::_3DScene::reset_volumes($self->canvas);
Slic3r::GUI::_3DScene::reset_current_canvas();
$self->_loaded(0); $self->_loaded(0);
if (! $self->IsShown && ! $force) { if (! $self->IsShown && ! $force) {

View File

@ -142,10 +142,10 @@ public:
} }
m_gcode += "G1"; m_gcode += "G1";
if (std::abs(dx) > EPSILON) if (std::abs(rot.x - rotated_current_pos.x) > EPSILON)
m_gcode += set_format_X(rot.x); m_gcode += set_format_X(rot.x);
if (std::abs(dy) > EPSILON) if (std::abs(rot.y - rotated_current_pos.y) > EPSILON)
m_gcode += set_format_Y(rot.y); m_gcode += set_format_Y(rot.y);
if (e != 0.f) if (e != 0.f)

View File

@ -1754,21 +1754,6 @@ bool _3DScene::init(wxGLCanvas* canvas)
return s_canvas_mgr.init(canvas); return s_canvas_mgr.init(canvas);
} }
bool _3DScene::set_current(wxGLCanvas* canvas, bool force)
{
return s_canvas_mgr.set_current(canvas, force);
}
void _3DScene::reset_current_canvas()
{
s_canvas_mgr.set_current(nullptr, false);
}
void _3DScene::set_active(wxGLCanvas* canvas, bool active)
{
s_canvas_mgr.set_active(canvas, active);
}
void _3DScene::set_as_dirty(wxGLCanvas* canvas) void _3DScene::set_as_dirty(wxGLCanvas* canvas)
{ {
s_canvas_mgr.set_as_dirty(canvas); s_canvas_mgr.set_as_dirty(canvas);

View File

@ -516,10 +516,6 @@ public:
static bool init(wxGLCanvas* canvas); static bool init(wxGLCanvas* canvas);
static bool set_current(wxGLCanvas* canvas, bool force);
static void reset_current_canvas();
static void set_active(wxGLCanvas* canvas, bool active);
static void set_as_dirty(wxGLCanvas* canvas); static void set_as_dirty(wxGLCanvas* canvas);
static unsigned int get_volumes_count(wxGLCanvas* canvas); static unsigned int get_volumes_count(wxGLCanvas* canvas);

View File

@ -83,8 +83,11 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, cons
const auto model_id = model.id; const auto model_id = model.id;
bool default_variant = true; // Mark the first variant as default in the GUI
for (const auto &variant : model.variants) { for (const auto &variant : model.variants) {
const auto label = wxString::Format("%s %s %s", variant.name, _(L("mm")), _(L("nozzle"))); const auto label = wxString::Format("%s %s %s %s", variant.name, _(L("mm")), _(L("nozzle")),
(default_variant ? _(L("(default)")) : wxString()));
default_variant = false;
auto *cbox = new Checkbox(panel, label, model_id, variant.name); auto *cbox = new Checkbox(panel, label, model_id, variant.name);
const size_t idx = cboxes.size(); const size_t idx = cboxes.size();
cboxes.push_back(cbox); cboxes.push_back(cbox);
@ -113,11 +116,6 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, cons
sizer->Add(all_none_sizer, 0, wxEXPAND); sizer->Add(all_none_sizer, 0, wxEXPAND);
SetSizer(sizer); SetSizer(sizer);
if (cboxes.size() > 0) {
cboxes[0]->SetValue(true);
on_checkbox(cboxes[0], true);
}
} }
void PrinterPicker::select_all(bool select) void PrinterPicker::select_all(bool select)
@ -130,6 +128,14 @@ void PrinterPicker::select_all(bool select)
} }
} }
void PrinterPicker::select_one(size_t i, bool select)
{
if (i < cboxes.size() && cboxes[i]->GetValue() != select) {
cboxes[i]->SetValue(select);
on_checkbox(cboxes[i], select);
}
}
void PrinterPicker::on_checkbox(const Checkbox *cbox, bool checked) void PrinterPicker::on_checkbox(const Checkbox *cbox, bool checked)
{ {
variants_checked += checked ? 1 : -1; variants_checked += checked ? 1 : -1;
@ -232,6 +238,7 @@ PageWelcome::PageWelcome(ConfigWizard *parent) :
AppConfig &appconfig_vendors = this->wizard_p()->appconfig_vendors; AppConfig &appconfig_vendors = this->wizard_p()->appconfig_vendors;
printer_picker = new PrinterPicker(this, vendor_prusa->second, appconfig_vendors); printer_picker = new PrinterPicker(this, vendor_prusa->second, appconfig_vendors);
printer_picker->select_one(0, true); // Select the default (first) model/variant on the Prusa vendor
printer_picker->Bind(EVT_PRINTER_PICK, [this, &appconfig_vendors](const PrinterPickerEvent &evt) { printer_picker->Bind(EVT_PRINTER_PICK, [this, &appconfig_vendors](const PrinterPickerEvent &evt) {
appconfig_vendors.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable); appconfig_vendors.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable);
this->on_variant_checked(); this->on_variant_checked();
@ -886,9 +893,9 @@ const wxString& ConfigWizard::name()
{ {
// A different naming convention is used for the Wizard on Windows vs. OSX & GTK. // A different naming convention is used for the Wizard on Windows vs. OSX & GTK.
#if WIN32 #if WIN32
static const wxString config_wizard_name = _(L("Configuration Wizard")); static const wxString config_wizard_name = L("Configuration Wizard");
#else #else
static const wxString config_wizard_name = _(L("Configuration Assistant")); static const wxString config_wizard_name = L("Configuration Assistant");
#endif #endif
return config_wizard_name; return config_wizard_name;
} }

View File

@ -56,6 +56,7 @@ struct PrinterPicker: wxPanel
PrinterPicker(wxWindow *parent, const VendorProfile &vendor, const AppConfig &appconfig_vendors); PrinterPicker(wxWindow *parent, const VendorProfile &vendor, const AppConfig &appconfig_vendors);
void select_all(bool select); void select_all(bool select);
void select_one(size_t i, bool select);
void on_checkbox(const Checkbox *cbox, bool checked); void on_checkbox(const Checkbox *cbox, bool checked);
}; };

View File

@ -1408,15 +1408,14 @@ GLGizmoBase* GLCanvas3D::Gizmos::_get_current() const
return (it != m_gizmos.end()) ? it->second : nullptr; return (it != m_gizmos.end()) ? it->second : nullptr;
} }
GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context) GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas)
: m_canvas(canvas) : m_canvas(canvas)
, m_context(context) , m_context(nullptr)
, m_timer(nullptr) , m_timer(nullptr)
, m_config(nullptr) , m_config(nullptr)
, m_print(nullptr) , m_print(nullptr)
, m_model(nullptr) , m_model(nullptr)
, m_dirty(true) , m_dirty(true)
, m_active(true)
, m_initialized(false) , m_initialized(false)
, m_use_VBOs(false) , m_use_VBOs(false)
, m_force_zoom_to_bed_enabled(false) , m_force_zoom_to_bed_enabled(false)
@ -1434,7 +1433,10 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context)
, m_reload_delayed(false) , m_reload_delayed(false)
{ {
if (m_canvas != nullptr) if (m_canvas != nullptr)
{
m_context = new wxGLContext(m_canvas);
m_timer = new wxTimer(m_canvas); m_timer = new wxTimer(m_canvas);
}
} }
GLCanvas3D::~GLCanvas3D() GLCanvas3D::~GLCanvas3D()
@ -1447,6 +1449,12 @@ GLCanvas3D::~GLCanvas3D()
m_timer = nullptr; m_timer = nullptr;
} }
if (m_context != nullptr)
{
delete m_context;
m_context = nullptr;
}
_deregister_callbacks(); _deregister_callbacks();
} }
@ -1455,6 +1463,9 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl)
if (m_initialized) if (m_initialized)
return true; return true;
if ((m_canvas == nullptr) || (m_context == nullptr))
return false;
::glClearColor(1.0f, 1.0f, 1.0f, 1.0f); ::glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
::glClearDepth(1.0f); ::glClearDepth(1.0f);
@ -1520,19 +1531,14 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl)
return true; return true;
} }
bool GLCanvas3D::set_current(bool force) bool GLCanvas3D::set_current()
{ {
if ((force || m_active) && (m_canvas != nullptr) && (m_context != nullptr)) if ((m_canvas != nullptr) && (m_context != nullptr))
return m_canvas->SetCurrent(*m_context); return m_canvas->SetCurrent(*m_context);
return false; return false;
} }
void GLCanvas3D::set_active(bool active)
{
m_active = active;
}
void GLCanvas3D::set_as_dirty() void GLCanvas3D::set_as_dirty()
{ {
m_dirty = true; m_dirty = true;
@ -1549,7 +1555,7 @@ void GLCanvas3D::reset_volumes()
if (!m_volumes.empty()) if (!m_volumes.empty())
{ {
// ensures this canvas is current // ensures this canvas is current
if ((m_canvas == nullptr) || !_3DScene::set_current(m_canvas, true)) if (!set_current())
return; return;
m_volumes.release_geometry(); m_volumes.release_geometry();
@ -1655,6 +1661,8 @@ void GLCanvas3D::set_bed_shape(const Pointfs& shape)
// Set the origin and size for painting of the coordinate system axes. // Set the origin and size for painting of the coordinate system axes.
m_axes.origin = Pointf3(0.0, 0.0, (coordf_t)GROUND_Z); m_axes.origin = Pointf3(0.0, 0.0, (coordf_t)GROUND_Z);
set_axes_length(0.3f * (float)m_bed.get_bounding_box().max_size()); set_axes_length(0.3f * (float)m_bed.get_bounding_box().max_size());
m_dirty = true;
} }
void GLCanvas3D::set_auto_bed_shape() void GLCanvas3D::set_auto_bed_shape()
@ -1850,7 +1858,7 @@ void GLCanvas3D::render()
return; return;
// ensures this canvas is current and initialized // ensures this canvas is current and initialized
if (!_3DScene::set_current(m_canvas, false) || !_3DScene::init(m_canvas)) if (!set_current() || !_3DScene::init(m_canvas))
return; return;
if (m_force_zoom_to_bed_enabled) if (m_force_zoom_to_bed_enabled)
@ -1933,7 +1941,7 @@ void GLCanvas3D::reload_scene(bool force)
reset_volumes(); reset_volumes();
// ensures this canvas is current // ensures this canvas is current
if (!_3DScene::set_current(m_canvas, true)) if (!set_current())
return; return;
set_bed_shape(dynamic_cast<const ConfigOptionPoints*>(m_config->option("bed_shape"))->values); set_bed_shape(dynamic_cast<const ConfigOptionPoints*>(m_config->option("bed_shape"))->values);
@ -2008,7 +2016,7 @@ void GLCanvas3D::reload_scene(bool force)
void GLCanvas3D::load_print_toolpaths() void GLCanvas3D::load_print_toolpaths()
{ {
// ensures this canvas is current // ensures this canvas is current
if (!_3DScene::set_current(m_canvas, true)) if (!set_current())
return; return;
if (m_print == nullptr) if (m_print == nullptr)
@ -2376,7 +2384,7 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const
if ((m_canvas != nullptr) && (m_print != nullptr)) if ((m_canvas != nullptr) && (m_print != nullptr))
{ {
// ensures that this canvas is current // ensures that this canvas is current
if (!_3DScene::set_current(m_canvas, true)) if (!set_current())
return; return;
if (m_volumes.empty()) if (m_volumes.empty())
@ -2693,11 +2701,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
#endif #endif
} }
else if (evt.LeftDClick() && (m_hover_volume_id != -1)) else if (evt.LeftDClick() && (m_hover_volume_id != -1))
{
m_active = false;
m_on_double_click_callback.call(); m_on_double_click_callback.call();
m_active = true;
}
else if (evt.LeftDown() || evt.RightDown()) else if (evt.LeftDown() || evt.RightDown())
{ {
// If user pressed left or right button we first check whether this happened // If user pressed left or right button we first check whether this happened
@ -2793,11 +2797,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{ {
// if right clicking on volume, propagate event through callback // if right clicking on volume, propagate event through callback
if (m_volumes.volumes[volume_idx]->hover) if (m_volumes.volumes[volume_idx]->hover)
{
m_active = false;
m_on_right_click_callback.call(pos.x, pos.y); m_on_right_click_callback.call(pos.x, pos.y);
m_active = true;
}
} }
} }
} }
@ -3004,7 +3004,7 @@ Point GLCanvas3D::get_local_mouse_position() const
bool GLCanvas3D::_is_shown_on_screen() const bool GLCanvas3D::_is_shown_on_screen() const
{ {
return (m_canvas != nullptr) ? m_active && m_canvas->IsShownOnScreen() : false; return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
} }
void GLCanvas3D::_force_zoom_to_bed() void GLCanvas3D::_force_zoom_to_bed()
@ -3019,7 +3019,7 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h)
return; return;
// ensures that this canvas is current // ensures that this canvas is current
_3DScene::set_current(m_canvas, false); set_current();
::glViewport(0, 0, w, h); ::glViewport(0, 0, w, h);
::glMatrixMode(GL_PROJECTION); ::glMatrixMode(GL_PROJECTION);

View File

@ -401,9 +401,6 @@ private:
Model* m_model; Model* m_model;
bool m_dirty; bool m_dirty;
// the active member has been introduced to overcome a bug in wxWidgets method IsShownOnScreen() which always return true
// when a window is inside a wxNotebook
bool m_active;
bool m_initialized; bool m_initialized;
bool m_use_VBOs; bool m_use_VBOs;
bool m_force_zoom_to_bed_enabled; bool m_force_zoom_to_bed_enabled;
@ -444,14 +441,13 @@ private:
PerlCallback m_on_gizmo_scale_uniformly_callback; PerlCallback m_on_gizmo_scale_uniformly_callback;
public: public:
GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context); GLCanvas3D(wxGLCanvas* canvas);
~GLCanvas3D(); ~GLCanvas3D();
bool init(bool useVBOs, bool use_legacy_opengl); bool init(bool useVBOs, bool use_legacy_opengl);
bool set_current(bool force); bool set_current();
void set_active(bool active);
void set_as_dirty(); void set_as_dirty();
unsigned int get_volumes_count() const; unsigned int get_volumes_count() const;

View File

@ -114,20 +114,13 @@ std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool exten
} }
GLCanvas3DManager::GLCanvas3DManager() GLCanvas3DManager::GLCanvas3DManager()
: m_context(nullptr) : m_current(nullptr)
, m_current(nullptr)
, m_gl_initialized(false) , m_gl_initialized(false)
, m_use_legacy_opengl(false) , m_use_legacy_opengl(false)
, m_use_VBOs(false) , m_use_VBOs(false)
{ {
} }
GLCanvas3DManager::~GLCanvas3DManager()
{
if (m_context != nullptr)
delete m_context;
}
bool GLCanvas3DManager::add(wxGLCanvas* canvas) bool GLCanvas3DManager::add(wxGLCanvas* canvas)
{ {
if (canvas == nullptr) if (canvas == nullptr)
@ -136,14 +129,7 @@ bool GLCanvas3DManager::add(wxGLCanvas* canvas)
if (_get_canvas(canvas) != m_canvases.end()) if (_get_canvas(canvas) != m_canvases.end())
return false; return false;
if (m_context == nullptr) GLCanvas3D* canvas3D = new GLCanvas3D(canvas);
{
m_context = new wxGLContext(canvas);
if (m_context == nullptr)
return false;
}
GLCanvas3D* canvas3D = new GLCanvas3D(canvas, m_context);
if (canvas3D == nullptr) if (canvas3D == nullptr)
return false; return false;
@ -213,41 +199,6 @@ bool GLCanvas3DManager::init(wxGLCanvas* canvas)
return false; return false;
} }
bool GLCanvas3DManager::set_current(wxGLCanvas* canvas, bool force)
{
// given canvas is already current, return
if (m_current == canvas)
return true;
if (canvas == nullptr)
{
m_current = nullptr;
return true;
}
// set given canvas as current
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
{
bool res = it->second->set_current(force);
if (res)
{
m_current = canvas;
return true;
}
}
m_current = nullptr;
return false;
}
void GLCanvas3DManager::set_active(wxGLCanvas* canvas, bool active)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_active(active);
}
void GLCanvas3DManager::set_as_dirty(wxGLCanvas* canvas) void GLCanvas3DManager::set_as_dirty(wxGLCanvas* canvas)
{ {
CanvasesMap::iterator it = _get_canvas(canvas); CanvasesMap::iterator it = _get_canvas(canvas);

View File

@ -43,7 +43,6 @@ class GLCanvas3DManager
typedef std::map<wxGLCanvas*, GLCanvas3D*> CanvasesMap; typedef std::map<wxGLCanvas*, GLCanvas3D*> CanvasesMap;
wxGLContext* m_context;
CanvasesMap m_canvases; CanvasesMap m_canvases;
wxGLCanvas* m_current; wxGLCanvas* m_current;
GLInfo m_gl_info; GLInfo m_gl_info;
@ -53,7 +52,6 @@ class GLCanvas3DManager
public: public:
GLCanvas3DManager(); GLCanvas3DManager();
~GLCanvas3DManager();
bool add(wxGLCanvas* canvas); bool add(wxGLCanvas* canvas);
bool remove(wxGLCanvas* canvas); bool remove(wxGLCanvas* canvas);
@ -70,8 +68,6 @@ public:
bool init(wxGLCanvas* canvas); bool init(wxGLCanvas* canvas);
bool set_current(wxGLCanvas* canvas, bool force);
void set_active(wxGLCanvas* canvas, bool active);
void set_as_dirty(wxGLCanvas* canvas); void set_as_dirty(wxGLCanvas* canvas);
unsigned int get_volumes_count(wxGLCanvas* canvas) const; unsigned int get_volumes_count(wxGLCanvas* canvas) const;

View File

@ -321,9 +321,10 @@ void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_l
auto local_menu = new wxMenu(); auto local_menu = new wxMenu();
wxWindowID config_id_base = wxWindow::NewControlId((int)ConfigMenuCnt); wxWindowID config_id_base = wxWindow::NewControlId((int)ConfigMenuCnt);
const auto config_wizard_tooltip = wxString::Format(_(L("Run %s")), ConfigWizard::name()); auto config_wizard_name = _(ConfigWizard::name().wx_str());
const auto config_wizard_tooltip = wxString::Format(_(L("Run %s")), config_wizard_name);
// Cmd+, is standard on OS X - what about other operating systems? // Cmd+, is standard on OS X - what about other operating systems?
local_menu->Append(config_id_base + ConfigMenuWizard, ConfigWizard::name() + dots, config_wizard_tooltip); local_menu->Append(config_id_base + ConfigMenuWizard, config_wizard_name + dots, config_wizard_tooltip);
local_menu->Append(config_id_base + ConfigMenuSnapshots, _(L("Configuration Snapshots"))+dots, _(L("Inspect / activate configuration snapshots"))); local_menu->Append(config_id_base + ConfigMenuSnapshots, _(L("Configuration Snapshots"))+dots, _(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 + 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->Append(config_id_base + ConfigMenuUpdate, _(L("Check for updates")), _(L("Check for configuration updates")));

View File

@ -40,49 +40,30 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
m_preset_bundle = preset_bundle; m_preset_bundle = preset_bundle;
// Vertical sizer to hold the choice menu and the rest of the page. // Vertical sizer to hold the choice menu and the rest of the page.
#ifdef __WXOSX__
auto *main_sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->SetSizeHints(this);
this->SetSizer(main_sizer);
// Create additional panel to Fit() it from OnActivate()
// It's needed for tooltip showing on OSX
m_tmp_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
auto panel = m_tmp_panel;
auto sizer = new wxBoxSizer(wxVERTICAL);
m_tmp_panel->SetSizer(sizer);
m_tmp_panel->Layout();
main_sizer->Add(m_tmp_panel, 1, wxEXPAND | wxALL, 0);
#else
Tab *panel = this; Tab *panel = this;
auto *sizer = new wxBoxSizer(wxVERTICAL); auto *sizer = new wxBoxSizer(wxVERTICAL);
sizer->SetSizeHints(panel); sizer->SetSizeHints(panel);
panel->SetSizer(sizer); panel->SetSizer(sizer);
#endif //__WXOSX__
// preset chooser // preset chooser
m_presets_choice = new wxBitmapComboBox(panel, wxID_ANY, "", wxDefaultPosition, wxSize(270, -1), 0, 0,wxCB_READONLY); m_presets_choice = new wxBitmapComboBox(panel, wxID_ANY, "", wxDefaultPosition, wxSize(270, -1), 0, 0,wxCB_READONLY);
/*
m_cc_presets_choice = new wxComboCtrl(panel, wxID_ANY, L(""), wxDefaultPosition, wxDefaultSize, wxCB_READONLY);
wxDataViewTreeCtrlComboPopup* popup = new wxDataViewTreeCtrlComboPopup;
if (popup != nullptr)
{
// 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.
// m_cc_presets_choice->UseAltPopupWindow();
// m_cc_presets_choice->EnablePopupAnimation(false);
m_cc_presets_choice->SetPopupControl(popup);
popup->SetStringValue(from_u8("Text1"));
popup->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this, popup](wxCommandEvent& evt)
{
auto selected = popup->GetItemText(popup->GetSelection());
if (selected != _(L("System presets")) && selected != _(L("Default presets")))
{
m_cc_presets_choice->SetText(selected);
std::string selected_string = selected.ToUTF8().data();
#ifdef __APPLE__
#else
select_preset(selected_string);
#endif
}
});
// popup->Bind(wxEVT_KEY_DOWN, [popup](wxKeyEvent& evt) { popup->OnKeyEvent(evt); });
// popup->Bind(wxEVT_KEY_UP, [popup](wxKeyEvent& evt) { popup->OnKeyEvent(evt); });
auto icons = new wxImageList(16, 16, true, 1);
popup->SetImageList(icons);
icons->Add(*new wxIcon(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG));
icons->Add(*new wxIcon(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG));
}
*/
auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
//buttons //buttons
@ -173,37 +154,6 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
m_hsizer = new wxBoxSizer(wxHORIZONTAL); m_hsizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(m_hsizer, 1, wxEXPAND, 0); sizer->Add(m_hsizer, 1, wxEXPAND, 0);
/*
//temporary left vertical sizer
m_left_sizer = new wxBoxSizer(wxVERTICAL);
m_hsizer->Add(m_left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3);
// tree
m_presetctrl = new wxDataViewTreeCtrl(panel, wxID_ANY, wxDefaultPosition, wxSize(200, -1), wxDV_NO_HEADER);
m_left_sizer->Add(m_presetctrl, 1, wxEXPAND);
m_preset_icons = new wxImageList(16, 16, true, 1);
m_presetctrl->SetImageList(m_preset_icons);
m_preset_icons->Add(*new wxIcon(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG));
m_preset_icons->Add(*new wxIcon(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG));
m_presetctrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxCommandEvent& evt)
{
auto selected = m_presetctrl->GetItemText(m_presetctrl->GetSelection());
if (selected != _(L("System presets")) && selected != _(L("Default presets")))
{
std::string selected_string = selected.ToUTF8().data();
#ifdef __APPLE__
#else
select_preset(selected_string);
#endif
}
});
*/
//left vertical sizer //left vertical sizer
m_left_sizer = new wxBoxSizer(wxVERTICAL); m_left_sizer = new wxBoxSizer(wxVERTICAL);
m_hsizer->Add(m_left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3); m_hsizer->Add(m_left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3);
@ -279,7 +229,12 @@ PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bo
} }
} }
// Initialize the page. // Initialize the page.
PageShp page(new Page(this, title, icon_idx)); #ifdef __WXOSX__
auto panel = m_tmp_panel;
#else
auto panel = this;
#endif
PageShp page(new Page(panel, title, icon_idx));
page->SetScrollbars(1, 1, 1, 1); page->SetScrollbars(1, 1, 1, 1);
page->Hide(); page->Hide();
m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5); m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5);
@ -290,6 +245,18 @@ PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bo
return page; return page;
} }
void Tab::OnActivate()
{
#ifdef __WXOSX__
wxWindowUpdateLocker noUpdates(this);
auto size = GetSizer()->GetSize();
m_tmp_panel->GetSizer()->SetMinSize(size.x + m_size_move, size.y);
Fit();
m_size_move *= -1;
#endif // __WXOSX__
}
void Tab::update_labels_colour() void Tab::update_labels_colour()
{ {
Freeze(); Freeze();
@ -1248,6 +1215,7 @@ void TabPrint::OnActivate()
{ {
m_recommended_thin_wall_thickness_description_line->SetText( m_recommended_thin_wall_thickness_description_line->SetText(
from_u8(PresetHints::recommended_thin_wall_thickness(*m_preset_bundle))); from_u8(PresetHints::recommended_thin_wall_thickness(*m_preset_bundle)));
Tab::OnActivate();
} }
void TabFilament::build() void TabFilament::build()
@ -1405,6 +1373,7 @@ void TabFilament::update()
void TabFilament::OnActivate() void TabFilament::OnActivate()
{ {
m_volumetric_speed_description_line->SetText(from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle))); m_volumetric_speed_description_line->SetText(from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle)));
Tab::OnActivate();
} }
wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticText) wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticText)

View File

@ -102,6 +102,10 @@ using PageShp = std::shared_ptr<Page>;
class Tab: public wxPanel class Tab: public wxPanel
{ {
wxNotebook* m_parent; wxNotebook* m_parent;
#ifdef __WXOSX__
wxPanel* m_tmp_panel;
int m_size_move = -1;
#endif // __WXOSX__
protected: protected:
std::string m_name; std::string m_name;
const wxString m_title; const wxString m_title;
@ -118,7 +122,6 @@ protected:
wxButton* m_undo_btn; wxButton* m_undo_btn;
wxButton* m_undo_to_sys_btn; wxButton* m_undo_to_sys_btn;
wxButton* m_question_btn; wxButton* m_question_btn;
wxComboCtrl* m_cc_presets_choice; wxComboCtrl* m_cc_presets_choice;
wxDataViewTreeCtrl* m_presetctrl; wxDataViewTreeCtrl* m_presetctrl;
wxImageList* m_preset_icons; wxImageList* m_preset_icons;
@ -198,7 +201,7 @@ public:
Tab() {} Tab() {}
Tab(wxNotebook* parent, const wxString& title, const char* name, bool no_controller) : Tab(wxNotebook* parent, const wxString& title, const char* name, bool no_controller) :
m_parent(parent), m_title(title), m_name(name), m_no_controller(no_controller) { m_parent(parent), m_title(title), m_name(name), m_no_controller(no_controller) {
Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL, name);
get_tabs_list().push_back(this); get_tabs_list().push_back(this);
} }
~Tab(){ ~Tab(){
@ -242,7 +245,7 @@ public:
PageShp add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages = false); PageShp add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages = false);
virtual void OnActivate(){} virtual void OnActivate();
virtual void on_preset_loaded(){} virtual void on_preset_loaded(){}
virtual void build() = 0; virtual void build() = 0;
virtual void update() = 0; virtual void update() = 0;

View File

@ -71,6 +71,7 @@ Http::priv::priv(const std::string &url) :
form(nullptr), form(nullptr),
form_end(nullptr), form_end(nullptr),
headerlist(nullptr), headerlist(nullptr),
limit(0),
cancel(false) cancel(false)
{ {
if (curl == nullptr) { if (curl == nullptr) {
@ -201,7 +202,6 @@ std::string Http::priv::body_size_error()
void Http::priv::http_perform() void Http::priv::http_perform()
{ {
::curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); ::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb); ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
::curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void*>(this)); ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void*>(this));
@ -230,8 +230,6 @@ void Http::priv::http_perform()
} }
CURLcode res = ::curl_easy_perform(curl); CURLcode res = ::curl_easy_perform(curl);
long http_status = 0;
::curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status);
if (res != CURLE_OK) { if (res != CURLE_OK) {
if (res == CURLE_ABORTED_BY_CALLBACK) { if (res == CURLE_ABORTED_BY_CALLBACK) {
@ -242,17 +240,22 @@ void Http::priv::http_perform()
if (progressfn) { progressfn(dummyprogress, cancel); } if (progressfn) { progressfn(dummyprogress, cancel); }
} else { } else {
// The abort comes from the CURLOPT_READFUNCTION callback, which means reading file failed // The abort comes from the CURLOPT_READFUNCTION callback, which means reading file failed
if (errorfn) { errorfn(std::move(buffer), "Error reading file for file upload", http_status); } if (errorfn) { errorfn(std::move(buffer), "Error reading file for file upload", 0); }
} }
} }
else if (res == CURLE_WRITE_ERROR) { else if (res == CURLE_WRITE_ERROR) {
if (errorfn) { errorfn(std::move(buffer), body_size_error(), http_status); } if (errorfn) { errorfn(std::move(buffer), body_size_error(), 0); }
} else { } else {
if (errorfn) { errorfn(std::move(buffer), curl_error(res), http_status); } if (errorfn) { errorfn(std::move(buffer), curl_error(res), 0); }
}; };
} else { } else {
if (completefn) { long http_status = 0;
completefn(std::move(buffer), http_status); ::curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status);
if (http_status >= 400) {
if (errorfn) { errorfn(std::move(buffer), std::string(), http_status); }
} else {
if (completefn) { completefn(std::move(buffer), http_status); }
} }
} }
} }

View File

@ -29,7 +29,16 @@ public:
typedef std::shared_ptr<Http> Ptr; typedef std::shared_ptr<Http> Ptr;
typedef std::function<void(std::string /* body */, unsigned /* http_status */)> CompleteFn; typedef std::function<void(std::string /* body */, unsigned /* http_status */)> CompleteFn;
// A HTTP request may fail at various stages of completeness (URL parsing, DNS lookup, TCP connection, ...).
// If the HTTP request could not be made or failed before completion, the `error` arg contains a description
// of the error and `http_status` is zero.
// If the HTTP request was completed but the response HTTP code is >= 400, `error` is empty and `http_status` contains the response code.
// In either case there may or may not be a body.
typedef std::function<void(std::string /* body */, std::string /* error */, unsigned /* http_status */)> ErrorFn; typedef std::function<void(std::string /* body */, std::string /* error */, unsigned /* http_status */)> ErrorFn;
// See the Progress struct above.
// Writing true to the `cancel` reference cancels the request in progress.
typedef std::function<void(Progress, bool& /* cancel */)> ProgressFn; typedef std::function<void(Progress, bool& /* cancel */)> ProgressFn;
Http(Http &&other); Http(Http &&other);
@ -46,7 +55,8 @@ public:
Http& operator=(const Http &) = delete; Http& operator=(const Http &) = delete;
Http& operator=(Http &&) = delete; Http& operator=(Http &&) = delete;
// Sets a maximum size of the data that can be received. The default is 5MB. // Sets a maximum size of the data that can be received.
// A value of zero sets the default limit, which is is 5MB.
Http& size_limit(size_t sizeLimit); Http& size_limit(size_t sizeLimit);
// Sets a HTTP header field. // Sets a HTTP header field.
Http& header(std::string name, const std::string &value); Http& header(std::string name, const std::string &value);

View File

@ -78,10 +78,10 @@ bool OctoPrint::test(wxString &msg) const
auto http = Http::get(std::move(url)); auto http = Http::get(std::move(url));
set_auth(http); set_auth(http);
http.on_error([&](std::string, std::string error, unsigned status) { http.on_error([&](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error getting version: %1% (HTTP %2%)") % error % status; BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error getting version: %1%, HTTP %2%, body: `%3%`") % error % status % body;
res = false; res = false;
msg = format_error(error, status); msg = format_error(body, error, status);
}) })
.on_complete([&](std::string body, unsigned) { .on_complete([&](std::string body, unsigned) {
BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: Got version: %1%") % body; BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: Got version: %1%") % body;
@ -140,8 +140,8 @@ bool OctoPrint::send_gcode(const std::string &filename) const
progress_dialog.Update(PROGRESS_RANGE); progress_dialog.Update(PROGRESS_RANGE);
}) })
.on_error([&](std::string body, std::string error, unsigned status) { .on_error([&](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error uploading file: %1% (HTTP %2%)") % error % status; BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error uploading file: %1%, HTTP %2%, body: `%3%`") % error % status % body;
auto errormsg = wxString::Format("%s: %s", errortitle, format_error(error, status)); auto errormsg = wxString::Format("%s: %s", errortitle, format_error(body, error, status));
GUI::show_error(&progress_dialog, std::move(errormsg)); GUI::show_error(&progress_dialog, std::move(errormsg));
res = false; res = false;
}) })
@ -183,15 +183,13 @@ std::string OctoPrint::make_url(const std::string &path) const
} }
} }
wxString OctoPrint::format_error(const std::string &error, unsigned status) wxString OctoPrint::format_error(const std::string &body, const std::string &error, unsigned status)
{ {
auto wxerror = wxString::FromUTF8(error.data());
if (status != 0) { if (status != 0) {
return wxString::Format("HTTP %u: %s", status, auto wxbody = wxString::FromUTF8(body.data());
(status == 401 ? _(L("Invalid API key")) : wxerror)); return wxString::Format("HTTP %u: %s", status, wxbody);
} else { } else {
return wxerror; return wxString::FromUTF8(error.data());
} }
} }

View File

@ -26,7 +26,7 @@ private:
void set_auth(Http &http) const; void set_auth(Http &http) const;
std::string make_url(const std::string &path) const; std::string make_url(const std::string &path) const;
static wxString format_error(const std::string &error, unsigned status); static wxString format_error(const std::string &body, const std::string &error, unsigned status);
}; };

View File

@ -537,15 +537,15 @@ bool PresetUpdater::config_update() const
incompats_map.emplace(std::make_pair(std::move(vendor), std::move(restrictions))); incompats_map.emplace(std::make_pair(std::move(vendor), std::move(restrictions)));
} }
p->had_config_update = true; // This needs to be done before a dialog is shown because of OnIdle() + CallAfter() in Perl
GUI::MsgDataIncompatible dlg(std::move(incompats_map)); GUI::MsgDataIncompatible dlg(std::move(incompats_map));
const auto res = dlg.ShowModal(); const auto res = dlg.ShowModal();
if (res == wxID_REPLACE) { if (res == wxID_REPLACE) {
BOOST_LOG_TRIVIAL(info) << "User wants to re-configure..."; BOOST_LOG_TRIVIAL(info) << "User wants to re-configure...";
p->perform_updates(std::move(updates)); p->perform_updates(std::move(updates));
GUI::ConfigWizard wizard(nullptr, GUI::ConfigWizard::RR_DATA_INCOMPAT); GUI::ConfigWizard wizard(nullptr, GUI::ConfigWizard::RR_DATA_INCOMPAT);
if (wizard.run(GUI::get_preset_bundle(), this)) { if (! wizard.run(GUI::get_preset_bundle(), this)) {
p->had_config_update = true;
} else {
return false; return false;
} }
} else { } else {
@ -566,6 +566,8 @@ bool PresetUpdater::config_update() const
updates_map.emplace(std::make_pair(std::move(vendor), std::move(ver_str))); updates_map.emplace(std::make_pair(std::move(vendor), std::move(ver_str)));
} }
p->had_config_update = true; // Ditto, see above
GUI::MsgUpdateConfig dlg(std::move(updates_map)); GUI::MsgUpdateConfig dlg(std::move(updates_map));
const auto res = dlg.ShowModal(); const auto res = dlg.ShowModal();
@ -581,8 +583,6 @@ bool PresetUpdater::config_update() const
} else { } else {
BOOST_LOG_TRIVIAL(info) << "User refused the update"; BOOST_LOG_TRIVIAL(info) << "User refused the update";
} }
p->had_config_update = true;
} else { } else {
BOOST_LOG_TRIVIAL(info) << "No configuration updates available."; BOOST_LOG_TRIVIAL(info) << "No configuration updates available.";
} }

View File

@ -31,7 +31,7 @@
try { try {
THIS->do_export(print, path, preview_data); THIS->do_export(print, path, preview_data);
} catch (std::exception& e) { } catch (std::exception& e) {
croak(e.what()); croak("%s\n", e.what());
} }
%}; %};

View File

@ -190,18 +190,6 @@ remove_all_canvases()
CODE: CODE:
_3DScene::remove_all_canvases(); _3DScene::remove_all_canvases();
void
reset_current_canvas()
CODE:
_3DScene::reset_current_canvas();
void
set_active(canvas, active)
SV *canvas;
bool active;
CODE:
_3DScene::set_active((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), active);
void void
set_as_dirty(canvas) set_as_dirty(canvas)
SV *canvas; SV *canvas;