diff --git a/resources/images/collapse.svg b/resources/images/collapse.svg new file mode 100644 index 0000000000..eb4c8e47cf --- /dev/null +++ b/resources/images/collapse.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 25a142b106..801bc09b4c 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1717,18 +1717,26 @@ void GLCanvas3D::update_volumes_colors_by_extruder() m_volumes.update_colors_by_extruder(m_config); } -float GLCanvas3D::get_collapse_toolbar_width() +bool GLCanvas3D::is_collapse_toolbar_on_left() const { - GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); - - return collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0; + auto state = wxGetApp().plater()->get_sidebar_docking_state(); + return state == Sidebar::Left; } -float GLCanvas3D::get_collapse_toolbar_height() +float GLCanvas3D::get_collapse_toolbar_width() const { GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); + const auto state = wxGetApp().plater()->get_sidebar_docking_state(); - return collapse_toolbar.is_enabled() ? collapse_toolbar.get_height() : 0; + return state != Sidebar::None ? collapse_toolbar.get_width() : 0; +} + +float GLCanvas3D::get_collapse_toolbar_height() const +{ + GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); + const auto state = wxGetApp().plater()->get_sidebar_docking_state(); + + return state != Sidebar::None ? collapse_toolbar.get_height() : 0; } bool GLCanvas3D::make_current_for_postinit() { @@ -4844,11 +4852,6 @@ void GLCanvas3D::update_ui_from_settings() _refresh_if_shown_on_screen(); } #endif // ENABLE_RETINA_GL - -#ifdef SUPPORT_COLLAPSE_BUTTON - if (wxGetApp().is_editor()) - wxGetApp().plater()->enable_collapse_toolbar(wxGetApp().app_config->get("show_collapse_button") == "1"); -#endif } // BBS: add partplate logic @@ -7156,6 +7159,9 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale() collapse_toolbar.set_icons_size(size); #endif // ENABLE_RETINA_GL + // Update collapse toolbar + collapse_toolbar.set_enabled(wxGetApp().plater()->get_sidebar_docking_state() != Sidebar::None); + //BBS: GUI refactor: GLToolbar #if BBS_TOOLBAR_ON_TOP float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : GLToolbar::Default_Icons_Size; @@ -7433,6 +7439,23 @@ void GLCanvas3D::_render_gizmos_overlay() } } +float GLCanvas3D::get_main_toolbar_offset() const +{ + const float cnv_width = get_canvas_size().get_width(); + const float collapse_toolbar_width = get_collapse_toolbar_width(); + const float gizmo_width = m_gizmos.get_scaled_total_width(); + const float assemble_width = m_assemble_view_toolbar.get_width(); + const float separator_width = m_separator_toolbar.get_width(); + const float toolbar_total_width = m_main_toolbar.get_width() + separator_width + gizmo_width + assemble_width + collapse_toolbar_width; + + if (cnv_width < toolbar_total_width) { + return is_collapse_toolbar_on_left() ? collapse_toolbar_width : 0; + } else { + const float offset = (cnv_width - toolbar_total_width) / 2; + return is_collapse_toolbar_on_left() ? offset + collapse_toolbar_width : offset; + } +} + //BBS: GUI refactor: GLToolbar adjust //when rendering, {0, 0} is at the center, left-up is -0.5, 0.5, right-up is 0.5, -0.5 void GLCanvas3D::_render_main_toolbar() @@ -7443,12 +7466,7 @@ void GLCanvas3D::_render_main_toolbar() const Size cnv_size = get_canvas_size(); const float top = 0.5f * (float)cnv_size.get_height(); - GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); - const float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; - const float gizmo_width = m_gizmos.get_scaled_total_width(); - const float assemble_width = m_assemble_view_toolbar.get_width(); - const float separator_width = m_separator_toolbar.get_width(); - const float left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + separator_width + gizmo_width + assemble_width - collapse_toolbar_width)); + const float left = -0.5f * cnv_size.get_width() + get_main_toolbar_offset(); m_main_toolbar.set_position(top, left); m_main_toolbar.render(*this); if (m_toolbar_highlighter.m_render_arrow) @@ -7579,7 +7597,8 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); - imgui.set_next_window_pos(canvas_w * 0, canvas_h * 0, ImGuiCond_Always, 0, 0); + const float y_offset = is_collapse_toolbar_on_left() ? (get_collapse_toolbar_height() + 5) : 0; + imgui.set_next_window_pos(canvas_w * 0, canvas_h * 0 + y_offset, ImGuiCond_Always, 0, 0); imgui.set_next_window_size(window_width, window_height, ImGuiCond_Always); if (show_scroll) @@ -7781,13 +7800,10 @@ void GLCanvas3D::_render_assemble_view_toolbar() const return; const Size cnv_size = get_canvas_size(); - GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); - const float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; const float gizmo_width = m_gizmos.get_scaled_total_width(); - const float assemble_width = m_assemble_view_toolbar.get_width(); const float separator_width = m_separator_toolbar.get_width(); const float top = 0.5f * (float)cnv_size.get_height(); - const float main_toolbar_left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + gizmo_width + assemble_width + separator_width - collapse_toolbar_width)); + const float main_toolbar_left = -0.5f * cnv_size.get_width() + get_main_toolbar_offset(); const float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width + separator_width); m_assemble_view_toolbar.set_position(top, left); @@ -7809,7 +7825,7 @@ void GLCanvas3D::_render_return_toolbar() const auto canvas_h = float(cnv_size.get_height()); float window_width = real_size.x + button_icon_size.x + imgui.scaled(2.0f); float window_height = button_icon_size.y + imgui.scaled(2.0f); - float window_pos_x = 30.0f; + float window_pos_x = 30.0f + (is_collapse_toolbar_on_left() ? (get_collapse_toolbar_width() + 5.f) : 0); float window_pos_y = 14.0f; imgui.set_next_window_pos(window_pos_x, window_pos_y, ImGuiCond_Always, 0, 0); @@ -7855,13 +7871,10 @@ void GLCanvas3D::_render_separator_toolbar_right() const return; const Size cnv_size = get_canvas_size(); - GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); - const float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; const float gizmo_width = m_gizmos.get_scaled_total_width(); - const float assemble_width = m_assemble_view_toolbar.get_width(); const float separator_width = m_separator_toolbar.get_width(); const float top = 0.5f * (float)cnv_size.get_height(); - const float main_toolbar_left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + gizmo_width + assemble_width + separator_width - collapse_toolbar_width)); + const float main_toolbar_left = -0.5f * cnv_size.get_width() + get_main_toolbar_offset(); const float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width + separator_width / 2); m_separator_toolbar.set_position(top, left); @@ -7874,13 +7887,8 @@ void GLCanvas3D::_render_separator_toolbar_left() const return; const Size cnv_size = get_canvas_size(); - GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); - const float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; - const float gizmo_width = m_gizmos.get_scaled_total_width(); - const float assemble_width = m_assemble_view_toolbar.get_width(); - const float separator_width = m_separator_toolbar.get_width(); const float top = 0.5f * (float)cnv_size.get_height(); - const float main_toolbar_left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + gizmo_width + assemble_width + separator_width - collapse_toolbar_width)); + const float main_toolbar_left = -0.5f * cnv_size.get_width() + get_main_toolbar_offset(); const float left = main_toolbar_left + (m_main_toolbar.get_width()); m_separator_toolbar.set_position(top, left); @@ -7889,12 +7897,18 @@ void GLCanvas3D::_render_separator_toolbar_left() const void GLCanvas3D::_render_collapse_toolbar() const { - GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); + auto& plater = *wxGetApp().plater(); + const auto sidebar_docking_dir = plater.get_sidebar_docking_state(); + if (sidebar_docking_dir == Sidebar::None) { + return; + } + + GLToolbar& collapse_toolbar = plater.get_collapse_toolbar(); const Size cnv_size = get_canvas_size(); const float top = 0.5f * (float)cnv_size.get_height(); - //const float left = (0.5f * (float)cnv_size.get_width() - (float)collapse_toolbar.get_width() - band); - const float left = -0.5f * (float)cnv_size.get_width(); + const float left = sidebar_docking_dir == Sidebar::Right ? 0.5f * (float) cnv_size.get_width() - (float) collapse_toolbar.get_width() : + -0.5f * (float) cnv_size.get_width(); collapse_toolbar.set_position(top, left); collapse_toolbar.render(*this); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 901ff007cd..84cb030b8e 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -858,15 +858,17 @@ public: //BBS: add part plate related logic void select_plate(); //BBS: GUI refactor: GLToolbar&&gizmo - float get_main_toolbar_height() { return m_main_toolbar.get_height();} - float get_main_toolbar_width() { return m_main_toolbar.get_width();} - float get_assemble_view_toolbar_width() { return m_assemble_view_toolbar.get_width(); } - float get_assemble_view_toolbar_height() { return m_assemble_view_toolbar.get_height(); } - float get_assembly_paint_toolbar_width() { return m_paint_toolbar_width; } - float get_separator_toolbar_width() { return m_separator_toolbar.get_width(); } - float get_separator_toolbar_height() { return m_separator_toolbar.get_height(); } - float get_collapse_toolbar_width(); - float get_collapse_toolbar_height(); + float get_main_toolbar_offset() const; + float get_main_toolbar_height() const { return m_main_toolbar.get_height(); } + float get_main_toolbar_width() const { return m_main_toolbar.get_width(); } + float get_assemble_view_toolbar_width() const { return m_assemble_view_toolbar.get_width(); } + float get_assemble_view_toolbar_height() const { return m_assemble_view_toolbar.get_height(); } + float get_assembly_paint_toolbar_width() const { return m_paint_toolbar_width; } + float get_separator_toolbar_width() const { return m_separator_toolbar.get_width(); } + float get_separator_toolbar_height() const { return m_separator_toolbar.get_height(); } + bool is_collapse_toolbar_on_left() const; + float get_collapse_toolbar_width() const; + float get_collapse_toolbar_height() const; void update_volumes_colors_by_extruder(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index d6e9093509..3b29a986d5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -81,20 +81,22 @@ GLGizmosManager::EType GLGizmosManager::get_gizmo_from_mouse(const Vec2d &mouse_ if (! m_enabled) return Undefined; - float cnv_h = (float) m_parent.get_canvas_size().get_height(); - float height = get_scaled_total_height(); float icons_size = m_layout.scaled_icons_size(); float border = m_layout.scaled_border(); //BBS: GUI refactor: GLToolbar&&Gizmo adjust - float cnv_w = (float)m_parent.get_canvas_size().get_width(); - float width = get_scaled_total_width(); //float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();; - const float separator_width = m_parent.get_separator_toolbar_width(); - float top_x = std::max(0.0f, 0.5f * (cnv_w - (width + separator_width + m_parent.get_main_toolbar_width() - m_parent.get_collapse_toolbar_width() + m_parent.get_assemble_view_toolbar_width()))); - top_x += m_parent.get_main_toolbar_width() + separator_width / 2 + border; - if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) + float top_x; + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + const float cnv_w = (float)m_parent.get_canvas_size().get_width(); + top_x = 0.5f * cnv_w + 0.5f * (m_parent.get_assembly_paint_toolbar_width()); + } else { + const float separator_width = m_parent.get_separator_toolbar_width(); + + top_x = m_parent.get_main_toolbar_offset(); + top_x += m_parent.get_main_toolbar_width() + separator_width / 2 + border; + } float top_y = 0; float stride_x = m_layout.scaled_stride_x(); @@ -1078,13 +1080,11 @@ void GLGizmosManager::do_render_overlay() const else { //BBS: GUI refactor: GLToolbar&&Gizmo adjust float main_toolbar_width = (float)m_parent.get_main_toolbar_width(); - float assemble_view_width = (float)m_parent.get_assemble_view_toolbar_width(); - float collapse_width = (float)m_parent.get_collapse_toolbar_width(); float separator_width = (float)m_parent.get_separator_toolbar_width(); //float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale(); //float zoomed_top_x = 0.5f *(cnv_w + main_toolbar_width - 2 * space_width - width) * inv_zoom; - float main_toolbar_left = std::max(-0.5f * cnv_w, -0.5f * (main_toolbar_width + get_scaled_total_width() + assemble_view_width + separator_width - collapse_width)); + float main_toolbar_left = -0.5f * cnv_w + m_parent.get_main_toolbar_offset(); //float zoomed_top_x = 0.5f *(main_toolbar_width + collapse_width - width - assemble_view_width) * inv_zoom; top_x = main_toolbar_left + main_toolbar_width + separator_width / 2; top_x = top_x * inv_cnv_w * 2; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 8223ca0823..74aa65ae32 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -762,7 +762,7 @@ void MainFrame::update_layout() //BBS: add bed exclude area m_plater->set_bed_shape({ { 0.0, 0.0 }, { 200.0, 0.0 }, { 200.0, 200.0 }, { 0.0, 200.0 } }, {}, 0.0, {}, {}, true); m_plater->get_collapse_toolbar().set_enabled(false); - m_plater->collapse_sidebar(true); + m_plater->enable_sidebar(false); m_plater->Show(); break; } @@ -2523,9 +2523,18 @@ void MainFrame::init_menubar_as_editor() wxGetApp().toggle_show_gcode_window(); m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT)); }, - this, [this]() { return m_plater->is_preview_shown(); }, + this, [this]() { return m_tabpanel->GetSelection() == tpPreview; }, [this]() { return wxGetApp().show_gcode_window(); }, this); + append_menu_item( + viewMenu, wxID_ANY, _L("Reset Window Layout"), _L("Reset to default window layout"), + [this](wxCommandEvent&) { m_plater->reset_window_layout(); }, "", this, + [this]() { + return (m_tabpanel->GetSelection() == TabPosition::tp3DEditor || m_tabpanel->GetSelection() == TabPosition::tpPreview) && + m_plater->is_sidebar_enabled(); + }, + this); + viewMenu->AppendSeparator(); append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Labels") + "\t" + ctrl + "E", _L("Show object labels in 3D scene"), [this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT)); }, this, diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index a524aade72..4cc09a9b5e 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -60,6 +60,7 @@ #endif #include #include +#include #include "libslic3r/libslic3r.h" #include "libslic3r/Format/STL.hpp" @@ -372,7 +373,6 @@ struct Sidebar::priv //ScalableButton *btn_eject_device; ScalableButton* btn_export_gcode_removable; //exports to removable drives (appears only if removable drive is connected) - bool is_collapsed {false}; Search::OptionsSearcher searcher; std::string ams_list_device; @@ -1759,19 +1759,9 @@ void Sidebar::update_mode() Layout(); } -bool Sidebar::is_collapsed() { return p->is_collapsed; } +bool Sidebar::is_collapsed() { return p->plater->is_sidebar_collapsed(); } -void Sidebar::collapse(bool collapse) -{ - p->is_collapsed = collapse; - - this->Show(!collapse); - p->plater->Layout(); - - // save collapsing state to the AppConfig - //if (wxGetApp().is_editor()) - // wxGetApp().app_config->set_bool("collapsed_sidebar", collapse); -} +void Sidebar::collapse(bool collapse) { p->plater->collapse_sidebar(collapse); } #ifdef _MSW_DARK_MODE void Sidebar::show_mode_sizer(bool show) @@ -1949,6 +1939,28 @@ enum ExportingStatus{ EXPORTING_TO_LOCAL }; + +// TODO: listen on dark ui change +class FloatFrame : public wxAuiFloatingFrame +{ +public: + FloatFrame(wxWindow* parent, wxAuiManager* ownerMgr, const wxAuiPaneInfo& pane) : wxAuiFloatingFrame(parent, ownerMgr, pane) + { + wxGetApp().UpdateFrameDarkUI(this); + } +}; + +class AuiMgr : public wxAuiManager +{ +public: + AuiMgr() : wxAuiManager(){} + + virtual wxAuiFloatingFrame* CreateFloatingFrame(wxWindow* parent, const wxAuiPaneInfo& p) override + { + return new FloatFrame(parent, this, p); + } +}; + // Plater / private struct Plater::priv { @@ -1971,10 +1983,17 @@ struct Plater::priv Slic3r::GCodeProcessorResult gcode_result; // GUI elements - wxSizer* panel_sizer{ nullptr }; + AuiMgr m_aui_mgr; + wxString m_default_window_layout; wxPanel* current_panel{ nullptr }; std::vector panels; Sidebar *sidebar; + struct SidebarLayout + { + bool is_enabled{false}; + bool is_collapsed{false}; + bool show{false}; + } sidebar_layout; Bed3D bed; Camera camera; //BBS: partplate related structure @@ -2166,8 +2185,11 @@ struct Plater::priv if (current_panel == view3D) view3D->get_canvas3d()->show_overhang(show); } - bool is_sidebar_collapsed() const { return sidebar->is_collapsed(); } + void enable_sidebar(bool enabled); void collapse_sidebar(bool collapse); + void update_sidebar(bool force_update = false); + void reset_window_layout(); + Sidebar::DockingState get_sidebar_docking_state(); bool is_view3D_layers_editing_enabled() const { return (current_panel == view3D) && view3D->get_canvas3d()->is_layers_editing_enabled(); } @@ -2381,6 +2403,7 @@ struct Plater::priv //BBS: change dark/light mode void on_change_color_mode(SimpleEvent& evt); void on_apple_change_color_mode(wxSysColourChangedEvent& evt); + void apply_color_mode(); void on_update_geometry(Vec3dsEvent<2>&); void on_3dcanvas_mouse_dragging_started(SimpleEvent&); void on_3dcanvas_mouse_dragging_finished(SimpleEvent&); @@ -2390,6 +2413,8 @@ struct Plater::priv void update_publish_dialog_status(wxString &msg, int percent = -1); void on_action_print_plate_from_sdcard(SimpleEvent&); + void on_tab_selection_changing(wxBookCtrlEvent&); + // Set the bed shape to a single closed 2D polygon(array of two element arrays), // triangulate the bed and store the triangles into m_bed.m_triangles, // fills the m_bed.m_grid_lines and sets m_bed.m_origin. @@ -2540,6 +2565,13 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) //BBS :partplatelist construction , partplate_list(this->q, &model) { + m_aui_mgr.SetManagedWindow(q); + m_aui_mgr.SetDockSizeConstraint(1, 1); + //m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE, 0); + //m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_SASH_SIZE, 2); + m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_CAPTION_SIZE, 18); + m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_GRADIENT_TYPE, wxAUI_GRADIENT_NONE); + this->q->SetFont(Slic3r::GUI::wxGetApp().normal_font()); //BBS: use the first partplate's print for background process @@ -2581,11 +2613,14 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) this->q->Bind(EVT_CREATE_FILAMENT, &priv::on_create_filament, this); this->q->Bind(EVT_MODIFY_FILAMENT, &priv::on_modify_filament, this); - view3D = new View3D(q, bed, &model, config, &background_process); - //BBS: use partplater's gcode - preview = new Preview(q, bed, &model, config, &background_process, partplate_list.get_current_slice_result(), [this]() { schedule_background_process(); }); + main_frame->m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGING, &priv::on_tab_selection_changing, this); - assemble_view = new AssembleView(q, bed, &model, config, &background_process); + auto* panel_3d = new wxPanel(q); + view3D = new View3D(panel_3d, bed, &model, config, &background_process); + //BBS: use partplater's gcode + preview = new Preview(panel_3d, bed, &model, config, &background_process, partplate_list.get_current_slice_result(), [this]() { schedule_background_process(); }); + + assemble_view = new AssembleView(panel_3d, bed, &model, config, &background_process); #ifdef __APPLE__ // BBS @@ -2606,23 +2641,35 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) update(); - auto* hsizer = new wxBoxSizer(wxHORIZONTAL); - auto* vsizer = new wxBoxSizer(wxVERTICAL); + // Orca: Make sidebar dockable + m_aui_mgr.AddPane(sidebar, wxAuiPaneInfo() + .Name("sidebar") + .Left() + .CloseButton(false) + .TopDockable(false) + .BottomDockable(false) + .Floatable(true) + .BestSize(wxSize(42 * wxGetApp().em_unit(), 90 * wxGetApp().em_unit()))); - // BBS: move sidebar to left side - hsizer->Add(sidebar, 0, wxEXPAND | wxLEFT | wxRIGHT, 0); - auto spliter_1 = new ::StaticLine(q, true); - spliter_1->SetLineColour("#A6A9AA"); - hsizer->Add(spliter_1, 0, wxEXPAND); - - panel_sizer = new wxBoxSizer(wxHORIZONTAL); + auto* panel_sizer = new wxBoxSizer(wxHORIZONTAL); panel_sizer->Add(view3D, 1, wxEXPAND | wxALL, 0); panel_sizer->Add(preview, 1, wxEXPAND | wxALL, 0); panel_sizer->Add(assemble_view, 1, wxEXPAND | wxALL, 0); - vsizer->Add(panel_sizer, 1, wxEXPAND | wxALL, 0); - hsizer->Add(vsizer, 1, wxEXPAND | wxALL, 0); + panel_3d->SetSizer(panel_sizer); + m_aui_mgr.AddPane(panel_3d, wxAuiPaneInfo().Name("main").CenterPane().PaneBorder(false)); - q->SetSizer(hsizer); + m_default_window_layout = m_aui_mgr.SavePerspective(); + + // Load previous window layout + { + const auto cfg = wxGetApp().app_config; + wxString layout = wxString::FromUTF8(cfg->get("window_layout")); + if (!layout.empty()) { + m_aui_mgr.LoadPerspective(layout, false); + auto& sidebar = m_aui_mgr.GetPane(this->sidebar); + sidebar_layout.is_collapsed = !sidebar.IsShown(); + } + } menus.init(q); @@ -2827,6 +2874,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) q->SetDropTarget(new PlaterDropTarget(q)); // if my understanding is right, wxWindow takes the owenership q->Layout(); + apply_color_mode(); + set_current_panel(wxGetApp().is_editor() ? static_cast(view3D) : static_cast(preview)); // updates camera type from .ini file @@ -2952,6 +3001,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) // bool is_collapsed = wxGetApp().app_config->get("collapsed_sidebar") == "1"; // sidebar->collapse(is_collapsed); //} + update_sidebar(true); } Plater::priv::~priv() @@ -2960,6 +3010,7 @@ Plater::priv::~priv() delete config; // Saves the database of visited (already shown) hints into hints.ini. notification_manager->deactivate_loaded_hints(); + main_frame->m_tabpanel->Unbind(wxEVT_NOTEBOOK_PAGE_CHANGING, &priv::on_tab_selection_changing, this); } void Plater::priv::update(unsigned int flags) @@ -2998,6 +3049,8 @@ void Plater::priv::update(unsigned int flags) if (get_config("autocenter") == "true" && this->sidebar->obj_manipul()->IsShown()) this->sidebar->obj_manipul()->UpdateAndShow(true); #endif + + update_sidebar(); } void Plater::priv::select_view(const std::string& direction) @@ -3115,14 +3168,66 @@ void Plater::priv::select_next_view_3D() // set_current_panel(view3D); } -void Plater::priv::collapse_sidebar(bool collapse) +void Plater::priv::enable_sidebar(bool enabled) { - if (q->m_only_gcode && !collapse) - return; - sidebar->collapse(collapse); - notification_manager->set_sidebar_collapsed(collapse); + if (q->m_only_gcode) + enabled = false; + + sidebar_layout.is_enabled = enabled; + update_sidebar(); } +void Plater::priv::collapse_sidebar(bool collapse) +{ + if (q->m_only_gcode) + return; + + sidebar_layout.is_collapsed = collapse; + update_sidebar(); +} + +void Plater::priv::update_sidebar(bool force_update) { + auto& sidebar = m_aui_mgr.GetPane(this->sidebar); + bool needs_update = force_update; + + if (!sidebar_layout.is_enabled) { + if (sidebar.IsShown()) { + sidebar.Hide(); + needs_update = true; + } + } else { + bool should_show = sidebar_layout.show && !sidebar_layout.is_collapsed; + if (should_show != sidebar.IsShown()) { + sidebar.Show(should_show); + needs_update = true; + } + } + + if (needs_update) { + notification_manager->set_sidebar_collapsed(sidebar.IsShown()); + m_aui_mgr.Update(); + } +} + +void Plater::priv::reset_window_layout() +{ + m_aui_mgr.LoadPerspective(m_default_window_layout, false); + sidebar_layout.is_collapsed = false; + update_sidebar(true); +} + +Sidebar::DockingState Plater::priv::get_sidebar_docking_state() { + if (!sidebar_layout.is_enabled) { + return Sidebar::None; + } + + const auto& sidebar = m_aui_mgr.GetPane(this->sidebar); + if(sidebar.IsFloating()) { + return Sidebar::None; + } + + return sidebar.dock_direction == wxAUI_DOCK_RIGHT ? Sidebar::Right : Sidebar::Left; +} void Plater::priv::reset_all_gizmos() { @@ -4535,6 +4640,17 @@ void Plater::priv::reset(bool apply_presets_change) // BBS m_saved_timestamp = m_backup_timestamp = size_t(-1); + + // Save window layout + if (sidebar_layout.is_enabled) { + // Reset show state + auto& sidebar = m_aui_mgr.GetPane(this->sidebar); + if (!sidebar_layout.is_collapsed && !sidebar.IsShown()) { + sidebar.Show(); + } + auto layout = m_aui_mgr.SavePerspective(); + wxGetApp().app_config->set("window_layout", layout.utf8_string()); + } } void Plater::priv::center_selection() @@ -5775,7 +5891,7 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) p->Hide(); } - panel_sizer->Layout(); + m_aui_mgr.Update(); if (wxGetApp().plater()) { Camera& cam = wxGetApp().plater()->get_camera(); @@ -6628,6 +6744,13 @@ void Plater::priv::on_action_print_plate_from_sdcard(SimpleEvent&) m_select_machine_dlg->ShowModal(); } +void Plater::priv::on_tab_selection_changing(wxBookCtrlEvent& e) +{ + const int new_sel = e.GetSelection(); + sidebar_layout.show = new_sel == MainFrame::tp3DEditor || new_sel == MainFrame::tpPreview; + update_sidebar(); +} + int Plater::priv::update_print_required_data(Slic3r::DynamicPrintConfig config, Slic3r::Model model, Slic3r::PlateDataPtrs plate_data_list, std::string file_name, std::string file_path) { if (!m_select_machine_dlg) m_select_machine_dlg = new SelectMachineDialog(q); @@ -6826,6 +6949,8 @@ void Plater::priv::on_apple_change_color_mode(wxSysColourChangedEvent& evt) { preview->get_canvas3d()->on_change_color_mode(m_is_dark); assemble_view->get_canvas3d()->on_change_color_mode(m_is_dark); } + + apply_color_mode(); } void Plater::priv::on_change_color_mode(SimpleEvent& evt) { @@ -6834,6 +6959,37 @@ void Plater::priv::on_change_color_mode(SimpleEvent& evt) { preview->get_canvas3d()->on_change_color_mode(m_is_dark); assemble_view->get_canvas3d()->on_change_color_mode(m_is_dark); if (m_send_to_sdcard_dlg) m_send_to_sdcard_dlg->on_change_color_mode(); + + apply_color_mode(); +} + +void Plater::priv::apply_color_mode() +{ + const bool is_dark = wxGetApp().dark_mode(); + wxColour orca_color = wxColour(59, 68, 70);//wxColour(ColorRGBA::ORCA().r_uchar(), ColorRGBA::ORCA().g_uchar(), ColorRGBA::ORCA().b_uchar()); + orca_color = is_dark ? StateColor::darkModeColorFor(orca_color) : StateColor::lightModeColorFor(orca_color); + wxColour sash_color = is_dark ? wxColour(38, 46, 48) : wxColour(206, 206, 206); + m_aui_mgr.GetArtProvider()->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR, sash_color); + m_aui_mgr.GetArtProvider()->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR, *wxWHITE); + m_aui_mgr.GetArtProvider()->SetColour(wxAUI_DOCKART_SASH_COLOUR, sash_color); + m_aui_mgr.GetArtProvider()->SetColour(wxAUI_DOCKART_BORDER_COLOUR, is_dark ? *wxBLACK : wxColour(165, 165, 165)); + m_aui_mgr.Update(); +} + +static void get_position(wxWindowBase* child, wxWindowBase* until_parent, int& x, int& y) { + int res_x = 0, res_y = 0; + + while (child != until_parent && child != nullptr) { + int _x, _y; + child->GetPosition(&_x, &_y); + res_x += _x; + res_y += _y; + + child = child->GetParent(); + } + + x = res_x; + y = res_y; } void Plater::priv::on_right_click(RBtnEvent& evt) @@ -6895,8 +7051,8 @@ void Plater::priv::on_right_click(RBtnEvent& evt) #else //BBS: GUI refactor: move sidebar to the left int x, y; - current_panel->GetPosition(&x, &y); - q->PopupMenu(menu, (int)evt.data.first.x() + x, (int)evt.data.first.y()); + get_position(current_panel, wxGetApp().mainframe, x, y); + q->PopupMenu(menu, (int) evt.data.first.x() + x, (int) evt.data.first.y() + y); //q->PopupMenu(menu); #endif } @@ -6912,8 +7068,8 @@ void Plater::priv::on_plate_right_click(RBtnPlateEvent& evt) #else //BBS: GUI refactor: move sidebar to the left int x, y; - current_panel->GetPosition(&x, &y); - q->PopupMenu(menu, (int)evt.data.first.x() + x, (int)evt.data.first.y()); + get_position(current_panel, wxGetApp().mainframe, x, y); + q->PopupMenu(menu, (int) evt.data.first.x() + x, (int) evt.data.first.y() + y); //q->PopupMenu(menu); #endif } @@ -7270,7 +7426,7 @@ bool Plater::priv::init_collapse_toolbar() item.name = "collapse_sidebar"; // set collapse svg name - item.icon_filename = "*.svg"; + item.icon_filename = "collapse.svg"; item.sprite_id = 0; item.left.action_callback = []() { wxGetApp().plater()->collapse_sidebar(!wxGetApp().plater()->is_sidebar_collapsed()); @@ -8150,9 +8306,6 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString& project_ if (!skip_confirm && (result = close_with_confirm(check)) == wxID_CANCEL) return wxID_CANCEL; - //BBS: add only gcode mode - bool previous_gcode = m_only_gcode; - m_only_gcode = false; m_exported_file = false; m_loading_project = false; @@ -8197,8 +8350,7 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString& project_ p->select_view_3D("3D"); p->select_view("topfront"); p->camera.requires_zoom_to_bed = true; - if (previous_gcode) - collapse_sidebar(false); + enable_sidebar(!m_only_gcode); up_to_date(true, false); up_to_date(true, true); @@ -8230,9 +8382,6 @@ void Plater::load_project(wxString const& filename2, return; } - //BBS: add only gcode mode - bool previous_gcode = m_only_gcode; - // BBS if (m_loading_project) { //some error cases happens @@ -8302,8 +8451,7 @@ void Plater::load_project(wxString const& filename2, p->partplate_list.select_plate_view(); } - if (previous_gcode) - collapse_sidebar(false); + enable_sidebar(!m_only_gcode); wxGetApp().app_config->update_last_backup_dir(model().get_backup_path()); if (load_restore && !originfile.empty()) { @@ -10014,8 +10162,13 @@ void Plater::show_view3D_labels(bool show) { p->show_view3D_labels(show); } bool Plater::is_view3D_overhang_shown() const { return p->is_view3D_overhang_shown(); } void Plater::show_view3D_overhang(bool show) { p->show_view3D_overhang(show); } -bool Plater::is_sidebar_collapsed() const { return p->is_sidebar_collapsed(); } -void Plater::collapse_sidebar(bool show) { p->collapse_sidebar(show); } +bool Plater::is_sidebar_enabled() const { return p->sidebar_layout.is_enabled; } +void Plater::enable_sidebar(bool enabled) { p->enable_sidebar(enabled); } +bool Plater::is_sidebar_collapsed() const { return p->sidebar_layout.is_collapsed; } +void Plater::collapse_sidebar(bool collapse) { p->collapse_sidebar(collapse); } +Sidebar::DockingState Plater::get_sidebar_docking_state() const { return p->get_sidebar_docking_state(); } + +void Plater::reset_window_layout() { p->reset_window_layout(); } //BBS void Plater::select_curr_plate_all() { p->select_curr_plate_all(); } @@ -12193,11 +12346,6 @@ bool Plater::init_collapse_toolbar() return p->init_collapse_toolbar(); } -void Plater::enable_collapse_toolbar(bool enable) -{ - p->collapse_toolbar.set_enabled(enable); -} - const Camera& Plater::get_camera() const { return p->camera; diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 5e9833ba56..e968981e8b 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -122,6 +122,11 @@ class Sidebar : public wxPanel { ConfigOptionMode m_mode; public: + enum DockingState + { + None, Left, Right + }; + Sidebar(Plater *parent); Sidebar(Sidebar &&) = delete; Sidebar(const Sidebar &) = delete; @@ -313,8 +318,13 @@ public: bool is_view3D_overhang_shown() const; void show_view3D_overhang(bool show); + bool is_sidebar_enabled() const; + void enable_sidebar(bool enabled); bool is_sidebar_collapsed() const; - void collapse_sidebar(bool show); + void collapse_sidebar(bool collapse); + Sidebar::DockingState get_sidebar_docking_state() const; + + void reset_window_layout(); // Called after the Preferences dialog is closed and the program settings are saved. // Update the UI based on the current preferences. @@ -541,7 +551,6 @@ public: #endif bool init_collapse_toolbar(); - void enable_collapse_toolbar(bool enable); const Camera& get_camera() const; Camera& get_camera();