c++ - Best way to implement performing actions on tree nodes, preferably without using visitors -


i have user interface tree view on left, , viewer on right (a bit email client). viewer on right displays detail of whatever have selected in tree on left.

the user interface has "add", "edit" , "delete" buttons. these buttons act differently depending on "node" in tree selected.

if have node of particular type selected, , user clicks "edit", need open appropriate edit dialog particular type of node, details of node.

now, there's lot of different types of node , implementing visitor class feels bit messy (currenty visitor has 48 entries....). work nicely though - editing have openeditdialog class inherits visitor, , opens appropriate edit dialog:

abstracttreenode->accept(openeditdialog());

the problem have implement abstract visitor class every "action" want perform on node , reason can't thinking i'm missing trick.

the other way of been implement functions in nodes themselves:

abstracttreenode->openeditdialog(); 

i'm ording node around bit here, maybe better:

abstracttreenode->editclickedevent(); 

i can't think polluting node though.

i did think of third way i've not given thought yet. have templated wrapper class gets added tree instead allows me perhaps call free-functions perform whatever actions, guess acts go between nodes , interface:

(pseudo code off top of head give idea):

template <class t> treenode(t &modelnode) {     m_modelnode = modelnode; }  template <> void treenode<areanode>::editclickedevent() {     openeditdialog(m_modelnode); // called concrete areanode }  template <> void treenode<locationnode>::editclickedevent() {     openeditdialog(m_modelnode); // called concrete locationnode } 

etc..

so extending nodes in different way using visitor , seems little bit neater.

now before go ahead , take plunge using 1 of these methods, thought it'd wise input.

thanks! hope makes sense..

edit:

i've mocked templated wrapper idea..

class inode { public:     virtual ~inode() {}     virtual void foo() = 0; };  class areanode : public inode { public:     areanode() {}     virtual ~areanode() {}     void foo() { printf("areanode::foo\r\n"); } };  class rolenode : public inode { public:     rolenode() {}     virtual ~rolenode() {}     void foo() { printf("rolenode::foo\r\n"); } };  class itreenode { public:     virtual ~itreenode() {}     virtual void bar() = 0;     virtual void foo() = 0; };  template <class t> class mainviewtreenode : public itreenode { public:     mainviewtreenode() : m_node() {}     virtual ~mainviewtreenode() {}     void bar() {}     void foo() { m_node.foo(); } protected:     t m_node; };  template <> void mainviewtreenode<areanode>::bar() {     printf("mainviewtreenode<areanode>::bar\r\n"); }  template <> void mainviewtreenode<rolenode>::bar() {     printf("mainviewtreenode<rolenode>::bar\r\n"); }  int _tmain(int argc, _tchar* argv[]) {     mainviewtreenode<rolenode> role;     mainviewtreenode<areanode> area;      std::list<itreenode*> nodes;     nodes.push_back(&role);     nodes.push_back(&area);      std::list<itreenode*>::iterator = nodes.begin();      (; != nodes.end(); ++it)     {         (*it)->foo();         (*it)->bar();     }      getchar();     return 0; } 

thanks.

visitor useful when have many operations , few types. if have many types, few operations, use normal polymorphism.


Comments

Popular posts from this blog

c++ - How do I get a multi line tooltip in MFC -

asp.net - In javascript how to find the height and width -

c# - DataTable to EnumerableRowCollection -