arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

WidgetBase.h

Go to the documentation of this file.
00001 //------------------------------------------------------------------------
00002 //
00003 //   Joe Kniss
00004 //     6-20-03
00005 //                   ________    ____   ___ 
00006 //                  |        \  /    | /  /
00007 //                  +---+     \/     |/  /
00008 //                  +--+|  |\    /|     < 
00009 //                  |  ||  | \  / |  |\  \ 
00010 //                  |      |  \/  |  | \  \ 
00011 //                   \_____|      |__|  \__\
00012 //                       Copyright  2003 
00013 //                      Joe Michael Kniss
00014 //                   <<< jmk@cs.utah.edu >>>
00015 //               "All Your Base are Belong to Us"
00016 //-------------------------------------------------------------------------
00017 
00018 // WidgetBase.h
00019 
00020 
00021 #ifndef __WIDGET_BASE_DOT_H
00022 #define __WIDGET_BASE_DOT_H
00023 
00024 #include <smartptr.h>
00025 #include <mathGutz.h>
00026 #include <arrayGutz.h>
00027 #include <eventGutz.h>
00028 #include <signalGutz.h>
00029 #include <vector>
00030 #include <list>
00031 #include "Constraint.h"
00032 #include "WidgetState.h"
00033 #include "../renderable/Renderable.h"
00034 
00035 #include <iostream>
00036 
00037 
00038 ///////////////////////////////////////////////////////////////////////////
00039 ///////////////////////////////////////////////////////////////////////////
00040 /// The widget item base class, virtual, needs a concrete sub-class to
00041 ///  do anything.  We are using the Renderable interface for mouse events,
00042 ///  so the name & cast for gl style picking is: #RENDERABLE_NAME and 
00043 ///  "(unsigned int)(Renderable*)this", respectively. See: Renderable.h.
00044 ///
00045 /// The widget framework is divided into 2 layers.  
00046 ///  - Behavior
00047 ///  - Appearance
00048 ///
00049 /// The Behavior layer defines how widgets interact and are constrained 
00050 ///  to one another.  This level describes how the widgets move, but now how
00051 ///  they look.
00052 ///
00053 /// The Appearance layer defines how they look.  For instance, we are most
00054 ///  likely using minimal OpenGL widget geometry, like GLU quadric objects.
00055 ///  These are balls, tubes, cones, etc...  We might also like to use widgets
00056 ///  in 2D without opengl, or maybe develop a custom "skin" to make our 
00057 ///  widgets look different than everyone else's.  Whatever the reason, we can 
00058 ///  easly customize the appearance of the widgets by creating new concrete
00059 ///  basic widgets that simply draw the geometry we want, with any shader,
00060 ///  colors etc.  This only requires the implementation of a few functions,
00061 ///  for instance:
00062 /// \code
00063 ///   float draw( const gutz::RenderEvent &re );
00064 ///   WidgetItem *clone();
00065 ///   // and possibly these if applicable:
00066 ///   void _invalidate();
00067 ///   void _update();
00068 /// \endcode
00069 /// See how GLUNodeWidget implements the NodeWidget with only a few 
00070 ///   functions.  
00071 ///
00072 /// The actions described by widgets are very general, for the most part
00073 ///   they contain information about spatial position or some parameter 
00074 ///   that they represent.  There is realy no need to create a new widget
00075 ///   everytime you need some new action, nearly all widgets contain
00076 ///   signals, see gutz::Signal.  These signals are called whenever the 
00077 ///   parameter of interest changes, which can be captured by your class
00078 ///   that implements the action associated with that parameter.  For 
00079 ///   instance, you may want some kind of clipping plane for opengl.  Your
00080 ///   instinct might say, subclass FrameWiget and have it handle the clipping
00081 ///   action.  That would lead to a mas-proliferation of "special" widgets that
00082 ///   differ from their base class only in how they implement the symantics
00083 ///   of the widget.  It is far better to create a "ClipObject" that gets
00084 ///   "connected", see gutz::connect(), to the FrameWidget::planeChanged signal.
00085 ///   Whenever the user modifies the position/orientation of the FrameWidget,
00086 ///   the ClipObject will recieve the planeChanged signal and update the 
00087 ///   clipping plane.   This kind of sepparation is important since it could
00088 ///   become difficult to maintain and improve the widget framework if there are
00089 ///   many classes that "know" about how the widget is implemented.
00090 ///
00091 /// Of course you will want to build custom widgets with a slider here, another bar 
00092 ///   there, whatever.  You should.  But remember to keep the behavior implentation
00093 ///   higher in the hierarchy, the appearance lower (most derived), and little 
00094 ///   or no built in symantics, just signals to communicate parameter changes. \n
00095 ///   TODO: need more examples here...
00096 ///
00097 /// The divison between NodeWidget and GLUNodeWidget illustrates the 
00098 ///   sepparation between behavior and appearance: NodeWidget handles the
00099 ///   behavior, and GLUNodeWidget handles the specific appearance for 
00100 ///   GLU spheres.  Behavior implementation should always reside above any
00101 ///   and all apperance implementation in the class hierarchy.
00102 ///
00103 /// All parameters, such as position and orientation should be delivered
00104 ///   in "WORLD" space; see gutz::BaseManip
00105 ///   for a definition of this.   By delivered, I mean when you call 
00106 ///   getPoint, getPos, getOrient, etc... or recieve a signal such as 
00107 ///   pointChanged etc.. these positions and orientations should always be
00108 ///   in "WORLD" space, not the local frame that the widget may live in.
00109 ///   It is very likely that widgets store these parameters in a Manip, so
00110 ///   as you might expect, this means that we are using 
00111 ///   gutz::BaseManip::getWorldPos() when you ask for a widget's position.
00112 ///   This also means that any setPos functions should use positions/orientations
00113 ///   that are defined in "WORLD" space.  The widget is responsible for 
00114 ///   transforming these parameters into their local frame. 
00115 ///
00116 /// See also WidgetFactory, gutz::Signal, gutz::connect, gutz::disconnect.
00117 ///////////////////////////////////////////////////////////////////////////
00118 ///////////////////////////////////////////////////////////////////////////
00119 class WidgetItem : public Renderable {
00120 public:
00121 
00122    typedef gutz::SmartPtr<WidgetItem>    WidgetItemSP;
00123    
00124    typedef gutz::vec2f                Point2;      ///<2D point
00125    typedef gutz::arrayOwn1<Point2>    Point2Array; ///<2D point array
00126 
00127    typedef gutz::vec3f                Point3;      ///<3D point
00128    typedef gutz::arrayOwn1<Point3>    Point3Array; ///<3D point array
00129 
00130    virtual ~WidgetItem() 
00131    { 
00132       if(_parent) _parent->delChild(this);
00133       _parent = 0;
00134       _eventMap = gutz::EventKeyMap();
00135       _constraintMap = ConstraintMap();
00136    }
00137 
00138    ///////////////////////////////////////////////////////////////////
00139    ///@name clone/factory function.
00140    ///   Should only be implemented by concrete widget class.  
00141    ///   It is also nice if you have a clone{subWidgetType}() function. 
00142    ///   so that we can
00143    ///   use this for generic WidgetFactory objects.  If you have a 
00144    ///   specific clone function, you can define the WidgetItem::clone 
00145    ///   function to call the specific one, to eliminate potentially 
00146    ///   redundant code at the "appearance level" of the hierarchy.
00147    ///   for instance 
00148    ///   \code
00149    ///      WidgetItem *clone() const { return cloneNode(); }
00150    ///      virtual NodeWidget *cloneNode() const =0; 
00151    ///   \endcode
00152    ///   In this case, any concrete subclass of NodeWidget only needs to 
00153    ///   implement cloneNode(), not clone().  
00154    ///
00155    ///   This is a very important function, it replaces the copy 
00156    ///   constructor since it is protected at this level of the hierarchy.
00157    ///   This is nessesary since we are sepparating behavior and appearance,
00158    ///   and therefore can't copy at the behavior (this) level of the hierarchy.
00159    ///   Any widget that can be publically constructed MUST implement a clone
00160    ///   function, but it should be left virtual. 
00161    ///  
00162    ///   Here is an example of a clone definition in SomeWidget, 
00163    ///    a concrete (appearance) widget class.
00164    /// \code
00165    ///   virtual WidgetItem *SomeWidget::clone() const
00166    ///   {  
00167    ///       return new SomeWidget(*this); 
00168    ///   }
00169    /// \endcode
00170    ///@{
00171    virtual WidgetItem *clone() const = 0;
00172    ///@}
00173    ///////////////////////////////////////////////////////////////////
00174 
00175    ///////////////////////////////////////////////////////////////////
00176    ///@name Modified
00177    ///   When this is called the widget knows it has been changed
00178    ///   and will emmit update events.  This is used mostly for 
00179    ///   composite widgets that handle some events using their
00180    ///   own manipulator; when this happens they have to notify 
00181    ///   their child widgets that they changed, so that they can
00182    ///   update their children and anybody recieving attached signals.
00183    ///   
00184    ///   As a user of widgets, you can IGNORE this function, doesn't apply
00185    ///   to you.  When you are building new widgets, however, this function
00186    ///   comes in handy.  Composite widgets should always forward this 
00187    ///   "event" onto children and emmit any relevant signals.  
00188    ///@{
00189    virtual void setChanged() = 0;
00190    ///@}
00191 
00192    ///////////////////////////////////////////////////////////////////
00193    /// apply a 4x4 transformation matrix, must be defined by a
00194    ///  sub-class.
00195    virtual void    applyXform(gutz::mat4f xf) = 0;
00196 
00197    ///////////////////////////////////////////////////////////////////
00198    ///@name Events duplicated from <Renderable>. 
00199    ///   These are duplicated
00200    ///      to insure/ease framework issues, notice that mouse and 
00201    ///      move handle the "check with parent" and mouseDef(), moveDef()
00202    ///      are what actually implement the behavior.
00203    ///@{
00204 
00205    ///////////////////
00206    /// main draw event...
00207    ///   Framework only, do not override,
00208    ///   Might need to add functionality here later. \n
00209    void draw(const gutz::RenderEvent &r)
00210    { drawDef(r); }
00211    /// PURE VIRTUAL draw defintion, must be implemented
00212    ///   by concrete base class, be sure to apply the
00213    ///   matrix associated with this widget (_mat)
00214    virtual void drawDef(const gutz::RenderEvent &r) = 0;
00215    
00216    ///////////////////
00217    /// a mouse event... 
00218    ///   checks with parent, then calls mouseDef() \n
00219    ///   Framework only, do not override.
00220    bool mouse(const gutz::MouseEvent &me)  
00221    {
00222       if(_parent && _parent->mouseChild(this,me)) return true;
00223       return mouseDef(me);
00224    }
00225    ///////////////////
00226    /// override this one to implement mouse behavior
00227    virtual bool mouseDef(const gutz::MouseEvent &me)     
00228    {
00229       std::cerr << " event id = " << getEvent(me) << std::endl;
00230       return _manip->mouse(me);
00231       return getEvent(me) != NO_EVENT; 
00232    }
00233 
00234    ///////////////////
00235    /// a child was moused, called before their mouseDef.
00236    ///  return true if & only if parent will be handling the mouse event \n
00237    ///  return false if the child handles it's own mouse event \n
00238    virtual bool mouseChild(WidgetItem *child, const gutz::MouseEvent &me)
00239    { return false; }
00240 
00241    ///////////////////
00242    /// a move event, 
00243    ///   checks with parent, then calls moveDef().
00244    ///   Framework only, do not override.
00245    bool move(const gutz::MouseMoveEvent &mme) 
00246    { 
00247       if(_parent && _parent->moveChild(this,mme)) return true;
00248       return moveDef(mme); 
00249    }
00250 
00251    ///////////////////
00252    /// override this one to implement move behavior
00253    virtual bool moveDef(const gutz::MouseMoveEvent &mme) 
00254    {
00255       if(_manip->move(mme))
00256       {
00257          setChanged();
00258          return true;
00259       }
00260       return false;
00261    }
00262    
00263    ///////////////////
00264    /// a child wants to be moved. 
00265    /// if true, child does nothing (parent moves them)
00266    /// if false, child moves self
00267    virtual bool moveChild(WidgetItem *child, const gutz::MouseMoveEvent &mme)
00268    { return false; }
00269 
00270    ///@}
00271    ///////////////////////////////////////////////////////////////////
00272 
00273    ///////////////////////////////////////////////////////////////////
00274    ///@name Parent/Child management
00275    ///@{
00276 
00277    /// a child was added
00278    virtual void addChild(WidgetItem *child) {}
00279    /// a child was deleted/ changed parent
00280    virtual void delChild(WidgetItem *child) {}
00281    
00282    /// a (new?) parent now owns you :)
00283    virtual void setParent(WidgetItem *parent)
00284    {   if(_parent)
00285        {
00286           _parent->delChild(this); 
00287           _manip->setParent(0);
00288        }
00289        _parent = parent; 
00290        if(_parent)
00291        {
00292           _manip->setParent( _parent->getManip() );
00293           _parent->addChild(this); 
00294        }
00295    }
00296 
00297    ///@}
00298    ///////////////////////////////////////////////////////////////////
00299 
00300    ///////////////////////////////////////////////////////////////////
00301    /// get the "tightest 2D bounding polygon" in screen space
00302    virtual Point2Array  getValidArea() const {return Point2Array(0,Point2(0));}
00303 
00304    ///////////////////////////////////////////////////////////////////
00305    ///@name Event & constraint mapper. 
00306    ///     All widgets have the default
00307    ///     event of: gutz::GUTZ_LEFT_MOUSE -> MOVE 
00308    ///     you may want to nuke this event if it isn't applicable:
00309    ///     delEvent(gutz::GUTZ_LEFT_MOUSE);
00310    ///     event keys are defined in: gutzKeyMouse.h
00311    ///@{
00312 
00313    enum WIGET_BEHAVIORS {
00314       NO_EVENT =0,   ///< widget does nothing (by itself, but maybe parent does)
00315       MOVE,          ///< move according to world space deltas (default left mouse)
00316       ROTATE,        ///< rotate around center of widget 
00317       WB_LAST        ///< sub classes add events starting here (not an event)
00318    };
00319 
00320    /// addEvent. constraint defaults to "Free Move" constraint
00321    void              addEvent(const unsigned int key, 
00322                               const unsigned int event,
00323                               const ConstraintSP cnst = new Constraint())
00324    { _eventMap[key] = event; _constraintMap[key] = cnst; }
00325    
00326    /// getEvent, returns the event if one is defined, returns
00327    /// NO_EVENT if the mouse is up
00328    ///  works for both: gutz::MouseEvent and gutz::MouseMoveEvent
00329    /// This function is usefull in implementation, externally
00330    /// use getEvent(unsigned int).
00331    unsigned int getEvent(const gutz::MouseEvent &me) const
00332    {
00333       if(!me.isButtonDown()) return NO_EVENT;
00334       return _eventMap[me.getButton()];
00335    }
00336 
00337    /// what is the event assigned to a key
00338    unsigned int getEvent(unsigned int key) const
00339    {
00340       return _eventMap[key];
00341    }
00342 
00343    /// delete an event from the event map
00344    void              delEvent(const unsigned int key)
00345    { _eventMap.erase(key); _constraintMap.erase(key);  }
00346    /// delete all events from the event map
00347    void              nukeEvents()
00348    {
00349       _eventMap = gutz::EventKeyMap();
00350       _constraintMap = ConstraintMap();
00351    }
00352 
00353    gutz::EventKeyMap getEvents() const { return _eventMap; }
00354    void              setEvents(const gutz::EventKeyMap &eventMap)
00355    { _eventMap = eventMap;   }
00356 
00357    ConstraintMap     getConstraints() const { return _constraintMap; }
00358    void              setConstraints(const ConstraintMap &cnstMap)
00359    { _constraintMap = cnstMap; }
00360    ///@}
00361    ///////////////////////////////////////////////////////////////////
00362 
00363    ///////////////////////////////////////////////////////////////////
00364    ///@name Some appearance management
00365    ///@{
00366    ColorWStateSP getColor() const                    { return _color; }
00367    void          setColor(ColorWState * const color) { _color = color; }
00368    ///@}
00369    ///////////////////////////////////////////////////////////////////
00370 
00371 
00372 protected:
00373 
00374    /// called before widget changes, see also _update()
00375    /// some window systems need these calls before and 
00376    /// after something changes, respectively,
00377    /// you'll have to specify them in your concrete class, if you need them.
00378    ///  They are quite usefull, if you need to update when a widget changes, 
00379    ///  but you don't (nescessarily) care what changed
00380    virtual void _invalidate() 
00381    {}
00382    /// called after widget is changed
00383    virtual void _update() 
00384    {}
00385    /// called if something about how it looks changes, does not include 
00386    /// changes to the transform, just things like radius and color.
00387    virtual void appearanceChanged() {}
00388 
00389 
00390    /// protected constructor, object cannot be publically created
00391    WidgetItem(WidgetItem *parent = 0) 
00392       : Renderable(), _parent(parent), _color(0) 
00393    {
00394       if(parent) parent->addChild(this);
00395       addEvent(gutz::GUTZ_LEFT_MOUSE,MOVE);
00396    }
00397    
00398    /// copies everything associated with the widget, see detailed comments.
00399    /// You should always implement the copy constructor and assignment 
00400    ///    operator of every widget.  If the widget can't be publicly constructed,
00401    ///    like this or many other "behavioral" widget specs, you should declare
00402    ///    the copy constructor as protected.  A subclassed widget should always
00403    ///    call it's base class's copy constructor, like this
00404    /// \code
00405    ///   /// definition of MyWidget's copy constructor
00406    ///   MyWidget::MyWidget(const MyWidget &mw)
00407    ///   : MyBaseClass(mw) // , ... init my member attribs
00408    ///   { /* other initiallization ... */ }
00409    /// \endcode
00410    /// checkout the copy constructors: WidgetItem <- NodeWidget <- GLUNodeWidget 
00411    ///
00412    /// Note that the assignment operator's ( operator= ) behavior is quite 
00413    ///   different from the copy constructor's.
00414    WidgetItem(const WidgetItem &wi)
00415       : Renderable(wi),
00416         _parent(wi._parent), 
00417         _eventMap(wi._eventMap),
00418         _constraintMap(wi._constraintMap),
00419         _color(0)
00420    {
00421       if( wi._color ) setColor( wi._color->cloneColor() );
00422    }
00423 
00424    /// CAREFULL, this ONLY copies data associated with the widget!
00425    ///   It does not copy things like the parent, space,
00426    ///   behavior, Event & Constraint maps, etc.. right now it just copies
00427    ///   the transform (_mat). The assignment operator is treated differently
00428    ///   than the copy constructor, in that it doesn't change the 
00429    ///   behavior (events) or appearance of a widget, it just sets the
00430    ///   data to be equal.  However, like the copy constructor, you 
00431    ///   should always call your base classes assignment operator:
00432    /// \code
00433    ///   /// definition of MyWidget's assignment op
00434    ///   MyWidget &MyWidget::operator=(const MyWidget &mw)
00435    ///   {
00436    ///      MyBaseClass::operator=(mw);
00437    ///      /// ... member attrib copy
00438    ///      return *this;
00439    ///   }
00440    /// \endcode
00441    WidgetItem &operator=(const WidgetItem &wi)
00442    {
00443       Renderable::operator =(wi);
00444       return *this;
00445    }
00446 
00447    WidgetItemSP       _parent;
00448    gutz::EventKeyMap  _eventMap;
00449    ConstraintMap      _constraintMap;
00450    /// carefull, you need to check if this is a NULL pointer
00451    ColorWStateSP      _color;
00452 };
00453 
00454 typedef gutz::SmartPtr<WidgetItem> WidgetItemSP;
00455 typedef std::vector<WidgetItemSP>  WidgetItemSPVec;
00456 typedef WidgetItemSPVec::iterator  WidgetItemSPVecIter;
00457 
00458 typedef std::list<WidgetItemSP>          WidgetItemSPList;
00459 typedef WidgetItemSPList::iterator       WidgetItemSPListIter;
00460 typedef WidgetItemSPList::const_iterator WidgetItemSPListCIter;
00461 
00462 
00463 
00464 #endif
00465 

Send questions, comments, and bug reports to:
jmk