From 460021f7d088645df079a3650b99f0937d1abf6d Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 30 Jul 2018 12:17:32 +0200 Subject: [PATCH] EXPERIMENTS for Linux --- xs/src/slic3r/GUI/GUI_ObjectParts.cpp | 117 +++++++++++ xs/src/slic3r/GUI/GUI_ObjectParts.hpp | 4 + xs/src/slic3r/GUI/wxExtensions.cpp | 284 +++++++++++++++++++++++++- xs/src/slic3r/GUI/wxExtensions.hpp | 188 ++++++++++++++++- 4 files changed, 589 insertions(+), 4 deletions(-) diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp index 39e49bcba..31c6742c6 100644 --- a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -427,6 +427,8 @@ void add_objects_list(wxWindow* parent, wxBoxSizer* sizer) const auto ol_sizer = content_objects_list(parent); sizer->Add(ol_sizer, 1, wxEXPAND | wxTOP, 20); set_objects_list_sizer(ol_sizer); + + sizer->Add(get_experimental_sizer(parent), 0, wxEXPAND | wxTOP, 20); } Line add_og_to_object_settings(const std::string& option_name, const std::string& sidetext, int def_value = 0) @@ -1368,5 +1370,120 @@ void update_rotation_value(const double angle, const std::string& axis) og->set_value("rotation_"+axis, deg); } + +// **************************************** EXPERIMENRS **************************************** +// wxDataViewCtrl *tmp_ctrl = nullptr; +// MyMusicTreeModel *m_music_model = nullptr; + +wxSizer* get_experimental_sizer(wxWindow* parent) +{ + auto tmp_ctrl = new wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize); + tmp_ctrl->SetInitialSize(wxSize(-1, 150)); // TODO - Set correct height according to the opened/closed objects +// tmp_ctrl->Connect(wxEVT_CHAR, +// wxKeyEventHandler(MyFrame::OnDataViewChar), +// NULL, this); + + auto m_music_model = new MyMusicTreeModel; + tmp_ctrl->AssociateModel(m_music_model); + +#if wxUSE_DRAG_AND_DROP && wxUSE_UNICODE + tmp_ctrl->EnableDragSource(wxDF_UNICODETEXT); + tmp_ctrl->EnableDropTarget(wxDF_UNICODETEXT); +#endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE + + // column 0 of the view control: + + wxDataViewTextRenderer *tr = + new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_INERT); + wxDataViewColumn *column0 = + new wxDataViewColumn("title", tr, 0, 200, wxALIGN_LEFT, + wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE); + tmp_ctrl->AppendColumn(column0); +#if 0 + // Call this and sorting is enabled + // immediately upon start up. + column0->SetAsSortKey(); +#endif + + // column 1 of the view control: + + tr = new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_EDITABLE); + wxDataViewColumn *column1 = + new wxDataViewColumn("artist", tr, 1, 150, wxALIGN_LEFT, + wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE | + wxDATAVIEW_COL_RESIZABLE); + column1->SetMinWidth(150); // this column can't be resized to be smaller + tmp_ctrl->AppendColumn(column1); + + // column 2 of the view control: + + wxDataViewSpinRenderer *sr = + new wxDataViewSpinRenderer(0, 2010, wxDATAVIEW_CELL_EDITABLE, + wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL); + wxDataViewColumn *column2 = + new wxDataViewColumn("year", sr, 2, 60, wxALIGN_LEFT, + wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE); + tmp_ctrl->AppendColumn(column2); + + // column 3 of the view control: + + wxArrayString choices; + choices.Add("good"); + choices.Add("bad"); + choices.Add("lousy"); + wxDataViewChoiceRenderer *c = + new wxDataViewChoiceRenderer(choices, wxDATAVIEW_CELL_EDITABLE, + wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL); + wxDataViewColumn *column3 = + new wxDataViewColumn("rating", c, 3, 100, wxALIGN_LEFT, + wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE); + tmp_ctrl->AppendColumn(column3); + + // column 4 of the view control: + + tmp_ctrl->AppendProgressColumn("popularity", 4, wxDATAVIEW_CELL_INERT, 80); + + // column 5 of the view control: + + MyCustomRenderer *cr = new MyCustomRenderer(wxDATAVIEW_CELL_ACTIVATABLE); + wxDataViewColumn *column5 = + new wxDataViewColumn("custom", cr, 5, -1, wxALIGN_LEFT, + wxDATAVIEW_COL_RESIZABLE); + tmp_ctrl->AppendColumn(column5); + + + // select initially the ninth symphony: + tmp_ctrl->Select(m_music_model->GetNinthItem()); + + + const wxSizerFlags border = wxSizerFlags().DoubleBorder(); + + wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL); + auto add_btn = new wxButton(parent, wxID_ANY, "Add Mozart"); + auto del_btn = new wxButton(parent, wxID_ANY, "Delete selected"); + button_sizer->Add(add_btn, border); + button_sizer->Add(del_btn, border); + + add_btn->Bind(wxEVT_BUTTON, [m_music_model](wxCommandEvent&) + { + m_music_model->AddToClassical("Eine kleine Nachtmusik", "Wolfgang Mozart", 1787); + }); + + del_btn->Bind(wxEVT_BUTTON, [tmp_ctrl, m_music_model](wxCommandEvent&){ + wxDataViewItemArray items; + int len = tmp_ctrl->GetSelections(items); + for (int i = 0; i < len; i++) + if (items[i].IsOk()) + m_music_model->Delete(items[i]); + }); + + auto sizer = new wxBoxSizer(wxVERTICAL); + sizer->Add(tmp_ctrl, 0, wxEXPAND | wxLEFT, 20); + sizer->Add(button_sizer); + return sizer; +} + +// **************************************** EXPERIMENRS **************************************** + } //namespace GUI } //namespace Slic3r \ No newline at end of file diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp b/xs/src/slic3r/GUI/GUI_ObjectParts.hpp index 9728f77d8..f8d7821c1 100644 --- a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp +++ b/xs/src/slic3r/GUI/GUI_ObjectParts.hpp @@ -107,6 +107,10 @@ void update_scale_values(const Pointf3& size, float scale); void update_rotation_values(); // update rotation value after "gizmos" void update_rotation_value(const double angle, const std::string& axis); + + +wxSizer* get_experimental_sizer(wxWindow* parent); + } //namespace GUI } //namespace Slic3r #endif //slic3r_GUI_ObjectParts_hpp_ \ No newline at end of file diff --git a/xs/src/slic3r/GUI/wxExtensions.cpp b/xs/src/slic3r/GUI/wxExtensions.cpp index 422c999d1..0690ecee2 100644 --- a/xs/src/slic3r/GUI/wxExtensions.cpp +++ b/xs/src/slic3r/GUI/wxExtensions.cpp @@ -682,7 +682,285 @@ unsigned int PrusaObjectDataViewModel::GetChildren(const wxDataViewItem &parent, } +// ************************************** EXPERIMENTS *************************************** +// ---------------------------------------------------------------------------- +// MyMusicTreeModel +// ---------------------------------------------------------------------------- + +MyMusicTreeModel::MyMusicTreeModel() +{ + m_root = new MyMusicTreeModelNode(NULL, "My Music"); + + // setup pop music + m_pop = new MyMusicTreeModelNode(m_root, "Pop music"); + m_pop->Append( + new MyMusicTreeModelNode(m_pop, "You are not alone", "Michael Jackson", 1995)); + m_pop->Append( + new MyMusicTreeModelNode(m_pop, "Take a bow", "Madonna", 1994)); + m_root->Append(m_pop); + + // setup classical music + m_classical = new MyMusicTreeModelNode(m_root, "Classical music"); + m_ninth = new MyMusicTreeModelNode(m_classical, "Ninth symphony", + "Ludwig van Beethoven", 1824); + m_classical->Append(m_ninth); + m_classical->Append(new MyMusicTreeModelNode(m_classical, "German Requiem", + "Johannes Brahms", 1868)); + m_root->Append(m_classical); + + m_classicalMusicIsKnownToControl = false; +} + +wxString MyMusicTreeModel::GetTitle(const wxDataViewItem &item) const +{ + MyMusicTreeModelNode *node = (MyMusicTreeModelNode*)item.GetID(); + if (!node) // happens if item.IsOk()==false + return wxEmptyString; + + return node->m_title; +} + +wxString MyMusicTreeModel::GetArtist(const wxDataViewItem &item) const +{ + MyMusicTreeModelNode *node = (MyMusicTreeModelNode*)item.GetID(); + if (!node) // happens if item.IsOk()==false + return wxEmptyString; + + return node->m_artist; +} + +int MyMusicTreeModel::GetYear(const wxDataViewItem &item) const +{ + MyMusicTreeModelNode *node = (MyMusicTreeModelNode*)item.GetID(); + if (!node) // happens if item.IsOk()==false + return 2000; + + return node->m_year; +} + +void MyMusicTreeModel::AddToClassical(const wxString &title, const wxString &artist, + unsigned int year) +{ + if (!m_classical) + { + wxASSERT(m_root); + + // it was removed: restore it + m_classical = new MyMusicTreeModelNode(m_root, "Classical music"); + m_root->Append(m_classical); + + // notify control + wxDataViewItem child((void*)m_classical); + wxDataViewItem parent((void*)m_root); + ItemAdded(parent, child); + } + + // add to the classical music node a new node: + MyMusicTreeModelNode *child_node = + new MyMusicTreeModelNode(m_classical, title, artist, year); + m_classical->Append(child_node); + + // FIXME: what's m_classicalMusicIsKnownToControl for? + if (m_classicalMusicIsKnownToControl) + { + // notify control + wxDataViewItem child((void*)child_node); + wxDataViewItem parent((void*)m_classical); + ItemAdded(parent, child); + } +} + +void MyMusicTreeModel::Delete(const wxDataViewItem &item) +{ + MyMusicTreeModelNode *node = (MyMusicTreeModelNode*)item.GetID(); + if (!node) // happens if item.IsOk()==false + return; + + wxDataViewItem parent(node->GetParent()); + if (!parent.IsOk()) + { + wxASSERT(node == m_root); + + // don't make the control completely empty: + printf("Cannot remove the root item!"); + return; + } + + // is the node one of those we keep stored in special pointers? + if (node == m_pop) + m_pop = NULL; + else if (node == m_classical) + m_classical = NULL; + else if (node == m_ninth) + m_ninth = NULL; + + // first remove the node from the parent's array of children; + // NOTE: MyMusicTreeModelNodePtrArray is only an array of _pointers_ + // thus removing the node from it doesn't result in freeing it + node->GetParent()->GetChildren().Remove(node); + + // free the node + delete node; + + // notify control + ItemDeleted(parent, item); +} + +int MyMusicTreeModel::Compare(const wxDataViewItem &item1, const wxDataViewItem &item2, + unsigned int column, bool ascending) const +{ + wxASSERT(item1.IsOk() && item2.IsOk()); + // should never happen + + if (IsContainer(item1) && IsContainer(item2)) + { + wxVariant value1, value2; + GetValue(value1, item1, 0); + GetValue(value2, item2, 0); + + wxString str1 = value1.GetString(); + wxString str2 = value2.GetString(); + int res = str1.Cmp(str2); + if (res) return res; + + // items must be different + wxUIntPtr litem1 = (wxUIntPtr)item1.GetID(); + wxUIntPtr litem2 = (wxUIntPtr)item2.GetID(); + + return litem1 - litem2; + } + + return wxDataViewModel::Compare(item1, item2, column, ascending); +} + +void MyMusicTreeModel::GetValue(wxVariant &variant, + const wxDataViewItem &item, unsigned int col) const +{ + wxASSERT(item.IsOk()); + + MyMusicTreeModelNode *node = (MyMusicTreeModelNode*)item.GetID(); + switch (col) + { + case 0: + variant = node->m_title; + break; + case 1: + variant = node->m_artist; + break; + case 2: + variant = (long)node->m_year; + break; + case 3: + variant = node->m_quality; + break; + case 4: + variant = 80L; // all music is very 80% popular + break; + case 5: + if (GetYear(item) < 1900) + variant = "old"; + else + variant = "new"; + break; + + default: + printf("MyMusicTreeModel::GetValue: wrong column %d", col); + } +} + +bool MyMusicTreeModel::SetValue(const wxVariant &variant, + const wxDataViewItem &item, unsigned int col) +{ + wxASSERT(item.IsOk()); + + MyMusicTreeModelNode *node = (MyMusicTreeModelNode*)item.GetID(); + switch (col) + { + case 0: + node->m_title = variant.GetString(); + return true; + case 1: + node->m_artist = variant.GetString(); + return true; + case 2: + node->m_year = variant.GetLong(); + return true; + case 3: + node->m_quality = variant.GetString(); + return true; + + default: + printf("MyMusicTreeModel::SetValue: wrong column"); + } + return false; +} + +bool MyMusicTreeModel::IsEnabled(const wxDataViewItem &item, + unsigned int col) const +{ + wxASSERT(item.IsOk()); + + MyMusicTreeModelNode *node = (MyMusicTreeModelNode*)item.GetID(); + + // disable Beethoven's ratings, his pieces can only be good + return !(col == 3 && node->m_artist.EndsWith("Beethoven")); +} + +wxDataViewItem MyMusicTreeModel::GetParent(const wxDataViewItem &item) const +{ + // the invisible root node has no parent + if (!item.IsOk()) + return wxDataViewItem(0); + + MyMusicTreeModelNode *node = (MyMusicTreeModelNode*)item.GetID(); + + // "MyMusic" also has no parent + if (node == m_root) + return wxDataViewItem(0); + + return wxDataViewItem((void*)node->GetParent()); +} + +bool MyMusicTreeModel::IsContainer(const wxDataViewItem &item) const +{ + // the invisble root node can have children + // (in our model always "MyMusic") + if (!item.IsOk()) + return true; + + MyMusicTreeModelNode *node = (MyMusicTreeModelNode*)item.GetID(); + return node->IsContainer(); +} + +unsigned int MyMusicTreeModel::GetChildren(const wxDataViewItem &parent, + wxDataViewItemArray &array) const +{ + MyMusicTreeModelNode *node = (MyMusicTreeModelNode*)parent.GetID(); + if (!node) + { + array.Add(wxDataViewItem((void*)m_root)); + return 1; + } + + if (node == m_classical) + { + MyMusicTreeModel *model = (MyMusicTreeModel*)(const MyMusicTreeModel*) this; + model->m_classicalMusicIsKnownToControl = true; + } + + if (node->GetChildCount() == 0) + { + return 0; + } + + unsigned int count = node->GetChildren().GetCount(); + for (unsigned int pos = 0; pos < count; pos++) + { + MyMusicTreeModelNode *child = node->GetChildren().Item(pos); + array.Add(wxDataViewItem((void*)child)); + } + + return count; +} + // ***************************************************************************** - - - diff --git a/xs/src/slic3r/GUI/wxExtensions.hpp b/xs/src/slic3r/GUI/wxExtensions.hpp index 3d0ca8564..8b4000d55 100644 --- a/xs/src/slic3r/GUI/wxExtensions.hpp +++ b/xs/src/slic3r/GUI/wxExtensions.hpp @@ -477,8 +477,194 @@ public: private: wxString m_value; }; -// ***************************************************************************** +// ******************************* EXPERIMENTS ********************************************** +// ---------------------------------------------------------------------------- +// MyMusicTreeModelNode: a node inside MyMusicTreeModel +// ---------------------------------------------------------------------------- +class MyMusicTreeModelNode; +WX_DEFINE_ARRAY_PTR(MyMusicTreeModelNode*, MyMusicTreeModelNodePtrArray); +class MyMusicTreeModelNode +{ +public: + MyMusicTreeModelNode(MyMusicTreeModelNode* parent, + const wxString &title, const wxString &artist, + unsigned int year) + { + m_parent = parent; + + m_title = title; + m_artist = artist; + m_year = year; + m_quality = "good"; + + m_container = false; + } + + MyMusicTreeModelNode(MyMusicTreeModelNode* parent, + const wxString &branch) + { + m_parent = parent; + + m_title = branch; + m_year = -1; + + m_container = true; + } + + ~MyMusicTreeModelNode() + { + // free all our children nodes + size_t count = m_children.GetCount(); + for (size_t i = 0; i < count; i++) + { + MyMusicTreeModelNode *child = m_children[i]; + delete child; + } + } + + bool IsContainer() const + { + return m_container; + } + + MyMusicTreeModelNode* GetParent() + { + return m_parent; + } + MyMusicTreeModelNodePtrArray& GetChildren() + { + return m_children; + } + MyMusicTreeModelNode* GetNthChild(unsigned int n) + { + return m_children.Item(n); + } + void Insert(MyMusicTreeModelNode* child, unsigned int n) + { + m_children.Insert(child, n); + } + void Append(MyMusicTreeModelNode* child) + { + m_children.Add(child); + } + unsigned int GetChildCount() const + { + return m_children.GetCount(); + } + +public: // public to avoid getters/setters + wxString m_title; + wxString m_artist; + int m_year; + wxString m_quality; + + // TODO/FIXME: + // the GTK version of wxDVC (in particular wxDataViewCtrlInternal::ItemAdded) + // needs to know in advance if a node is or _will be_ a container. + // Thus implementing: + // bool IsContainer() const + // { return m_children.GetCount()>0; } + // doesn't work with wxGTK when MyMusicTreeModel::AddToClassical is called + // AND the classical node was removed (a new node temporary without children + // would be added to the control) + bool m_container; + +private: + MyMusicTreeModelNode *m_parent; + MyMusicTreeModelNodePtrArray m_children; +}; + + +// ---------------------------------------------------------------------------- +// MyMusicTreeModel +// ---------------------------------------------------------------------------- + +/* +Implement this data model +Title Artist Year Judgement +-------------------------------------------------------------------------- +1: My Music: +2: Pop music +3: You are not alone Michael Jackson 1995 good +4: Take a bow Madonna 1994 good +5: Classical music +6: Ninth Symphony Ludwig v. Beethoven 1824 good +7: German Requiem Johannes Brahms 1868 good +*/ + +class MyMusicTreeModel : public wxDataViewModel +{ +public: + MyMusicTreeModel(); + ~MyMusicTreeModel() + { + delete m_root; + } + + // helper method for wxLog + + wxString GetTitle(const wxDataViewItem &item) const; + wxString GetArtist(const wxDataViewItem &item) const; + int GetYear(const wxDataViewItem &item) const; + + // helper methods to change the model + + void AddToClassical(const wxString &title, const wxString &artist, + unsigned int year); + void Delete(const wxDataViewItem &item); + + wxDataViewItem GetNinthItem() const + { + return wxDataViewItem(m_ninth); + } + + // override sorting to always sort branches ascendingly + + int Compare(const wxDataViewItem &item1, const wxDataViewItem &item2, + unsigned int column, bool ascending) const override;//; + + // implementation of base class virtuals to define model + + virtual unsigned int GetColumnCount() const override//wxOVERRIDE + { + return 6; + } + + virtual wxString GetColumnType(unsigned int col) const override//wxOVERRIDE + { + if (col == 2) + return wxT("long"); + + return wxT("string"); + } + + virtual void GetValue(wxVariant &variant, + const wxDataViewItem &item, unsigned int col) const override;//wxOVERRIDE; + virtual bool SetValue(const wxVariant &variant, + const wxDataViewItem &item, unsigned int col) override;//wxOVERRIDE; + + virtual bool IsEnabled(const wxDataViewItem &item, + unsigned int col) const override;//wxOVERRIDE; + + virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override;//wxOVERRIDE; + virtual bool IsContainer(const wxDataViewItem &item) const override;//wxOVERRIDE; + virtual unsigned int GetChildren(const wxDataViewItem &parent, + wxDataViewItemArray &array) const override;//wxOVERRIDE; + +private: + MyMusicTreeModelNode* m_root; + + // pointers to some "special" nodes of the tree: + MyMusicTreeModelNode* m_pop; + MyMusicTreeModelNode* m_classical; + MyMusicTreeModelNode* m_ninth; + + // ?? + bool m_classicalMusicIsKnownToControl; +}; + +// ****************************************************************************************** #endif // slic3r_GUI_wxExtensions_hpp_