diff --git a/resources/icons/disclosure_triangle_close.png b/resources/icons/disclosure_triangle_close.png new file mode 100644 index 0000000000..0660422c7f Binary files /dev/null and b/resources/icons/disclosure_triangle_close.png differ diff --git a/resources/icons/disclosure_triangle_open.png b/resources/icons/disclosure_triangle_open.png new file mode 100644 index 0000000000..81112f2a26 Binary files /dev/null and b/resources/icons/disclosure_triangle_open.png differ diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 0e2893b574..2d487edd58 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -817,26 +817,13 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl sizer->Add(main_page, 1, wxEXPAND | wxALL, 1); // Experiments with new UI - wxCollapsiblePane *collpane = new wxCollapsiblePane(main_page, wxID_ANY, "Frequently Changing Parameters:"); - collpane->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, ([parent, main_page, collpane](wxCommandEvent e){ - wxWindowUpdateLocker noUpdates_cp(collpane); - wxWindowUpdateLocker noUpdates(main_page); - parent->Layout(); - main_page->Layout(); - collpane->Refresh(); - })); + // *** Frequently Changing Parameters *** + auto* collpane = new PrusaCollapsiblePane(main_page, wxID_ANY, "Frequently Changing Parameters:"); // add the pane with a zero proportion value to the sizer which contains it main_sizer->Add(collpane, 0, wxGROW | wxALL, 0); wxWindow *win = collpane->GetPane(); -#ifdef __WXMSW__ - wxColour& clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - collpane->GetControlWidget()->SetWindowStyleFlag(wxNO_BORDER); - collpane->GetControlWidget()->SetBackgroundColour(clr); - collpane->SetBackgroundColour(clr); - win->SetBackgroundColour(clr); -#endif //__WXMSW__ DynamicPrintConfig* config = &g_PresetBundle->prints.get_edited_preset().config; m_optgroup = std::make_shared(win, "", config); @@ -952,57 +939,24 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl m_optgroup->append_line(line); wxSizer *paneSz = new wxBoxSizer(wxVERTICAL); - paneSz->Add(m_optgroup->sizer, 1, wxGROW | wxEXPAND | /*wxBOTTOM*/wxALL, /*2*/5); + paneSz->Add(m_optgroup->sizer, 1, wxGROW | wxEXPAND | wxLEFT | wxRIGHT, 5); win->SetSizer(paneSz); paneSz->SetSizeHints(win); - - wxCollapsiblePane *collpane_objects = new wxCollapsiblePane(main_page, wxID_ANY, "Objects List:"); - collpane_objects->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, ([parent, main_page, collpane_objects](wxCommandEvent e){ - wxWindowUpdateLocker noUpdates_cp(collpane_objects); - wxWindowUpdateLocker noUpdates(main_page); - parent->Layout(); - main_page->Layout(); - collpane_objects->Refresh(); - })); - + // *** Objects List *** + auto *collpane_objects = new PrusaCollapsiblePane(main_page, wxID_ANY, "Objects List:"); // add the pane with a zero proportion value to the sizer which contains it main_sizer->Add(collpane_objects, 0, wxGROW | wxALL, 0); wxWindow *win_objects = collpane_objects->GetPane(); -#ifdef __WXMSW__ - collpane_objects->GetControlWidget()->SetWindowStyleFlag(wxNO_BORDER); - collpane_objects->GetControlWidget()->SetBackgroundColour(clr); - collpane_objects->SetBackgroundColour(clr); - win_objects->SetBackgroundColour(clr); -#endif //__WXMSW__ - -// auto common_sizer = new wxBoxSizer(wxVERTICAL); -// common_sizer->Add(m_optgroup->sizer); - -// auto listctrl = new wxDataViewListCtrl(win, wxID_ANY, wxDefaultPosition, wxSize(-1, 100)); -// listctrl->AppendToggleColumn("Toggle"); -// listctrl->AppendTextColumn("Text"); -// wxVector data; -// data.push_back(wxVariant(true)); -// data.push_back(wxVariant("row 1")); -// listctrl->AppendItem(data); -// data.clear(); -// data.push_back(wxVariant(false)); -// data.push_back(wxVariant("row 3")); -// listctrl->AppendItem(data); -// data.clear(); -// data.push_back(wxVariant(false)); -// data.push_back(wxVariant("row 2")); -// listctrl->AppendItem(data); -// common_sizer->Add(listctrl, 0, wxEXPAND | wxALL, 1); // ********************************************************************************************** auto objects_ctrl = new wxDataViewCtrl(win_objects, wxID_ANY, wxDefaultPosition, wxDefaultSize); wxSizer *objects_sz = new wxBoxSizer(wxVERTICAL); - objects_ctrl->SetBestFittingSize(wxSize(-1, 200)); + objects_ctrl->SetBestFittingSize(wxSize(-1, 200)); + // TODO - Set correct height according to the opened/closed objects // objects_ctrl->SetMinSize(wxSize(-1, 200)); objects_sz->Add(objects_ctrl, 1, wxGROW | wxALL, 5); @@ -1041,6 +995,29 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl win_objects->SetSizer(paneSz_objects); paneSz_objects->SetSizeHints(win_objects); + + +// auto common_sizer = new wxBoxSizer(wxVERTICAL); +// common_sizer->Add(m_optgroup->sizer); + +// auto listctrl = new wxDataViewListCtrl(win, wxID_ANY, wxDefaultPosition, wxSize(-1, 100)); +// listctrl->AppendToggleColumn("Toggle"); +// listctrl->AppendTextColumn("Text"); +// wxVector data; +// data.push_back(wxVariant(true)); +// data.push_back(wxVariant("row 1")); +// listctrl->AppendItem(data); +// data.clear(); +// data.push_back(wxVariant(false)); +// data.push_back(wxVariant("row 3")); +// listctrl->AppendItem(data); +// data.clear(); +// data.push_back(wxVariant(false)); +// data.push_back(wxVariant("row 2")); +// listctrl->AppendItem(data); +// common_sizer->Add(listctrl, 0, wxEXPAND | wxALL, 1); + + } ConfigOptionsGroup* get_optgroup() diff --git a/xs/src/slic3r/GUI/wxExtensions.cpp b/xs/src/slic3r/GUI/wxExtensions.cpp index 0fb335118a..03d6bdaef9 100644 --- a/xs/src/slic3r/GUI/wxExtensions.cpp +++ b/xs/src/slic3r/GUI/wxExtensions.cpp @@ -1,5 +1,11 @@ #include "wxExtensions.hpp" +#include "GUI.hpp" +#include "../../libslic3r/Utils.hpp" + +#include +#include + const unsigned int wxCheckListBoxComboPopup::DefaultWidth = 200; const unsigned int wxCheckListBoxComboPopup::DefaultHeight = 200; const unsigned int wxCheckListBoxComboPopup::DefaultItemHeight = 18; @@ -166,6 +172,119 @@ void wxDataViewTreeCtrlComboPopup::OnDataViewTreeCtrlSelection(wxCommandEvent& e cmb->SetText(selected); } +// *** PrusaCollapsiblePane *** +// ---------------------------------------------------------------------------- +bool PrusaCollapsiblePane::Create(wxWindow *parent, wxWindowID id, const wxString& label, + const wxPoint& pos, const wxSize& size, long style, const wxValidator& val, const wxString& name) +{ + if (!wxControl::Create(parent, id, pos, size, style, val, name)) + return false; + m_pStaticLine = NULL; + m_strLabel = label; + + // sizer containing the expand button and possibly a static line + m_sz = new wxBoxSizer(wxHORIZONTAL); + + m_bmp_close.LoadFile(Slic3r::GUI::from_u8(Slic3r::var("disclosure_triangle_close.png")), wxBITMAP_TYPE_PNG); + m_bmp_open.LoadFile(Slic3r::GUI::from_u8(Slic3r::var("disclosure_triangle_open.png")), wxBITMAP_TYPE_PNG); + + m_pDisclosureTriangleButton = new wxButton(this, wxID_ANY, m_strLabel, wxPoint(0, 0), + wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); + m_pDisclosureTriangleButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) + { + if (event.GetEventObject() != m_pDisclosureTriangleButton) + { + event.Skip(); + return; + } + + Collapse(!IsCollapsed()); + + // this change was generated by the user - send the event + wxCollapsiblePaneEvent ev(this, GetId(), IsCollapsed()); + GetEventHandler()->ProcessEvent(ev); + }); + + UpdateBtnBmp(); + + m_sz->Add(m_pDisclosureTriangleButton, 0, wxLEFT | wxTOP | wxBOTTOM, GetBorder()); + + // do not set sz as our sizers since we handle the pane window without using sizers + m_pPane = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, + wxTAB_TRAVERSAL | wxNO_BORDER, wxT("wxCollapsiblePanePane")); + + wxColour& clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + m_pDisclosureTriangleButton->SetBackgroundColour(clr); + this->SetBackgroundColour(clr); + m_pPane->SetBackgroundColour(clr); + + // start as collapsed: + m_pPane->Hide(); + + return true; +} + +void PrusaCollapsiblePane::UpdateBtnBmp() +{ + IsCollapsed() ? + m_pDisclosureTriangleButton->SetBitmap(m_bmp_close) : + m_pDisclosureTriangleButton->SetBitmap(m_bmp_open); + Layout(); +// m_pDisclosureTriangleButton->Refresh(); +} + +void PrusaCollapsiblePane::Collapse(bool collapse) +{ + // optimization + if (IsCollapsed() == collapse) + return; + + InvalidateBestSize(); + + // update our state + m_pPane->Show(!collapse); + + // update button label +// m_pDisclosureTriangleButton->SetLabel(m_strLabel); + UpdateBtnBmp(); + + OnStateChange(GetBestSize()); +} + +void PrusaCollapsiblePane::SetLabel(const wxString &label) +{ + m_strLabel = label; + + m_pDisclosureTriangleButton->SetLabel(m_strLabel); + + Layout(); +} + +bool PrusaCollapsiblePane::Layout() +{ + if (!m_pDisclosureTriangleButton || !m_pPane || !m_sz) + return false; // we need to complete the creation first! + + wxSize oursz(GetSize()); + + // move & resize the button and the static line + m_sz->SetDimension(0, 0, oursz.GetWidth(), m_sz->GetMinSize().GetHeight()); + m_sz->Layout(); + + if (IsExpanded()) + { + // move & resize the container window + int yoffset = m_sz->GetSize().GetHeight() + GetBorder(); + m_pPane->SetSize(0, yoffset, + oursz.x, oursz.y - yoffset); + + // this is very important to make the pane window layout show correctly + m_pPane->Layout(); + } + + return true; +} + // ***************************************************************************** // ---------------------------------------------------------------------------- // MyObjectTreeModel @@ -178,17 +297,19 @@ MyObjectTreeModel::MyObjectTreeModel() auto root2 = new MyObjectTreeModelNode("Object2"); m_objects.emplace(root2); - root2->Append(new MyObjectTreeModelNode(root2, "SubObject1")); - root2->Append(new MyObjectTreeModelNode(root2, "SubObject2")); - root2->Append(new MyObjectTreeModelNode(root2, "SubObject3")); + root2->Append(new MyObjectTreeModelNode(root2, "SubObject2_1")); + root2->Append(new MyObjectTreeModelNode(root2, "SubObject2_2")); + root2->Append(new MyObjectTreeModelNode(root2, "SubObject2_3")); auto root3 = new MyObjectTreeModelNode("Object3"); m_objects.emplace(root3); auto root4 = new MyObjectTreeModelNode("Object4"); m_objects.emplace(root4); - root4->Append(new MyObjectTreeModelNode(root4, "SubObject1")); - root4->Append(new MyObjectTreeModelNode(root4, "SubObject2")); - root4->Append(new MyObjectTreeModelNode(root4, "SubObject3")); + root4->Append(new MyObjectTreeModelNode(root4, "SubObject4_1")); + root4->Append(new MyObjectTreeModelNode(root4, "SubObject4_2")); + + auto root5 = new MyObjectTreeModelNode("Object5"); + m_objects.emplace(root5); } wxString MyObjectTreeModel::GetName(const wxDataViewItem &item) const diff --git a/xs/src/slic3r/GUI/wxExtensions.hpp b/xs/src/slic3r/GUI/wxExtensions.hpp index 6ebdbe8b20..ec3b0d4790 100644 --- a/xs/src/slic3r/GUI/wxExtensions.hpp +++ b/xs/src/slic3r/GUI/wxExtensions.hpp @@ -5,6 +5,10 @@ #include #include #include +#include +#include +#include + #include #include @@ -53,6 +57,63 @@ public: void SetItemsCnt(int cnt) { m_cnt_open_items = cnt; } }; + + +// *** PrusaCollapsiblePane *** +// ---------------------------------------------------------------------------- +class PrusaCollapsiblePane : public wxCollapsiblePane +{ +#ifdef __WXMSW__ + wxButton* m_pDisclosureTriangleButton = nullptr; + wxBitmap m_bmp_close; + wxBitmap m_bmp_open; +#endif //__WXMSW__ +public: + PrusaCollapsiblePane() {} + + + PrusaCollapsiblePane( wxWindow *parent, + wxWindowID winid, + const wxString& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxCP_DEFAULT_STYLE, + const wxValidator& val = wxDefaultValidator, + const wxString& name = wxCollapsiblePaneNameStr) + { +#ifdef __WXMSW__ + Create(parent, winid, label, pos, size, style, val, name); +#else + this->Create(parent, winid, label); +#endif //__WXMSW__ + this->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, ([parent, this](wxCommandEvent e){ + wxWindowUpdateLocker noUpdates_cp(this); + wxWindowUpdateLocker noUpdates(parent); + parent->GetParent()->Layout(); + parent->Layout(); + this->Refresh(); + })); + } + + bool Create(wxWindow *parent, + wxWindowID id, + const wxString& label, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& val, + const wxString& name); + +#ifdef __WXMSW__ + void UpdateBtnBmp(); + void Collapse(bool collapse) override; + void SetLabel(const wxString &label) override; + bool Layout() override; +#endif //__WXMSW__ + +}; + + // ***************************************************************************** // ---------------------------------------------------------------------------- // MyObjectTreeModelNode: a node inside MyObjectTreeModel