   advice needed on design
  i need a few comments and directions.the code at hand is a custom GUI system that has some flaws.imagine the following:   /*Widget base class for Buttons, Dialogs, Listbox, ... */class Widget{public:Widget ( int id,  Rect position,  Widget* parent, EventHandler* handler ,... ); //more stuffvoid setPos ( Rect pos );Rect getPos ();bool isVisible () const;void setVisible ( bool );bool isActive () const;void setActive ( bool );Font* getFont ();void setFont ( Font* );addChild ( Widget* );getChild ( int id );// ...virtual void onDraw () = 0;virtual void onEnter () = 0;//...private://DataRect Position;bool Visible, Active;Font* Font;// ....std::vector<Widget*> Children;};//you can see that a widget has attributes like Visible, Position, Font, ...the thing is there are many more attributes, like Caption, TabOrder, DrawStyle, Images, BackColor, FontColor, ShadowColor, tons of attributes. (i have factored some style attributes, like 'ShadowColor', out of the Widget class in a global Sytlesheet class. stillit should be possible to change colors/styles of every Widget independently)A custom widget derived from 'Widget' needs to receive notifications on when a certain attribute has changed so it can synchronize and update itself and possibly its attached children as well. (when someone calls setPos() on a DialogWindow we would want to move all children with it). this can be done by having a private interface method in 'Widget' so that every derived class will have to implement it:   virtual void onFontChanged () = 0; //someone called setFont() on the widgetvirtual void onPositionUpdated () = 0; //someone called setPosition() on the widgetvirtual void onActivate () = 0; // ...//also, a function call has to be included in every set() method:void Widget::setPos ( Rect pos ){Position = pos;this->onPositionChanged (); //callback ourself}this is fine because every custom widget will want to do different things when a base attributeis changed. say a button could properly resize itself when the font size changed. a slidercan update its relative thumb position when position has changed, ...however... with said tons of attributes this gets messy pretty quick and it's a pain to update20 custom widget classes. there has to be an easier way to update/add/remove attribute code.my first idea was to remove all the attributes and methods from Widget and make somewhat like this (all pseudo code):   /*Attribute- storage for some widget's attribute*/template<typename T>class Attribute{public:Attribute ( string name );void set ( T newValue );T get ();private:T Attrib;string Name;};so this looks like:   Attribute<int> FontSize ("iFontSize");Attribute<Rect> Position ("rPosition");Attribute<bool> Visible ("bVisible");then instead of setPos(), setVisible(), ...  we have a single method in Widget base class:   void setAttribute ( string attribname, T value ){switch ( attribname ){case "iFontSize":m_Attributes [ attribname ] = value; //look up attribute and change itthis->onAttributeChanged ( attribname ); // call derived widget's handler.break;case "rPosition":case "bVisible":case "bActive"://...}}onAttributeChanged() would of course be virtual and when overloaded could look like this:   virtual void Button::onAttributeChanged ( string attribname ){/* someone called setAttribute on the widget,  so update own state accordingly: */switch ( attribname ){case "iFontSize":case "rPosition":case "bVisible":case "bActive":// ...}}-----------------------------i just typed this off the top of my head and i'm sure it has several flaws and is overly complicated.but if done right it would make it a lot easier. just add a new attribute, say "FontColor", put it in the table andinstall it in every widget's onAttributeChanged method (if needed at all). it would lead to a much cleaner and smaller 'Widget' interface.i'm just curious on what you think and how you would handle this.i think i spent too much time thinking about this stuff and i can't seem to see a better obvious solution thanks[edited by - glitchh on February 10, 2004 3:26:31 AM]
  This looks to my mind as though you are moving from a good design to a bad design.Maintaining that switch statement in each derived class will drive you more nuts than maintaining the virtual functions will cause you pain.   [edited by - petewood on February 10, 2004 8:04:29 AM];  Use event handlers, not virtual functions. Having to derive a class everytime you want to attach an event handler to it is so MFC. 