diff --git a/include/wex/metro.h b/include/wex/metro.h index 78da26d3..346dd1d7 100644 --- a/include/wex/metro.h +++ b/include/wex/metro.h @@ -425,142 +425,249 @@ class wxMetroListBox : public wxScrolledWindow { DECLARE_EVENT_TABLE(); }; - -class wxMetroDataViewModelNode; -WX_DEFINE_ARRAY_PTR(wxMetroDataViewModelNode*, wxMetroDataViewModelNodePtrArray); - -class wxMetroDataViewModelNode +//-------------------------------------------------------------------- +class wxMetroDataViewTreeStoreNode { public: - wxMetroDataViewModelNode(wxMetroDataViewModelNode* parent, - const wxString& name, const bool& is_container) + wxMetroDataViewTreeStoreNode(wxMetroDataViewTreeStoreNode* parent, + const wxString& text, + wxClientData* data = NULL); + virtual ~wxMetroDataViewTreeStoreNode(); + + void SetText(const wxString& text) + { + m_text = text; + } + wxString GetText() const + { + return m_text; + } + void SetData(wxClientData* data) + { + delete m_data; m_data = data; + } + wxClientData* GetData() const { - m_parent = parent; - m_name = name; - m_container = is_container; + return m_data; } - - ~wxMetroDataViewModelNode() + wxDataViewItem GetItem() const { - // free all our children nodes - size_t count = m_children.GetCount(); - for (size_t i = 0; i < count; i++) { - wxMetroDataViewModelNode* child = m_children[i]; - delete child; - } + return wxDataViewItem(const_cast(static_cast(this))); } - bool IsContainer() const + virtual bool IsContainer() { - return m_container; + return false; } - wxMetroDataViewModelNode* GetParent() + wxMetroDataViewTreeStoreNode* GetParent() { return m_parent; } - wxMetroDataViewModelNodePtrArray& GetChildren() + +private: + wxMetroDataViewTreeStoreNode* m_parent; + wxString m_text; + wxClientData* m_data; +}; + +typedef wxVector wxMetroDataViewTreeStoreNodes; + +class wxMetroDataViewTreeStoreContainerNode : public wxMetroDataViewTreeStoreNode +{ +public: + wxMetroDataViewTreeStoreContainerNode(wxMetroDataViewTreeStoreNode* parent, + const wxString& text, + wxClientData* data = NULL); + virtual ~wxMetroDataViewTreeStoreContainerNode(); + + const wxMetroDataViewTreeStoreNodes& GetChildren() const { return m_children; } - wxMetroDataViewModelNode* GetNthChild(unsigned int n) + wxMetroDataViewTreeStoreNodes& GetChildren() { - return m_children.Item(n); + return m_children; } - void Insert(wxMetroDataViewModelNode* child, unsigned int n) + + wxMetroDataViewTreeStoreNodes::iterator FindChild(wxMetroDataViewTreeStoreNode* node); + + void SetExpanded(bool expanded = true) { - m_children.Insert(child, n); + m_isExpanded = expanded; } - void Append(wxMetroDataViewModelNode* child) + bool IsExpanded() const { - m_children.Add(child); + return m_isExpanded; } - unsigned int GetChildCount() const + + virtual bool IsContainer() wxOVERRIDE { - return m_children.GetCount(); + return true; } -public: // public to avoid getters/setters - wxString m_name; - - bool m_container; + void DestroyChildren(); private: - wxMetroDataViewModelNode* m_parent; - wxMetroDataViewModelNodePtrArray m_children; + wxMetroDataViewTreeStoreNodes m_children; + bool m_isExpanded; }; +//----------------------------------------------------------------------------- -class wxMetroDataViewModel : public wxDataViewModel { +class wxMetroDataViewTreeStore : public wxDataViewModel +{ public: - wxMetroDataViewModel(); - ~wxMetroDataViewModel() - { - DeleteAllItems(); - } + wxMetroDataViewTreeStore(); + ~wxMetroDataViewTreeStore(); - // override sorting to always sort branches ascendingly + wxDataViewItem AppendItem(const wxDataViewItem& parent, + const wxString& text, + wxClientData* data = NULL); + wxDataViewItem PrependItem(const wxDataViewItem& parent, + const wxString& text, + wxClientData* data = NULL); + wxDataViewItem InsertItem(const wxDataViewItem& parent, const wxDataViewItem& previous, + const wxString& text, + wxClientData* data = NULL); - int Compare(const wxDataViewItem& item1, const wxDataViewItem& item2, - unsigned int column, bool ascending) const wxOVERRIDE; + wxDataViewItem PrependContainer(const wxDataViewItem& parent, + const wxString& text, + wxClientData* data = NULL); + wxDataViewItem AppendContainer(const wxDataViewItem& parent, + const wxString& text, + wxClientData* data = NULL); + wxDataViewItem InsertContainer(const wxDataViewItem& parent, const wxDataViewItem& previous, + const wxString& text, + wxClientData* data = NULL); + + wxDataViewItem GetNthChild(const wxDataViewItem& parent, unsigned int pos) const; + int GetChildCount(const wxDataViewItem& parent) const; + + void SetItemText(const wxDataViewItem& item, const wxString& text); + wxString GetItemText(const wxDataViewItem& item) const; + void SetItemData(const wxDataViewItem& item, wxClientData* data); + wxClientData* GetItemData(const wxDataViewItem& item) const; - // implementation of base class virtuals to define model + void DeleteItem(const wxDataViewItem& item); + void DeleteChildren(const wxDataViewItem& item); + void DeleteAllItems(); + + // implement base methods virtual void GetValue(wxVariant& variant, const wxDataViewItem& item, unsigned int col) const wxOVERRIDE; virtual bool SetValue(const wxVariant& variant, const wxDataViewItem& item, unsigned int col) wxOVERRIDE; - - virtual bool IsEnabled(const wxDataViewItem& item, - unsigned int col) const wxOVERRIDE; - virtual wxDataViewItem GetParent(const wxDataViewItem& item) const wxOVERRIDE; virtual bool IsContainer(const wxDataViewItem& item) const wxOVERRIDE; - virtual unsigned int GetChildren(const wxDataViewItem& parent, - wxDataViewItemArray& array) const wxOVERRIDE; - - wxString GetItemtext(const wxDataViewItem& item) const; + virtual unsigned int GetChildren(const wxDataViewItem& item, wxDataViewItemArray& children) const wxOVERRIDE; - void DeleteAllItems(); + virtual int Compare(const wxDataViewItem& item1, const wxDataViewItem& item2, + unsigned int column, bool ascending) const wxOVERRIDE; - wxDataViewItem AppendItem(const wxDataViewItem& parent, const wxString& text); + virtual bool HasDefaultCompare() const wxOVERRIDE + { + return true; + } - wxDataViewItem AppendContainer(const wxDataViewItem& parent, const wxString& text); + wxMetroDataViewTreeStoreNode* FindNode(const wxDataViewItem& item) const; + wxMetroDataViewTreeStoreContainerNode* FindContainerNode(const wxDataViewItem& item) const; + wxMetroDataViewTreeStoreNode* GetRoot() const { return m_root; } -private: - wxMetroDataViewModelNode* m_root; - +public: + wxMetroDataViewTreeStoreNode* m_root; }; -class wxMetroDataViewCtrl : public wxDataViewCtrl { + +class wxMetroDataViewTreeCtrl : public wxDataViewCtrl +{ public: - wxMetroDataViewCtrl(wxWindow* parent, int id, - const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize) - : wxDataViewCtrl(parent, id, pos, size) { - SetBackgroundStyle(wxBG_STYLE_CUSTOM); - SetBackgroundColour(*wxWHITE); - SetFont(wxMetroTheme::Font(wxMT_LIGHT, 15)); - - m_model = new wxMetroDataViewModel; - AssociateModel(m_model.get()); - - wxDataViewTextRenderer* tr = new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_INERT); - wxDataViewColumn* column0 = new wxDataViewColumn("title", tr, 0, FromDIP(200), wxALIGN_LEFT, wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE); - AppendColumn(column0); + wxMetroDataViewTreeCtrl() { } + wxMetroDataViewTreeCtrl(wxWindow* parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDV_NO_HEADER, + const wxValidator& validator = wxDefaultValidator) + { + Create(parent, id, pos, size, style, validator); + } + + bool Create(wxWindow* parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDV_NO_HEADER, + const wxValidator& validator = wxDefaultValidator); + + wxMetroDataViewTreeStore* GetStore() + { + return (wxMetroDataViewTreeStore*)GetModel(); + } + const wxMetroDataViewTreeStore* GetStore() const + { + return (const wxMetroDataViewTreeStore*)GetModel(); + } + + bool IsContainer(const wxDataViewItem& item) const + { + return GetStore()->IsContainer(item); } - bool IsContainer(const wxDataViewItem& item) { return m_model->IsContainer(item); } - wxString GetItemText(const wxDataViewItem& item) { return m_model->GetItemtext(item); } + wxDataViewItem AppendItem(const wxDataViewItem& parent, + const wxString& text, wxClientData* data = NULL); + wxDataViewItem PrependItem(const wxDataViewItem& parent, + const wxString& text, wxClientData* data = NULL); + wxDataViewItem InsertItem(const wxDataViewItem& parent, const wxDataViewItem& previous, + const wxString& text, wxClientData* data = NULL); + + wxDataViewItem PrependContainer(const wxDataViewItem& parent, + const wxString& text, wxClientData* data = NULL); + wxDataViewItem AppendContainer(const wxDataViewItem& parent, + const wxString& text, wxClientData* data = NULL); + wxDataViewItem InsertContainer(const wxDataViewItem& parent, const wxDataViewItem& previous, + const wxString& text, wxClientData* data = NULL); + + wxDataViewItem GetNthChild(const wxDataViewItem& parent, unsigned int pos) const + { + return GetStore()->GetNthChild(parent, pos); + } + int GetChildCount(const wxDataViewItem& parent) const + { + return GetStore()->GetChildCount(parent); + } + wxDataViewItem GetItemParent(wxDataViewItem item) const + { + return GetStore()->GetParent(item); + } - void DeleteAllItems() { m_model->DeleteAllItems(); } + void SetItemText(const wxDataViewItem& item, const wxString& text); + wxString GetItemText(const wxDataViewItem& item) const + { + return GetStore()->GetItemText(item); + } + void SetItemData(const wxDataViewItem& item, wxClientData* data) + { + GetStore()->SetItemData(item, data); + } + wxClientData* GetItemData(const wxDataViewItem& item) const + { + return GetStore()->GetItemData(item); + } - wxDataViewItem AppendItem(const wxDataViewItem& parent, const wxString& text) { return m_model->AppendItem(parent, text); } + void DeleteItem(const wxDataViewItem& item); + void DeleteChildren(const wxDataViewItem& item); + void DeleteAllItems(); - wxDataViewItem AppendContainer(const wxDataViewItem& parent, const wxString& text) { return m_model->AppendContainer(parent, text); } + void OnExpanded(wxDataViewEvent& event); + void OnCollapsed(wxDataViewEvent& event); + void OnSize(wxSizeEvent& event); private: - wxObjectDataPtr m_model; + wxDECLARE_EVENT_TABLE(); + wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxMetroDataViewTreeCtrl); }; diff --git a/src/metro.cpp b/src/metro.cpp index 913668b5..254234a7 100644 --- a/src/metro.cpp +++ b/src/metro.cpp @@ -1724,173 +1724,574 @@ void wxMetroPopupMenu::Popup(wxWindow *parent, const wxPoint &pos, int origin) { menu->Popup(pos, origin); } +//------------------------------------------------------------------------------------ +wxMetroDataViewTreeStoreNode::wxMetroDataViewTreeStoreNode( + wxMetroDataViewTreeStoreNode* parent, + const wxString& text, wxClientData* data) + : m_text(text) +{ + m_parent = parent; + m_data = data; +} -wxString wxMetroDataViewModel::GetItemtext(const wxDataViewItem& item) const +wxMetroDataViewTreeStoreNode::~wxMetroDataViewTreeStoreNode() { - wxMetroDataViewModelNode* node = (wxMetroDataViewModelNode*)item.GetID(); - if (!node) // happens if item.IsOk()==false - return wxEmptyString; + delete m_data; +} - return node->m_name; +wxMetroDataViewTreeStoreContainerNode::wxMetroDataViewTreeStoreContainerNode( + wxMetroDataViewTreeStoreNode* parent, const wxString& text, wxClientData* data) + : wxMetroDataViewTreeStoreNode(parent, text, data) +{ + m_isExpanded = false; } -void wxMetroDataViewModel::GetValue(wxVariant& variant, const wxDataViewItem& item, unsigned int col) const +wxMetroDataViewTreeStoreContainerNode::~wxMetroDataViewTreeStoreContainerNode() { -// if (item) { - wxMetroDataViewModelNode* node = (wxMetroDataViewModelNode*)item.GetID(); - switch (col) - { - case 0: - if (node) - variant = node->m_name; - else - variant = wxEmptyString; - break; - default: - wxLogError("wxMetroDataViewModel::GetValue: wrong column %d", col); - } - // } - // else - // variant = wxEmptyString; + DestroyChildren(); } -bool wxMetroDataViewModel::SetValue(const wxVariant& variant, const wxDataViewItem& item, unsigned int col) +wxMetroDataViewTreeStoreNodes::iterator +wxMetroDataViewTreeStoreContainerNode::FindChild(wxMetroDataViewTreeStoreNode* node) { -// wxASSERT(item.IsOk()); - if (!item) { - return false; + wxMetroDataViewTreeStoreNodes::iterator iter; + for (iter = m_children.begin(); iter != m_children.end(); ++iter) + { + if (*iter == node) + break; } - else { - wxMetroDataViewModelNode* node = (wxMetroDataViewModelNode*)item.GetID(); - switch (col) - { - case 0: - node->m_name = variant.GetString(); - return true; - default: - wxLogError("wxMetroDataViewModel::SetValue: wrong column"); - } - return false; + + return iter; +} + +void wxMetroDataViewTreeStoreContainerNode::DestroyChildren() +{ + wxMetroDataViewTreeStoreNodes::const_iterator iter; + for (iter = m_children.begin(); iter != m_children.end(); ++iter) + { + delete* iter; } + + m_children.clear(); } -bool wxMetroDataViewModel::IsEnabled(const wxDataViewItem& item, - unsigned int col) const +//----------------------------------------------------------------------------- + +wxMetroDataViewTreeStore::wxMetroDataViewTreeStore() { - // wxASSERT(item.IsOk()); - // do not allow editing - return true; + m_root = new wxMetroDataViewTreeStoreContainerNode(NULL, wxEmptyString); } -wxDataViewItem wxMetroDataViewModel::GetParent(const wxDataViewItem& item) const +wxMetroDataViewTreeStore::~wxMetroDataViewTreeStore() { - // the invisible root node has no parent - if (!item.IsOk()) - return wxDataViewItem(0); + delete m_root; +} - wxMetroDataViewModelNode* node = (wxMetroDataViewModelNode*)item.GetID(); +wxDataViewItem wxMetroDataViewTreeStore::AppendItem(const wxDataViewItem& parent, + const wxString& text, wxClientData* data) +{ + wxMetroDataViewTreeStoreContainerNode* parent_node = FindContainerNode(parent); + if (!parent_node) return wxDataViewItem(0); - return wxDataViewItem((void*)node->GetParent()); + wxMetroDataViewTreeStoreNode* node = + new wxMetroDataViewTreeStoreNode(parent_node, text, data); + parent_node->GetChildren().push_back(node); + + return node->GetItem(); } -bool wxMetroDataViewModel::IsContainer(const wxDataViewItem& item) const +wxDataViewItem wxMetroDataViewTreeStore::PrependItem(const wxDataViewItem& parent, + const wxString& text, wxClientData* data) { - // the invisible root node can have children - if (!item.IsOk()) - return true; + wxMetroDataViewTreeStoreContainerNode* parent_node = FindContainerNode(parent); + if (!parent_node) return wxDataViewItem(0); + + wxMetroDataViewTreeStoreNode* node = + new wxMetroDataViewTreeStoreNode(parent_node, text, data); + wxMetroDataViewTreeStoreNodes& children = parent_node->GetChildren(); + children.insert(children.begin(), node); + + return node->GetItem(); +} + +wxDataViewItem +wxMetroDataViewTreeStore::InsertItem(const wxDataViewItem& parent, + const wxDataViewItem& previous, + const wxString& text, + wxClientData* data) +{ + wxMetroDataViewTreeStoreContainerNode* parent_node = FindContainerNode(parent); + if (!parent_node) return wxDataViewItem(0); + + wxMetroDataViewTreeStoreNode* previous_node = FindNode(previous); + wxMetroDataViewTreeStoreNodes& children = parent_node->GetChildren(); + const wxMetroDataViewTreeStoreNodes::iterator iter = parent_node->FindChild(previous_node); + if (iter == children.end()) return wxDataViewItem(0); + + wxMetroDataViewTreeStoreNode* node = + new wxMetroDataViewTreeStoreNode(parent_node, text, data); + children.insert(iter, node); + + return node->GetItem(); +} + +wxDataViewItem wxMetroDataViewTreeStore::PrependContainer(const wxDataViewItem& parent, + const wxString& text, wxClientData* data) +{ + wxMetroDataViewTreeStoreContainerNode* parent_node = FindContainerNode(parent); + if (!parent_node) return wxDataViewItem(0); + + wxMetroDataViewTreeStoreContainerNode* node = + new wxMetroDataViewTreeStoreContainerNode(parent_node, text, data); + wxMetroDataViewTreeStoreNodes& children = parent_node->GetChildren(); + children.insert(children.begin(), node); + + return node->GetItem(); +} + +wxDataViewItem +wxMetroDataViewTreeStore::AppendContainer(const wxDataViewItem& parent, + const wxString& text, + wxClientData* data) +{ + wxMetroDataViewTreeStoreContainerNode* parent_node = FindContainerNode(parent); + if (!parent_node) return wxDataViewItem(0); + + wxMetroDataViewTreeStoreContainerNode* node = + new wxMetroDataViewTreeStoreContainerNode(parent_node, text, data); + parent_node->GetChildren().push_back(node); + + return node->GetItem(); +} + +wxDataViewItem +wxMetroDataViewTreeStore::InsertContainer(const wxDataViewItem& parent, + const wxDataViewItem& previous, + const wxString& text, + wxClientData* data) +{ + wxMetroDataViewTreeStoreContainerNode* parent_node = FindContainerNode(parent); + if (!parent_node) return wxDataViewItem(0); + + wxMetroDataViewTreeStoreNode* previous_node = FindNode(previous); + wxMetroDataViewTreeStoreNodes& children = parent_node->GetChildren(); + const wxMetroDataViewTreeStoreNodes::iterator iter = parent_node->FindChild(previous_node); + if (iter == children.end()) return wxDataViewItem(0); + + wxMetroDataViewTreeStoreContainerNode* node = + new wxMetroDataViewTreeStoreContainerNode(parent_node, text, data); + children.insert(iter, node); + + return node->GetItem(); +} + +bool wxMetroDataViewTreeStore::IsContainer(const wxDataViewItem& item) const +{ + wxMetroDataViewTreeStoreNode* node = FindNode(item); + if (!node) return false; - wxMetroDataViewModelNode* node = (wxMetroDataViewModelNode*)item.GetID(); return node->IsContainer(); } -unsigned int wxMetroDataViewModel::GetChildren(const wxDataViewItem& parent, - wxDataViewItemArray& array) const +wxDataViewItem wxMetroDataViewTreeStore::GetNthChild(const wxDataViewItem& parent, unsigned int pos) const { - wxMetroDataViewModelNode* node = (wxMetroDataViewModelNode*)parent.GetID(); - if (!node) { - array.Add(wxDataViewItem(0)); - return 1; - } + wxMetroDataViewTreeStoreContainerNode* parent_node = FindContainerNode(parent); + if (!parent_node) return wxDataViewItem(0); + + wxMetroDataViewTreeStoreNode* const node = parent_node->GetChildren()[pos]; + if (node) + return node->GetItem(); + + return wxDataViewItem(0); +} - if (node->GetChildCount() == 0) { +int wxMetroDataViewTreeStore::GetChildCount(const wxDataViewItem& parent) const +{ + wxMetroDataViewTreeStoreNode* node = FindNode(parent); + if (!node) return -1; + + if (!node->IsContainer()) return 0; - } - unsigned int count = node->GetChildren().GetCount(); - for (unsigned int pos = 0; pos < count; pos++) { - wxMetroDataViewModelNode* child = node->GetChildren().Item(pos); - array.Add(wxDataViewItem((void*)child)); + wxMetroDataViewTreeStoreContainerNode* container_node = (wxMetroDataViewTreeStoreContainerNode*)node; + return (int)container_node->GetChildren().size(); +} + +void wxMetroDataViewTreeStore::SetItemText(const wxDataViewItem& item, const wxString& text) +{ + wxMetroDataViewTreeStoreNode* node = FindNode(item); + if (!node) return; + + node->SetText(text); +} + +wxString wxMetroDataViewTreeStore::GetItemText(const wxDataViewItem& item) const +{ + wxMetroDataViewTreeStoreNode* node = FindNode(item); + if (!node) return wxEmptyString; + + return node->GetText(); +} + +void wxMetroDataViewTreeStore::SetItemData(const wxDataViewItem& item, wxClientData* data) +{ + wxMetroDataViewTreeStoreNode* node = FindNode(item); + if (!node) return; + + node->SetData(data); +} + +wxClientData* wxMetroDataViewTreeStore::GetItemData(const wxDataViewItem& item) const +{ + wxMetroDataViewTreeStoreNode* node = FindNode(item); + if (!node) return NULL; + + return node->GetData(); +} + +void wxMetroDataViewTreeStore::DeleteItem(const wxDataViewItem& item) +{ + if (!item.IsOk()) return; + + wxDataViewItem parent_item = GetParent(item); + + wxMetroDataViewTreeStoreContainerNode* parent_node = FindContainerNode(parent_item); + if (!parent_node) return; + + const wxMetroDataViewTreeStoreNodes::iterator + iter = parent_node->FindChild(FindNode(item)); + if (iter != parent_node->GetChildren().end()) + { + delete* iter; + parent_node->GetChildren().erase(iter); } +} - return count; +void wxMetroDataViewTreeStore::DeleteChildren(const wxDataViewItem& item) +{ + wxMetroDataViewTreeStoreContainerNode* node = FindContainerNode(item); + if (!node) return; + + node->DestroyChildren(); } -void wxMetroDataViewModel::DeleteAllItems() +void wxMetroDataViewTreeStore::DeleteAllItems() { -/* -// wxMetroDataViewModelNode* root = (wxMetroDataViewModelNode*)wxDataViewItem(0).GetID(); -// if (root) { - while (!m_root->GetChildren().IsEmpty()) - { - wxMetroDataViewModelNode* node = m_root->GetNthChild(0); - m_root->GetChildren().Remove(node); - delete node; - } -// } - Cleared(); + DeleteChildren(wxDataViewItem(m_root)); +} + +void +wxMetroDataViewTreeStore::GetValue(wxVariant& variant, + const wxDataViewItem& item, + unsigned int WXUNUSED(col)) const +{ + // if (col != 0) return; + + wxMetroDataViewTreeStoreNode* node = FindNode(item); + if (!node) return; + /* + wxBitmapBundle bb; + if (node->IsContainer()) + { + wxMetroDataViewTreeStoreContainerNode* container = (wxMetroDataViewTreeStoreContainerNode*)node; + if (container->IsExpanded()) + bb = container->GetExpandedBitmapBundle(); + } + + if (!bb.IsOk()) + bb = node->GetBitmapBundle(); + + wxDataViewIconText data(node->GetText(), bb); + + variant << data; */ + variant = node->GetText(); } -wxMetroDataViewModel::wxMetroDataViewModel() +bool +wxMetroDataViewTreeStore::SetValue(const wxVariant& variant, + const wxDataViewItem& item, + unsigned int WXUNUSED(col)) { - m_root = new wxMetroDataViewModelNode(NULL, wxEmptyString, true); + // if (col != 0) return false; + + wxMetroDataViewTreeStoreNode* node = FindNode(item); + if (!node) return false; + + wxDataViewIconText data; + + data << variant; + + node->SetText(data.GetText()); + + return true; +} + +wxDataViewItem wxMetroDataViewTreeStore::GetParent(const wxDataViewItem& item) const +{ + wxMetroDataViewTreeStoreNode* node = FindNode(item); + if (!node) return wxDataViewItem(0); + + wxMetroDataViewTreeStoreNode* parent = node->GetParent(); + if (!parent) return wxDataViewItem(0); + + if (parent == m_root) + return wxDataViewItem(0); + + return parent->GetItem(); } -int wxMetroDataViewModel::Compare(const wxDataViewItem& item1, const wxDataViewItem& item2, - unsigned int column, bool ascending) const +unsigned int wxMetroDataViewTreeStore::GetChildren(const wxDataViewItem& item, wxDataViewItemArray& children) const { - wxASSERT(item1.IsOk() && item2.IsOk()); - // should never happen + wxMetroDataViewTreeStoreContainerNode* node = FindContainerNode(item); + if (!node) return 0; - if (IsContainer(item1) && IsContainer(item2)) + wxMetroDataViewTreeStoreNodes::iterator iter; + for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); ++iter) { - wxVariant value1, value2; - GetValue(value1, item1, 0); - GetValue(value2, item2, 0); + wxMetroDataViewTreeStoreNode* child = *iter; + children.Add(child->GetItem()); + } + + return node->GetChildren().size(); +} + +int wxMetroDataViewTreeStore::Compare(const wxDataViewItem& item1, const wxDataViewItem& item2, + unsigned int WXUNUSED(column), bool WXUNUSED(ascending)) const +{ + wxMetroDataViewTreeStoreNode* node1 = FindNode(item1); + wxMetroDataViewTreeStoreNode* node2 = FindNode(item2); + + if (!node1 || !node2 || (node1 == node2)) + return 0; + + wxMetroDataViewTreeStoreContainerNode* const parent = + (wxMetroDataViewTreeStoreContainerNode*)node1->GetParent(); + + wxCHECK_MSG(node2->GetParent() == parent, 0, + wxS("Comparing items with different parent.")); + + if (node1->IsContainer() && !node2->IsContainer()) + return -1; + + if (node2->IsContainer() && !node1->IsContainer()) + return 1; + + wxMetroDataViewTreeStoreNodes::const_iterator iter; + for (iter = parent->GetChildren().begin(); iter != parent->GetChildren().end(); ++iter) + { + if (*iter == node1) + return -1; + + if (*iter == node2) + return 1; + } + + wxFAIL_MSG(wxS("Unreachable")); + return 0; +} + +wxMetroDataViewTreeStoreNode* wxMetroDataViewTreeStore::FindNode(const wxDataViewItem& item) const +{ + if (!item.IsOk()) + return m_root; + + return (wxMetroDataViewTreeStoreNode*)item.GetID(); +} + +wxMetroDataViewTreeStoreContainerNode* wxMetroDataViewTreeStore::FindContainerNode(const wxDataViewItem& item) const +{ + if (!item.IsOk()) + return (wxMetroDataViewTreeStoreContainerNode*)m_root; + + wxMetroDataViewTreeStoreNode* node = (wxMetroDataViewTreeStoreNode*)item.GetID(); + + if (!node->IsContainer()) + return NULL; + + return (wxMetroDataViewTreeStoreContainerNode*)node; +} + +//----------------------------------------------------------------------------- +// wxMetroDataViewTreeCtrl +//----------------------------------------------------------------------------- + +wxIMPLEMENT_DYNAMIC_CLASS(wxMetroDataViewTreeCtrl, wxDataViewCtrl); + +wxBEGIN_EVENT_TABLE(wxMetroDataViewTreeCtrl, wxDataViewCtrl) +EVT_DATAVIEW_ITEM_EXPANDED(-1, wxMetroDataViewTreeCtrl::OnExpanded) +EVT_DATAVIEW_ITEM_COLLAPSED(-1, wxMetroDataViewTreeCtrl::OnCollapsed) +EVT_SIZE(wxMetroDataViewTreeCtrl::OnSize) +wxEND_EVENT_TABLE() + +bool wxMetroDataViewTreeCtrl::Create(wxWindow* parent, wxWindowID id, + const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator) +{ + if (!wxDataViewCtrl::Create(parent, id, pos, size, style, validator)) + return false; + + SetBackgroundStyle(wxBG_STYLE_CUSTOM); + SetBackgroundColour(*wxWHITE); + SetFont(wxMetroTheme::Font(wxMT_LIGHT, 15)); + + // create the standard model and a column in the tree + wxMetroDataViewTreeStore* store = new wxMetroDataViewTreeStore; + AssociateModel(store); + store->DecRef(); + + AppendTextColumn + ( + wxString(), // no label (header is not shown anyhow) + 0, // the only model column + wxDATAVIEW_CELL_INERT, + -1, // default width + wxALIGN_NOT, // and alignment + 0 // not resizable + ); + + return true; +} + +wxDataViewItem wxMetroDataViewTreeCtrl::AppendItem(const wxDataViewItem& parent, + const wxString& text, wxClientData* data) +{ + wxDataViewItem res = GetStore()-> + AppendItem(parent, text, data); + + GetStore()->ItemAdded(parent, res); + + return res; +} + +wxDataViewItem wxMetroDataViewTreeCtrl::PrependItem(const wxDataViewItem& parent, + const wxString& text, wxClientData* data) +{ + wxDataViewItem res = GetStore()-> + PrependItem(parent, text, data); + + GetStore()->ItemAdded(parent, res); + + return res; +} + +wxDataViewItem wxMetroDataViewTreeCtrl::InsertItem(const wxDataViewItem& parent, const wxDataViewItem& previous, + const wxString& text, wxClientData* data) +{ + wxDataViewItem res = GetStore()-> + InsertItem(parent, previous, text, data); + + GetStore()->ItemAdded(parent, res); + + return res; +} + +wxDataViewItem wxMetroDataViewTreeCtrl::PrependContainer(const wxDataViewItem& parent, + const wxString& text, wxClientData* data) +{ + wxDataViewItem res = GetStore()-> + PrependContainer(parent, text, data); + + GetStore()->ItemAdded(parent, res); + + return res; +} + +wxDataViewItem wxMetroDataViewTreeCtrl::AppendContainer(const wxDataViewItem& parent, + const wxString& text, wxClientData* data) +{ + wxDataViewItem res = GetStore()-> + AppendContainer(parent, text, data); + + GetStore()->ItemAdded(parent, res); + + return res; +} - wxString str1 = value1.GetString(); - wxString str2 = value2.GetString(); - int res = str1.Cmp(str2); - if (res) return res; +wxDataViewItem wxMetroDataViewTreeCtrl::InsertContainer(const wxDataViewItem& parent, const wxDataViewItem& previous, + const wxString& text, wxClientData* data) +{ + wxDataViewItem res = GetStore()-> + InsertContainer(parent, previous, text, data); + + GetStore()->ItemAdded(parent, res); + + return res; +} + +void wxMetroDataViewTreeCtrl::SetItemText(const wxDataViewItem& item, const wxString& text) +{ + GetStore()->SetItemText(item, text); + + // notify control + GetStore()->ValueChanged(item, 0); +} + + +void wxMetroDataViewTreeCtrl::DeleteItem(const wxDataViewItem& item) +{ + wxDataViewItem parent_item = GetStore()->GetParent(item); - // items must be different - wxUIntPtr litem1 = (wxUIntPtr)item1.GetID(); - wxUIntPtr litem2 = (wxUIntPtr)item2.GetID(); + GetStore()->DeleteItem(item); - return litem1 - litem2; + // notify control + GetStore()->ItemDeleted(parent_item, item); +} + +void wxMetroDataViewTreeCtrl::DeleteChildren(const wxDataViewItem& item) +{ + wxMetroDataViewTreeStoreContainerNode* node = GetStore()->FindContainerNode(item); + if (!node) return; + + wxDataViewItemArray array; + wxMetroDataViewTreeStoreNodes::iterator iter; + for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); ++iter) + { + wxMetroDataViewTreeStoreNode* child = *iter; + array.Add(child->GetItem()); } - return wxDataViewModel::Compare(item1, item2, column, ascending); + GetStore()->DeleteChildren(item); + + // notify control + GetStore()->ItemsDeleted(item, array); } +void wxMetroDataViewTreeCtrl::DeleteAllItems() +{ + GetStore()->DeleteAllItems(); -wxDataViewItem wxMetroDataViewModel::AppendItem(const wxDataViewItem& parent, const wxString& text) + GetStore()->Cleared(); +} + +void wxMetroDataViewTreeCtrl::OnExpanded(wxDataViewEvent& event) { - wxMetroDataViewModelNode* nodeparent = (wxMetroDataViewModelNode*)parent.GetID(); - if (!nodeparent) nodeparent = m_root; + wxMetroDataViewTreeStoreContainerNode* container = GetStore()->FindContainerNode(event.GetItem()); + if (!container) return; - wxMetroDataViewModelNode* node = new wxMetroDataViewModelNode(nodeparent, text, false); - nodeparent->GetChildren().push_back(node); + container->SetExpanded(true); - return wxDataViewItem((void*)node); + GetStore()->ItemChanged(event.GetItem()); } -wxDataViewItem wxMetroDataViewModel::AppendContainer(const wxDataViewItem& parent, const wxString& text) +void wxMetroDataViewTreeCtrl::OnCollapsed(wxDataViewEvent& event) { - wxMetroDataViewModelNode* nodeparent = (wxMetroDataViewModelNode*)parent.GetID(); - if (!nodeparent) nodeparent =m_root; - wxMetroDataViewModelNode* node = new wxMetroDataViewModelNode(nodeparent, text, true); - nodeparent->GetChildren().push_back(node); - return wxDataViewItem((void*)node->GetParent()); + wxMetroDataViewTreeStoreContainerNode* container = GetStore()->FindContainerNode(event.GetItem()); + if (!container) return; + + container->SetExpanded(false); + + GetStore()->ItemChanged(event.GetItem()); } +void wxMetroDataViewTreeCtrl::OnSize(wxSizeEvent& event) +{ +#if defined(wxHAS_GENERIC_DATAVIEWCTRL) + // automatically resize our only column to take the entire control width + if (GetColumnCount()) + { + wxSize size = GetClientSize(); + GetColumn(0)->SetWidth(size.x); + } +#endif + event.Skip(true); +}