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_WINDOW
17#define OSGWIDGET_WINDOW
20#include <osg/MatrixTransform>
22#include <osg/ClipNode>
23#include <osgWidget/Types>
24#include <osgWidget/Util>
25#include <osgWidget/Widget>
29// These are helper callbacks you can attach to Windows that will make them moveable,
30// rotatable, and scalable respectively.
31bool OSGWIDGET_EXPORT callbackWindowMove (Event&);
32bool OSGWIDGET_EXPORT callbackWindowRotate (Event&);
33bool OSGWIDGET_EXPORT callbackWindowScale (Event&);
35// These are helper callbacks you can attach to Windows to that will make various
36// keyboard events behave as you might imagine.
37bool OSGWIDGET_EXPORT callbackWindowTabFocus(Event&);
39class OSGWIDGET_EXPORT Window:
40 public osg::MatrixTransform,
41 public UIObjectParent<Widget>,
42 public EventInterface,
46 typedef std::list<osg::observer_ptr<Window> > WindowList;
53 Sizes(point_type c = -1.0f, point_type m = -1.0f):
58 // TODO: This is a class that puts (embeds) the Window inside of a Widget
59 // interface, to help assemble Windows with Windows, and what have you.
60 class OSGWIDGET_EXPORT EmbeddedWindow: public Widget {
61 osg::ref_ptr<Window> _window;
64 META_Object (osgWidget::Window, EmbeddedWindow);
66 EmbeddedWindow (const std::string& = "", point_type = 0.0f, point_type = 0.0f);
67 EmbeddedWindow (const EmbeddedWindow&, const osg::CopyOp&);
69 virtual void parented (Window*);
70 virtual void unparented (Window*);
71 virtual void managed (WindowManager*);
72 virtual void unmanaged (WindowManager*);
73 virtual void positioned ();
75 bool setWindow (Window*);
76 void updateSizeFromWindow ();
82 const Window* getWindow() const {
87 // These correspond to special regions honored by the WindowManager. Most Windows
88 // will want to be NONE, unless they need to exist in the foreground or background
96 // If you only want to display a portion of a Window (such as when it is embedded),
97 // you will need to set the VisibilityMode to WM_PARTIAL. Otherwise, the entire
98 // Window is visible by default. The final enum, VM_ENTIRE, says that no Scissoring
99 // should take place at all, and is useful in cases where you want to properly
100 // scale or rotate Windows.
101 enum VisibilityMode {
107 // Anchors are very similar in that they allow us to pre-apply transformations in the
108 // call to Window::update() that allow us to position a Window somewhere relative
109 // to the WindowManger's viewable area. However, unlike the ALIGNMENT enums, these
110 // are totally optional (whereas a Widget must always have some ALIGNMENT value set.
111 enum VerticalAnchor {
118 enum HorizontalAnchor {
125 Window (const std::string& = "");
126 Window (const Window&, const osg::CopyOp&);
128 bool resize (point_type = 0.0f, point_type = 0.0f);
129 bool resizeAdd (point_type = 0.0f, point_type = 0.0f);
130 bool resizePercent (point_type = 0.0f, point_type = 0.0f);
132 virtual void update ();
133 virtual void managed (WindowManager*);
134 virtual void unmanaged (WindowManager*);
135 virtual bool addWidget (Widget*);
136 virtual bool insertWidget (Widget*, unsigned int);
137 virtual bool removeWidget (Widget*);
138 virtual bool replaceWidget (Widget*, Widget*);
140 // This method wraps our Geode's addDrawable() method and returns the index of
141 // the newly-added Drawable.
142 unsigned int addDrawableAndGetIndex (osg::Drawable*);
143 unsigned int addChildAndGetIndex (osg::Node*);
145 bool isVisible () const;
146 bool isXYWithinVisible (float, float) const;
147 void setVisibleArea (int = 0, int = 0, int = 0, int = 0);
148 void addVisibleArea (int = 0, int = 0, int = 0, int = 0);
149 bool setFocused (const Widget*);
150 bool setFocused (const std::string&);
152 bool setFirstFocusable ();
153 bool setNextFocusable ();
154 bool getFocusList (WidgetList&) const;
155 bool getEmbeddedList (WindowList&) const;
156 void getParentList (WindowList&) const;
158 XYCoord localXY (double, double) const;
159 XYCoord getAbsoluteOrigin () const;
161 // This method wraps the current Window in a EmbeddedWindow object and returns it.
162 EmbeddedWindow* embed(
163 const std::string& = "",
164 Widget::Layer = Widget::LAYER_MIDDLE,
168 Widget* getFocused() {
169 return _focused.get();
172 const Widget* getFocused() const {
173 return _focused.get();
177 return _setVisible(true);
181 return _setVisible(false);
184 bool isPointerXYWithinVisible(float x, float y) const {
185 XYCoord xy = localXY(x, y);
187 return isXYWithinVisible(xy.x(), xy.y());
190 osg::Geode* getGeode() {
194 const osg::Geode* getGeode() const {
198 Widget* getBackground() {
202 const Widget* getBackground() const {
206 WindowManager* getWindowManager() {
210 const WindowManager* getWindowManager() const {
214 Window* getParent() {
218 const Window* getParent() const {
222 Window* getTopmostParent() {
223 return _getTopmostParent();
226 const Window* getTopmostParent() const {
227 return _getTopmostParent();
230 unsigned int getIndex() const {
234 matrix_type getX() const {
238 matrix_type getY() const {
242 matrix_type getZ() const {
246 point_type getWidth() const {
247 return _width.current;
250 point_type getHeight() const {
251 return _height.current;
254 point_type getMinWidth() const {
255 return _width.minimum;
258 point_type getMinHeight() const {
259 return _height.minimum;
262 VerticalAnchor getAnchorVertical() const {
266 HorizontalAnchor getAnchorHorizontal() const {
270 XYCoord getOrigin() const {
271 return XYCoord(_x, _y);
274 XYCoord getSize() const {
275 return XYCoord(_width.current, _height.current);
278 XYCoord getMinSize() const {
279 return XYCoord(_width.minimum, _height.minimum);
282 matrix_type getZRange() const {
286 Strata getStrata() const {
290 const Quad& getVisibleArea() const {
294 VisibilityMode getVisibilityMode() const {
298 Point getPosition() const {
299 return Point(_x, _y, _z);
302 matrix_type getRotate() const {
306 matrix_type getScale() const {
310 matrix_type getScaleDenominator() const {
314 void setX(matrix_type x) {
318 void setY(matrix_type y) {
322 void setZ(matrix_type z) {
326 void setZRange(matrix_type zRange) {
330 void setPosition(matrix_type x, matrix_type y, matrix_type z) {
336 void setPosition(const Point& p) {
337 setPosition(p.x(), p.y(), p.z());
340 void setOrigin(matrix_type x, matrix_type y) {
345 void setOrigin(const XYCoord& xy) {
346 setOrigin(xy.x(), xy.y());
349 void setRotate(matrix_type r) {
353 void setScale(matrix_type s) {
357 void setScaleDenominator(matrix_type sd) {
361 void setAnchorVertical(VerticalAnchor va) {
365 void setAnchorHorizontal(HorizontalAnchor ha) {
369 void setStrata(Strata s) {
373 void setVisibilityMode(VisibilityMode v) {
377 void addX(matrix_type x) {
381 void addY(matrix_type y) {
385 void addZ(matrix_type z) {
389 void addRotate(matrix_type r) {
393 void addScale(matrix_type s) {
394 _s += s / (_scaleDenom != 0.0f ? _scaleDenom : 1.0f);
397 void addOrigin(matrix_type x, matrix_type y) {
402 void attachMoveCallback() {
403 addCallback(new Callback(&callbackWindowMove, EVENT_MOUSE_DRAG));
406 void attachRotateCallback() {
407 addCallback(new Callback(&callbackWindowRotate, EVENT_MOUSE_DRAG));
410 void attachScaleCallback() {
411 addCallback(new Callback(&callbackWindowScale, EVENT_MOUSE_DRAG));
414 void attachTabFocusCallback() {
415 addCallback(new Callback(&callbackWindowTabFocus, EVENT_KEY_DOWN));
418 typedef point_type (Widget::*Getter)() const;
422 typedef std::less<point_type> Less;
423 typedef std::greater<point_type> Greater;
424 typedef std::plus<point_type> Plus;
426 friend class WindowManager;
428 // The (optional) Window that this Window is parented inside.
431 // The WindowManger to which this window is attached.
434 // The positional index this Node holds within it's parent WindowManager.
437 // The X and Y values of the Window (origin).
441 // A pair of values representing the currently calculated Z value and the
442 // depth range for all children to be used during the call to update().
446 // This is a special value that can be used to "force" a Window not to be
447 // focusable and instead always exist in the foreground or background.
450 // A flag determining whether our visible area is the full Window or rather
451 // a portion of the Window.
454 // A rotation value in degrees.
457 // This will also need to adjust geom internally so that picking is correct.
460 matrix_type _scaleDenom;
465 VerticalAnchor _vAnchor;
466 HorizontalAnchor _hAnchor;
468 // Not all windows have widgets that can focus, but if they do this should
469 // be a pointer to it.
470 osg::observer_ptr<Widget> _focused;
472 // The "visible" area that will define both the glScissor bounds AND will
473 // be used to make sure our pick is valid. The values herein correspond to
474 // X, Y, W, and H--in that order.
477 // This helper method is used by _compare<>() and _accumulate<>(), so ignore this
478 // function and go see the docs for those instead. This thing is huge and unwieldy
479 // and not to be triffled with! :)
481 point_type _forEachAssignOrApply(
488 point_type val = 0.0f;
489 unsigned int c = begin;
491 ConstIterator e = end > 0 ? _objects.begin() + end : _objects.end() + end;
493 // I WARNED YOU! If you try and understand what this does your head will
494 // explode! But let me say a few things: in MSVC you can't add to an iterator
495 // such that the add will cause it to increment past the end of the container.
496 // This appears to be safe in GCC, where it will just return the last
497 // item therein, but causes an assertion error in other compilers. I'm not
498 // sure if there is a cleaner remedy for this, so what we do for now is keep a
499 // count variable called "c" that makes sure our iterator's opterator+()
500 // method is safe to call.
502 ConstIterator i = _objects.begin() + begin;
508 if(i->valid()) v = (i->get()->*get)();
510 // If you want to assign to val, and NOT add a sequence of them...
512 if(T()(v, val)) val = v;
515 // If you want to accumulate a value INTO val...
516 else val = T()(v, val);
518 // Make sure our iterator is safe to increment. Otherwise, set it to
520 // TODO: This isn't 100% accurate, as it does not YET take into account
521 // our requested end in any way other than implicitly. It should, however,
522 // work okay for now.
523 if((c + add) < _objects.size()) i += add;
531 void _setWidthAndHeightUnknownSizeError (const std::string&, point_type);
532 void _setWidthAndHeightNotPAError (const std::string&, point_type);
533 void _setWidthAndHeight ();
534 void _removeFromGeode (Widget*);
536 Widget* _getBackground() const;
537 Window* _getTopmostParent() const;
539 // This method will return the T'th value returned by applying the Getter member function
540 // pointer to each iterator in the range of iterators defined by offset and add. In
541 // plain language, this helper method will apply some standard Widget::get* function
542 // to a range of objects in the _objects Vector, and will return the T'th of that.
543 // The template T can be any functor accepting two point_type values that return
544 // a bool. For example, this is commonly used with std::less to find the smallest
545 // width in a range of Widgets.
553 return _forEachAssignOrApply<T>(get, begin, end, add, true);
556 // This method will return the T'th value accumulated by applying the Getter member
557 // function to each iterator in the range of iterators defined by offset and add (similar
558 // to above). For example, this method can be used to apply std::plus to every
559 // width in a range of Widgets, and return the total.
561 point_type _accumulate(
567 return _forEachAssignOrApply<T>(get, begin, end, add, false);
570 osg::Geode* _geode() {
571 return dynamic_cast<osg::Geode*>(getChild(0));
574 const osg::Geode* _geode() const {
575 return dynamic_cast<const osg::Geode*>(getChild(0));
579 return _getBackground();
582 const Widget* _bg() const {
583 return _getBackground();
586 osg::Scissor* _scissor() {
587 return dynamic_cast<osg::Scissor*>(
588 getStateSet()->getAttribute(osg::StateAttribute::SCISSOR)
592 bool _setWidget (Widget*, int = -1);
593 bool _setVisible (bool);
594 void _setFocused (Widget*);
595 void _setStyled (Widget*);
596 void _setParented (Widget*, bool=false);
597 void _setManaged (Widget*, bool=false);
599 void _positionWidget(Widget*, point_type, point_type);
601 // These return the smallest and largest width and height values for the given
603 point_type _getMinWidgetWidth (int = 0, int = 0, int = 1) const;
604 point_type _getMinWidgetHeight (int = 0, int = 0, int = 1) const;
605 point_type _getMaxWidgetWidth (int = 0, int = 0, int = 1) const;
606 point_type _getMaxWidgetHeight (int = 0, int = 0, int = 1) const;
608 // These return the smallest and largest minWidth and minHeight values for
609 // the given range of Widgets.
610 point_type _getMinWidgetMinWidth (int = 0, int = 0, int = 1) const;
611 point_type _getMinWidgetMinHeight (int = 0, int = 0, int = 1) const;
612 point_type _getMaxWidgetMinWidth (int = 0, int = 0, int = 1) const;
613 point_type _getMaxWidgetMinHeight (int = 0, int = 0, int = 1) const;
615 // These return the smallest and largest width and height total (width + pad)
616 // values for the given range of Widgets.
617 point_type _getMinWidgetWidthTotal (int = 0, int = 0, int = 1) const;
618 point_type _getMinWidgetHeightTotal (int = 0, int = 0, int = 1) const;
619 point_type _getMaxWidgetWidthTotal (int = 0, int = 0, int = 1) const;
620 point_type _getMaxWidgetHeightTotal (int = 0, int = 0, int = 1) const;
622 // These return the smallest and largest minWidth and minHeight total
623 // (width + pad) values for the given range of Widgets.
624 point_type _getMinWidgetMinWidthTotal (int = 0, int = 0, int = 1) const;
625 point_type _getMinWidgetMinHeightTotal (int = 0, int = 0, int = 1) const;
626 point_type _getMaxWidgetMinWidthTotal (int = 0, int = 0, int = 1) const;
627 point_type _getMaxWidgetMinHeightTotal (int = 0, int = 0, int = 1) const;
629 // These return the smallest and largest horizontal and vertical padding
630 // values for the given range of Widgets.
631 point_type _getMinWidgetPadHorizontal (int = 0, int = 0, int = 1) const;
632 point_type _getMinWidgetPadVertical (int = 0, int = 0, int = 1) const;
633 point_type _getMaxWidgetPadHorizontal (int = 0, int = 0, int = 1) const;
634 point_type _getMaxWidgetPadVertical (int = 0, int = 0, int = 1) const;
636 point_type _getNumFill(int = 0, int = 0, int = 1) const;
638 // This method is passed the additional values by which width and height should be
639 // modified as calculed by the parent method, Window::resize. Keep in mind that these
640 // values can be negative (indicating a potential "shrink" request) or positive (which
641 // would indicate a "grow" request).
642 virtual void _resizeImplementation(point_type, point_type) = 0;
644 // These are made into implementation functions since getting the width or height
645 // of a window can potentially be an expensive operation, and we'll want to cache
646 // results if possible (which is handled transparently by the actual Window::resize
647 // method). They return a Sizes struct which contains two members: cur (for current)
648 // and min (minimum). It's important that the Window know it's minimum possible
649 // size so that it can ignore invalid requests to resize.
651 // Default versions using BoundingBox calculations are provided, but some Windows
652 // override this (Table, Box).
653 virtual Sizes _getWidthImplementation () const;
654 virtual Sizes _getHeightImplementation () const;
658typedef Window::WindowList WindowList;