root/OpenSceneGraph/trunk/src/osgWidget/Window.cpp @ 10624

Revision 10624, 28.0 kB (checked in by robert, 5 years ago)

From Jean-Sebastien Guay, "osgWidget::Window::setWindow() calls parented() (which does an addChild()) on the new window, but it does not call unparented() (which does a removeChild()) on the old window before. So it works fine if there was no window previously, but if an app creates new windows and calls setWindow() to replace the previous one, they will all add up instead and be on top of each other...

This is fixed in the file attached."

Line 
1// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
2// $Id: Window.cpp 66 2008-07-14 21:54:09Z cubicool $
3
4#include <algorithm>
5#include <osgGA/GUIEventAdapter>
6#include <osgWidget/WindowManager>
7
8namespace osgWidget {
9
10bool callbackWindowMove(Event& ev) {
11    if(!ev.getWindow() || !ev.getWindowManager()->isLeftMouseButtonDown()) return false;
12
13    ev.getWindow()->addOrigin(ev.x, ev.y);
14    ev.getWindow()->update();
15   
16    return true;
17}
18
19bool callbackWindowRotate(Event& ev) {
20    if(!ev.getWindow() || !ev.getWindowManager()->isRightMouseButtonDown()) return false;
21
22    ev.getWindow()->addRotate(ev.y);
23    ev.getWindow()->update();
24   
25    return true;
26}
27
28bool callbackWindowScale(Event& ev) {
29    if(!ev.getWindow() || !ev.getWindowManager()->isMiddleMouseButtonDown()) return false;
30
31    ev.getWindow()->addScale(ev.y);
32    ev.getWindow()->update();
33   
34    return true;
35}
36
37bool callbackWindowTabFocus(Event& ev) {
38    if(!ev.getWindow() || ev.key != osgGA::GUIEventAdapter::KEY_Tab) return false;
39   
40    return ev.getWindow()->setNextFocusable();
41}
42
43Window::EmbeddedWindow::EmbeddedWindow(const std::string& name, point_type w, point_type h):
44Widget(name, w, h) {
45}
46
47Window::EmbeddedWindow::EmbeddedWindow(const EmbeddedWindow& wiw, const osg::CopyOp& co):
48Widget(wiw, co) {
49    // TODO: Get this!
50    // _window = 0;
51}
52
53void Window::EmbeddedWindow::parented(Window* parent) {
54    if(!_window.valid()) return;
55
56    if(!_window->_parent) {
57        _window->_parent = parent;
58
59        // Add this Window to the Window, on the same level as a Window's
60        // internal Geode. This will require special handling of events!
61        parent->addChild(_window.get());
62    }
63
64    else warn()
65        << "EmbeddedWindow Widget [" << _name
66        << "] cannot embed itself in Window [" << _window->getName()
67        << "], since it is already a child of [" << _window->_parent->getName()
68        << "]" << std::endl
69    ;
70}
71
72void Window::EmbeddedWindow::unparented(Window*) {
73    if(_window.valid()) {
74        _window->_parent = 0;
75
76        if(_parent) _parent->removeChild(_window.get());
77    }
78}
79
80void Window::EmbeddedWindow::managed(WindowManager* wm) {
81    if(!_window.valid()) return;
82
83    _window->setNodeMask(wm->getNodeMask());
84    _window->managed(wm);
85}
86
87void Window::EmbeddedWindow::unmanaged(WindowManager* wm) {
88    _window->unmanaged(wm);
89}
90
91void Window::EmbeddedWindow::positioned() {
92    if(!_window.valid()) return;
93
94    point_type x = getX();
95    point_type y = getY();
96    point_type w = getWidth();
97    point_type h = getHeight();
98
99    // If the widget is fillable, ask the internal Window to resize itself.
100    // Whether or not the Window honors this reqest will be up to it.
101    _window->setOrigin(x, y);
102    _window->setZ(_calculateZ(getLayer() + 1));
103    _window->setZRange(_calculateZ(LAYER_TOP - (getLayer() + 1)));
104    _window->setVisibleArea(0, 0, static_cast<int>(w), static_cast<int>(h));
105    _window->resize(w, h);
106}
107
108bool Window::EmbeddedWindow::setWindow(Window* win) {
109    if(!win) {
110        warn()
111            << "EmbeddedWindow [" << _name
112            << "] attempted to set a NULL Window." << std::endl
113        ;
114
115        return false;
116    }
117
118    if (_window.valid() && _parent)
119        unparented(_parent);
120
121    _window = win;
122
123    _window->resize();
124    _window->setVisibilityMode(VM_PARTIAL);
125
126    if(_parent) parented(_parent);
127
128    WindowManager* wm = _getWindowManager();
129
130    if(wm) managed(wm);
131
132    return true;
133}
134
135void Window::EmbeddedWindow::updateSizeFromWindow() {
136    setSize(_window->getSize());
137
138    if(_parent) _parent->resize();
139}
140
141Window::Window(const std::string& name):
142_parent     (0),
143_wm         (0),
144_index      (0),
145_x          (0.0f),
146_y          (0.0f),
147_z          (0.0f),
148_zRange     (0.0f),
149_strata     (STRATA_NONE),
150_vis        (VM_FULL),
151_r          (0.0f),
152_s          (1.0f),
153_scaleDenom (100.0f),
154_vAnchor    (VA_NONE),
155_hAnchor    (HA_NONE) {
156    _name = name.size() ? name : generateRandomName("Window");
157
158    // TODO: Fix the "bg" name.
159    osg::Geode* geode = new osg::Geode();
160    Widget*     bg    = new Widget(name + "bg", 0.0f, 0.0f);
161
162    bg->setLayer(Widget::LAYER_BG);
163    bg->setColor(1.0f, 1.0f, 1.0f, 1.0f);
164
165    _setParented(bg);
166
167    geode->addDrawable(bg);
168
169    addChild(geode);
170    setDataVariance(osg::Object::DYNAMIC);
171    setEventMask(EVENT_ALL);
172
173    getOrCreateStateSet()->setAttributeAndModes(
174        new osg::Scissor(0, 0, 0, 0),
175        osg::StateAttribute::ON
176    );
177}
178
179Window::Window(const Window& window, const osg::CopyOp& co):
180MatrixTransform (window, co),
181EventInterface  (window),
182StyleInterface  (window),
183_parent         (0),
184_wm             (0),
185_x              (window._x),
186_y              (window._y),
187_z              (window._z),
188_zRange         (window._zRange),
189_strata         (window._strata),
190_vis            (window._vis),
191_r              (window._r),
192_s              (window._s),
193_scaleDenom     (window._scaleDenom),
194_width          (window._width),
195_height         (window._height),
196_vAnchor        (window._vAnchor),
197_hAnchor        (window._hAnchor),
198_visibleArea    (window._visibleArea) {
199    // Construct our vector of Widgets for easier use. :)
200    // TODO: I almost certainly will need to use the getPosition() thing here eventually
201    // for things to work 100% properly. For example, some Geodes may contain labels,
202    // etc. Also, any widget that doesn't support simple addWidget probably won't
203    // work (Table?)
204    osg::Geode* geode = _geode();
205
206    Widget* bg = dynamic_cast<Widget*>(geode->getDrawable(0));
207
208    if(bg) {
209        _setParented(bg);
210
211        // TODO: This is silly...
212        bg->setName(_name + "bg");
213    }
214
215    for(unsigned int i = 1; i < geode->getNumDrawables(); i++) {
216        Widget* widget = dynamic_cast<Widget*>(geode->getDrawable(i));
217
218        if(!widget) continue;
219
220        // TODO: Properly test this...
221        if(!widget->canClone()) {
222            // geode->removeDrawable(widget);
223
224            continue;
225        }
226
227        _setParented(widget);
228
229        _objects.push_back(widget);
230    }
231
232    geode->setName(_name);
233}
234
235// This is the method by which all Windows are redrawn/resized. Keep in mind that not all
236// Windows are required to absolutely honor a resize request, which is why we call the
237// _getWidthImplementation() and _getHeightImplementation() functions instead of using the
238// values passed in.
239bool Window::resize(point_type width, point_type height) {
240    // First, we query and store what sizes the Window currently is.
241    _setWidthAndHeight();
242
243    // Second, we determine if there is a difference between what the size currently
244    // is and what the user has requested.
245    point_type diffWidth  = width > 0.0f ? width - _width.current : 0.0f;
246    point_type diffHeight = height > 0.0f ? height - _height.current : 0.0f;
247
248    return resizeAdd(diffWidth, diffHeight);
249}
250
251bool Window::resizeAdd(point_type diffWidth, point_type diffHeight) {
252    if(
253        _width.current + diffWidth < _width.minimum ||
254        _height.current + diffHeight < _height.minimum
255    ) {
256        warn()
257            << "Window [" << _name << "] can't call resizeAdd() with the "
258            << "values " << diffWidth << " and " << diffHeight << std::endl
259        ;
260
261        return false;
262    }
263
264    // Now we initiate the resize, which may or may not succeed.
265    _resizeImplementation(diffWidth, diffHeight);
266
267    // Inform each widget that it has been positioned.
268    for(Iterator i = begin(); i != end(); i++) if(i->valid()) {
269        i->get()->dirtyBound();
270        i->get()->setDimensions();
271        i->get()->positioned();
272    }
273
274    _setWidthAndHeight();
275
276    Widget* bg = _bg();
277
278    bg->setSize(_width.current, _height.current);
279    bg->dirtyBound();
280    bg->positioned();
281
282    update();
283
284    return true;
285}
286
287bool Window::resizePercent(point_type width, point_type height) {
288    if(!_parent && !_wm) {
289        warn()
290            << "Window [" << _name
291            << "] cannot resizePercent without being managed or parented."
292            << std::endl
293        ;
294
295        return false;
296    }
297
298    if(!_parent) return resize(
299        _wm->getWidth() * (width / 100.0f),
300        _wm->getHeight() * (height / 100.0f)
301    );
302   
303    else return resize(
304        _parent->getWidth() * (width / 100.0f),
305        _parent->getHeight() * (height / 100.0f)
306    );
307}
308
309void Window::update() {
310    WindowList wl;
311
312    getEmbeddedList(wl);
313
314    for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) w->get()->update();
315
316    matrix_type x  = _x;
317    matrix_type y  = _y;
318    XYCoord     xy = getAbsoluteOrigin();
319
320    // We only honor ANCHOR requests on topmost Windows, not embedded ones.
321    if((_vAnchor != VA_NONE || _hAnchor != HA_NONE) && !_parent && _wm) {
322        if(_vAnchor == VA_TOP) y = _wm->getHeight() - _height.current;
323        else if(_vAnchor == VA_CENTER) y = osg::round(_wm->getHeight() / 2.0f);
324        else if(_vAnchor == VA_BOTTOM) y = 0.0f;
325
326        if(_hAnchor == HA_LEFT) x = 0.0f;
327        else if(_hAnchor == HA_CENTER) x = osg::round(_wm->getWidth() / 2.0f);
328        else if(_hAnchor == HA_RIGHT) x = _wm->getWidth() - _width.current + _visibleArea[2];
329
330        xy.set(x, y);
331    }
332   
333    matrix_type z = _z;
334
335    // We can't do proper scissoring until we have access to our parent WindowManager, and
336    // we need to determine the sorting method we want to use.
337    if(_wm) {
338        if(_wm->isUsingRenderBins()) {
339            getOrCreateStateSet()->setRenderBinDetails(
340                static_cast<int>((1.0f - fabs(_z)) * OSGWIDGET_RENDERBIN_MOD),
341                "RenderBin"
342            );
343
344            z = 0.0f;
345        }
346
347        int sx = static_cast<int>(xy.x());
348        int sy = static_cast<int>(xy.y());
349        int sw = static_cast<int>(_width.current);
350        int sh = static_cast<int>(_height.current);
351
352        // This sets the Scissor area to some offset defined by the user.
353        if(_vis == VM_PARTIAL) {
354            sw = static_cast<int>(_visibleArea[2]);
355            sh = static_cast<int>(_visibleArea[3]);
356        }
357
358        // Otherwise, use the size of the WindowManager itself.
359        else if(_vis == VM_ENTIRE) {
360            sx = 0;
361            sy = 0;
362            sw = static_cast<int>(_wm->getWidth());
363            sh = static_cast<int>(_wm->getHeight());
364        }
365
366        _scissor()->setScissor(sx, sy, sw, sh);
367    }
368
369    // Update the Window itself, setting it's matrix according to translate, rotate, and
370    // scale values.
371    osg::Matrix r = osg::Matrix::rotate(
372        osg::DegreesToRadians(_r),
373        osg::Vec3d(0.0f, 0.0f, 1.0f)
374    );
375
376    osg::Matrix s = osg::Matrix::scale(_s, _s, 1.0f);
377    osg::Matrix t = osg::Matrix::translate(x - _visibleArea[0], y - _visibleArea[1], z);
378
379    setMatrix(r * s * t);
380}
381
382void Window::_setWidthAndHeightUnknownSizeError(const std::string& size, point_type val) {
383    warn()
384        << "Window [" << _name << "] doesn't know its " << size
385        << " (" << val << ")." << std::endl
386    ;
387}
388
389void Window::_setWidthAndHeightNotPAError(const std::string& size, point_type val) {
390    warn()
391        << "Window [" << _name
392        << "] should be pixel-aligned, but a remainder was detected for it's "
393        << size << " (" << val << ")." << std::endl
394    ;
395}
396
397// Since there is so much error-checking associated with setting the width and height properly
398// of a Window, this function attempts to abstract some of that tedium.
399void Window::_setWidthAndHeight() {
400    _width  = _getWidthImplementation();
401    _height = _getHeightImplementation();
402
403    if(_width.current < 0.0f) _setWidthAndHeightUnknownSizeError("current width", _width.current);
404
405    if(_width.minimum < 0.0f) _setWidthAndHeightUnknownSizeError("minimum width", _width.minimum);
406
407    if(_height.current < 0.0f) _setWidthAndHeightUnknownSizeError("current height", _height.current);
408
409    if(_height.minimum < 0.0f) _setWidthAndHeightUnknownSizeError("minimum height", _height.minimum);
410
411    if(hasDecimal(_width.current)) _setWidthAndHeightNotPAError("current width", _width.current);
412   
413    if(hasDecimal(_width.minimum)) _setWidthAndHeightNotPAError("minimum width", _width.minimum);
414   
415    if(hasDecimal(_height.current)) _setWidthAndHeightNotPAError("current height", _height.current);
416   
417    if(hasDecimal(_height.minimum)) _setWidthAndHeightNotPAError("minimum height", _height.minimum);
418}
419
420void Window::_removeFromGeode(Widget* widget) {
421    if(!widget) return;
422
423    widget->_index = 0;
424
425    _setParented(widget, true);
426
427    _geode()->removeDrawable(widget);
428}
429
430// This is a somewhat complicated function designed to only be called by derived classes,
431// allowing them to insert Widgets (which can be added to the Window in any way the derived
432// class sees fit) into the REAL internal _objects container.
433// TODO: This doesn't handle insertion properly!!!
434bool Window::_setWidget(Widget* widget, int index) {
435    if(!widget) {
436        warn() << "Window [" << _name << "] called addWidget with NULL." << std::endl;
437       
438        return false;
439    }
440
441    if(widget->_parent) {
442        warn()
443            << "Window [" << _name
444            << "] attempted to parent Widget [" << widget->getName()
445            << "], which is already parented by [" << widget->_parent->getName()
446            << "]." << std::endl
447        ;
448
449        return false;
450    }
451
452    if(index >= 0 && index >= static_cast<int>(size())) {
453        warn()
454            << "Window [" << _name
455            << "] attempted to manually insert the Widget [" << widget->getName()
456            << "] at position " << index
457            << ", but there is not enough space available."
458            << std::endl
459        ;
460
461        return false;
462    }
463
464    // If we're just appending another widget...
465    if(index < 0) _objects.push_back(widget);
466
467    // Otherwise, we're inserting and need to call removeWidget on the old
468    // one (if valid)...
469    else {
470        if(_objects[index].valid()) _removeFromGeode(_objects[index].get());
471
472        _objects[index] = widget;
473    }
474
475    osg::Geode* geode = _geode();
476
477    widget->_index = geode->getNumDrawables();
478
479    geode->addDrawable(widget);
480   
481    _setParented(widget);
482    _setManaged(widget);
483    _setStyled(widget);
484
485    // We make sure and resize after every added Widget. This ensures the most
486    // accurate geometry...
487    resize();
488
489    return true;
490}
491
492bool Window::_setVisible(bool visible) {
493    if(!_wm) return false;
494
495    _wm->setValue(_index, visible);
496
497    return true;
498}
499
500void Window::_setFocused(Widget* widget) {
501    if(widget && _wm) {
502        Event ev(_wm);
503
504        ev._window = this;
505
506        if(_focused.valid()) {
507            ev._widget = _focused.get();
508
509            _focused->callMethodAndCallbacks(ev.makeType(EVENT_UNFOCUS));
510        }
511
512        _focused   = widget;
513        ev._widget = widget;
514
515        _focused->callMethodAndCallbacks(ev.makeType(EVENT_FOCUS));
516    }
517}
518
519void Window::_setStyled(Widget* widget) {
520    if(!widget || !_wm) return;
521
522    if(!widget->_isStyled) return;
523
524    widget->_isStyled = true;
525
526    _wm->getStyleManager()->applyStyles(widget);
527}
528
529void Window::_setParented(Widget* widget, bool setUnparented) {
530    if(!widget) return;
531   
532    if(!setUnparented) {
533        widget->_parent = this;
534
535        widget->parented(this);
536    }
537
538    else {
539        widget->unparented(this);
540
541        widget->_parent = 0;
542    }
543}
544
545void Window::_setManaged(Widget* widget, bool setUnmanaged) {
546    if(!widget || !_wm) return;
547   
548    // Tell the widget it's managed if it isn't already...
549    if(!setUnmanaged) {
550        if(widget->_isManaged) return;
551
552        widget->_isManaged = true;
553
554        widget->managed(_wm);
555    }
556
557    // Otherwise, make sure it IS managed and tell it that it no longer will be. :)
558    else {
559        if(!widget->_isManaged) return;
560
561        widget->_isManaged = false;
562
563        widget->unmanaged(_wm);
564    }
565}
566
567Widget* Window::_getBackground() const {
568    const osg::Geode* geode = _geode();
569
570    // lol...
571    if(geode) return dynamic_cast<Widget*>(const_cast<osg::Drawable*>(geode->getDrawable(0)));
572
573    return 0;
574}
575
576Window* Window::_getTopmostParent() const {
577    WindowList windowList;
578
579    getParentList(windowList);
580
581    return windowList.back().get();
582}
583
584// This will position a widget based on the amount of width and height it has
585// to fill. The x/y values should already be set, since we will be adding here.
586// However, the width and height can be anything and will be adjusted accordingly.
587void Window::_positionWidget(Widget* widget, point_type width, point_type height) {
588    point_type w  = widget->getWidth();
589    point_type h  = widget->getHeight();
590    point_type pl = widget->getPadLeft();
591    point_type pr = widget->getPadRight();
592    point_type pt = widget->getPadTop();
593    point_type pb = widget->getPadBottom();
594
595    if(widget->canFill()) {
596        point_type nw = osg::round(width - pr - pl);
597        point_type nh = osg::round(height - pt - pb);
598
599        widget->addOrigin(pl, pb);
600
601        if(w != nw) widget->setWidth(nw);
602        if(h != nh) widget->setHeight(nh);
603
604        return;
605    }
606
607    point_type ha = osg::round((width - w - pl - pr) / 2.0f);
608    point_type va = osg::round((height - h - pt - pb) / 2.0f);
609
610    // Handle HORIZONTAL alignment.
611    if(widget->getAlignHorizontal() == Widget::HA_LEFT) widget->addX(pl);
612
613    else if(widget->getAlignHorizontal() == Widget::HA_RIGHT) widget->addX(width - w - pr);
614
615    else widget->addX(ha + pl);
616
617    // Handle VERTICAL alignment.
618    if(widget->getAlignVertical() == Widget::VA_BOTTOM) widget->addY(height - h - pt);
619
620    else if(widget->getAlignVertical() == Widget::VA_TOP) widget->addY(pb);
621
622    else widget->addY(va + pb);
623}
624
625bool Window::isVisible() const {
626    if(!_wm) return false;
627
628    return _wm->getValue(_index);
629}
630
631bool Window::isXYWithinVisible(float x, float y) const {
632    return
633        (x >= _visibleArea[0] && x <= (_visibleArea[0] + _visibleArea[2])) &&
634        (y >= _visibleArea[1] && y <= (_visibleArea[1] + _visibleArea[3]))
635    ;
636}
637
638void Window::setVisibleArea(int x, int y, int w, int h) {
639    _visibleArea[0] = x;
640    _visibleArea[1] = y;
641    _visibleArea[2] = w;
642    _visibleArea[3] = h;
643}
644
645void Window::addVisibleArea(int x, int y, int w, int h) {
646    _visibleArea[0] += x;
647    _visibleArea[1] += y;
648    _visibleArea[2] += w;
649    _visibleArea[3] += h;
650}
651
652// The topmost Window always has this method called, instead of the embedded window directly.
653bool Window::setFocused(const Widget* widget) {
654    // TODO: I've turned on the warn() here, but perhaps I shouldn't? I need to define
655    // the conditions under which it's okay to call setFocus() with a NULL widget.
656    if(!widget) {
657        warn() << "Window [" << _name << "] can't focus a NULL Widget." << std::endl;
658
659        return false;
660    }
661
662    ConstIterator i = std::find(begin(), end(), widget);
663
664    bool found = false;
665
666    if(i == end()) {
667        // We couldn't find the widget in the toplevel, so lets see if one of our
668        // EmbeddedWindow objects has it.
669        WindowList wl;
670
671        getEmbeddedList(wl);
672
673        for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) {
674            ConstIterator ii = std::find(w->get()->begin(), w->get()->end(), widget);
675           
676            if(ii != w->get()->end()) {
677                found = true;
678                i     = ii;
679            }
680        }
681    }
682
683    else found = true;
684
685    if(!found) {
686        warn()
687            << "Window [" << _name
688            << "] couldn't find the Widget [" << widget->getName()
689            << "] in it's object list." << std::endl
690        ;
691
692        return false;
693    }
694
695    _setFocused(i->get());
696
697    return true;
698}
699
700bool Window::setFocused(const std::string& name) {
701    Widget* w1 = getByName(name);
702
703    bool found = false;
704
705    if(!w1) {
706        // Just like above, we couldn't find the widget in the toplevel, so lets see if
707        // one of our EmbeddedWindow objects has it. The difference here is that we
708        // search by name.
709        WindowList wl;
710
711        getEmbeddedList(wl);
712
713        for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) {
714            Widget* w2 = w->get()->getByName(name);
715
716            if(w2) {
717                found = true;
718                w1    = w2;
719            }
720        }
721    }
722
723    else found = true;
724
725    if(!found) {
726        warn()
727            << "Window [" << _name
728            << "] couldn't find a Widget named [" << name
729            << "] to set as it's focus." << std::endl
730        ;
731
732        return false;
733    }
734
735    _setFocused(w1);
736   
737    return true;
738}
739
740bool Window::grabFocus() {
741    if(!_wm) return false;
742
743    return _wm->setFocused(this);
744}
745
746bool Window::setFirstFocusable() {
747    WidgetList focusList;
748
749    if(getFocusList(focusList)) {
750        _setFocused(focusList.front().get());
751
752        return true;
753    }
754
755    return false;
756}
757
758bool Window::setNextFocusable() {
759    WidgetList focusList;
760
761    if(!getFocusList(focusList)) return false;
762
763    WidgetList::iterator w = focusList.begin();
764
765    // TODO: This needs to be a more complicated object, since the focus may be
766    // in a child Window instead of a Widget.
767    unsigned int focusedIndex = 0;
768
769    for(unsigned int i = 0; w != focusList.end(); w++, i++) if(*w == _focused) {
770        focusedIndex = i;
771
772        break;
773    }
774
775    if(focusedIndex < focusList.size() - 1) _setFocused((++w)->get());
776
777    else _setFocused(focusList.front().get());
778
779    return true;
780}
781
782XYCoord Window::localXY(double absx, double absy) const {
783    XYCoord xy = getAbsoluteOrigin();
784    double  x  = absx - xy.x();
785    double  y  = absy - xy.y();
786
787    return XYCoord(x + _visibleArea[0], y + _visibleArea[1]);
788}
789
790XYCoord Window::getAbsoluteOrigin() const {
791    XYCoord xy(0, 0);
792
793    WindowList windowList;
794
795    getParentList(windowList);
796
797    for(WindowList::iterator i = windowList.begin(); i != windowList.end(); i++) {
798        if(!i->valid()) continue;
799
800        xy.x() += static_cast<int>(i->get()->getX());
801        xy.y() += static_cast<int>(i->get()->getY());
802    }
803
804    return xy;
805}
806
807Window::EmbeddedWindow* Window::embed(
808    const std::string& newName,
809    Widget::Layer      layer,
810    unsigned int       layerOffset
811) {
812    EmbeddedWindow* ew = new EmbeddedWindow(
813        newName.size() > 0 ? newName : _name + "Embedded",
814        getWidth(),
815        getHeight()
816    );
817
818    ew->setWindow(this);
819    ew->setSize(getWidth(), getHeight());
820    ew->setCanFill(true);
821    ew->setLayer(layer, layerOffset);
822
823    return ew;
824}
825
826bool Window::getFocusList(WidgetList& wl) const {
827    for(ConstIterator i = begin(); i != end(); i++) if(i->valid()) {
828        EmbeddedWindow* ew = dynamic_cast<EmbeddedWindow*>(i->get());
829
830        if(!ew) {
831            if(i->get()->canFocus()) wl.push_back(i->get());
832        }
833
834        else {
835            if(ew->getWindow()) ew->getWindow()->getFocusList(wl);
836        }
837    }
838
839    return wl.size() != 0;
840}
841
842bool Window::getEmbeddedList(WindowList& wl) const {
843    for(ConstIterator i = begin(); i != end(); i++) if(i->valid()) {
844        EmbeddedWindow* ew = dynamic_cast<EmbeddedWindow*>(i->get());
845
846        if(!ew || !ew->getWindow()) continue;
847
848        else {
849            wl.push_back(ew->getWindow());
850
851            ew->getWindow()->getEmbeddedList(wl);
852        }
853    }
854
855    return wl.size() != 0;
856}
857
858void Window::getParentList(WindowList& wl) const {
859    const Window* current = this;
860
861    while(current) {
862        wl.push_back(const_cast<Window*>(current));
863
864        if(current->_parent) current = current->_parent;
865
866        else current = 0;
867    }
868}
869
870void Window::managed(WindowManager* wm) {
871    _wm = wm;
872
873    for(Iterator i = begin(); i != end(); i++) {
874        _setManaged(i->get());
875        _setStyled(i->get());
876    }
877
878    setFirstFocusable();
879    resize();
880    update();
881}
882
883void Window::unmanaged(WindowManager* wm) {
884    for(Iterator i = begin(); i != end(); i++) _setManaged(i->get(), true);
885
886    _wm = 0;
887}
888
889bool Window::addWidget(Widget* widget) {
890    return _setWidget(widget);
891}
892
893bool Window::insertWidget(Widget* widget, unsigned int pos) {
894    return _setWidget(widget, pos);
895}
896
897bool Window::removeWidget(Widget* widget) {
898    if(!widget) return false;
899
900    if(_remove(widget)) {
901        _removeFromGeode(widget);
902
903        resize();
904
905        return true;
906    }
907
908    return false;
909}
910
911bool Window::replaceWidget(Widget* oldWidget, Widget* newWidget) {
912    return false;
913}
914
915unsigned int Window::addDrawableAndGetIndex(osg::Drawable* drawable) {
916    osg::Geode* geode = _geode();
917
918    if(geode->addDrawable(drawable)) return geode->getDrawableIndex(drawable);
919
920    // 0 is a valid error return code here, since our background widget should be
921    // the first child.
922    return 0;
923}
924
925unsigned int Window::addChildAndGetIndex(osg::Node* node) {
926    if(addChild(node)) return getChildIndex(node);
927
928    return 0;
929}
930
931// All of the subsequent functions are very boring and uninteresting, although hopefully
932// self-explanatory. They simply wrap calls to _compare<>() with the proper templates, and
933// forward the optional iteration ranges...
934
935point_type Window::_getMinWidgetWidth(int begin, int end, int add) const {
936    return _compare<Less>(&Widget::getWidth, begin, end, add);
937}
938
939point_type Window::_getMinWidgetHeight(int begin, int end, int add) const {
940    return _compare<Less>(&Widget::getHeight, begin, end, add);
941}
942
943point_type Window::_getMaxWidgetWidth(int begin, int end, int add) const {
944    return _compare<Greater>(&Widget::getWidth, begin, end, add);
945}
946
947point_type Window::_getMaxWidgetHeight(int begin, int end, int add) const {
948    return _compare<Greater>(&Widget::getHeight, begin, end, add);
949}
950
951point_type Window::_getMinWidgetMinWidth(int begin, int end, int add) const {
952    return _compare<Less>(&Widget::getMinWidth, begin, end, add);
953}
954
955point_type Window::_getMinWidgetMinHeight(int begin, int end, int add) const {
956    return _compare<Less>(&Widget::getMinHeight, begin, end, add);
957}
958
959point_type Window::_getMaxWidgetMinWidth(int begin, int end, int add) const {
960    return _compare<Greater>(&Widget::getMinWidth, begin, end, add);
961}
962
963point_type Window::_getMaxWidgetMinHeight(int begin, int end, int add) const {
964    return _compare<Greater>(&Widget::getMinHeight, begin, end, add);
965}
966
967point_type Window::_getMinWidgetWidthTotal(int begin, int end, int add) const {
968    return _compare<Less>(&Widget::getWidthTotal, begin, end, add);
969}
970
971point_type Window::_getMinWidgetHeightTotal(int begin, int end, int add) const {
972    return _compare<Less>(&Widget::getHeightTotal, begin, end, add);
973}
974
975point_type Window::_getMaxWidgetWidthTotal(int begin, int end, int add) const {
976    return _compare<Greater>(&Widget::getWidthTotal, begin, end, add);
977}
978
979point_type Window::_getMaxWidgetHeightTotal(int begin, int end, int add) const {
980    return _compare<Greater>(&Widget::getHeightTotal, begin, end, add);
981}
982
983point_type Window::_getMinWidgetMinWidthTotal(int begin, int end, int add) const {
984    return _compare<Less>(&Widget::getMinWidthTotal, begin, end, add);
985}
986
987point_type Window::_getMinWidgetMinHeightTotal(int begin, int end, int add) const {
988    return _compare<Less>(&Widget::getMinHeightTotal, begin, end, add);
989}
990
991point_type Window::_getMaxWidgetMinWidthTotal(int begin, int end, int add) const {
992    return _compare<Greater>(&Widget::getMinWidthTotal, begin, end, add);
993}
994
995point_type Window::_getMaxWidgetMinHeightTotal(int begin, int end, int add) const {
996    return _compare<Greater>(&Widget::getMinHeightTotal, begin, end, add);
997}
998
999point_type Window::_getMinWidgetPadHorizontal(int begin, int end, int add) const {
1000    return _compare<Less>(&Widget::getPadHorizontal, begin, end, add);
1001}
1002
1003point_type Window::_getMinWidgetPadVertical(int begin, int end, int add) const {
1004    return _compare<Less>(&Widget::getPadVertical, begin, end, add);
1005}
1006
1007point_type Window::_getMaxWidgetPadHorizontal(int begin, int end, int add) const {
1008    return _compare<Greater>(&Widget::getPadHorizontal, begin, end, add);
1009}
1010
1011point_type Window::_getMaxWidgetPadVertical(int begin, int end, int add) const {
1012    return _compare<Greater>(&Widget::getPadVertical, begin, end, add);
1013}
1014
1015point_type Window::_getNumFill(int begin, int end, int add) const {
1016    return _accumulate<Plus>(&Widget::getFillAsNumeric, begin, end, add);
1017}
1018
1019Window::Sizes Window::_getWidthImplementation() const {
1020    osg::BoundingBox bb = getGeode()->getBoundingBox();
1021   
1022    point_type w = osg::round(bb.xMax() - bb.xMin());
1023
1024    return Sizes(w, 0.0f);
1025}
1026
1027Window::Sizes Window::_getHeightImplementation() const {
1028    osg::BoundingBox bb = getGeode()->getBoundingBox();
1029
1030    point_type h = osg::round(bb.yMax() - bb.yMin());
1031
1032    return Sizes(h, 0.0f);
1033}
1034
1035}
Note: See TracBrowser for help on using the browser.