root/OpenSceneGraph/trunk/include/osgWidget/Window @ 13041

Revision 13041, 21.5 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield
2 *
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.
7 *
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.
12*/
13
14// Code by: Jeremy Moles (cubicool) 2007-2008
15
16#ifndef OSGWIDGET_WINDOW
17#define OSGWIDGET_WINDOW
18
19#include <osg/Scissor>
20#include <osg/MatrixTransform>
21#include <osg/Geode>
22#include <osg/ClipNode>
23#include <osgWidget/Types>
24#include <osgWidget/Util>
25#include <osgWidget/Widget>
26
27namespace osgWidget {
28
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&);
34
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&);
38
39class OSGWIDGET_EXPORT Window:
40    public osg::MatrixTransform,
41    public UIObjectParent<Widget>,
42    public EventInterface,
43    public StyleInterface
44{
45    public:
46        typedef std::list<osg::observer_ptr<Window> > WindowList;
47
48        struct Sizes
49        {
50            point_type current;
51            point_type minimum;
52
53            Sizes(point_type c = -1.0f, point_type m = -1.0f):
54            current(c),
55            minimum(m) {}
56        };
57
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;
62
63        public:
64            META_Object   (osgWidget::Window, EmbeddedWindow);
65
66            EmbeddedWindow (const std::string& = "", point_type = 0.0f, point_type = 0.0f);
67            EmbeddedWindow (const EmbeddedWindow&, const osg::CopyOp&);
68
69            virtual void parented   (Window*);
70            virtual void unparented (Window*);
71            virtual void managed    (WindowManager*);
72            virtual void unmanaged  (WindowManager*);
73            virtual void positioned ();
74
75            bool setWindow            (Window*);
76            void updateSizeFromWindow ();
77
78            Window* getWindow() {
79                return _window.get();
80            }
81
82            const Window* getWindow() const {
83                return _window.get();
84            }
85        };
86
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
89        // for some reason.
90        enum Strata {
91            STRATA_NONE,
92            STRATA_BACKGROUND,
93            STRATA_FOREGROUND
94        };
95
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 {
102            VM_FULL,
103            VM_PARTIAL,
104            VM_ENTIRE
105        };
106
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 {
112            VA_NONE,
113            VA_CENTER,
114            VA_TOP,
115            VA_BOTTOM
116        };
117
118        enum HorizontalAnchor {
119            HA_NONE,
120            HA_CENTER,
121            HA_LEFT,
122            HA_RIGHT
123        };
124
125        Window (const std::string& = "");
126        Window (const Window&, const osg::CopyOp&);
127
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);
131
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*);
139
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*);
144
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&);
151        bool grabFocus         ();
152        bool setFirstFocusable ();
153        bool setNextFocusable  ();
154        bool getFocusList      (WidgetList&) const;
155        bool getEmbeddedList   (WindowList&) const;
156        void getParentList     (WindowList&) const;
157
158        XYCoord localXY           (double, double) const;
159        XYCoord getAbsoluteOrigin () const;
160
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,
165            unsigned int       = 0
166        );
167
168        Widget* getFocused() {
169            return _focused.get();
170        }
171
172        const Widget* getFocused() const {
173            return _focused.get();
174        }
175
176        bool show() {
177            return _setVisible(true);
178        }
179
180        bool hide() {
181            return _setVisible(false);
182        }
183
184        bool isPointerXYWithinVisible(float x, float y) const {
185            XYCoord xy = localXY(x, y);
186
187            return isXYWithinVisible(xy.x(), xy.y());
188        }
189
190        osg::Geode* getGeode() {
191            return _geode();
192        }
193
194        const osg::Geode* getGeode() const {
195            return _geode();
196        }
197
198        Widget* getBackground() {
199            return _bg();
200        }
201
202        const Widget* getBackground() const {
203            return _bg();
204        }
205
206        WindowManager* getWindowManager() {
207            return _wm;
208        }
209
210        const WindowManager* getWindowManager() const {
211            return _wm;
212        }
213
214        Window* getParent() {
215            return _parent;
216        }
217
218        const Window* getParent() const {
219            return _parent;
220        }
221
222        Window* getTopmostParent() {
223            return _getTopmostParent();
224        }
225
226        const Window* getTopmostParent() const {
227            return _getTopmostParent();
228        }
229
230        unsigned int getIndex() const {
231            return _index;
232        }
233
234        matrix_type getX() const {
235            return _x;
236        }
237
238        matrix_type getY() const {
239            return _y;
240        }
241
242        matrix_type getZ() const {
243            return _z;
244        }
245
246        point_type getWidth() const {
247            return _width.current;
248        }
249
250        point_type getHeight() const {
251            return _height.current;
252        }
253
254        point_type getMinWidth() const {
255            return _width.minimum;
256        }
257
258        point_type getMinHeight() const {
259            return _height.minimum;
260        }
261
262        VerticalAnchor getAnchorVertical() const {
263            return _vAnchor;
264        }
265
266        HorizontalAnchor getAnchorHorizontal() const {
267            return _hAnchor;
268        }
269
270        XYCoord getOrigin() const {
271            return XYCoord(_x, _y);
272        }
273
274        XYCoord getSize() const {
275            return XYCoord(_width.current, _height.current);
276        }
277
278        XYCoord getMinSize() const {
279            return XYCoord(_width.minimum, _height.minimum);
280        }
281
282        matrix_type getZRange() const {
283            return _zRange;
284        }
285
286        Strata getStrata() const {
287            return _strata;
288        }
289
290        const Quad& getVisibleArea() const {
291            return _visibleArea;
292        }
293
294        VisibilityMode getVisibilityMode() const {
295            return _vis;
296        }
297
298        Point getPosition() const {
299            return Point(_x, _y, _z);
300        }
301
302        matrix_type getRotate() const {
303            return _r;
304        }
305
306        matrix_type getScale() const {
307            return _s;
308        }
309
310        matrix_type getScaleDenominator() const {
311            return _scaleDenom;
312        }
313
314        void setX(matrix_type x) {
315            _x = x;
316        }
317
318        void setY(matrix_type y) {
319            _y = y;
320        }
321
322        void setZ(matrix_type z) {
323            _z = z;
324        }
325
326        void setZRange(matrix_type zRange) {
327            _zRange = zRange;
328        }
329
330        void setPosition(matrix_type x, matrix_type y, matrix_type z) {
331            _x = x;
332            _y = y;
333            _z = z;
334        }
335
336        void setPosition(const Point& p) {
337            setPosition(p.x(), p.y(), p.z());
338        }
339
340        void setOrigin(matrix_type x, matrix_type y) {
341            _x = x;
342            _y = y;
343        }
344
345        void setOrigin(const XYCoord& xy) {
346                setOrigin(xy.x(), xy.y());
347        }
348
349        void setRotate(matrix_type r) {
350            _r = r;
351        }
352
353        void setScale(matrix_type s) {
354            _s = s;
355        }
356
357        void setScaleDenominator(matrix_type sd) {
358            _scaleDenom = sd;
359        }
360
361        void setAnchorVertical(VerticalAnchor va) {
362            _vAnchor = va;
363        }
364
365        void setAnchorHorizontal(HorizontalAnchor ha) {
366            _hAnchor = ha;
367        }
368
369        void setStrata(Strata s) {
370            _strata = s;
371        }
372
373        void setVisibilityMode(VisibilityMode v) {
374            _vis = v;
375        }
376
377        void addX(matrix_type x) {
378            _x += x;
379        }
380
381        void addY(matrix_type y) {
382            _y += y;
383        }
384
385        void addZ(matrix_type z) {
386            _z += z;
387        }
388
389        void addRotate(matrix_type r) {
390            _r += r;
391        }
392
393        void addScale(matrix_type s) {
394            _s += s / (_scaleDenom != 0.0f ? _scaleDenom : 1.0f);
395        }
396
397        void addOrigin(matrix_type x, matrix_type y) {
398            _x += x;
399            _y += y;
400        }
401
402        void attachMoveCallback() {
403            addCallback(new Callback(&callbackWindowMove, EVENT_MOUSE_DRAG));
404        }
405
406        void attachRotateCallback() {
407            addCallback(new Callback(&callbackWindowRotate, EVENT_MOUSE_DRAG));
408        }
409
410        void attachScaleCallback() {
411            addCallback(new Callback(&callbackWindowScale, EVENT_MOUSE_DRAG));
412        }
413
414        void attachTabFocusCallback() {
415            addCallback(new Callback(&callbackWindowTabFocus, EVENT_KEY_DOWN));
416        }
417
418        typedef point_type (Widget::*Getter)() const;
419
420    protected:
421
422        typedef std::less<point_type>    Less;
423        typedef std::greater<point_type> Greater;
424        typedef std::plus<point_type>    Plus;
425
426        friend class WindowManager;
427
428        // The (optional) Window that this Window is parented inside.
429        Window* _parent;
430
431        // The WindowManger to which this window is attached.
432        WindowManager* _wm;
433
434        // The positional index this Node holds within it's parent WindowManager.
435        unsigned int _index;
436
437        // The X and Y values of the Window (origin).
438        matrix_type _x;
439        matrix_type _y;
440
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().
443        matrix_type _z;
444        matrix_type _zRange;
445
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.
448        Strata _strata;
449
450        // A flag determining whether our visible area is the full Window or rather
451        // a portion of the Window.
452        VisibilityMode _vis;
453
454        // A rotation value in degrees.
455        matrix_type _r;
456
457        // This will also need to adjust geom internally so that picking is correct.
458        matrix_type _s;
459
460        matrix_type _scaleDenom;
461
462        Sizes _width;
463        Sizes _height;
464
465        VerticalAnchor   _vAnchor;
466        HorizontalAnchor _hAnchor;
467
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;
471
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.
475        Quad _visibleArea;
476
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! :)
480        template<typename T>
481        point_type _forEachAssignOrApply(
482            Getter get,
483            int    begin,
484            int    end,
485            int    add,
486            bool   assign
487        ) const {
488            point_type   val = 0.0f;
489            unsigned int c   = begin;
490
491            ConstIterator e = end > 0 ? _objects.begin() + end : _objects.end() + end;
492
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.
501            for(
502                ConstIterator i = _objects.begin() + begin;
503                i < e;
504                c += add
505            ) {
506                point_type v = 0.0f;
507
508                if(i->valid()) v = (i->get()->*get)();
509
510                // If you want to assign to val, and NOT add a sequence of them...
511                if(assign) {
512                    if(T()(v, val)) val = v;
513                }
514
515                // If you want to accumulate a value INTO val...
516                else val = T()(v, val);
517
518                // Make sure our iterator is safe to increment. Otherwise, set it to
519                // whatever end is.
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;
524
525                else i = e;
526            }
527
528            return val;
529        }
530
531        void _setWidthAndHeightUnknownSizeError (const std::string&, point_type);
532        void _setWidthAndHeightNotPAError       (const std::string&, point_type);
533        void _setWidthAndHeight                 ();
534        void _removeFromGeode                   (Widget*);
535
536        Widget* _getBackground() const;
537        Window* _getTopmostParent() const;
538
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.
546        template<typename T>
547        point_type _compare(
548            Getter get,
549            int    begin = 0,
550            int    end   = 0,
551            int    add   = 1
552        ) const {
553            return _forEachAssignOrApply<T>(get, begin, end, add, true);
554        }
555
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.
560        template<typename T>
561        point_type _accumulate(
562            Getter get,
563            int    begin = 0,
564            int    end   = 0,
565            int    add   = 1
566        ) const {
567            return _forEachAssignOrApply<T>(get, begin, end, add, false);
568        }
569
570        osg::Geode* _geode() {
571            return dynamic_cast<osg::Geode*>(getChild(0));
572        }
573
574        const osg::Geode* _geode() const {
575            return dynamic_cast<const osg::Geode*>(getChild(0));
576        }
577
578        Widget* _bg() {
579            return _getBackground();
580        }
581
582        const Widget* _bg() const {
583            return _getBackground();
584        }
585
586        osg::Scissor* _scissor() {
587            return dynamic_cast<osg::Scissor*>(
588                getStateSet()->getAttribute(osg::StateAttribute::SCISSOR)
589            );
590        }
591
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);
598
599        void _positionWidget(Widget*, point_type, point_type);
600
601        // These return the smallest and largest width and height values for the given
602        // range of Widgets.
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;
607
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;
614
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;
621
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;
628
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;
635
636        point_type _getNumFill(int = 0, int = 0, int = 1) const;
637
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" reqeust).
642        virtual void _resizeImplementation(point_type, point_type) = 0;
643
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 actualy 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 invaled requests to resize.
650        //
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;
655
656};
657
658typedef Window::WindowList WindowList;
659
660}
661
662#endif
Note: See TracBrowser for help on using the browser.