wxWidgets开发之MVC架构树形控件二

阅读: 评论:0

wxWidgets开发之MVC架构树形控件二

wxWidgets开发之MVC架构树形控件二

前面已经介绍了一下关于wxDataViewModal跟wxDataViewCtrl的相关函数,而且提到了节点的设计。嗯,这节分享一下关于节点的设计。

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 nodessize_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/setterswxString                m_title;wxString                m_artist;int                     m_year;wxString                m_quality;bool m_container;private:MyMusicTreeModelNode          *m_parent;MyMusicTreeModelNodePtrArray   m_children;
};
class MyMusicTreeModel: public wxDataViewModel
{
public:MyMusicTreeModel();~MyMusicTreeModel(){delete m_root;}// helper method for wxLogwxString GetTitle( const wxDataViewItem &item ) const;wxString GetArtist( const wxDataViewItem &item ) const;int GetYear( const wxDataViewItem &item ) const;// helper methods to change the modelvoid 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 ascendinglyint Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,unsigned int column, bool ascending ) const wxOVERRIDE;// implementation of base class virtuals to define modelvirtual unsigned int GetColumnCount() const wxOVERRIDE{return 6;}virtual wxString GetColumnType( unsigned int col ) const wxOVERRIDE{if (col == 2)return "long";return "string";}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;private:MyMusicTreeModelNode*   m_root;// pointers to some "special" nodes of the tree:MyMusicTreeModelNode*   m_pop;MyMusicTreeModelNode*   m_classical;MyMusicTreeModelNode*   m_ninth;// ??bool                    m_classicalMusicIsKnownToControl;
};
MyMusicTreeModel::MyMusicTreeModel()
{m_root = new MyMusicTreeModelNode( NULL, "My Music" );// setup pop musicm_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 musicm_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()==falsereturn wxEmptyString;return node->m_title;
}wxString MyMusicTreeModel::GetArtist( const wxDataViewItem &item ) const
{MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();if (!node)      // happens if item.IsOk()==falsereturn wxEmptyString;return node->m_artist;
}int MyMusicTreeModel::GetYear( const wxDataViewItem &item ) const
{MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();if (!node)      // happens if item.IsOk()==falsereturn 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 itm_classical = new MyMusicTreeModelNode( m_root, "Classical music" );m_root->Append( m_classical );// notify controlwxDataViewItem 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 controlwxDataViewItem 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()==falsereturn;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 itnode->GetParent()->GetChildren().Remove( node );// free the nodedelete node;// notify controlItemDeleted( parent, item );
}int MyMusicTreeModel::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,unsigned int column, bool ascending ) const
{wxASSERT(item1.IsOk() && item2.IsOk());// should never happenif (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 differentwxUIntPtr 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% popularbreak;case 5:if (GetYear(item) < 1900)variant = "old";elsevariant = "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 goodreturn !(col == 3 && node->m_artist.EndsWith("Beethoven"));
}wxDataViewItem MyMusicTreeModel::GetParent( const wxDataViewItem &item ) const
{// the invisible root node has no parentif (!item.IsOk())return wxDataViewItem(0);MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();// "MyMusic" also has no parentif (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;
}

结果如图:

节点数据结构有wxString m_title; wxString m_artist; int m_year;wxString m_quality; 在MyMusicTreeModel构造函数中new出来,并且各个之间的层级关系构建完毕。着重看GetChildren() 跟GetValue()函数

根据上节分享的内容知道GetChildren只会构建所有的节点数据。GetValue()往节点填充数据。

这里分享简单的节点设计思想,当然在实际开发业务过程中遇到大量的数据,我们采用类的方式实现。

本文发布于:2024-02-01 07:33:36,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170674401634917.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

下一篇:java addtext
标签:控件   架构   wxWidgets   MVC
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23