mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 09:17:52 -06:00
First experiments with ObjectsTreeList
This commit is contained in:
parent
993294579d
commit
db549e8609
4 changed files with 992 additions and 2 deletions
|
@ -72,7 +72,7 @@ sub new {
|
||||||
});
|
});
|
||||||
|
|
||||||
# Initialize preview notebook
|
# 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
|
# Initialize handlers for canvases
|
||||||
my $on_select_object = sub {
|
my $on_select_object = sub {
|
||||||
|
@ -485,6 +485,7 @@ sub new {
|
||||||
$buttons_sizer->Add($self->{btn_export_gcode}, 0, wxALIGN_RIGHT, 0);
|
$buttons_sizer->Add($self->{btn_export_gcode}, 0, wxALIGN_RIGHT, 0);
|
||||||
|
|
||||||
my $right_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
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($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($frequently_changed_parameters_sizer, 0, wxEXPAND | wxTOP, 0) if defined $frequently_changed_parameters_sizer;
|
||||||
$right_sizer->Add($buttons_sizer, 0, wxEXPAND | wxBOTTOM, 5);
|
$right_sizer->Add($buttons_sizer, 0, wxEXPAND | wxBOTTOM, 5);
|
||||||
|
@ -522,6 +523,7 @@ sub new {
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->update_ui_from_settings();
|
$self->update_ui_from_settings();
|
||||||
|
$self->Layout;
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
|
@ -812,6 +812,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
|
||||||
// Experiments with new UI
|
// Experiments with new UI
|
||||||
wxCollapsiblePane *collpane = new wxCollapsiblePane(parent, wxID_ANY, "Print settings:");
|
wxCollapsiblePane *collpane = new wxCollapsiblePane(parent, wxID_ANY, "Print settings:");
|
||||||
collpane->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, ([parent, collpane](wxCommandEvent e){
|
collpane->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, ([parent, collpane](wxCommandEvent e){
|
||||||
|
wxWindowUpdateLocker noUpdates_cp(collpane);
|
||||||
wxWindowUpdateLocker noUpdates(parent);
|
wxWindowUpdateLocker noUpdates(parent);
|
||||||
parent->Layout();
|
parent->Layout();
|
||||||
collpane->Refresh();
|
collpane->Refresh();
|
||||||
|
@ -942,9 +943,142 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
|
||||||
};
|
};
|
||||||
m_optgroup->append_line(line);
|
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);
|
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);
|
win->SetSizer(paneSz);
|
||||||
paneSz->SetSizeHints(win);
|
paneSz->SetSizeHints(win);
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,3 +165,446 @@ void wxDataViewTreeCtrlComboPopup::OnDataViewTreeCtrlSelection(wxCommandEvent& e
|
||||||
auto selected = GetItemText(GetSelection());
|
auto selected = GetItemText(GetSelection());
|
||||||
cmb->SetText(selected);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// *****************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#include <wx/checklst.h>
|
#include <wx/checklst.h>
|
||||||
#include <wx/combo.h>
|
#include <wx/combo.h>
|
||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
|
#include <wx/dc.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup
|
class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup
|
||||||
{
|
{
|
||||||
|
@ -50,4 +53,412 @@ public:
|
||||||
void SetItemsCnt(int cnt) { m_cnt_open_items = cnt; }
|
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_
|
#endif // slic3r_GUI_wxExtensions_hpp_
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue