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