diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index 12058c3f61..e5c6689bed 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -536,9 +536,6 @@ int CLI::run(int argc, char **argv) return -1; } - //gui->app_config = app_config; - //app_config = nullptr; - // gui->autosave = m_config.opt_string("autosave"); GUI::GUI_App::SetInstance(gui); gui->CallAfter([gui, this, &load_configs] { diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 8ce01a3530..c22e504dff 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -55,7 +55,6 @@ // Enable G-Code viewer #define ENABLE_GCODE_VIEWER (1 && ENABLE_2_3_0_ALPHA1) -#define ENABLE_GCODE_USE_WXWIDGETS_SLIDER (1 && ENABLE_GCODE_VIEWER) #define ENABLE_GCODE_VIEWER_STATISTICS (0 && ENABLE_GCODE_VIEWER) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index 021d73882e..597b9ad607 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -20,9 +20,9 @@ #include #include #include -#if !ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#if !ENABLE_GCODE_VIEWER #include -#endif // !ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#endif // !ENABLE_GCODE_VIEWER #include #include @@ -537,7 +537,7 @@ wxString Control::get_label(int tick) const if (value >= m_values.size()) return "ErrVal"; -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#if ENABLE_GCODE_VIEWER if (m_draw_mode == dmSequentialGCodeView) return wxString::Format("%d", static_cast(m_values[value])); else { @@ -551,7 +551,7 @@ wxString Control::get_label(int tick) const wxNumberFormatter::ToString(m_label_koef * value, 2, wxNumberFormatter::Style_None) : wxNumberFormatter::ToString(m_values[value], 2, wxNumberFormatter::Style_None); return format_wxstr("%1%\n(%2%)", str, m_values.empty() ? value : value + 1); -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#endif // ENABLE_GCODE_VIEWER } void Control::draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, bool right_side/*=true*/) const @@ -792,10 +792,10 @@ void Control::draw_colored_band(wxDC& dc) void Control::draw_one_layer_icon(wxDC& dc) { -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#if ENABLE_GCODE_VIEWER if (m_draw_mode == dmSequentialGCodeView) return; -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#endif // ENABLE_GCODE_VIEWER const wxBitmap& icon = m_is_one_layer ? m_focus == fiOneLayerIcon ? m_bmp_one_layer_lock_off.bmp() : m_bmp_one_layer_lock_on.bmp() : @@ -1302,11 +1302,11 @@ void Control::OnWheel(wxMouseEvent& event) ssLower : ssHigher; } -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#if ENABLE_GCODE_VIEWER move_current_thumb((m_draw_mode == dmSequentialGCodeView) ? event.GetWheelRotation() < 0 : event.GetWheelRotation() > 0); #else move_current_thumb(event.GetWheelRotation() > 0); -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#endif // ENABLE_GCODE_VIEWER } void Control::OnKeyDown(wxKeyEvent &event) @@ -1328,34 +1328,34 @@ void Control::OnKeyDown(wxKeyEvent &event) UseDefaultColors(false); else if (is_horizontal()) { -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#if ENABLE_GCODE_VIEWER if (m_is_focused) { -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#endif // ENABLE_GCODE_VIEWER if (key == WXK_LEFT || key == WXK_RIGHT) move_current_thumb(key == WXK_LEFT); else if (key == WXK_UP || key == WXK_DOWN) { m_selection = key == WXK_UP ? ssHigher : ssLower; Refresh(); } -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#if ENABLE_GCODE_VIEWER } -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#endif // ENABLE_GCODE_VIEWER } else { -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#if ENABLE_GCODE_VIEWER if (m_is_focused) { -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#endif // ENABLE_GCODE_VIEWER if (key == WXK_LEFT || key == WXK_RIGHT) { m_selection = key == WXK_LEFT ? ssHigher : ssLower; Refresh(); } else if (key == WXK_UP || key == WXK_DOWN) move_current_thumb(key == WXK_UP); -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#if ENABLE_GCODE_VIEWER } -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#endif // ENABLE_GCODE_VIEWER } event.Skip(); // !Needed to have EVT_CHAR generated as well diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp index a17fb2b6fa..fea1ba172e 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSlider.hpp @@ -73,9 +73,9 @@ enum DrawMode dmRegular, dmSlaPrint, dmSequentialFffPrint, -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#if ENABLE_GCODE_VIEWER dmSequentialGCodeView, -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#endif // ENABLE_GCODE_VIEWER }; using t_mode = CustomGCode::Mode; @@ -214,9 +214,9 @@ public: void SetTicksValues(const Slic3r::CustomGCode::Info &custom_gcode_per_print_z); void SetDrawMode(bool is_sla_print, bool is_sequential_print); -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#if ENABLE_GCODE_VIEWER void SetDrawMode(DrawMode mode) { m_draw_mode = mode; } -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#endif // ENABLE_GCODE_VIEWER void SetManipulationMode(t_mode mode) { m_mode = mode; } t_mode GetManipulationMode() const { return m_mode; } diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index acf1da4c71..c4bc391d18 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -324,9 +324,6 @@ void GCodeViewer::render() const m_sequential_view.marker.render(); render_shells(); render_legend(); -#if !ENABLE_GCODE_USE_WXWIDGETS_SLIDER - render_sequential_bar(); -#endif // !ENABLE_GCODE_USE_WXWIDGETS_SLIDER #if ENABLE_GCODE_VIEWER_STATISTICS render_statistics(); #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -383,15 +380,13 @@ void GCodeViewer::set_options_visibility_from_flags(unsigned int flags) enable_legend(is_flag_set(9)); } -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER void GCodeViewer::set_layers_z_range(const std::array& layers_z_range) { bool keep_sequential_current = layers_z_range[1] <= m_layers_z_range[1]; m_layers_z_range = layers_z_range; refresh_render_paths(keep_sequential_current); - wxGetApp().plater()->update_preview_horz_slider(); + wxGetApp().plater()->update_preview_moves_slider(); } -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER bool GCodeViewer::init_shaders() { @@ -1159,93 +1154,6 @@ void GCodeViewer::render_legend() const ImGui::PopStyleVar(); } -#if !ENABLE_GCODE_USE_WXWIDGETS_SLIDER -void GCodeViewer::render_sequential_bar() const -{ - static const float MARGIN = 125.0f; - static const float BUTTON_W = 50.0f; - - auto apply_button_action = [this](unsigned int value) { - m_sequential_view.current = std::clamp(value, m_sequential_view.first, m_sequential_view.last); - refresh_render_paths(true); - }; - - if (m_sequential_view.last <= m_sequential_view.first) - return; - - ImGuiWrapper& imgui = *wxGetApp().imgui(); - const ImGuiStyle& style = ImGui::GetStyle(); - - Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size(); - - float left = wxGetApp().plater()->get_view_toolbar().get_width(); - float width = static_cast(cnv_size.get_width()) - left; - - ImGui::SetNextWindowBgAlpha(0.5f); - imgui.set_next_window_pos(left, static_cast(cnv_size.get_height()), ImGuiCond_Always, 0.0f, 1.0f); - ImGui::SetNextWindowSize({ width, -1.0f }, ImGuiCond_Always); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - imgui.begin(std::string("Sequential"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove); - - ImGui::SetCursorPosX(MARGIN); - imgui.disabled_begin(m_sequential_view.first == m_sequential_view.current); - if (ImGui::Button("< 1", { BUTTON_W, 0.0f })) - apply_button_action(m_sequential_view.current - 1); - imgui.disabled_end(); - - ImGui::SameLine(); - imgui.disabled_begin(m_sequential_view.current - m_sequential_view.first < 10); - if (ImGui::Button("< 10", { BUTTON_W, 0.0f })) - apply_button_action(m_sequential_view.current - 10); - imgui.disabled_end(); - - ImGui::SameLine(); - imgui.disabled_begin(m_sequential_view.current - m_sequential_view.first < 100); - if (ImGui::Button("< 100", { BUTTON_W, 0.0f })) - apply_button_action(m_sequential_view.current - 100); - imgui.disabled_end(); - - ImGui::SameLine(width - MARGIN - 3 * BUTTON_W - 2 * style.ItemSpacing.x - style.WindowPadding.x); - imgui.disabled_begin(m_sequential_view.last - m_sequential_view.current < 100); - if (ImGui::Button("> 100", { BUTTON_W, 0.0f })) - apply_button_action(m_sequential_view.current + 100); - imgui.disabled_end(); - - ImGui::SameLine(); - imgui.disabled_begin(m_sequential_view.last - m_sequential_view.current < 10); - if (ImGui::Button("> 10", { BUTTON_W, 0.0f })) - apply_button_action(m_sequential_view.current + 10); - imgui.disabled_end(); - - ImGui::SameLine(); - imgui.disabled_begin(m_sequential_view.last == m_sequential_view.current); - if (ImGui::Button("> 1", { BUTTON_W, 0.0f })) - apply_button_action(m_sequential_view.current + 1); - imgui.disabled_end(); - - int index = 1 + static_cast(m_sequential_view.current); - int i_min = 1 + static_cast(m_sequential_view.first); - int i_max = 1 + static_cast(m_sequential_view.last); - - std::string low_str = std::to_string(i_min); - ImGui::SetCursorPosX(MARGIN - style.ItemSpacing.x - ImGui::CalcTextSize(low_str.c_str()).x); - ImGui::AlignTextToFramePadding(); - imgui.text(low_str); - ImGui::SameLine(MARGIN); - ImGui::PushItemWidth(-MARGIN); - if (ImGui::SliderInt("##slider int", &index, i_min, i_max)) { - m_sequential_view.current = static_cast(index - 1); - refresh_render_paths(true); - } - ImGui::PopItemWidth(); - ImGui::SameLine(); - imgui.text(std::to_string(i_max)); - - imgui.end(); - ImGui::PopStyleVar(); -} -#endif // !ENABLE_GCODE_USE_WXWIDGETS_SLIDER - #if ENABLE_GCODE_VIEWER_STATISTICS void GCodeViewer::render_statistics() const { diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index a4ac3358d2..e53bcb0c62 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -149,42 +149,6 @@ class GCodeViewer void reset_ranges() { ranges.reset(); } }; -#if !ENABLE_GCODE_USE_WXWIDGETS_SLIDER - struct SequentialView - { - class Marker - { - GL_Model m_model; - Transform3f m_world_transform; - std::array m_color{ 1.0f, 1.0f, 1.0f, 1.0f }; - bool m_visible{ false }; - Shader m_shader; - - public: - void init(); - - const BoundingBoxf3& get_bounding_box() const { return m_model.get_bounding_box(); } - - void set_world_transform(const Transform3f& transform) { m_world_transform = transform; } - void set_color(const std::array& color) { m_color = color; } - - bool is_visible() const { return m_visible; } - void set_visible(bool visible) { m_visible = visible; } - - void render() const; - - private: - void init_shader(); - }; - - unsigned int first{ 0 }; - unsigned int last{ 0 }; - unsigned int current{ 0 }; - Vec3f current_position{ Vec3f::Zero() }; - Marker marker; - }; -#endif // !ENABLE_GCODE_USE_WXWIDGETS_SLIDER - #if ENABLE_GCODE_VIEWER_STATISTICS struct Statistics { @@ -231,7 +195,6 @@ class GCodeViewer #endif // ENABLE_GCODE_VIEWER_STATISTICS public: -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER struct SequentialView { class Marker @@ -265,7 +228,6 @@ public: Vec3f current_position{ Vec3f::Zero() }; Marker marker; }; -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER enum class EViewType : unsigned char { @@ -322,10 +284,8 @@ public: const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; } const std::vector& get_layers_zs() const { return m_layers_zs; }; -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER const SequentialView& get_sequential_view() const { return m_sequential_view; } void update_sequential_view_current(unsigned int low, unsigned int high) { m_sequential_view.current = high; refresh_render_paths(true); } -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER EViewType get_view_type() const { return m_view_type; } void set_view_type(EViewType type) { @@ -341,16 +301,7 @@ public: void set_toolpath_role_visibility_flags(unsigned int flags) { m_extrusions.role_visibility_flags = flags; } unsigned int get_options_visibility_flags() const; void set_options_visibility_from_flags(unsigned int flags); -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER void set_layers_z_range(const std::array& layers_z_range); -#else - void set_layers_z_range(const std::array& layers_z_range) - { - bool keep_sequential_current = layers_z_range[1] <= m_layers_z_range[1]; - m_layers_z_range = layers_z_range; - refresh_render_paths(keep_sequential_current); - } -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER bool is_legend_enabled() const { return m_legend_enabled; } void enable_legend(bool enable) { m_legend_enabled = enable; } @@ -363,9 +314,6 @@ private: void render_toolpaths() const; void render_shells() const; void render_legend() const; -#if !ENABLE_GCODE_USE_WXWIDGETS_SLIDER - void render_sequential_bar() const; -#endif // !ENABLE_GCODE_USE_WXWIDGETS_SLIDER #if ENABLE_GCODE_VIEWER_STATISTICS void render_statistics() const; #endif // ENABLE_GCODE_VIEWER_STATISTICS diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 073a9cd35e..7629bc969b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1523,7 +1523,11 @@ wxDEFINE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_BED_SHAPE, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_TAB, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_RESETGIZMOS, SimpleEvent); +#if ENABLE_GCODE_VIEWER +wxDEFINE_EVENT(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, wxKeyEvent); +#else wxDEFINE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent); +#endif // ENABLE_GCODE_VIEWER wxDEFINE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent); wxDEFINE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); @@ -3405,7 +3409,11 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) keyCode == WXK_DOWN) { if (dynamic_cast(m_canvas->GetParent()) != nullptr) +#if ENABLE_GCODE_VIEWER + post_event(wxKeyEvent(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, evt)); +#else post_event(wxKeyEvent(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, evt)); +#endif // ENABLE_GCODE_VIEWER } } } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d4df60ad2a..43d37607c5 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -107,7 +107,11 @@ wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_BED_SHAPE, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_TAB, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_RESETGIZMOS, SimpleEvent); +#if ENABLE_GCODE_VIEWER +wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, wxKeyEvent); +#else wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent); +#endif // ENABLE_GCODE_VIEWER wxDECLARE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent); wxDECLARE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); @@ -553,10 +557,8 @@ public: #if ENABLE_GCODE_VIEWER void reset_gcode_toolpaths() { m_gcode_viewer.reset(); } -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER const GCodeViewer::SequentialView& get_gcode_sequential_view() const { return m_gcode_viewer.get_sequential_view(); } void update_gcode_sequential_view_current(unsigned int low, unsigned int high) { m_gcode_viewer.update_sequential_view_current(low, high); } -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER #endif // ENABLE_GCODE_VIEWER void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 9a2a51e9ce..ea23f8daaa 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -323,6 +323,12 @@ void GUI_App::init_app_config() } } +void GUI_App::init_single_instance_checker(const std::string &name, const std::string &path) +{ + BOOST_LOG_TRIVIAL(debug) << "init wx instance checker " << name << " "<< path; + m_single_instance_checker = std::make_unique(boost::nowide::widen(name), boost::nowide::widen(path)); +} + bool GUI_App::OnInit() { try { @@ -451,6 +457,10 @@ bool GUI_App::on_init_inner() preset_updater->slic3r_update_notify(); preset_updater->sync(preset_bundle); }); +#ifdef _WIN32 + //sets window property to mainframe so other instances can indentify it + OtherInstanceMessageHandler::init_windows_properties(mainframe, m_instance_hash_int); +#endif //WIN32 } }); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 3afadf4e0e..984a1241e7 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -106,6 +107,9 @@ class GUI_App : public wxApp std::unique_ptr m_printhost_job_queue; ConfigWizard* m_wizard; // Managed by wxWindow tree std::unique_ptr m_other_instance_message_handler; + std::unique_ptr m_single_instance_checker; + std::string m_instance_hash_string; + size_t m_instance_hash_int; public: bool OnInit() override; bool initialized() const { return m_initialized; } @@ -194,6 +198,12 @@ public: RemovableDriveManager* removable_drive_manager() { return m_removable_drive_manager.get(); } OtherInstanceMessageHandler* other_instance_message_handler() { return m_other_instance_message_handler.get(); } + wxSingleInstanceChecker* single_instance_checker() {return m_single_instance_checker.get();} + + void init_single_instance_checker(const std::string &name, const std::string &path); + void set_instance_hash (const size_t hash) { m_instance_hash_int = hash; m_instance_hash_string = std::to_string(hash); } + std::string get_instance_hash_string () { return m_instance_hash_string; } + size_t get_instance_hash_int () { return m_instance_hash_int; } ImGuiWrapper* imgui() { return m_imgui.get(); } diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 9547e0bf89..714ed3c9ef 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -183,9 +183,11 @@ Preview::Preview( #endif // ENABLE_GCODE_VIEWER : m_canvas_widget(nullptr) , m_canvas(nullptr) - , m_double_slider_sizer(nullptr) #if ENABLE_GCODE_VIEWER , m_bottom_toolbar_sizer(nullptr) + , m_layers_slider_sizer(nullptr) +#else + , m_double_slider_sizer(nullptr) #endif // ENABLE_GCODE_VIEWER , m_label_view_type(nullptr) , m_choice_view_type(nullptr) @@ -248,7 +250,7 @@ bool Preview::init(wxWindow* parent, Model* model) m_canvas->enable_collapse_toolbar(true); #if ENABLE_GCODE_VIEWER - m_double_slider_sizer = create_vert_slider_sizer(); + m_layers_slider_sizer = create_layers_slider_sizer(); #else m_double_slider_sizer = new wxBoxSizer(wxHORIZONTAL); create_double_slider(); @@ -319,15 +321,17 @@ bool Preview::init(wxWindow* parent, Model* model) wxBoxSizer* top_sizer = new wxBoxSizer(wxHORIZONTAL); top_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0); +#if ENABLE_GCODE_VIEWER + top_sizer->Add(m_layers_slider_sizer, 0, wxEXPAND, 0); +#else top_sizer->Add(m_double_slider_sizer, 0, wxEXPAND, 0); - -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER - m_horz_slider = new DoubleSlider::Control(this, wxID_ANY, 0, 0, 0, 100, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL); - m_horz_slider->SetDrawMode(DoubleSlider::dmSequentialGCodeView); - m_horz_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_horz_slider_scroll_changed, this); -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#endif // ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER + m_moves_slider = new DoubleSlider::Control(this, wxID_ANY, 0, 0, 0, 100, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL); + m_moves_slider->SetDrawMode(DoubleSlider::dmSequentialGCodeView); + m_moves_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this); + m_bottom_toolbar_sizer = new wxBoxSizer(wxHORIZONTAL); m_bottom_toolbar_sizer->AddSpacer(10); m_bottom_toolbar_sizer->Add(m_label_view_type, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5); @@ -336,10 +340,8 @@ bool Preview::init(wxWindow* parent, Model* model) m_bottom_toolbar_sizer->Add(m_label_show, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5); m_bottom_toolbar_sizer->Add(m_combochecklist_options, 0, wxALIGN_CENTER_VERTICAL, 5); m_bottom_toolbar_sizer->Add(m_combochecklist_features, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5); -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER m_bottom_toolbar_sizer->AddSpacer(10); - m_bottom_toolbar_sizer->Add(m_horz_slider, 1, wxALL | wxEXPAND, 5); -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER + m_bottom_toolbar_sizer->Add(m_moves_slider, 1, wxALL | wxEXPAND, 5); #else wxBoxSizer* bottom_sizer = new wxBoxSizer(wxHORIZONTAL); bottom_sizer->Add(m_label_view_type, 0, wxALIGN_CENTER_VERTICAL, 5); @@ -517,10 +519,8 @@ void Preview::msw_rescale() { // rescale slider #if ENABLE_GCODE_VIEWER - if (m_vert_slider != nullptr) m_vert_slider->msw_rescale(); -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER - if (m_horz_slider != nullptr) m_horz_slider->msw_rescale(); -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER + if (m_layers_slider != nullptr) m_layers_slider->msw_rescale(); + if (m_moves_slider != nullptr) m_moves_slider->msw_rescale(); #else if (m_slider) m_slider->msw_rescale(); #endif // ENABLE_GCODE_VIEWER @@ -532,25 +532,31 @@ void Preview::msw_rescale() refresh_print(); } +#if ENABLE_GCODE_VIEWER +void Preview::move_layers_slider(wxKeyEvent& evt) +{ + if (m_layers_slider != nullptr) m_layers_slider->OnKeyDown(evt); +} +#else void Preview::move_double_slider(wxKeyEvent& evt) { -#if ENABLE_GCODE_VIEWER - if (m_vert_slider != nullptr) m_vert_slider->OnKeyDown(evt); -#else if (m_slider) m_slider->OnKeyDown(evt); -#endif // ENABLE_GCODE_VIEWER } +#endif // ENABLE_GCODE_VIEWER +#if ENABLE_GCODE_VIEWER +void Preview::edit_layers_slider(wxKeyEvent& evt) +{ + if (m_layers_slider != nullptr) m_layers_slider->OnChar(evt); +} +#else void Preview::edit_double_slider(wxKeyEvent& evt) { -#if ENABLE_GCODE_VIEWER - if (m_vert_slider != nullptr) m_vert_slider->OnChar(evt); -#else if (m_slider) m_slider->OnChar(evt); -#endif // ENABLE_GCODE_VIEWER } +#endif // ENABLE_GCODE_VIEWER void Preview::bind_event_handlers() { @@ -614,9 +620,9 @@ void Preview::show_hide_ui_elements(const std::string& what) #endif // !ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER -void Preview::hide_vert_slider() +void Preview::hide_layers_slider() { - m_double_slider_sizer->Hide((size_t)0); + m_layers_slider_sizer->Hide((size_t)0); Layout(); } #else @@ -756,29 +762,29 @@ void Preview::update_bottom_toolbar() #endif // ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER -wxBoxSizer* Preview::create_vert_slider_sizer() +wxBoxSizer* Preview::create_layers_slider_sizer() { wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); - m_vert_slider = new DoubleSlider::Control(this, wxID_ANY, 0, 0, 0, 100); + m_layers_slider = new DoubleSlider::Control(this, wxID_ANY, 0, 0, 0, 100); - m_vert_slider->SetDrawMode(wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA, + m_layers_slider->SetDrawMode(wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA, wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects")); - sizer->Add(m_vert_slider, 0, wxEXPAND, 0); + sizer->Add(m_layers_slider, 0, wxEXPAND, 0); // sizer, m_canvas_widget - m_canvas_widget->Bind(wxEVT_KEY_DOWN, &Preview::update_vert_slider_from_canvas, this); + m_canvas_widget->Bind(wxEVT_KEY_DOWN, &Preview::update_layers_slider_from_canvas, this); m_canvas_widget->Bind(wxEVT_KEY_UP, [this](wxKeyEvent& event) { if (event.GetKeyCode() == WXK_SHIFT) - m_vert_slider->UseDefaultColors(true); + m_layers_slider->UseDefaultColors(true); event.Skip(); }); - m_vert_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_vert_slider_scroll_changed, this); + m_layers_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_layers_slider_scroll_changed, this); Bind(DoubleSlider::wxCUSTOMEVT_TICKSCHANGED, [this](wxEvent&) { Model& model = wxGetApp().plater()->model(); - model.custom_gcode_per_print_z = m_vert_slider->GetTicksValues(); + model.custom_gcode_per_print_z = m_layers_slider->GetTicksValues(); m_schedule_background_process(); update_view_type(false); @@ -850,8 +856,7 @@ static int find_close_layer_idx(const std::vector& zs, double &z, double } #if ENABLE_GCODE_VIEWER -void Preview::check_vert_slider_values(std::vector& ticks_from_model, - const std::vector& layers_z) +void Preview::check_layers_slider_values(std::vector& ticks_from_model, const std::vector& layers_z) #else void Preview::check_slider_values(std::vector& ticks_from_model, const std::vector& layers_z) @@ -873,34 +878,34 @@ void Preview::check_slider_values(std::vector& ticks_from_mod } #if ENABLE_GCODE_VIEWER -void Preview::update_vert_slider(const std::vector& layers_z, bool keep_z_range) +void Preview::update_layers_slider(const std::vector& layers_z, bool keep_z_range) { // Save the initial slider span. - double z_low = m_vert_slider->GetLowerValueD(); - double z_high = m_vert_slider->GetHigherValueD(); - bool was_empty = m_vert_slider->GetMaxValue() == 0; + double z_low = m_layers_slider->GetLowerValueD(); + double z_high = m_layers_slider->GetHigherValueD(); + bool was_empty = m_layers_slider->GetMaxValue() == 0; bool force_sliders_full_range = was_empty; if (!keep_z_range) { - bool span_changed = layers_z.empty() || std::abs(layers_z.back() - m_vert_slider->GetMaxValueD()) > DoubleSlider::epsilon()/*1e-6*/; + bool span_changed = layers_z.empty() || std::abs(layers_z.back() - m_layers_slider->GetMaxValueD()) > DoubleSlider::epsilon()/*1e-6*/; force_sliders_full_range |= span_changed; -} - bool snap_to_min = force_sliders_full_range || m_vert_slider->is_lower_at_min(); - bool snap_to_max = force_sliders_full_range || m_vert_slider->is_higher_at_max(); + } + bool snap_to_min = force_sliders_full_range || m_layers_slider->is_lower_at_min(); + bool snap_to_max = force_sliders_full_range || m_layers_slider->is_higher_at_max(); // Detect and set manipulation mode for double slider - update_vert_slider_mode(); + update_layers_slider_mode(); CustomGCode::Info& ticks_info_from_model = wxGetApp().plater()->model().custom_gcode_per_print_z; - check_vert_slider_values(ticks_info_from_model.gcodes, layers_z); + check_layers_slider_values(ticks_info_from_model.gcodes, layers_z); - m_vert_slider->SetSliderValues(layers_z); - assert(m_vert_slider->GetMinValue() == 0); - m_vert_slider->SetMaxValue(layers_z.empty() ? 0 : layers_z.size() - 1); + m_layers_slider->SetSliderValues(layers_z); + assert(m_layers_slider->GetMinValue() == 0); + m_layers_slider->SetMaxValue(layers_z.empty() ? 0 : layers_z.size() - 1); int idx_low = 0; - int idx_high = m_vert_slider->GetMaxValue(); + int idx_high = m_layers_slider->GetMaxValue(); if (!layers_z.empty()) { if (!snap_to_min) { int idx_new = find_close_layer_idx(layers_z, z_low, DoubleSlider::epsilon()/*1e-6*/); @@ -913,17 +918,15 @@ void Preview::update_vert_slider(const std::vector& layers_z, bool keep_ idx_high = idx_new; } } - m_vert_slider->SetSelectionSpan(idx_low, idx_high); - - m_vert_slider->SetTicksValues(ticks_info_from_model); + m_layers_slider->SetSelectionSpan(idx_low, idx_high); + m_layers_slider->SetTicksValues(ticks_info_from_model); bool sla_print_technology = wxGetApp().plater()->printer_technology() == ptSLA; bool sequential_print = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects"); - m_vert_slider->SetDrawMode(sla_print_technology, sequential_print); + m_layers_slider->SetDrawMode(sla_print_technology, sequential_print); + m_layers_slider->SetExtruderColors(wxGetApp().plater()->get_extruder_colors_from_plater_config()); - m_vert_slider->SetExtruderColors(wxGetApp().plater()->get_extruder_colors_from_plater_config()); - - m_double_slider_sizer->Show((size_t)0); + m_layers_slider_sizer->Show((size_t)0); Layout(); } #else @@ -980,7 +983,7 @@ void Preview::update_double_slider(const std::vector & layers_z, bool ke #endif // ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER -void Preview::update_vert_slider_mode() +void Preview::update_layers_slider_mode() #else void Preview::update_double_slider_mode() #endif // ENABLE_GCODE_VIEWER @@ -1033,17 +1036,17 @@ void Preview::update_double_slider_mode() } #if ENABLE_GCODE_VIEWER - m_vert_slider->SetModeAndOnlyExtruder(one_extruder_printed_model, only_extruder); + m_layers_slider->SetModeAndOnlyExtruder(one_extruder_printed_model, only_extruder); #else m_slider->SetModeAndOnlyExtruder(one_extruder_printed_model, only_extruder); #endif // ENABLE_GCODE_VIEWER } #if ENABLE_GCODE_VIEWER -void Preview::reset_vert_slider() +void Preview::reset_layers_slider() { - m_vert_slider->SetHigherValue(0); - m_vert_slider->SetLowerValue(0); + m_layers_slider->SetHigherValue(0); + m_layers_slider->SetLowerValue(0); } #else void Preview::reset_double_slider() @@ -1054,7 +1057,7 @@ void Preview::reset_double_slider() #endif // ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER -void Preview::update_vert_slider_from_canvas(wxKeyEvent& event) +void Preview::update_layers_slider_from_canvas(wxKeyEvent& event) { if (event.HasModifiers()) { event.Skip(); @@ -1064,20 +1067,19 @@ void Preview::update_vert_slider_from_canvas(wxKeyEvent& event) const auto key = event.GetKeyCode(); if (key == 'U' || key == 'D') { - const int new_pos = key == 'U' ? m_vert_slider->GetHigherValue() + 1 : m_vert_slider->GetHigherValue() - 1; - m_vert_slider->SetHigherValue(new_pos); - if (event.ShiftDown() || m_vert_slider->is_one_layer()) m_vert_slider->SetLowerValue(m_vert_slider->GetHigherValue()); + const int new_pos = key == 'U' ? m_layers_slider->GetHigherValue() + 1 : m_layers_slider->GetHigherValue() - 1; + m_layers_slider->SetHigherValue(new_pos); + if (event.ShiftDown() || m_layers_slider->is_one_layer()) m_layers_slider->SetLowerValue(m_layers_slider->GetHigherValue()); } else if (key == 'S') - m_vert_slider->ChangeOneLayerLock(); + m_layers_slider->ChangeOneLayerLock(); else if (key == WXK_SHIFT) - m_vert_slider->UseDefaultColors(false); + m_layers_slider->UseDefaultColors(false); else event.Skip(); } -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER -void Preview::update_horz_slider() +void Preview::update_moves_slider() { const GCodeViewer::SequentialView& view = m_canvas->get_gcode_sequential_view(); std::vector values(view.last - view.first + 1); @@ -1087,11 +1089,10 @@ void Preview::update_horz_slider() values[count++] = static_cast(i + 1); } - m_horz_slider->SetSliderValues(values); - m_horz_slider->SetMaxValue(view.last - view.first); - m_horz_slider->SetSelectionSpan(0, view.current); + m_moves_slider->SetSliderValues(values); + m_moves_slider->SetMaxValue(view.last - view.first); + m_moves_slider->SetSelectionSpan(0, view.current); } -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER #else void Preview::update_double_slider_from_canvas(wxKeyEvent & event) { @@ -1149,7 +1150,7 @@ void Preview::load_print_as_fff(bool keep_z_range) if (! has_layers) { #if ENABLE_GCODE_VIEWER - hide_vert_slider(); + hide_layers_slider(); #else reset_sliders(true); m_canvas->reset_legend_texture(); @@ -1246,14 +1247,14 @@ void Preview::load_print_as_fff(bool keep_z_range) if (zs.empty()) { // all layers filtered out #if ENABLE_GCODE_VIEWER - hide_vert_slider(); + hide_layers_slider(); #else reset_sliders(true); #endif // ENABLE_GCODE_VIEWER m_canvas_widget->Refresh(); } else #if ENABLE_GCODE_VIEWER - update_vert_slider(zs, keep_z_range); + update_layers_slider(zs, keep_z_range); #else update_sliders(zs, keep_z_range); #endif // ENABLE_GCODE_VIEWER @@ -1285,7 +1286,7 @@ void Preview::load_print_as_sla() if (n_layers == 0) { #if ENABLE_GCODE_VIEWER - hide_vert_slider(); + hide_layers_slider(); #else reset_sliders(true); #endif // ENABLE_GCODE_VIEWER @@ -1304,7 +1305,7 @@ void Preview::load_print_as_sla() if (n_layers > 0) #if ENABLE_GCODE_VIEWER - update_vert_slider(zs); + update_layers_slider(zs); #else update_sliders(zs); #endif // ENABLE_GCODE_VIEWER @@ -1314,7 +1315,7 @@ void Preview::load_print_as_sla() } #if ENABLE_GCODE_VIEWER -void Preview::on_vert_slider_scroll_changed(wxCommandEvent& event) +void Preview::on_layers_slider_scroll_changed(wxCommandEvent& event) #else void Preview::on_sliders_scroll_changed(wxCommandEvent& event) #endif // ENABLE_GCODE_VIEWER @@ -1325,7 +1326,7 @@ void Preview::on_sliders_scroll_changed(wxCommandEvent& event) if (tech == ptFFF) { #if ENABLE_GCODE_VIEWER - m_canvas->set_toolpaths_z_range({ m_vert_slider->GetLowerValueD(), m_vert_slider->GetHigherValueD() }); + m_canvas->set_toolpaths_z_range({ m_layers_slider->GetLowerValueD(), m_layers_slider->GetHigherValueD() }); m_canvas->set_as_dirty(); #else m_canvas->set_toolpaths_range(m_slider->GetLowerValueD() - 1e-6, m_slider->GetHigherValueD() + 1e-6); @@ -1336,9 +1337,9 @@ void Preview::on_sliders_scroll_changed(wxCommandEvent& event) else if (tech == ptSLA) { #if ENABLE_GCODE_VIEWER - m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_vert_slider->GetLowerValueD())); - m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_vert_slider->GetHigherValueD())); - m_canvas->set_use_clipping_planes(m_vert_slider->GetHigherValue() != 0); + m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_layers_slider->GetLowerValueD())); + m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_layers_slider->GetHigherValueD())); + m_canvas->set_use_clipping_planes(m_layers_slider->GetHigherValue() != 0); #else m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_slider->GetLowerValueD())); m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_slider->GetHigherValueD())); @@ -1349,13 +1350,13 @@ void Preview::on_sliders_scroll_changed(wxCommandEvent& event) } } -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER -void Preview::on_horz_slider_scroll_changed(wxCommandEvent& event) +#if ENABLE_GCODE_VIEWER +void Preview::on_moves_slider_scroll_changed(wxCommandEvent& event) { - m_canvas->update_gcode_sequential_view_current(static_cast(m_horz_slider->GetLowerValueD()), static_cast(m_horz_slider->GetHigherValueD())); + m_canvas->update_gcode_sequential_view_current(static_cast(m_moves_slider->GetLowerValueD()), static_cast(m_moves_slider->GetHigherValueD())); m_canvas->render(); } -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER +#endif // ENABLE_GCODE_VIEWER } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 4df48a153e..3f0d4b4e68 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -82,9 +82,11 @@ class Preview : public wxPanel { wxGLCanvas* m_canvas_widget; GLCanvas3D* m_canvas; - wxBoxSizer* m_double_slider_sizer; #if ENABLE_GCODE_VIEWER + wxBoxSizer* m_layers_slider_sizer; wxBoxSizer* m_bottom_toolbar_sizer; +#else + wxBoxSizer* m_double_slider_sizer; #endif // ENABLE_GCODE_VIEWER wxStaticText* m_label_view_type; wxChoice* m_choice_view_type; @@ -126,10 +128,8 @@ class Preview : public wxPanel #endif // !ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER - DoubleSlider::Control* m_vert_slider{ nullptr }; -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER - DoubleSlider::Control* m_horz_slider{ nullptr }; -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER + DoubleSlider::Control* m_layers_slider{ nullptr }; + DoubleSlider::Control* m_moves_slider{ nullptr }; #else DoubleSlider::Control* m_slider {nullptr}; #endif // ENABLE_GCODE_VIEWER @@ -162,8 +162,13 @@ Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config, void refresh_print(); void msw_rescale(); +#if ENABLE_GCODE_VIEWER + void move_layers_slider(wxKeyEvent& evt); + void edit_layers_slider(wxKeyEvent& evt); +#else void move_double_slider(wxKeyEvent& evt); void edit_double_slider(wxKeyEvent& evt); +#endif // ENABLE_GCODE_VIEWER void update_view_type(bool slice_completed); @@ -171,9 +176,7 @@ Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config, #if ENABLE_GCODE_VIEWER void update_bottom_toolbar(); -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER - void update_horz_slider(); -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER + void update_moves_slider(); #endif // ENABLE_GCODE_VIEWER private: @@ -183,7 +186,7 @@ private: void unbind_event_handlers(); #if ENABLE_GCODE_VIEWER - void hide_vert_slider(); + void hide_layers_slider(); #else void show_hide_ui_elements(const std::string& what); @@ -206,14 +209,14 @@ private: #if ENABLE_GCODE_VIEWER // Create/Update/Reset double slider on 3dPreview - wxBoxSizer* create_vert_slider_sizer(); - void check_vert_slider_values(std::vector& ticks_from_model, + wxBoxSizer* create_layers_slider_sizer(); + void check_layers_slider_values(std::vector& ticks_from_model, const std::vector& layers_z); - void reset_vert_slider(); - void update_vert_slider(const std::vector& layers_z, bool keep_z_range = false); - void update_vert_slider_mode(); + void reset_layers_slider(); + void update_layers_slider(const std::vector& layers_z, bool keep_z_range = false); + void update_layers_slider_mode(); // update vertical DoubleSlider after keyDown in canvas - void update_vert_slider_from_canvas(wxKeyEvent& event); + void update_layers_slider_from_canvas(wxKeyEvent& event); #else // Create/Update/Reset double slider on 3dPreview void create_double_slider(); @@ -230,10 +233,8 @@ private: void load_print_as_sla(); #if ENABLE_GCODE_VIEWER - void on_vert_slider_scroll_changed(wxCommandEvent& event); -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER - void on_horz_slider_scroll_changed(wxCommandEvent& event); -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER + void on_layers_slider_scroll_changed(wxCommandEvent& event); + void on_moves_slider_scroll_changed(wxCommandEvent& event); #else void on_sliders_scroll_changed(wxCommandEvent& event); #endif // ENABLE_GCODE_VIEWER diff --git a/src/slic3r/GUI/InstanceCheck.cpp b/src/slic3r/GUI/InstanceCheck.cpp index e408ce1183..2d11862707 100644 --- a/src/slic3r/GUI/InstanceCheck.cpp +++ b/src/slic3r/GUI/InstanceCheck.cpp @@ -1,13 +1,20 @@ #include "GUI_App.hpp" #include "InstanceCheck.hpp" +#include "libslic3r/Utils.hpp" +#include "libslic3r/Config.hpp" + #include "boost/nowide/convert.hpp" #include #include - +#include #include #include +#ifdef _WIN32 +#include +#endif //WIN32 + #if __linux__ #include /* Pull in all of D-Bus headers. */ #endif //__linux__ @@ -20,218 +27,225 @@ namespace instance_check_internal bool should_send; std::string cl_string; }; - static CommandLineAnalysis process_command_line(int argc, char** argv) //d:\3dmodels\Klapka\Klapka.3mf + static CommandLineAnalysis process_command_line(int argc, char** argv) { CommandLineAnalysis ret { false }; if (argc < 2) return ret; - ret.cl_string = argv[0]; - for (size_t i = 1; i < argc; i++) { - std::string token = argv[i]; - if (token == "--single-instance") { + ret.cl_string = escape_string_cstyle(argv[0]); + for (size_t i = 1; i < argc; ++i) { + const std::string token = argv[i]; + if (token == "--single-instance" || token == "--single-instance=1") { ret.should_send = true; } else { - ret.cl_string += " "; - ret.cl_string += token; + ret.cl_string += " : "; + ret.cl_string += escape_string_cstyle(token); } - } + } BOOST_LOG_TRIVIAL(debug) << "single instance: "<< ret.should_send << ". other params: " << ret.cl_string; return ret; } -} //namespace instance_check_internal -#if _WIN32 + + +#ifdef _WIN32 -namespace instance_check_internal -{ static HWND l_prusa_slicer_hwnd; static BOOL CALLBACK EnumWindowsProc(_In_ HWND hwnd, _In_ LPARAM lParam) { //checks for other instances of prusaslicer, if found brings it to front and return false to stop enumeration and quit this instance //search is done by classname(wxWindowNR is wxwidgets thing, so probably not unique) and name in window upper panel //other option would be do a mutex and check for its existence - TCHAR wndText[1000]; - TCHAR className[1000]; + //BOOST_LOG_TRIVIAL(error) << "ewp: version: " << l_version_wstring; + TCHAR wndText[1000]; + TCHAR className[1000]; GetClassName(hwnd, className, 1000); GetWindowText(hwnd, wndText, 1000); std::wstring classNameString(className); std::wstring wndTextString(wndText); if (wndTextString.find(L"PrusaSlicer") != std::wstring::npos && classNameString == L"wxWindowNR") { - l_prusa_slicer_hwnd = hwnd; - ShowWindow(hwnd, SW_SHOWMAXIMIZED); - SetForegroundWindow(hwnd); - return false; + //check if other instances has same instance hash + //if not it is not same version(binary) as this version + HANDLE handle = GetProp(hwnd, L"Instance_Hash_Minor"); + size_t other_instance_hash = PtrToUint(handle); + size_t other_instance_hash_major; + handle = GetProp(hwnd, L"Instance_Hash_Major"); + other_instance_hash_major = PtrToUint(handle); + other_instance_hash_major = other_instance_hash_major << 32; + other_instance_hash += other_instance_hash_major; + size_t my_instance_hash = GUI::wxGetApp().get_instance_hash_int(); + if(my_instance_hash == other_instance_hash) + { + BOOST_LOG_TRIVIAL(debug) << "win enum - found correct instance"; + l_prusa_slicer_hwnd = hwnd; + ShowWindow(hwnd, SW_SHOWMAXIMIZED); + SetForegroundWindow(hwnd); + return false; + } + BOOST_LOG_TRIVIAL(debug) << "win enum - found wrong instance"; } return true; } - static void send_message(const HWND hwnd) + static bool send_message(const std::string& message, const std::string &version) { - LPWSTR command_line_args = GetCommandLine(); - //Create a COPYDATASTRUCT to send the information - //cbData represents the size of the information we want to send. - //lpData represents the information we want to send. - //dwData is an ID defined by us(this is a type of ID different than WM_COPYDATA). - COPYDATASTRUCT data_to_send = { 0 }; - data_to_send.dwData = 1; - data_to_send.cbData = sizeof(TCHAR) * (wcslen(command_line_args) + 1); - data_to_send.lpData = command_line_args; + if (!EnumWindows(EnumWindowsProc, 0)) { + std::wstring wstr = boost::nowide::widen(message); + //LPWSTR command_line_args = wstr.c_str();//GetCommandLine(); + LPWSTR command_line_args = new wchar_t[wstr.size() + 1]; + copy(wstr.begin(), wstr.end(), command_line_args); + command_line_args[wstr.size()] = 0; + //Create a COPYDATASTRUCT to send the information + //cbData represents the size of the information we want to send. + //lpData represents the information we want to send. + //dwData is an ID defined by us(this is a type of ID different than WM_COPYDATA). + COPYDATASTRUCT data_to_send = { 0 }; + data_to_send.dwData = 1; + data_to_send.cbData = sizeof(TCHAR) * (wcslen(command_line_args) + 1); + data_to_send.lpData = command_line_args; - SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&data_to_send); - } -} //namespace instance_check_internal - -bool instance_check(int argc, char** argv, bool app_config_single_instance) -{ - instance_check_internal::CommandLineAnalysis cla = instance_check_internal::process_command_line(argc, argv); - if (cla.should_send || app_config_single_instance) { - // Call EnumWidnows with own callback. cons: Based on text in the name of the window and class name which is generic. - if (!EnumWindows(instance_check_internal::EnumWindowsProc, 0)) { - BOOST_LOG_TRIVIAL(info) << "instance check: Another instance found. This instance will terminate."; - instance_check_internal::send_message(instance_check_internal::l_prusa_slicer_hwnd); - return true; + SendMessage(l_prusa_slicer_hwnd, WM_COPYDATA, 0, (LPARAM)&data_to_send); + return true; } + return false; } - BOOST_LOG_TRIVIAL(info) << "instance check: Another instance not found or single-instance not set."; - return false; -} -#elif defined(__APPLE__) +#else -namespace instance_check_internal -{ - static int get_lock() + static bool get_lock(const std::string& name, const std::string& path) { - struct flock fl; - int fdlock; + std::string dest_dir = path + name; + BOOST_LOG_TRIVIAL(debug) <<"full lock path: "<< dest_dir; + struct flock fl; + int fdlock; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 1; - - if ((fdlock = open("/tmp/prusaslicer.lock", O_WRONLY | O_CREAT, 0666)) == -1) - return 0; + if ((fdlock = open(dest_dir.c_str(), O_WRONLY | O_CREAT, 0666)) == -1) + return true; if (fcntl(fdlock, F_SETLK, &fl) == -1) - return 0; + return true; - return 1; + return false; } -} //namespace instance_check_internal -bool instance_check(int argc, char** argv, bool app_config_single_instance) -{ - instance_check_internal::CommandLineAnalysis cla = instance_check_internal::process_command_line(argc, argv); - if (!instance_check_internal::get_lock() && (cla.should_send || app_config_single_instance)) { - BOOST_LOG_TRIVIAL(info) << "instance check: Another instance found. This instance will terminate."; - send_message_mac(cla.cl_string); - return true; +#endif //WIN32 +#if defined(__APPLE__) + + static bool send_message(const std::string &message_text, const std::string &version) + { + //std::string v(version); + //std::replace(v.begin(), v.end(), '.', '-'); + //if (!instance_check_internal::get_lock(v)) + { + send_message_mac(message_text, version); + return true; + } + return false; } - BOOST_LOG_TRIVIAL(info) << "instance check: Another instance not found or single-instance not set."; - return false; -} #elif defined(__linux__) -namespace instance_check_internal -{ - static int get_lock() + static bool send_message(const std::string &message_text, const std::string &version) { - struct flock fl; - int fdlock; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 1; - - if ((fdlock = open("/tmp/prusaslicer.lock", O_WRONLY | O_CREAT, 0666)) == -1) - return 0; - - if (fcntl(fdlock, F_SETLK, &fl) == -1) - return 0; - - return 1; - } - - static void send_message(std::string message_text) - { - DBusMessage* msg; - DBusMessageIter args; - DBusConnection* conn; - DBusError err; - dbus_uint32_t serial = 0; - const char* sigval = message_text.c_str(); - std::string interface_name = "com.prusa3d.prusaslicer.InstanceCheck"; - std::string method_name = "AnotherInstace"; - std::string object_name = "/com/prusa3d/prusaslicer/InstanceCheck"; + /*std::string v(version); + std::replace(v.begin(), v.end(), '.', '-'); + if (!instance_check_internal::get_lock(v))*/ + /*auto checker = new wxSingleInstanceChecker; + if ( !checker->IsAnotherRunning() ) */ + { + DBusMessage* msg; + DBusMessageIter args; + DBusConnection* conn; + DBusError err; + dbus_uint32_t serial = 0; + const char* sigval = message_text.c_str(); + //std::string interface_name = "com.prusa3d.prusaslicer.InstanceCheck"; + std::string interface_name = "com.prusa3d.prusaslicer.InstanceCheck.Object" + version; + std::string method_name = "AnotherInstace"; + //std::string object_name = "/com/prusa3d/prusaslicer/InstanceCheck"; + std::string object_name = "/com/prusa3d/prusaslicer/InstanceCheck/Object" + version; - // initialise the error value - dbus_error_init(&err); + // initialise the error value + dbus_error_init(&err); - // connect to bus, and check for errors (use SESSION bus everywhere!) - conn = dbus_bus_get(DBUS_BUS_SESSION, &err); - if (dbus_error_is_set(&err)) { - BOOST_LOG_TRIVIAL(error) << "DBus Connection Error. Message to another instance wont be send."; - BOOST_LOG_TRIVIAL(error) << "DBus Connection Error: "<< err.message; - dbus_error_free(&err); - return; - } - if (NULL == conn) { - BOOST_LOG_TRIVIAL(error) << "DBus Connection is NULL. Message to another instance wont be send."; - return; - } + // connect to bus, and check for errors (use SESSION bus everywhere!) + conn = dbus_bus_get(DBUS_BUS_SESSION, &err); + if (dbus_error_is_set(&err)) { + BOOST_LOG_TRIVIAL(error) << "DBus Connection Error. Message to another instance wont be send."; + BOOST_LOG_TRIVIAL(error) << "DBus Connection Error: " << err.message; + dbus_error_free(&err); + return true; + } + if (NULL == conn) { + BOOST_LOG_TRIVIAL(error) << "DBus Connection is NULL. Message to another instance wont be send."; + return true; + } - //some sources do request interface ownership before constructing msg but i think its wrong. + //some sources do request interface ownership before constructing msg but i think its wrong. - //create new method call message - msg = dbus_message_new_method_call(interface_name.c_str(), object_name.c_str(), interface_name.c_str(), method_name.c_str()); - if (NULL == msg) { - BOOST_LOG_TRIVIAL(error) << "DBus Message is NULL. Message to another instance wont be send."; - dbus_connection_unref(conn); - return; - } - //the AnotherInstace method is not sending reply. - dbus_message_set_no_reply(msg, TRUE); + //create new method call message + msg = dbus_message_new_method_call(interface_name.c_str(), object_name.c_str(), interface_name.c_str(), method_name.c_str()); + if (NULL == msg) { + BOOST_LOG_TRIVIAL(error) << "DBus Message is NULL. Message to another instance wont be send."; + dbus_connection_unref(conn); + return true; + } + //the AnotherInstace method is not sending reply. + dbus_message_set_no_reply(msg, TRUE); - //append arguments to message - if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &sigval, DBUS_TYPE_INVALID)) { - BOOST_LOG_TRIVIAL(error) << "Ran out of memory while constructing args for DBus message. Message to another instance wont be send."; - dbus_message_unref(msg); - dbus_connection_unref(conn); - return; + //append arguments to message + if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &sigval, DBUS_TYPE_INVALID)) { + BOOST_LOG_TRIVIAL(error) << "Ran out of memory while constructing args for DBus message. Message to another instance wont be send."; + dbus_message_unref(msg); + dbus_connection_unref(conn); + return true; + } + + // send the message and flush the connection + if (!dbus_connection_send(conn, msg, &serial)) { + BOOST_LOG_TRIVIAL(error) << "Ran out of memory while sending DBus message."; + dbus_message_unref(msg); + dbus_connection_unref(conn); + return true; + } + dbus_connection_flush(conn); + + BOOST_LOG_TRIVIAL(trace) << "DBus message sent."; + + // free the message and close the connection + dbus_message_unref(msg); + dbus_connection_unref(conn); + return true; } - - // send the message and flush the connection - if (!dbus_connection_send(conn, msg, &serial)) { - BOOST_LOG_TRIVIAL(error) << "Ran out of memory while sending DBus message."; - dbus_message_unref(msg); - dbus_connection_unref(conn); - return; - } - dbus_connection_flush(conn); - - BOOST_LOG_TRIVIAL(trace) << "DBus message sent."; - - // free the message and close the connection - dbus_message_unref(msg); - dbus_connection_unref(conn); + return false; } + +#endif //__APPLE__/__linux__ } //namespace instance_check_internal bool instance_check(int argc, char** argv, bool app_config_single_instance) -{ +{ + std::size_t hashed_path = std::hash{}(boost::filesystem::system_complete(argv[0]).string()); + std::string lock_name = std::to_string(hashed_path); + GUI::wxGetApp().set_instance_hash(hashed_path); + BOOST_LOG_TRIVIAL(debug) <<"full path: "<< lock_name; instance_check_internal::CommandLineAnalysis cla = instance_check_internal::process_command_line(argc, argv); - if (!instance_check_internal::get_lock() && (cla.should_send || app_config_single_instance)) { +#ifdef _WIN32 + GUI::wxGetApp().init_single_instance_checker(lock_name + ".lock", data_dir() + "/cache/"); + if ((cla.should_send || app_config_single_instance) && GUI::wxGetApp().single_instance_checker()->IsAnotherRunning()) { +#else // mac & linx + if (instance_check_internal::get_lock(lock_name + ".lock", data_dir() + "/cache/") && (cla.should_send || app_config_single_instance)) { +#endif + instance_check_internal::send_message(cla.cl_string, lock_name); BOOST_LOG_TRIVIAL(info) << "instance check: Another instance found. This instance will terminate."; - instance_check_internal::send_message(cla.cl_string); return true; } BOOST_LOG_TRIVIAL(info) << "instance check: Another instance not found or single-instance not set."; return false; } -#endif //_WIN32/__APPLE__/__linux__ - - namespace GUI { @@ -248,23 +262,24 @@ void OtherInstanceMessageHandler::init(wxEvtHandler* callback_evt_handler) m_initialized = true; m_callback_evt_handler = callback_evt_handler; -#if _WIN32 - //create_listener_window(); -#endif //_WIN32 - #if defined(__APPLE__) - this->register_for_messages(); + this->register_for_messages(wxGetApp().get_instance_hash_string()); #endif //__APPLE__ #ifdef BACKGROUND_MESSAGE_LISTENER m_thread = boost::thread((boost::bind(&OtherInstanceMessageHandler::listen, this))); #endif //BACKGROUND_MESSAGE_LISTENER } -void OtherInstanceMessageHandler::shutdown() +void OtherInstanceMessageHandler::shutdown(MainFrame* main_frame) { BOOST_LOG_TRIVIAL(debug) << "message handler shutdown()."; assert(m_initialized); if (m_initialized) { +#ifdef _WIN32 + HWND hwnd = main_frame->GetHandle(); + RemoveProp(hwnd, L"Instance_Hash_Minor"); + RemoveProp(hwnd, L"Instance_Hash_Major"); +#endif //_WIN32 #if __APPLE__ //delete macos implementation this->unregister_for_messages(); @@ -287,12 +302,46 @@ void OtherInstanceMessageHandler::shutdown() } } +#ifdef _WIN32 +void OtherInstanceMessageHandler::init_windows_properties(MainFrame* main_frame, size_t instance_hash) +{ + size_t minor_hash = instance_hash & 0xFFFFFFFF; + size_t major_hash = (instance_hash & 0xFFFFFFFF00000000) >> 32; + HWND hwnd = main_frame->GetHandle(); + HANDLE handle_minor = UIntToPtr(minor_hash); + HANDLE handle_major = UIntToPtr(major_hash); + SetProp(hwnd, L"Instance_Hash_Minor", handle_minor); + SetProp(hwnd, L"Instance_Hash_Major", handle_major); + //BOOST_LOG_TRIVIAL(debug) << "window properties initialized " << instance_hash << " (" << minor_hash << " & "<< major_hash; +} + +#if 0 + +void OtherInstanceMessageHandler::print_window_info(HWND hwnd) +{ + std::wstring instance_hash = boost::nowide::widen(wxGetApp().get_instance_hash_string()); + TCHAR wndText[1000]; + TCHAR className[1000]; + GetClassName(hwnd, className, 1000); + GetWindowText(hwnd, wndText, 1000); + std::wstring classNameString(className); + std::wstring wndTextString(wndText); + HANDLE handle = GetProp(hwnd, L"Instance_Hash_Minor"); + size_t result = PtrToUint(handle); + handle = GetProp(hwnd, L"Instance_Hash_Major"); + size_t r2 = PtrToUint(handle); + r2 = (r2 << 32); + result += r2; + BOOST_LOG_TRIVIAL(info) << "window info: " << result; +} +#endif //0 +#endif //WIN32 namespace MessageHandlerInternal { // returns ::path to possible model or empty ::path if input string is not existing path - static boost::filesystem::path get_path(const std::string possible_path) + static boost::filesystem::path get_path(std::string possible_path) { - BOOST_LOG_TRIVIAL(debug) << "message part: " << possible_path; + BOOST_LOG_TRIVIAL(debug) << "message part:" << possible_path; if (possible_path.empty() || possible_path.size() < 3) { BOOST_LOG_TRIVIAL(debug) << "empty"; @@ -312,9 +361,9 @@ namespace MessageHandlerInternal } } //namespace MessageHandlerInternal -void OtherInstanceMessageHandler::handle_message(const std::string message) { +void OtherInstanceMessageHandler::handle_message(const std::string& message) { std::vector paths; - auto next_space = message.find(' '); + auto next_space = message.find(" : "); size_t last_space = 0; int counter = 0; @@ -323,17 +372,17 @@ void OtherInstanceMessageHandler::handle_message(const std::string message) { while (next_space != std::string::npos) { if (counter != 0) { - const std::string possible_path = message.substr(last_space, next_space - last_space); - boost::filesystem::path p = MessageHandlerInternal::get_path(possible_path); + std::string possible_path = message.substr(last_space, next_space - last_space); + boost::filesystem::path p = MessageHandlerInternal::get_path(std::move(possible_path)); if(!p.string().empty()) paths.emplace_back(p); } - last_space = next_space; - next_space = message.find(' ', last_space + 1); + last_space = next_space + 3; + next_space = message.find(" : ", last_space); counter++; } if (counter != 0 ) { - boost::filesystem::path p = MessageHandlerInternal::get_path(message.substr(last_space + 1)); + boost::filesystem::path p = MessageHandlerInternal::get_path(message.substr(last_space)); if (!p.string().empty()) paths.emplace_back(p); } @@ -401,13 +450,12 @@ namespace MessageHandlerDBusInternal { const char* interface_name = dbus_message_get_interface(message); const char* member_name = dbus_message_get_member(message); - + std::string our_interface = "com.prusa3d.prusaslicer.InstanceCheck.Object" + wxGetApp().get_instance_hash_string(); BOOST_LOG_TRIVIAL(trace) << "DBus message received: interface: " << interface_name << ", member: " << member_name; - if (0 == strcmp("org.freedesktop.DBus.Introspectable", interface_name) && 0 == strcmp("Introspect", member_name)) { respond_to_introspect(connection, message); return DBUS_HANDLER_RESULT_HANDLED; - } else if (0 == strcmp("com.prusa3d.prusaslicer.InstanceCheck", interface_name) && 0 == strcmp("AnotherInstace", member_name)) { + } else if (0 == strcmp(our_interface.c_str(), interface_name) && 0 == strcmp("AnotherInstace", member_name)) { handle_method_another_instance(connection, message); return DBUS_HANDLER_RESULT_HANDLED; } @@ -421,9 +469,11 @@ void OtherInstanceMessageHandler::listen() DBusError err; int name_req_val; DBusObjectPathVTable vtable; - std::string interface_name = "com.prusa3d.prusaslicer.InstanceCheck"; - std::string object_name = "/com/prusa3d/prusaslicer/InstanceCheck"; + std::string instance_hash = wxGetApp().get_instance_hash_string(); + std::string interface_name = "com.prusa3d.prusaslicer.InstanceCheck.Object" + instance_hash; + std::string object_name = "/com/prusa3d/prusaslicer/InstanceCheck/Object" + instance_hash; + //BOOST_LOG_TRIVIAL(debug) << "init dbus listen " << interface_name << " " << object_name; dbus_error_init(&err); // connect to the bus and check for errors (use SESSION bus everywhere!) @@ -469,7 +519,7 @@ void OtherInstanceMessageHandler::listen() return; } - BOOST_LOG_TRIVIAL(trace) << "Dbus object registered. Starting listening for messages."; + BOOST_LOG_TRIVIAL(trace) << "Dbus object "<< object_name <<" registered. Starting listening for messages."; for (;;) { // Wait for 1 second diff --git a/src/slic3r/GUI/InstanceCheck.hpp b/src/slic3r/GUI/InstanceCheck.hpp index 4207296a05..781cb139be 100644 --- a/src/slic3r/GUI/InstanceCheck.hpp +++ b/src/slic3r/GUI/InstanceCheck.hpp @@ -11,10 +11,11 @@ #include +#if __linux__ #include #include #include - +#endif // __linux__ namespace Slic3r { @@ -26,11 +27,13 @@ bool instance_check(int argc, char** argv, bool app_config_single_instance); #if __APPLE__ // apple implementation of inner functions of instance_check // in InstanceCheckMac.mm -void send_message_mac(const std::string msg); +void send_message_mac(const std::string& msg, const std::string& version); #endif //__APPLE__ namespace GUI { +class MainFrame; + #if __linux__ #define BACKGROUND_MESSAGE_LISTENER #endif // __linux__ @@ -52,7 +55,7 @@ public: // inits listening, on each platform different. On linux starts background thread void init(wxEvtHandler* callback_evt_handler); // stops listening, on linux stops the background thread - void shutdown(); + void shutdown(MainFrame* main_frame); //finds paths to models in message(= command line arguments, first should be prusaSlicer executable) //and sends them to plater via LoadFromOtherInstanceEvent @@ -60,7 +63,10 @@ public: // win32 - anybody who has hwnd can send message. // mac - anybody who posts notification with name:@"OtherPrusaSlicerTerminating" // linux - instrospectable on dbus - void handle_message(const std::string message); + void handle_message(const std::string& message); +#ifdef _WIN32 + static void init_windows_properties(MainFrame* main_frame, size_t instance_hash); +#endif //WIN32 private: bool m_initialized { false }; wxEvtHandler* m_callback_evt_handler { nullptr }; @@ -79,7 +85,7 @@ private: #if __APPLE__ //implemented at InstanceCheckMac.mm - void register_for_messages(); + void register_for_messages(const std::string &version_hash); void unregister_for_messages(); // Opaque pointer to RemovableDriveManagerMM void* m_impl_osx; diff --git a/src/slic3r/GUI/InstanceCheckMac.h b/src/slic3r/GUI/InstanceCheckMac.h index 9931bb6796..ed9d17418f 100644 --- a/src/slic3r/GUI/InstanceCheckMac.h +++ b/src/slic3r/GUI/InstanceCheckMac.h @@ -3,6 +3,6 @@ @interface OtherInstanceMessageHandlerMac : NSObject -(instancetype) init; --(void) add_observer; +-(void) add_observer:(NSString *)version; -(void) message_update:(NSNotification *)note; @end diff --git a/src/slic3r/GUI/InstanceCheckMac.mm b/src/slic3r/GUI/InstanceCheckMac.mm index cbc833c79c..67bf64980b 100644 --- a/src/slic3r/GUI/InstanceCheckMac.mm +++ b/src/slic3r/GUI/InstanceCheckMac.mm @@ -9,10 +9,12 @@ self = [super init]; return self; } --(void)add_observer +-(void)add_observer:(NSString *)version_hash { - NSLog(@"adding observer"); - [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(message_update:) name:@"OtherPrusaSlicerInstanceMessage" object:nil suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately]; + //NSLog(@"adding observer"); + //NSString *nsver = @"OtherPrusaSlicerInstanceMessage" + version_hash; + NSString *nsver = [NSString stringWithFormat: @"%@%@", @"OtherPrusaSlicerInstanceMessage", version_hash]; + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(message_update:) name:nsver object:nil suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately]; } -(void)message_update:(NSNotification *)msg @@ -36,19 +38,22 @@ namespace Slic3r { -void send_message_mac(const std::string msg) +void send_message_mac(const std::string &msg, const std::string &version) { NSString *nsmsg = [NSString stringWithCString:msg.c_str() encoding:[NSString defaultCStringEncoding]]; - //NSLog(@"sending msg %@", nsmsg); - [[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"OtherPrusaSlicerInstanceMessage" object:nil userInfo:[NSDictionary dictionaryWithObject:nsmsg forKey:@"data"] deliverImmediately:YES]; + //NSString *nsver = @"OtherPrusaSlicerInstanceMessage" + [NSString stringWithCString:version.c_str() encoding:[NSString defaultCStringEncoding]]; + NSString *nsver = [NSString stringWithCString:version.c_str() encoding:[NSString defaultCStringEncoding]]; + NSString *notifname = [NSString stringWithFormat: @"%@%@", @"OtherPrusaSlicerInstanceMessage", nsver]; + [[NSDistributedNotificationCenter defaultCenter] postNotificationName:notifname object:nil userInfo:[NSDictionary dictionaryWithObject:nsmsg forKey:@"data"] deliverImmediately:YES]; } namespace GUI { -void OtherInstanceMessageHandler::register_for_messages() +void OtherInstanceMessageHandler::register_for_messages(const std::string &version_hash) { m_impl_osx = [[OtherInstanceMessageHandlerMac alloc] init]; if(m_impl_osx) { - [m_impl_osx add_observer]; + NSString *nsver = [NSString stringWithCString:version_hash.c_str() encoding:[NSString defaultCStringEncoding]]; + [m_impl_osx add_observer:nsver]; } } @@ -59,7 +64,7 @@ void OtherInstanceMessageHandler::unregister_for_messages() [m_impl_osx release]; m_impl_osx = nullptr; } else { - NSLog(@"unreegister not required"); + NSLog(@"warning: unregister instance InstanceCheck notifications not required"); } } }//namespace GUI diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 73b78d3df2..8ba53ee640 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -242,7 +242,7 @@ void MainFrame::shutdown() // Stop the background thread of the removable drive manager, so that no new updates will be sent to the Plater. wxGetApp().removable_drive_manager()->shutdown(); //stop listening for messages from other instances - wxGetApp().other_instance_message_handler()->shutdown(); + wxGetApp().other_instance_message_handler()->shutdown(this); // Save the slic3r.ini.Usually the ini file is saved from "on idle" callback, // but in rare cases it may not have been called yet. wxGetApp().app_config->save(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index be5b5b3ab4..cbd040b330 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1642,9 +1642,7 @@ struct Plater::priv bool init_view_toolbar(); #if ENABLE_GCODE_VIEWER void update_preview_bottom_toolbar(); -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER - void update_preview_horz_slider(); -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER + void update_preview_moves_slider(); #endif // ENABLE_GCODE_VIEWER void reset_all_gizmos(); @@ -1975,8 +1973,13 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) config->option("bed_custom_model")->value); }); preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); }); +#if ENABLE_GCODE_VIEWER + preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, [this](wxKeyEvent& evt) { preview->move_layers_slider(evt); }); + preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_EDIT_COLOR_CHANGE, [this](wxKeyEvent& evt) { preview->edit_layers_slider(evt); }); +#else preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, [this](wxKeyEvent& evt) { preview->move_double_slider(evt); }); preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_EDIT_COLOR_CHANGE, [this](wxKeyEvent& evt) { preview->edit_double_slider(evt); }); +#endif // ENABLE_GCODE_VIEWER q->Bind(EVT_SLICING_COMPLETED, &priv::on_slicing_completed, this); q->Bind(EVT_PROCESS_COMPLETED, &priv::on_process_completed, this); @@ -2034,16 +2037,20 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) this->q->Bind(EVT_INSTANCE_GO_TO_FRONT, [this](InstanceGoToFrontEvent &) { BOOST_LOG_TRIVIAL(debug) << "prusaslicer window going forward"; //this code maximize app window on Fedora - wxGetApp().mainframe->Iconize(false); - if (wxGetApp().mainframe->IsMaximized()) - wxGetApp().mainframe->Maximize(true); - else - wxGetApp().mainframe->Maximize(false); - //this code (without code above) maximize window on Ubuntu - wxGetApp().mainframe->Restore(); - wxGetApp().GetTopWindow()->SetFocus(); // focus on my window - wxGetApp().GetTopWindow()->Raise(); // bring window to front - wxGetApp().GetTopWindow()->Show(true); // show the window + { + wxGetApp().mainframe->Iconize(false); + if (wxGetApp().mainframe->IsMaximized()) + wxGetApp().mainframe->Maximize(true); + else + wxGetApp().mainframe->Maximize(false); + } + //this code maximize window on Ubuntu + { + wxGetApp().mainframe->Restore(); + wxGetApp().GetTopWindow()->SetFocus(); // focus on my window + wxGetApp().GetTopWindow()->Raise(); // bring window to front + wxGetApp().GetTopWindow()->Show(true); // show the window + } }); wxGetApp().other_instance_message_handler()->init(this->q); @@ -3879,12 +3886,10 @@ void Plater::priv::update_preview_bottom_toolbar() preview->update_bottom_toolbar(); } -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER -void Plater::priv::update_preview_horz_slider() +void Plater::priv::update_preview_moves_slider() { - preview->update_horz_slider(); + preview->update_moves_slider(); } -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER #endif // ENABLE_GCODE_VIEWER bool Plater::priv::can_set_instance_to_object() const @@ -5482,12 +5487,10 @@ void Plater::update_preview_bottom_toolbar() p->update_preview_bottom_toolbar(); } -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER -void Plater::update_preview_horz_slider() +void Plater::update_preview_moves_slider() { - p->update_preview_horz_slider(); + p->update_preview_moves_slider(); } -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER #endif // ENABLE_GCODE_VIEWER const Mouse3DController& Plater::get_mouse3d_controller() const diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 82c8bbe076..21eba8ad13 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -320,9 +320,7 @@ public: #if ENABLE_GCODE_VIEWER void update_preview_bottom_toolbar(); -#if ENABLE_GCODE_USE_WXWIDGETS_SLIDER - void update_preview_horz_slider(); -#endif // ENABLE_GCODE_USE_WXWIDGETS_SLIDER + void update_preview_moves_slider(); #endif // ENABLE_GCODE_VIEWER const Mouse3DController& get_mouse3d_controller() const; diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 9e462d4bf1..25609b1660 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -102,7 +102,11 @@ void PreferencesDialog::build() def.label = L("Single Instance"); def.type = coBool; - def.tooltip = L("If this is enabled, when staring PrusaSlicer and another instance is running, that instance will be reactivated instead."); +#if __APPLE__ + def.tooltip = L("On OSX there is always only one instance of app running by default. However it is allowed to run multiple instances of same app from the command line. In such case this settings will allow only one instance."); +#else + def.tooltip = L("If this is enabled, when staring PrusaSlicer and another instance of same PrusaSlicer is running, that instance will be reactivated instead."); +#endif def.set_default_value(new ConfigOptionBool{ app_config->has("single_instance") ? app_config->get("single_instance") == "1" : false }); option = Option(def, "single_instance"); m_optgroup_general->append_single_option_line(option);