1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
14// Code by: Jeremy Moles (cubicool) 2007-2008
16#ifndef OSGWIDGET_WIDGET
17#define OSGWIDGET_WIDGET
19#include <osg/Texture2D>
20#include <osgWidget/EventInterface>
21#include <osgWidget/StyleInterface>
22#include <osgWidget/UIObjectParent>
23#include <osgWidget/Types>
30// A Widget is a rectangular region that receives events about the state of various input
31// devices such as the pointer and keyboard. It is aware of it's width, height, and origin but
32// nothing else. It is the job of higher-level container objects to organize layouts and
33// the like, and to contextualize the meaning of the widgets "origin" (whether it is absolute
35class OSGWIDGET_EXPORT Widget: public osg::Geometry, public EventInterface, public StyleInterface {
57 enum VerticalAlignment {
63 enum HorizontalAlignment {
75 Widget (const std::string& = "", point_type = 0.0f, point_type = 0.0f);
76 Widget (const Widget&, const osg::CopyOp&);
78 META_Object (osgWidget, Widget);
83 // This method is called when the widget is added to a Window; this is useful
84 // when the widget needs to do something advanced (like a Label). The parent
85 // is passed as the first argument, although _parent should already be set.
86 virtual void parented(Window*) {
89 virtual void unparented(Window*) {
92 // This method is called when the widget's parent Window is added to a
93 // WindowManager object. The base managed method (WHICH YOU MUST REMEMBER
94 // TO CALL IN YOUR DERIVED METHODS!) sets the TexMat properly depending
95 // on what coordinate system you're using.
96 virtual void managed(WindowManager*) {
99 virtual void unmanaged(WindowManager*) {
102 // This method is called when the widget is resized or reallocated in any
103 // way. This is useful when the widget manages some internal Drawables that need
104 // to be modified in some way.
105 virtual void positioned() {
116 void setPadding (point_type);
117 void setColor (color_type, color_type, color_type, color_type, Corner = ALL_CORNERS);
118 void addColor (color_type, color_type, color_type, color_type, Corner = ALL_CORNERS);
119 void setTexCoord (texcoord_type, texcoord_type, Corner = ALL_CORNERS);
120 void setLayer (Layer l, unsigned int offset = 0);
122 // These are additional texture coordinate setting methods.
123 // This method will use a given origin as the LOWER_LEFT point and texture the
124 // remaining area based on some width and height values.
125 void setTexCoordRegion(point_type, point_type, point_type, point_type);
127 // These are convenience methods for setting up wrapping modes.
128 void setTexCoordWrapHorizontal ();
129 void setTexCoordWrapVertical ();
131 bool setImage (osg::Image*, bool = false, bool = false);
133 template<class T> bool setImage(const osg::ref_ptr<T>& image, bool f1 = false, bool f2 = false) { return setImage(image.get(), f1, f2); }
136 bool setImage (const std::string&, bool = false, bool = false);
137 bool setTexture (osg::Texture*, bool = false, bool = false);
139 void addX (point_type);
140 void addY (point_type);
141 void addWidth (point_type);
142 void addHeight (point_type);
143 void addOrigin (point_type, point_type);
144 void addSize (point_type, point_type);
146 point_type getWidth () const;
147 point_type getHeight () const;
148 point_type getX () const;
149 point_type getY () const;
150 point_type getZ () const;
151 point_type getPadHorizontal () const;
152 point_type getPadVertical () const;
154 const Point& getPoint (Corner = ALL_CORNERS) const;
155 const Color& getColor (Corner = ALL_CORNERS) const;
156 const TexCoord& getTexCoord (Corner = ALL_CORNERS) const;
158 Color getImageColorAtXY (point_type x, point_type y) const;
159 XYCoord localXY (double, double) const;
161 bool isPaddingUniform() const;
163 bool isManaged() const {
167 bool isStyled() const {
171 void setDimensions(const Quad& q, point_type z = -1.0f) {
172 setDimensions(q[0], q[1], q[2], q[3], z);
175 void setX(point_type x) {
179 void setY(point_type y) {
180 setDimensions(-1.0f, y);
183 // This method should be use with extreme caution.
184 void setZ(point_type z) {
185 setDimensions(-1.0f, -1.0f, -1.0f, -1.0f, z);
188 void setWidth(point_type w) {
189 setDimensions(-1.0f, -1.0f, w);
192 void setHeight(point_type h) {
193 setDimensions(-1.0f, -1.0f, -1.0f, h);
196 void setOrigin(point_type x, point_type y) {
200 void setOrigin(const XYCoord& xy) {
201 setOrigin(xy.x(), xy.y());
204 void setSize(point_type w, point_type h) {
205 setDimensions(-1.0f, -1.0f, w, h);
208 void setSize(const XYCoord& xy) {
209 setSize(xy.x(), xy.y());
212 void setColor(const Color& col, Corner p = ALL_CORNERS) {
213 setColor(col.r(), col.g(), col.b(), col.a(), p);
216 void setTexCoord(const XYCoord& xy, Corner p = ALL_CORNERS) {
217 setTexCoord(xy.x(), xy.y(), p);
220 void setTexCoordRegion(const XYCoord& xy, point_type w, point_type h) {
221 setTexCoordRegion(xy.x(), xy.y(), w, h);
224 void setTexCoordRegion(point_type x, point_type y, const XYCoord& wh) {
225 setTexCoordRegion(x, y, wh.x(), wh.y());
228 void setTexCoordRegion(const XYCoord& xy, const XYCoord& wh) {
229 setTexCoordRegion(xy.x(), xy.y(), wh.x(), wh.y());
232 void addColor(const Color& col, Corner p = ALL_CORNERS) {
233 addColor(col.r(), col.g(), col.b(), col.a(), p);
236 void addOrigin(const XYCoord& xy) {
237 addOrigin(xy.x(), xy.y());
240 void addSize(const XYCoord& xy) {
241 addSize(xy.x(), xy.y());
244 void setMinimumSize(point_type width, point_type height) {
249 void setMinimumSize(const XYCoord& xy) {
250 setMinimumSize(xy.x(), xy.y());
253 void setPadLeft(point_type p) {
257 void setPadRight(point_type p) {
261 void setPadTop(point_type p) {
265 void setPadBottom(point_type p) {
269 void setAlignHorizontal(HorizontalAlignment h) {
273 void setAlignVertical(VerticalAlignment v) {
277 void setCoordinateMode(CoordinateMode cm) {
281 void setCanFill(bool f) {
285 void setCanClone(bool c) {
289 WindowManager* getWindowManager() {
290 return _getWindowManager();
293 const WindowManager* getWindowManager() const {
294 return _getWindowManager();
297 Window* getParent() {
301 const Window* getParent() const {
305 unsigned int getIndex() const {
309 XYCoord getOrigin() const {
310 return XYCoord(getX(), getY());
313 Color getImageColorAtXY(const XYCoord& xy) const {
314 return getImageColorAtXY(xy.x(), xy.y());
317 Color getImageColorAtPointerXY(double x, double y) const {
318 return getImageColorAtXY(localXY(x, y));
321 Point getPosition() const {
322 return Point(getX(), getY(), getZ());
325 XYCoord getSize() const {
326 return XYCoord(getWidth(), getHeight());
329 Quad getDimensions() const {
330 return Quad(getX(), getY(), getWidth(), getHeight());
333 point_type getPadLeft() const {
337 point_type getPadRight() const {
341 point_type getPadTop() const {
345 point_type getPadBottom() const {
349 HorizontalAlignment getAlignHorizontal() const {
353 VerticalAlignment getAlignVertical() const {
357 CoordinateMode getCoordinateMode() const {
361 bool canFill() const {
365 bool canClone() const {
369 // This casts the bool _fill variable to be used in iteratively in functions such
370 // as Window::_accumulate and whatnot.
371 point_type getFillAsNumeric() const {
372 return static_cast<point_type>(_canFill);
375 point_type getWidthTotal() const {
376 return getWidth() + getPadHorizontal();
379 point_type getHeightTotal() const {
380 return getHeight() + getPadVertical();
383 point_type getMinWidth() const {
387 point_type getMinHeight() const {
391 point_type getMinWidthTotal() const {
392 return _minWidth + getPadHorizontal();
395 point_type getMinHeightTotal() const {
396 return _minHeight + getPadVertical();
399 unsigned int getLayer() const {
405 point_type _calculateZ(unsigned int) const;
407 PointArray* _verts() {
408 return dynamic_cast<PointArray*>(getVertexArray());
411 const PointArray* _verts() const {
412 return dynamic_cast<const PointArray*>(getVertexArray());
415 ColorArray* _cols() {
416 return dynamic_cast<ColorArray*>(getColorArray());
419 const ColorArray* _cols() const {
420 return dynamic_cast<const ColorArray*>(getColorArray());
423 TexCoordArray* _texs() {
424 return dynamic_cast<TexCoordArray*>(getTexCoordArray(0));
427 const TexCoordArray* _texs() const {
428 return dynamic_cast<const TexCoordArray*>(getTexCoordArray(0));
431 osg::Texture* _texture() {
432 osg::StateSet* ss = getStateSet();
436 return dynamic_cast<osg::Texture2D*>(
437 ss->getTextureAttribute(0, osg::StateAttribute::TEXTURE)
441 const osg::Texture* _texture() const {
442 const osg::StateSet* ss = getStateSet();
446 return dynamic_cast<const osg::Texture2D*>(
447 ss->getTextureAttribute(0, osg::StateAttribute::TEXTURE)
451 osg::Image* _image() {
455 const osg::Image* _image() const {
461 // TODO: Because of the current class design, I don't think it's possible to
462 // have a ref_ptr here. :(
468 // Padding is the value of pixels of space between whatever the widget is "contianed"
469 // in and the point at which it starts getting placed.
471 point_type _padRight;
473 point_type _padBottom;
475 // The alignments are used in conjunction when the widget is NOT set to fill.
476 VerticalAlignment _valign;
477 HorizontalAlignment _halign;
479 // This flag determines how sizing values are interpretted by setDimensions().
480 CoordinateMode _coordMode;
482 // These are the relative values, which are not stored directly in our verts
483 // array but kept around for calculation later.
486 // This fill flag determines whether or not the widget will resize itself to fill
487 // all available space.
490 // Set this to false in an implementation to prevent copying.
493 // This variable is only used by the Window object to determine if it's necessary
494 // to call managed().
497 // This variable is like _isManaged; it is used to store whether the Widget has
501 // Set these variables to be the minimum size of a Widget so that it cannot be
502 // resized any smaller than this.
503 point_type _minWidth;
504 point_type _minHeight;
506 static osg::ref_ptr<PointArray> _norms;
508 WindowManager* _getWindowManager () const;
509 osg::Image* _getImage () const;
513typedef std::list<osg::observer_ptr<Widget> > WidgetList;
515// A Widget subclass that prints stuff using osg::notify(). :)
516struct NotifyWidget: public Widget {
517 META_Object(osgWidget, NotifyWidget);
519 NotifyWidget(const std::string& n = "", point_type w = 0.0f, point_type h = 0.0f):
521 setEventMask(EVENT_ALL);
524 NotifyWidget(const NotifyWidget& widget, const osg::CopyOp& co):
528 bool focus(const WindowManager*) {
529 osg::notify(osg::NOTICE) << _name << " > focus called" << std::endl;
534 bool unfocus(const WindowManager*) {
535 osg::notify(osg::NOTICE) << _name << " > unfocus called" << std::endl;
540 bool mouseEnter(double, double, const WindowManager*) {
541 osg::notify(osg::NOTICE) << _name << " > mouseEnter called" << std::endl;
546 bool mouseOver(double, double, const WindowManager*) {
547 osg::notify(osg::NOTICE) << _name << " > mouseOver called" << std::endl;
552 bool mouseLeave(double, double, const WindowManager*) {
553 osg::notify(osg::NOTICE) << _name << " > mouseLeave called" << std::endl;
558 bool mouseDrag(double, double, const WindowManager*) {
559 osg::notify(osg::NOTICE) << _name << " > mouseDrag called" << std::endl;
564 bool mousePush(double, double, const WindowManager*) {
565 osg::notify(osg::NOTICE) << _name << " > mousePush called" << std::endl;
570 bool mouseRelease(double, double, const WindowManager*) {
571 osg::notify(osg::NOTICE) << _name << " > mouseRelease called" << std::endl;
576 bool mouseScroll(double, double, const WindowManager*) {
577 osg::notify(osg::NOTICE) << _name << " > mouseScroll called" << std::endl;
582 bool keyPress(int, int, const WindowManager*) {
583 osg::notify(osg::NOTICE) << _name << " > keyPress called" << std::endl;
588 bool keyRelease(int, int, const WindowManager*) {
589 osg::notify(osg::NOTICE) << _name << " > keyRelease called" << std::endl;
595// A Widget that eats all events and returns true.
596struct NullWidget: public Widget {
597 META_Object(osgWidget, NullWidget);
599 NullWidget(const std::string& n = "", point_type w = 0.0f, point_type h = 0.0f):
601 setEventMask(EVENT_ALL);
604 NullWidget(const NullWidget& widget, const osg::CopyOp& co):
608 bool focus(const WindowManager*) {
612 bool unfocus(const WindowManager*) {
616 bool mouseEnter(double, double, const WindowManager*) {
620 bool mouseOver(double, double, const WindowManager*) {
624 bool mouseLeave(double, double, const WindowManager*) {
628 bool mouseDrag(double, double, const WindowManager*) {
632 bool mousePush(double, double, const WindowManager*) {
636 bool mouseRelease(double, double, const WindowManager*) {
640 bool mouseScroll(double, double, const WindowManager*) {
644 bool keyPress(int, int, const WindowManager*) {
648 bool keyRelease(int, int, const WindowManager*) {