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
Post a Comment