123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662 |
- /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield
- *
- * This library is open source and may be redistributed and/or modified under
- * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
- * (at your option) any later version. The full license is in LICENSE file
- * included with this distribution, and on the openscenegraph.org website.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * OpenSceneGraph Public License for more details.
- */
- // Code by: Jeremy Moles (cubicool) 2007-2008
- #ifndef OSGWIDGET_WINDOW
- #define OSGWIDGET_WINDOW
- #include <osg/Scissor>
- #include <osg/MatrixTransform>
- #include <osg/Geode>
- #include <osg/ClipNode>
- #include <osgWidget/Types>
- #include <osgWidget/Util>
- #include <osgWidget/Widget>
- namespace osgWidget {
- // These are helper callbacks you can attach to Windows that will make them moveable,
- // rotatable, and scalable respectively.
- bool OSGWIDGET_EXPORT callbackWindowMove (Event&);
- bool OSGWIDGET_EXPORT callbackWindowRotate (Event&);
- bool OSGWIDGET_EXPORT callbackWindowScale (Event&);
- // These are helper callbacks you can attach to Windows to that will make various
- // keyboard events behave as you might imagine.
- bool OSGWIDGET_EXPORT callbackWindowTabFocus(Event&);
- class OSGWIDGET_EXPORT Window:
- public osg::MatrixTransform,
- public UIObjectParent<Widget>,
- public EventInterface,
- public StyleInterface
- {
- public:
- typedef std::list<osg::observer_ptr<Window> > WindowList;
- struct Sizes
- {
- point_type current;
- point_type minimum;
- Sizes(point_type c = -1.0f, point_type m = -1.0f):
- current(c),
- minimum(m) {}
- };
- // TODO: This is a class that puts (embeds) the Window inside of a Widget
- // interface, to help assemble Windows with Windows, and what have you.
- class OSGWIDGET_EXPORT EmbeddedWindow: public Widget {
- osg::ref_ptr<Window> _window;
- public:
- META_Object (osgWidget::Window, EmbeddedWindow);
- EmbeddedWindow (const std::string& = "", point_type = 0.0f, point_type = 0.0f);
- EmbeddedWindow (const EmbeddedWindow&, const osg::CopyOp&);
- virtual void parented (Window*);
- virtual void unparented (Window*);
- virtual void managed (WindowManager*);
- virtual void unmanaged (WindowManager*);
- virtual void positioned ();
- bool setWindow (Window*);
- void updateSizeFromWindow ();
- Window* getWindow() {
- return _window.get();
- }
- const Window* getWindow() const {
- return _window.get();
- }
- };
- // These correspond to special regions honored by the WindowManager. Most Windows
- // will want to be NONE, unless they need to exist in the foreground or background
- // for some reason.
- enum Strata {
- STRATA_NONE,
- STRATA_BACKGROUND,
- STRATA_FOREGROUND
- };
- // If you only want to display a portion of a Window (such as when it is embedded),
- // you will need to set the VisibilityMode to WM_PARTIAL. Otherwise, the entire
- // Window is visible by default. The final enum, VM_ENTIRE, says that no Scissoring
- // should take place at all, and is useful in cases where you want to properly
- // scale or rotate Windows.
- enum VisibilityMode {
- VM_FULL,
- VM_PARTIAL,
- VM_ENTIRE
- };
- // Anchors are very similar in that they allow us to pre-apply transformations in the
- // call to Window::update() that allow us to position a Window somewhere relative
- // to the WindowManger's viewable area. However, unlike the ALIGNMENT enums, these
- // are totally optional (whereas a Widget must always have some ALIGNMENT value set.
- enum VerticalAnchor {
- VA_NONE,
- VA_CENTER,
- VA_TOP,
- VA_BOTTOM
- };
- enum HorizontalAnchor {
- HA_NONE,
- HA_CENTER,
- HA_LEFT,
- HA_RIGHT
- };
- Window (const std::string& = "");
- Window (const Window&, const osg::CopyOp&);
- bool resize (point_type = 0.0f, point_type = 0.0f);
- bool resizeAdd (point_type = 0.0f, point_type = 0.0f);
- bool resizePercent (point_type = 0.0f, point_type = 0.0f);
- virtual void update ();
- virtual void managed (WindowManager*);
- virtual void unmanaged (WindowManager*);
- virtual bool addWidget (Widget*);
- virtual bool insertWidget (Widget*, unsigned int);
- virtual bool removeWidget (Widget*);
- virtual bool replaceWidget (Widget*, Widget*);
- // This method wraps our Geode's addDrawable() method and returns the index of
- // the newly-added Drawable.
- unsigned int addDrawableAndGetIndex (osg::Drawable*);
- unsigned int addChildAndGetIndex (osg::Node*);
- bool isVisible () const;
- bool isXYWithinVisible (float, float) const;
- void setVisibleArea (int = 0, int = 0, int = 0, int = 0);
- void addVisibleArea (int = 0, int = 0, int = 0, int = 0);
- bool setFocused (const Widget*);
- bool setFocused (const std::string&);
- bool grabFocus ();
- bool setFirstFocusable ();
- bool setNextFocusable ();
- bool getFocusList (WidgetList&) const;
- bool getEmbeddedList (WindowList&) const;
- void getParentList (WindowList&) const;
- XYCoord localXY (double, double) const;
- XYCoord getAbsoluteOrigin () const;
- // This method wraps the current Window in a EmbeddedWindow object and returns it.
- EmbeddedWindow* embed(
- const std::string& = "",
- Widget::Layer = Widget::LAYER_MIDDLE,
- unsigned int = 0
- );
- Widget* getFocused() {
- return _focused.get();
- }
- const Widget* getFocused() const {
- return _focused.get();
- }
- bool show() {
- return _setVisible(true);
- }
- bool hide() {
- return _setVisible(false);
- }
- bool isPointerXYWithinVisible(float x, float y) const {
- XYCoord xy = localXY(x, y);
- return isXYWithinVisible(xy.x(), xy.y());
- }
- osg::Geode* getGeode() {
- return _geode();
- }
- const osg::Geode* getGeode() const {
- return _geode();
- }
- Widget* getBackground() {
- return _bg();
- }
- const Widget* getBackground() const {
- return _bg();
- }
- WindowManager* getWindowManager() {
- return _wm;
- }
- const WindowManager* getWindowManager() const {
- return _wm;
- }
- Window* getParent() {
- return _parent;
- }
- const Window* getParent() const {
- return _parent;
- }
- Window* getTopmostParent() {
- return _getTopmostParent();
- }
- const Window* getTopmostParent() const {
- return _getTopmostParent();
- }
- unsigned int getIndex() const {
- return _index;
- }
- matrix_type getX() const {
- return _x;
- }
- matrix_type getY() const {
- return _y;
- }
- matrix_type getZ() const {
- return _z;
- }
- point_type getWidth() const {
- return _width.current;
- }
- point_type getHeight() const {
- return _height.current;
- }
- point_type getMinWidth() const {
- return _width.minimum;
- }
- point_type getMinHeight() const {
- return _height.minimum;
- }
- VerticalAnchor getAnchorVertical() const {
- return _vAnchor;
- }
- HorizontalAnchor getAnchorHorizontal() const {
- return _hAnchor;
- }
- XYCoord getOrigin() const {
- return XYCoord(_x, _y);
- }
- XYCoord getSize() const {
- return XYCoord(_width.current, _height.current);
- }
- XYCoord getMinSize() const {
- return XYCoord(_width.minimum, _height.minimum);
- }
- matrix_type getZRange() const {
- return _zRange;
- }
- Strata getStrata() const {
- return _strata;
- }
- const Quad& getVisibleArea() const {
- return _visibleArea;
- }
- VisibilityMode getVisibilityMode() const {
- return _vis;
- }
- Point getPosition() const {
- return Point(_x, _y, _z);
- }
- matrix_type getRotate() const {
- return _r;
- }
- matrix_type getScale() const {
- return _s;
- }
- matrix_type getScaleDenominator() const {
- return _scaleDenom;
- }
- void setX(matrix_type x) {
- _x = x;
- }
- void setY(matrix_type y) {
- _y = y;
- }
- void setZ(matrix_type z) {
- _z = z;
- }
- void setZRange(matrix_type zRange) {
- _zRange = zRange;
- }
- void setPosition(matrix_type x, matrix_type y, matrix_type z) {
- _x = x;
- _y = y;
- _z = z;
- }
- void setPosition(const Point& p) {
- setPosition(p.x(), p.y(), p.z());
- }
- void setOrigin(matrix_type x, matrix_type y) {
- _x = x;
- _y = y;
- }
- void setOrigin(const XYCoord& xy) {
- setOrigin(xy.x(), xy.y());
- }
- void setRotate(matrix_type r) {
- _r = r;
- }
- void setScale(matrix_type s) {
- _s = s;
- }
- void setScaleDenominator(matrix_type sd) {
- _scaleDenom = sd;
- }
- void setAnchorVertical(VerticalAnchor va) {
- _vAnchor = va;
- }
- void setAnchorHorizontal(HorizontalAnchor ha) {
- _hAnchor = ha;
- }
- void setStrata(Strata s) {
- _strata = s;
- }
- void setVisibilityMode(VisibilityMode v) {
- _vis = v;
- }
- void addX(matrix_type x) {
- _x += x;
- }
- void addY(matrix_type y) {
- _y += y;
- }
- void addZ(matrix_type z) {
- _z += z;
- }
- void addRotate(matrix_type r) {
- _r += r;
- }
- void addScale(matrix_type s) {
- _s += s / (_scaleDenom != 0.0f ? _scaleDenom : 1.0f);
- }
- void addOrigin(matrix_type x, matrix_type y) {
- _x += x;
- _y += y;
- }
- void attachMoveCallback() {
- addCallback(new Callback(&callbackWindowMove, EVENT_MOUSE_DRAG));
- }
- void attachRotateCallback() {
- addCallback(new Callback(&callbackWindowRotate, EVENT_MOUSE_DRAG));
- }
- void attachScaleCallback() {
- addCallback(new Callback(&callbackWindowScale, EVENT_MOUSE_DRAG));
- }
- void attachTabFocusCallback() {
- addCallback(new Callback(&callbackWindowTabFocus, EVENT_KEY_DOWN));
- }
- typedef point_type (Widget::*Getter)() const;
- protected:
- typedef std::less<point_type> Less;
- typedef std::greater<point_type> Greater;
- typedef std::plus<point_type> Plus;
- friend class WindowManager;
- // The (optional) Window that this Window is parented inside.
- Window* _parent;
- // The WindowManger to which this window is attached.
- WindowManager* _wm;
- // The positional index this Node holds within it's parent WindowManager.
- unsigned int _index;
- // The X and Y values of the Window (origin).
- matrix_type _x;
- matrix_type _y;
- // A pair of values representing the currently calculated Z value and the
- // depth range for all children to be used during the call to update().
- matrix_type _z;
- matrix_type _zRange;
- // This is a special value that can be used to "force" a Window not to be
- // focusable and instead always exist in the foreground or background.
- Strata _strata;
- // A flag determining whether our visible area is the full Window or rather
- // a portion of the Window.
- VisibilityMode _vis;
- // A rotation value in degrees.
- matrix_type _r;
- // This will also need to adjust geom internally so that picking is correct.
- matrix_type _s;
- matrix_type _scaleDenom;
- Sizes _width;
- Sizes _height;
- VerticalAnchor _vAnchor;
- HorizontalAnchor _hAnchor;
- // Not all windows have widgets that can focus, but if they do this should
- // be a pointer to it.
- osg::observer_ptr<Widget> _focused;
- // The "visible" area that will define both the glScissor bounds AND will
- // be used to make sure our pick is valid. The values herein correspond to
- // X, Y, W, and H--in that order.
- Quad _visibleArea;
- // This helper method is used by _compare<>() and _accumulate<>(), so ignore this
- // function and go see the docs for those instead. This thing is huge and unwieldy
- // and not to be triffled with! :)
- template<typename T>
- point_type _forEachAssignOrApply(
- Getter get,
- int begin,
- int end,
- int add,
- bool assign
- ) const {
- point_type val = 0.0f;
- unsigned int c = begin;
- ConstIterator e = end > 0 ? _objects.begin() + end : _objects.end() + end;
- // I WARNED YOU! If you try and understand what this does your head will
- // explode! But let me say a few things: in MSVC you can't add to an iterator
- // such that the add will cause it to increment past the end of the container.
- // This appears to be safe in GCC, where it will just return the last
- // item therein, but causes an assertion error in other compilers. I'm not
- // sure if there is a cleaner remedy for this, so what we do for now is keep a
- // count variable called "c" that makes sure our iterator's opterator+()
- // method is safe to call.
- for(
- ConstIterator i = _objects.begin() + begin;
- i < e;
- c += add
- ) {
- point_type v = 0.0f;
- if(i->valid()) v = (i->get()->*get)();
- // If you want to assign to val, and NOT add a sequence of them...
- if(assign) {
- if(T()(v, val)) val = v;
- }
- // If you want to accumulate a value INTO val...
- else val = T()(v, val);
- // Make sure our iterator is safe to increment. Otherwise, set it to
- // whatever end is.
- // TODO: This isn't 100% accurate, as it does not YET take into account
- // our requested end in any way other than implicitly. It should, however,
- // work okay for now.
- if((c + add) < _objects.size()) i += add;
- else i = e;
- }
- return val;
- }
- void _setWidthAndHeightUnknownSizeError (const std::string&, point_type);
- void _setWidthAndHeightNotPAError (const std::string&, point_type);
- void _setWidthAndHeight ();
- void _removeFromGeode (Widget*);
- Widget* _getBackground() const;
- Window* _getTopmostParent() const;
- // This method will return the T'th value returned by applying the Getter member function
- // pointer to each iterator in the range of iterators defined by offset and add. In
- // plain language, this helper method will apply some standard Widget::get* function
- // to a range of objects in the _objects Vector, and will return the T'th of that.
- // The template T can be any functor accepting two point_type values that return
- // a bool. For example, this is commonly used with std::less to find the smallest
- // width in a range of Widgets.
- template<typename T>
- point_type _compare(
- Getter get,
- int begin = 0,
- int end = 0,
- int add = 1
- ) const {
- return _forEachAssignOrApply<T>(get, begin, end, add, true);
- }
- // This method will return the T'th value accumulated by applying the Getter member
- // function to each iterator in the range of iterators defined by offset and add (similar
- // to above). For example, this method can be used to apply std::plus to every
- // width in a range of Widgets, and return the total.
- template<typename T>
- point_type _accumulate(
- Getter get,
- int begin = 0,
- int end = 0,
- int add = 1
- ) const {
- return _forEachAssignOrApply<T>(get, begin, end, add, false);
- }
- osg::Geode* _geode() {
- return dynamic_cast<osg::Geode*>(getChild(0));
- }
- const osg::Geode* _geode() const {
- return dynamic_cast<const osg::Geode*>(getChild(0));
- }
- Widget* _bg() {
- return _getBackground();
- }
- const Widget* _bg() const {
- return _getBackground();
- }
- osg::Scissor* _scissor() {
- return dynamic_cast<osg::Scissor*>(
- getStateSet()->getAttribute(osg::StateAttribute::SCISSOR)
- );
- }
- bool _setWidget (Widget*, int = -1);
- bool _setVisible (bool);
- void _setFocused (Widget*);
- void _setStyled (Widget*);
- void _setParented (Widget*, bool=false);
- void _setManaged (Widget*, bool=false);
- void _positionWidget(Widget*, point_type, point_type);
- // These return the smallest and largest width and height values for the given
- // range of Widgets.
- point_type _getMinWidgetWidth (int = 0, int = 0, int = 1) const;
- point_type _getMinWidgetHeight (int = 0, int = 0, int = 1) const;
- point_type _getMaxWidgetWidth (int = 0, int = 0, int = 1) const;
- point_type _getMaxWidgetHeight (int = 0, int = 0, int = 1) const;
- // These return the smallest and largest minWidth and minHeight values for
- // the given range of Widgets.
- point_type _getMinWidgetMinWidth (int = 0, int = 0, int = 1) const;
- point_type _getMinWidgetMinHeight (int = 0, int = 0, int = 1) const;
- point_type _getMaxWidgetMinWidth (int = 0, int = 0, int = 1) const;
- point_type _getMaxWidgetMinHeight (int = 0, int = 0, int = 1) const;
- // These return the smallest and largest width and height total (width + pad)
- // values for the given range of Widgets.
- point_type _getMinWidgetWidthTotal (int = 0, int = 0, int = 1) const;
- point_type _getMinWidgetHeightTotal (int = 0, int = 0, int = 1) const;
- point_type _getMaxWidgetWidthTotal (int = 0, int = 0, int = 1) const;
- point_type _getMaxWidgetHeightTotal (int = 0, int = 0, int = 1) const;
- // These return the smallest and largest minWidth and minHeight total
- // (width + pad) values for the given range of Widgets.
- point_type _getMinWidgetMinWidthTotal (int = 0, int = 0, int = 1) const;
- point_type _getMinWidgetMinHeightTotal (int = 0, int = 0, int = 1) const;
- point_type _getMaxWidgetMinWidthTotal (int = 0, int = 0, int = 1) const;
- point_type _getMaxWidgetMinHeightTotal (int = 0, int = 0, int = 1) const;
- // These return the smallest and largest horizontal and vertical padding
- // values for the given range of Widgets.
- point_type _getMinWidgetPadHorizontal (int = 0, int = 0, int = 1) const;
- point_type _getMinWidgetPadVertical (int = 0, int = 0, int = 1) const;
- point_type _getMaxWidgetPadHorizontal (int = 0, int = 0, int = 1) const;
- point_type _getMaxWidgetPadVertical (int = 0, int = 0, int = 1) const;
- point_type _getNumFill(int = 0, int = 0, int = 1) const;
- // This method is passed the additional values by which width and height should be
- // modified as calculed by the parent method, Window::resize. Keep in mind that these
- // values can be negative (indicating a potential "shrink" request) or positive (which
- // would indicate a "grow" request).
- virtual void _resizeImplementation(point_type, point_type) = 0;
- // These are made into implementation functions since getting the width or height
- // of a window can potentially be an expensive operation, and we'll want to cache
- // results if possible (which is handled transparently by the actual Window::resize
- // method). They return a Sizes struct which contains two members: cur (for current)
- // and min (minimum). It's important that the Window know it's minimum possible
- // size so that it can ignore invalid requests to resize.
- //
- // Default versions using BoundingBox calculations are provided, but some Windows
- // override this (Table, Box).
- virtual Sizes _getWidthImplementation () const;
- virtual Sizes _getHeightImplementation () const;
- };
- typedef Window::WindowList WindowList;
- }
- #endif
|