First experiments with ObjectsTreeList

This commit is contained in:
YuSanka 2018-05-04 18:32:20 +02:00
parent 993294579d
commit db549e8609
4 changed files with 992 additions and 2 deletions

View file

@ -72,7 +72,7 @@ sub new {
});
# Initialize preview notebook
$self->{preview_notebook} = Wx::Notebook->new($self, -1, wxDefaultPosition, [335,335], wxNB_BOTTOM);
$self->{preview_notebook} = Wx::Notebook->new($self, -1, wxDefaultPosition, [-1,335], wxNB_BOTTOM);
# Initialize handlers for canvases
my $on_select_object = sub {
@ -485,6 +485,7 @@ sub new {
$buttons_sizer->Add($self->{btn_export_gcode}, 0, wxALIGN_RIGHT, 0);
my $right_sizer = Wx::BoxSizer->new(wxVERTICAL);
$right_sizer->SetMinSize([-1, 600]);
$right_sizer->Add($presets, 0, wxEXPAND | wxTOP, 10) if defined $presets;
$right_sizer->Add($frequently_changed_parameters_sizer, 0, wxEXPAND | wxTOP, 0) if defined $frequently_changed_parameters_sizer;
$right_sizer->Add($buttons_sizer, 0, wxEXPAND | wxBOTTOM, 5);
@ -522,6 +523,7 @@ sub new {
}
$self->update_ui_from_settings();
$self->Layout;
return $self;
}

View file

@ -812,6 +812,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
// Experiments with new UI
wxCollapsiblePane *collpane = new wxCollapsiblePane(parent, wxID_ANY, "Print settings:");
collpane->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, ([parent, collpane](wxCommandEvent e){
wxWindowUpdateLocker noUpdates_cp(collpane);
wxWindowUpdateLocker noUpdates(parent);
parent->Layout();
collpane->Refresh();
@ -942,9 +943,142 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
};
m_optgroup->append_line(line);
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<wxVariant> 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, wxID_ANY, wxDefaultPosition, wxDefaultSize);
wxSizer *objects_sz = new wxBoxSizer(wxVERTICAL);
objects_ctrl->SetMinSize(wxSize(-1, 200));
objects_sz->Add(objects_ctrl, 1, wxGROW | wxALL, 5);
auto objects_model = new MyObjectTreeModel;
objects_ctrl->AssociateModel(objects_model);
#if wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
objects_ctrl->EnableDragSource(wxDF_UNICODETEXT);
objects_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 *column00 = new wxDataViewColumn("Name", tr, 0, 150, wxALIGN_LEFT,
wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE);
objects_ctrl->AppendColumn(column00);
// column 1 of the view control:
tr = new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_INERT);
wxDataViewColumn *column01 = new wxDataViewColumn("Copy", tr, 1, 95, wxALIGN_CENTER_HORIZONTAL,
wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE);
objects_ctrl->AppendColumn(column01);
// column 2 of the view control:
tr = new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_INERT);
wxDataViewColumn *column02 = new wxDataViewColumn("Scale", tr, 2, 95, wxALIGN_CENTER_HORIZONTAL,
wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE);
objects_ctrl->AppendColumn(column02);
common_sizer->Add(objects_sz, 0, wxEXPAND | wxALL, 1);
// **********************************************************************************************
/* auto view_ctrl = new wxDataViewCtrl(win, wxID_ANY, wxDefaultPosition, wxDefaultSize);
wxSizer *PanelSz = new wxBoxSizer(wxVERTICAL);
view_ctrl->SetMinSize(wxSize(-1, 200));
PanelSz->Add(view_ctrl, 1, wxGROW | wxALL, 5);
PanelSz->Add( new wxStaticText(win, wxID_ANY, "Most of the cells above are editable!"), 0, wxGROW | wxALL, 5);
auto m_music_model = new MyMusicTreeModel;
view_ctrl->AssociateModel(m_music_model);
#if wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
view_ctrl->EnableDragSource(wxDF_UNICODETEXT);
view_ctrl->EnableDropTarget(wxDF_UNICODETEXT);
#endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
// column 0 of the view control:
tr = new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_INERT);
wxDataViewColumn *column0 =
new wxDataViewColumn("title", tr, 0, 150, wxALIGN_LEFT,
wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE);
view_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(100); // this column can't be resized to be smaller
view_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);
view_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);
view_ctrl->AppendColumn(column3);
// column 4 of the view control:
view_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);
view_ctrl->AppendColumn(column5);
// **********************************************************************************************
common_sizer->Add(PanelSz, 0, wxEXPAND | wxALL, 1);
*/
wxSizer *paneSz = new wxBoxSizer(wxVERTICAL);
paneSz->Add(m_optgroup->sizer, 1, wxGROW | wxEXPAND | wxBOTTOM, 2);
paneSz->Add(common_sizer/*m_optgroup->sizer*/, 1, wxGROW | wxEXPAND | wxBOTTOM, 2);
win->SetSizer(paneSz);
paneSz->SetSizeHints(win);
}

View file

@ -165,3 +165,446 @@ void wxDataViewTreeCtrlComboPopup::OnDataViewTreeCtrlSelection(wxCommandEvent& e
auto selected = GetItemText(GetSelection());
cmb->SetText(selected);
}
// *****************************************************************************
// ----------------------------------------------------------------------------
// MyObjectTreeModel
// ----------------------------------------------------------------------------
MyObjectTreeModel::MyObjectTreeModel()
{
auto root1 = new MyObjectTreeModelNode("Object1");
m_objects.emplace(root1);
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"));
auto root3 = new MyObjectTreeModelNode("Object3");
m_objects.emplace(root3);
auto root4 = new MyObjectTreeModelNode("Object4");
m_objects.emplace(root4);
root4->Append(new MyObjectTreeModelNode(root2, "SubObject1"));
root4->Append(new MyObjectTreeModelNode(root2, "SubObject2"));
root4->Append(new MyObjectTreeModelNode(root2, "SubObject3"));
}
wxString MyObjectTreeModel::GetName(const wxDataViewItem &item) const
{
MyObjectTreeModelNode *node = (MyObjectTreeModelNode*)item.GetID();
if (!node) // happens if item.IsOk()==false
return wxEmptyString;
return node->m_name;
}
wxString MyObjectTreeModel::GetCopyCnt(const wxDataViewItem &item) const
{
MyObjectTreeModelNode *node = (MyObjectTreeModelNode*)item.GetID();
if (!node) // happens if item.IsOk()==false
return wxEmptyString;
return node->m_copy;
}
wxString MyObjectTreeModel::GetScale(const wxDataViewItem &item) const
{
MyObjectTreeModelNode *node = (MyObjectTreeModelNode*)item.GetID();
if (!node) // happens if item.IsOk()==false
return wxEmptyString;
return node->m_scale;
}
// void MyObjectTreeModel::Delete(const wxDataViewItem &item)
// {
//
// }
void MyObjectTreeModel::GetValue(wxVariant &variant, const wxDataViewItem &item, unsigned int col) const
{
wxASSERT(item.IsOk());
MyObjectTreeModelNode *node = (MyObjectTreeModelNode*)item.GetID();
switch (col)
{
case 0:
variant = node->m_name;
break;
case 1:
variant = node->m_copy;
break;
case 2:
variant = node->m_scale;
break;
default:
;// wxLogError("MyMusicTreeModel::GetValue: wrong column %d", col);
}
}
bool MyObjectTreeModel::SetValue(const wxVariant &variant, const wxDataViewItem &item, unsigned int col)
{
wxASSERT(item.IsOk());
MyObjectTreeModelNode *node = (MyObjectTreeModelNode*)item.GetID();
switch (col)
{
case 0:
node->m_name = variant.GetString();
return true;
case 1:
node->m_copy = variant.GetString();
return true;
case 2:
node->m_scale = variant.GetString();
return true;
default:;
// wxLogError("MyObjectTreeModel::SetValue: wrong column");
}
return false;
}
// bool MyObjectTreeModel::IsEnabled(const wxDataViewItem &item, unsigned int col) const
// {
//
// }
wxDataViewItem MyObjectTreeModel::GetParent(const wxDataViewItem &item) const
{
// the invisible root node has no parent
if (!item.IsOk())
return wxDataViewItem(0);
MyObjectTreeModelNode *node = (MyObjectTreeModelNode*)item.GetID();
// objects nodes also has no parent
if (m_objects.find(node) != m_objects.end())
return wxDataViewItem(0);
return wxDataViewItem((void*)node->GetParent());
}
bool MyObjectTreeModel::IsContainer(const wxDataViewItem &item) const
{
// the invisble root node can have children
if (!item.IsOk())
return true;
MyObjectTreeModelNode *node = (MyObjectTreeModelNode*)item.GetID();
return node->IsContainer();
}
unsigned int MyObjectTreeModel::GetChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const
{
MyObjectTreeModelNode *node = (MyObjectTreeModelNode*)parent.GetID();
if (!node)
{
for (auto object: m_objects)
array.Add(wxDataViewItem((void*)object));
return m_objects.size();
}
if (node->GetChildCount() == 0)
{
return 0;
}
unsigned int count = node->GetChildren().GetCount();
for (unsigned int pos = 0; pos < count; pos++)
{
MyObjectTreeModelNode *child = node->GetChildren().Item(pos);
array.Add(wxDataViewItem((void*)child));
}
return count;
}
// *****************************************************************************
// ----------------------------------------------------------------------------
// 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:
//wxLogError("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:
;// wxLogError("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:;
// wxLogError("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;
}
// *****************************************************************************

View file

@ -4,6 +4,9 @@
#include <wx/checklst.h>
#include <wx/combo.h>
#include <wx/dataview.h>
#include <wx/dc.h>
#include <vector>
#include <set>
class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup
{
@ -50,4 +53,412 @@ public:
void SetItemsCnt(int cnt) { m_cnt_open_items = cnt; }
};
// *****************************************************************************
// ----------------------------------------------------------------------------
// MyObjectTreeModelNode: a node inside MyObjectTreeModel
// ----------------------------------------------------------------------------
class MyObjectTreeModelNode;
WX_DEFINE_ARRAY_PTR(MyObjectTreeModelNode*, MyObjectTreeModelNodePtrArray);
class MyObjectTreeModelNode
{
MyObjectTreeModelNode* m_parent;
MyObjectTreeModelNodePtrArray m_children;
public:
MyObjectTreeModelNode( const wxString &name) {
m_parent = NULL;
m_name = name;
m_copy = "1";
m_scale = "100%";
}
MyObjectTreeModelNode( MyObjectTreeModelNode* parent,
const wxString& sub_obj) {
m_parent = parent;
m_name = sub_obj;
m_copy = wxEmptyString;
m_scale = wxEmptyString;
}
~MyObjectTreeModelNode()
{
// free all our children nodes
size_t count = m_children.GetCount();
for (size_t i = 0; i < count; i++)
{
MyObjectTreeModelNode *child = m_children[i];
delete child;
}
}
wxString m_name;
wxString m_copy;
wxString m_scale;
bool m_container = false;
bool IsContainer() const
{
return m_container;
}
MyObjectTreeModelNode* GetParent()
{
return m_parent;
}
MyObjectTreeModelNodePtrArray& GetChildren()
{
return m_children;
}
MyObjectTreeModelNode* GetNthChild(unsigned int n)
{
return m_children.Item(n);
}
void Insert(MyObjectTreeModelNode* child, unsigned int n)
{
m_children.Insert(child, n);
}
void Append(MyObjectTreeModelNode* child)
{
if (!m_container)
m_container = true;
m_children.Add(child);
}
unsigned int GetChildCount() const
{
return m_children.GetCount();
}
};
// ----------------------------------------------------------------------------
// MyObjectTreeModel
// ----------------------------------------------------------------------------
class MyObjectTreeModel :public wxDataViewModel
{
std::set<MyObjectTreeModelNode*> m_objects;
public:
MyObjectTreeModel();
~MyObjectTreeModel()
{
for (auto object : m_objects)
delete object;
}
// helper method for wxLog
wxString GetName(const wxDataViewItem &item) const;
wxString GetCopyCnt(const wxDataViewItem &item) const;
wxString GetScale(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);
virtual unsigned int GetColumnCount() const override { return 3;}
virtual wxString GetColumnType(unsigned int col) const override{ return wxT("string"); }
virtual void GetValue(wxVariant &variant,
const wxDataViewItem &item, unsigned int col) const override;
virtual bool SetValue(const wxVariant &variant,
const wxDataViewItem &item, unsigned int col) override;
// virtual bool IsEnabled(const wxDataViewItem &item,
// unsigned int col) const override;
virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override;
virtual bool IsContainer(const wxDataViewItem &item) const override;
virtual unsigned int GetChildren(const wxDataViewItem &parent,
wxDataViewItemArray &array) const override;
};
// *****************************************************************************
// ----------------------------------------------------------------------------
// 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()
{
if (m_root)
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/*wxOVERRIDE*/;
// 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;
};
// ----------------------------------------------------------------------------
// MyCustomRenderer
// ----------------------------------------------------------------------------
class MyCustomRenderer : public wxDataViewCustomRenderer
{
public:
// This renderer can be either activatable or editable, for demonstration
// purposes. In real programs, you should select whether the user should be
// able to activate or edit the cell and it doesn't make sense to switch
// between the two -- but this is just an example, so it doesn't stop us.
explicit MyCustomRenderer(wxDataViewCellMode mode)
: wxDataViewCustomRenderer("string", mode, wxALIGN_CENTER)
{ }
virtual bool Render(wxRect rect, wxDC *dc, int state) override/*wxOVERRIDE*/
{
dc->SetBrush(*wxLIGHT_GREY_BRUSH);
dc->SetPen(*wxTRANSPARENT_PEN);
rect.Deflate(2);
dc->DrawRoundedRectangle(rect, 5);
RenderText(m_value,
0, // no offset
wxRect(dc->GetTextExtent(m_value)).CentreIn(rect),
dc,
state);
return true;
}
virtual bool ActivateCell(const wxRect& WXUNUSED(cell),
wxDataViewModel *WXUNUSED(model),
const wxDataViewItem &WXUNUSED(item),
unsigned int WXUNUSED(col),
const wxMouseEvent *mouseEvent) override/*wxOVERRIDE*/
{
wxString position;
if (mouseEvent)
position = wxString::Format("via mouse at %d, %d", mouseEvent->m_x, mouseEvent->m_y);
else
position = "from keyboard";
// wxLogMessage("MyCustomRenderer ActivateCell() %s", position);
return false;
}
virtual wxSize GetSize() const override/*wxOVERRIDE*/
{
return wxSize(60, 20);
}
virtual bool SetValue(const wxVariant &value) override/*wxOVERRIDE*/
{
m_value = value.GetString();
return true;
}
virtual bool GetValue(wxVariant &WXUNUSED(value)) const override/*wxOVERRIDE*/{ return true; }
virtual bool HasEditorCtrl() const override/*wxOVERRIDE*/{ return true; }
virtual wxWindow*
CreateEditorCtrl(wxWindow* parent,
wxRect labelRect,
const wxVariant& value) override/*wxOVERRIDE*/
{
wxTextCtrl* text = new wxTextCtrl(parent, wxID_ANY, value,
labelRect.GetPosition(),
labelRect.GetSize(),
wxTE_PROCESS_ENTER);
text->SetInsertionPointEnd();
return text;
}
virtual bool
GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) override/*wxOVERRIDE*/
{
wxTextCtrl* text = wxDynamicCast(ctrl, wxTextCtrl);
if (!text)
return false;
value = text->GetValue();
return true;
}
private:
wxString m_value;
};
// *****************************************************************************
#endif // slic3r_GUI_wxExtensions_hpp_