Thanks J-S, fix now merged and submitted to svn/trunk.

On Mon, Sep 21, 2009 at 3:17 PM, Jean-Sébastien Guay
<[email protected]> wrote:
> Hi Robert,
>
> 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.
>
> Thanks,
>
> J-S
> --
> ______________________________________________________
> Jean-Sebastien Guay    [email protected]
>                               http://www.cm-labs.com/
>                        http://whitestar02.webhop.org/
>
> // -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
> // $Id: Window.cpp 66 2008-07-14 21:54:09Z cubicool $
>
> #include <algorithm>
> #include <osgGA/GUIEventAdapter>
> #include <osgWidget/WindowManager>
>
> namespace osgWidget {
>
> bool callbackWindowMove(Event& ev) {
>    if(!ev.getWindow() || !ev.getWindowManager()->isLeftMouseButtonDown())
> return false;
>
>    ev.getWindow()->addOrigin(ev.x, ev.y);
>    ev.getWindow()->update();
>
>    return true;
> }
>
> bool callbackWindowRotate(Event& ev) {
>    if(!ev.getWindow() || !ev.getWindowManager()->isRightMouseButtonDown())
> return false;
>
>    ev.getWindow()->addRotate(ev.y);
>    ev.getWindow()->update();
>
>    return true;
> }
>
> bool callbackWindowScale(Event& ev) {
>    if(!ev.getWindow() || !ev.getWindowManager()->isMiddleMouseButtonDown())
> return false;
>
>    ev.getWindow()->addScale(ev.y);
>    ev.getWindow()->update();
>
>    return true;
> }
>
> bool callbackWindowTabFocus(Event& ev) {
>    if(!ev.getWindow() || ev.key != osgGA::GUIEventAdapter::KEY_Tab) return
> false;
>
>    return ev.getWindow()->setNextFocusable();
> }
>
> Window::EmbeddedWindow::EmbeddedWindow(const std::string& name, point_type
> w, point_type h):
> Widget(name, w, h) {
> }
>
> Window::EmbeddedWindow::EmbeddedWindow(const EmbeddedWindow& wiw, const
> osg::CopyOp& co):
> Widget(wiw, co) {
>    // TODO: Get this!
>    // _window = 0;
> }
>
> void Window::EmbeddedWindow::parented(Window* parent) {
>    if(!_window.valid()) return;
>
>    if(!_window->_parent) {
>        _window->_parent = parent;
>
>        // Add this Window to the Window, on the same level as a Window's
>        // internal Geode. This will require special handling of events!
>        parent->addChild(_window.get());
>    }
>
>    else warn()
>        << "EmbeddedWindow Widget [" << _name
>        << "] cannot embed itself in Window [" << _window->getName()
>        << "], since it is already a child of [" <<
> _window->_parent->getName()
>        << "]" << std::endl
>    ;
> }
>
> void Window::EmbeddedWindow::unparented(Window*) {
>    if(_window.valid()) {
>        _window->_parent = 0;
>
>        if(_parent) _parent->removeChild(_window.get());
>    }
> }
>
> void Window::EmbeddedWindow::managed(WindowManager* wm) {
>    if(!_window.valid()) return;
>
>    _window->setNodeMask(wm->getNodeMask());
>    _window->managed(wm);
> }
>
> void Window::EmbeddedWindow::unmanaged(WindowManager* wm) {
>    _window->unmanaged(wm);
> }
>
> void Window::EmbeddedWindow::positioned() {
>    if(!_window.valid()) return;
>
>    point_type x = getX();
>    point_type y = getY();
>    point_type w = getWidth();
>    point_type h = getHeight();
>
>    // If the widget is fillable, ask the internal Window to resize itself.
>    // Whether or not the Window honors this reqest will be up to it.
>    _window->setOrigin(x, y);
>    _window->setZ(_calculateZ(getLayer() + 1));
>    _window->setZRange(_calculateZ(LAYER_TOP - (getLayer() + 1)));
>    _window->setVisibleArea(0, 0, static_cast<int>(w), static_cast<int>(h));
>    _window->resize(w, h);
> }
>
> bool Window::EmbeddedWindow::setWindow(Window* win) {
>    if(!win) {
>        warn()
>            << "EmbeddedWindow [" << _name
>            << "] attempted to set a NULL Window." << std::endl
>        ;
>
>        return false;
>    }
>
>    if (_window.valid() && _parent)
>        unparented(_parent);
>
>    _window = win;
>
>    _window->resize();
>    _window->setVisibilityMode(VM_PARTIAL);
>
>    if(_parent) parented(_parent);
>
>    WindowManager* wm = _getWindowManager();
>
>    if(wm) managed(wm);
>
>    return true;
> }
>
> void Window::EmbeddedWindow::updateSizeFromWindow() {
>    setSize(_window->getSize());
>
>    if(_parent) _parent->resize();
> }
>
> Window::Window(const std::string& name):
> _parent     (0),
> _wm         (0),
> _index      (0),
> _x          (0.0f),
> _y          (0.0f),
> _z          (0.0f),
> _zRange     (0.0f),
> _strata     (STRATA_NONE),
> _vis        (VM_FULL),
> _r          (0.0f),
> _s          (1.0f),
> _scaleDenom (100.0f),
> _vAnchor    (VA_NONE),
> _hAnchor    (HA_NONE) {
>    _name = name.size() ? name : generateRandomName("Window");
>
>    // TODO: Fix the "bg" name.
>    osg::Geode* geode = new osg::Geode();
>    Widget*     bg    = new Widget(name + "bg", 0.0f, 0.0f);
>
>    bg->setLayer(Widget::LAYER_BG);
>    bg->setColor(1.0f, 1.0f, 1.0f, 1.0f);
>
>    _setParented(bg);
>
>    geode->addDrawable(bg);
>
>    addChild(geode);
>    setDataVariance(osg::Object::DYNAMIC);
>    setEventMask(EVENT_ALL);
>
>    getOrCreateStateSet()->setAttributeAndModes(
>        new osg::Scissor(0, 0, 0, 0),
>        osg::StateAttribute::ON
>    );
> }
>
> Window::Window(const Window& window, const osg::CopyOp& co):
> MatrixTransform (window, co),
> EventInterface  (window),
> StyleInterface  (window),
> _parent         (0),
> _wm             (0),
> _x              (window._x),
> _y              (window._y),
> _z              (window._z),
> _zRange         (window._zRange),
> _strata         (window._strata),
> _vis            (window._vis),
> _r              (window._r),
> _s              (window._s),
> _scaleDenom     (window._scaleDenom),
> _width          (window._width),
> _height         (window._height),
> _vAnchor        (window._vAnchor),
> _hAnchor        (window._hAnchor),
> _visibleArea    (window._visibleArea) {
>    // Construct our vector of Widgets for easier use. :)
>    // TODO: I almost certainly will need to use the getPosition() thing here
> eventually
>    // for things to work 100% properly. For example, some Geodes may contain
> labels,
>    // etc. Also, any widget that doesn't support simple addWidget probably
> won't
>    // work (Table?)
>    osg::Geode* geode = _geode();
>
>    Widget* bg = dynamic_cast<Widget*>(geode->getDrawable(0));
>
>    if(bg) {
>        _setParented(bg);
>
>        // TODO: This is silly...
>        bg->setName(_name + "bg");
>    }
>
>    for(unsigned int i = 1; i < geode->getNumDrawables(); i++) {
>        Widget* widget = dynamic_cast<Widget*>(geode->getDrawable(i));
>
>        if(!widget) continue;
>
>        // TODO: Properly test this...
>        if(!widget->canClone()) {
>            // geode->removeDrawable(widget);
>
>            continue;
>        }
>
>        _setParented(widget);
>
>        _objects.push_back(widget);
>    }
>
>    geode->setName(_name);
> }
>
> // This is the method by which all Windows are redrawn/resized. Keep in mind
> that not all
> // Windows are required to absolutely honor a resize request, which is why
> we call the
> // _getWidthImplementation() and _getHeightImplementation() functions
> instead of using the
> // values passed in.
> bool Window::resize(point_type width, point_type height) {
>    // First, we query and store what sizes the Window currently is.
>    _setWidthAndHeight();
>
>    // Second, we determine if there is a difference between what the size
> currently
>    // is and what the user has requested.
>    point_type diffWidth  = width > 0.0f ? width - _width.current : 0.0f;
>    point_type diffHeight = height > 0.0f ? height - _height.current : 0.0f;
>
>    return resizeAdd(diffWidth, diffHeight);
> }
>
> bool Window::resizeAdd(point_type diffWidth, point_type diffHeight) {
>    if(
>        _width.current + diffWidth < _width.minimum ||
>        _height.current + diffHeight < _height.minimum
>    ) {
>        warn()
>            << "Window [" << _name << "] can't call resizeAdd() with the "
>            << "values " << diffWidth << " and " << diffHeight << std::endl
>        ;
>
>        return false;
>    }
>
>    // Now we initiate the resize, which may or may not succeed.
>    _resizeImplementation(diffWidth, diffHeight);
>
>    // Inform each widget that it has been positioned.
>    for(Iterator i = begin(); i != end(); i++) if(i->valid()) {
>        i->get()->dirtyBound();
>        i->get()->setDimensions();
>        i->get()->positioned();
>    }
>
>    _setWidthAndHeight();
>
>    Widget* bg = _bg();
>
>    bg->setSize(_width.current, _height.current);
>    bg->dirtyBound();
>    bg->positioned();
>
>    update();
>
>    return true;
> }
>
> bool Window::resizePercent(point_type width, point_type height) {
>    if(!_parent && !_wm) {
>        warn()
>            << "Window [" << _name
>            << "] cannot resizePercent without being managed or parented."
>            << std::endl
>        ;
>
>        return false;
>    }
>
>    if(!_parent) return resize(
>        _wm->getWidth() * (width / 100.0f),
>        _wm->getHeight() * (height / 100.0f)
>    );
>
>    else return resize(
>        _parent->getWidth() * (width / 100.0f),
>        _parent->getHeight() * (height / 100.0f)
>    );
> }
>
> void Window::update() {
>    WindowList wl;
>
>    getEmbeddedList(wl);
>
>    for(WindowList::iterator w = wl.begin(); w != wl.end(); w++)
> w->get()->update();
>
>    matrix_type x  = _x;
>    matrix_type y  = _y;
>    XYCoord     xy = getAbsoluteOrigin();
>
>    // We only honor ANCHOR requests on topmost Windows, not embedded ones.
>    if((_vAnchor != VA_NONE || _hAnchor != HA_NONE) && !_parent && _wm) {
>        if(_vAnchor == VA_TOP) y = _wm->getHeight() - _height.current;
>        else if(_vAnchor == VA_CENTER) y = osg::round(_wm->getHeight() /
> 2.0f);
>        else if(_vAnchor == VA_BOTTOM) y = 0.0f;
>
>        if(_hAnchor == HA_LEFT) x = 0.0f;
>        else if(_hAnchor == HA_CENTER) x = osg::round(_wm->getWidth() /
> 2.0f);
>        else if(_hAnchor == HA_RIGHT) x = _wm->getWidth() - _width.current +
> _visibleArea[2];
>
>        xy.set(x, y);
>    }
>
>    matrix_type z = _z;
>
>    // We can't do proper scissoring until we have access to our parent
> WindowManager, and
>    // we need to determine the sorting method we want to use.
>    if(_wm) {
>        if(_wm->isUsingRenderBins()) {
>            getOrCreateStateSet()->setRenderBinDetails(
>                static_cast<int>((1.0f - fabs(_z)) *
> OSGWIDGET_RENDERBIN_MOD),
>                "RenderBin"
>            );
>
>            z = 0.0f;
>        }
>
>        int sx = static_cast<int>(xy.x());
>        int sy = static_cast<int>(xy.y());
>        int sw = static_cast<int>(_width.current);
>        int sh = static_cast<int>(_height.current);
>
>        // This sets the Scissor area to some offset defined by the user.
>        if(_vis == VM_PARTIAL) {
>            sw = static_cast<int>(_visibleArea[2]);
>            sh = static_cast<int>(_visibleArea[3]);
>        }
>
>        // Otherwise, use the size of the WindowManager itself.
>        else if(_vis == VM_ENTIRE) {
>            sx = 0;
>            sy = 0;
>            sw = static_cast<int>(_wm->getWidth());
>            sh = static_cast<int>(_wm->getHeight());
>        }
>
>        _scissor()->setScissor(sx, sy, sw, sh);
>    }
>
>    // Update the Window itself, setting it's matrix according to translate,
> rotate, and
>    // scale values.
>    osg::Matrix r = osg::Matrix::rotate(
>        osg::DegreesToRadians(_r),
>        osg::Vec3d(0.0f, 0.0f, 1.0f)
>    );
>
>    osg::Matrix s = osg::Matrix::scale(_s, _s, 1.0f);
>    osg::Matrix t = osg::Matrix::translate(x - _visibleArea[0], y -
> _visibleArea[1], z);
>
>    setMatrix(r * s * t);
> }
>
> void Window::_setWidthAndHeightUnknownSizeError(const std::string& size,
> point_type val) {
>    warn()
>        << "Window [" << _name << "] doesn't know its " << size
>        << " (" << val << ")." << std::endl
>    ;
> }
>
> void Window::_setWidthAndHeightNotPAError(const std::string& size,
> point_type val) {
>    warn()
>        << "Window [" << _name
>        << "] should be pixel-aligned, but a remainder was detected for it's
> "
>        << size << " (" << val << ")." << std::endl
>    ;
> }
>
> // Since there is so much error-checking associated with setting the width
> and height properly
> // of a Window, this function attempts to abstract some of that tedium.
> void Window::_setWidthAndHeight() {
>    _width  = _getWidthImplementation();
>    _height = _getHeightImplementation();
>
>    if(_width.current < 0.0f) _setWidthAndHeightUnknownSizeError("current
> width", _width.current);
>
>    if(_width.minimum < 0.0f) _setWidthAndHeightUnknownSizeError("minimum
> width", _width.minimum);
>
>    if(_height.current < 0.0f) _setWidthAndHeightUnknownSizeError("current
> height", _height.current);
>
>    if(_height.minimum < 0.0f) _setWidthAndHeightUnknownSizeError("minimum
> height", _height.minimum);
>
>    if(hasDecimal(_width.current)) _setWidthAndHeightNotPAError("current
> width", _width.current);
>
>    if(hasDecimal(_width.minimum)) _setWidthAndHeightNotPAError("minimum
> width", _width.minimum);
>
>    if(hasDecimal(_height.current)) _setWidthAndHeightNotPAError("current
> height", _height.current);
>
>    if(hasDecimal(_height.minimum)) _setWidthAndHeightNotPAError("minimum
> height", _height.minimum);
> }
>
> void Window::_removeFromGeode(Widget* widget) {
>    if(!widget) return;
>
>    widget->_index = 0;
>
>    _setParented(widget, true);
>
>    _geode()->removeDrawable(widget);
> }
>
> // This is a somewhat complicated function designed to only be called by
> derived classes,
> // allowing them to insert Widgets (which can be added to the Window in any
> way the derived
> // class sees fit) into the REAL internal _objects container.
> // TODO: This doesn't handle insertion properly!!!
> bool Window::_setWidget(Widget* widget, int index) {
>    if(!widget) {
>        warn() << "Window [" << _name << "] called addWidget with NULL." <<
> std::endl;
>
>        return false;
>    }
>
>    if(widget->_parent) {
>        warn()
>            << "Window [" << _name
>            << "] attempted to parent Widget [" << widget->getName()
>            << "], which is already parented by [" <<
> widget->_parent->getName()
>            << "]." << std::endl
>        ;
>
>        return false;
>    }
>
>    if(index >= 0 && index >= static_cast<int>(size())) {
>        warn()
>            << "Window [" << _name
>            << "] attempted to manually insert the Widget [" <<
> widget->getName()
>            << "] at position " << index
>            << ", but there is not enough space available."
>            << std::endl
>        ;
>
>        return false;
>    }
>
>    // If we're just appending another widget...
>    if(index < 0) _objects.push_back(widget);
>
>    // Otherwise, we're inserting and need to call removeWidget on the old
>    // one (if valid)...
>    else {
>        if(_objects[index].valid()) _removeFromGeode(_objects[index].get());
>
>        _objects[index] = widget;
>    }
>
>    osg::Geode* geode = _geode();
>
>    widget->_index = geode->getNumDrawables();
>
>    geode->addDrawable(widget);
>
>    _setParented(widget);
>    _setManaged(widget);
>    _setStyled(widget);
>
>    // We make sure and resize after every added Widget. This ensures the
> most
>    // accurate geometry...
>    resize();
>
>    return true;
> }
>
> bool Window::_setVisible(bool visible) {
>    if(!_wm) return false;
>
>    _wm->setValue(_index, visible);
>
>    return true;
> }
>
> void Window::_setFocused(Widget* widget) {
>    if(widget && _wm) {
>        Event ev(_wm);
>
>        ev._window = this;
>
>        if(_focused.valid()) {
>            ev._widget = _focused.get();
>
>            _focused->callMethodAndCallbacks(ev.makeType(EVENT_UNFOCUS));
>        }
>
>        _focused   = widget;
>        ev._widget = widget;
>
>        _focused->callMethodAndCallbacks(ev.makeType(EVENT_FOCUS));
>    }
> }
>
> void Window::_setStyled(Widget* widget) {
>    if(!widget || !_wm) return;
>
>    if(!widget->_isStyled) return;
>
>    widget->_isStyled = true;
>
>    _wm->getStyleManager()->applyStyles(widget);
> }
>
> void Window::_setParented(Widget* widget, bool setUnparented) {
>    if(!widget) return;
>
>    if(!setUnparented) {
>        widget->_parent = this;
>
>        widget->parented(this);
>    }
>
>    else {
>        widget->unparented(this);
>
>        widget->_parent = 0;
>    }
> }
>
> void Window::_setManaged(Widget* widget, bool setUnmanaged) {
>    if(!widget || !_wm) return;
>
>    // Tell the widget it's managed if it isn't already...
>    if(!setUnmanaged) {
>        if(widget->_isManaged) return;
>
>        widget->_isManaged = true;
>
>        widget->managed(_wm);
>    }
>
>    // Otherwise, make sure it IS managed and tell it that it no longer will
> be. :)
>    else {
>        if(!widget->_isManaged) return;
>
>        widget->_isManaged = false;
>
>        widget->unmanaged(_wm);
>    }
> }
>
> Widget* Window::_getBackground() const {
>    const osg::Geode* geode = _geode();
>
>    // lol...
>    if(geode) return
> dynamic_cast<Widget*>(const_cast<osg::Drawable*>(geode->getDrawable(0)));
>
>    return 0;
> }
>
> Window* Window::_getTopmostParent() const {
>    WindowList windowList;
>
>    getParentList(windowList);
>
>    return windowList.back().get();
> }
>
> // This will position a widget based on the amount of width and height it
> has
> // to fill. The x/y values should already be set, since we will be adding
> here.
> // However, the width and height can be anything and will be adjusted
> accordingly.
> void Window::_positionWidget(Widget* widget, point_type width, point_type
> height) {
>    point_type w  = widget->getWidth();
>    point_type h  = widget->getHeight();
>    point_type pl = widget->getPadLeft();
>    point_type pr = widget->getPadRight();
>    point_type pt = widget->getPadTop();
>    point_type pb = widget->getPadBottom();
>
>    if(widget->canFill()) {
>        point_type nw = osg::round(width - pr - pl);
>        point_type nh = osg::round(height - pt - pb);
>
>        widget->addOrigin(pl, pb);
>
>        if(w != nw) widget->setWidth(nw);
>        if(h != nh) widget->setHeight(nh);
>
>        return;
>    }
>
>    point_type ha = osg::round((width - w - pl - pr) / 2.0f);
>    point_type va = osg::round((height - h - pt - pb) / 2.0f);
>
>    // Handle HORIZONTAL alignment.
>    if(widget->getAlignHorizontal() == Widget::HA_LEFT) widget->addX(pl);
>
>    else if(widget->getAlignHorizontal() == Widget::HA_RIGHT)
> widget->addX(width - w - pr);
>
>    else widget->addX(ha + pl);
>
>    // Handle VERTICAL alignment.
>    if(widget->getAlignVertical() == Widget::VA_BOTTOM) widget->addY(height -
> h - pt);
>
>    else if(widget->getAlignVertical() == Widget::VA_TOP) widget->addY(pb);
>
>    else widget->addY(va + pb);
> }
>
> bool Window::isVisible() const {
>    if(!_wm) return false;
>
>    return _wm->getValue(_index);
> }
>
> bool Window::isXYWithinVisible(float x, float y) const {
>    return
>        (x >= _visibleArea[0] && x <= (_visibleArea[0] + _visibleArea[2])) &&
>        (y >= _visibleArea[1] && y <= (_visibleArea[1] + _visibleArea[3]))
>    ;
> }
>
> void Window::setVisibleArea(int x, int y, int w, int h) {
>    _visibleArea[0] = x;
>    _visibleArea[1] = y;
>    _visibleArea[2] = w;
>    _visibleArea[3] = h;
> }
>
> void Window::addVisibleArea(int x, int y, int w, int h) {
>    _visibleArea[0] += x;
>    _visibleArea[1] += y;
>    _visibleArea[2] += w;
>    _visibleArea[3] += h;
> }
>
> // The topmost Window always has this method called, instead of the embedded
> window directly.
> bool Window::setFocused(const Widget* widget) {
>    // TODO: I've turned on the warn() here, but perhaps I shouldn't? I need
> to define
>    // the conditions under which it's okay to call setFocus() with a NULL
> widget.
>    if(!widget) {
>        warn() << "Window [" << _name << "] can't focus a NULL Widget." <<
> std::endl;
>
>        return false;
>    }
>
>    ConstIterator i = std::find(begin(), end(), widget);
>
>    bool found = false;
>
>    if(i == end()) {
>        // We couldn't find the widget in the toplevel, so lets see if one of
> our
>        // EmbeddedWindow objects has it.
>        WindowList wl;
>
>        getEmbeddedList(wl);
>
>        for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) {
>            ConstIterator ii = std::find(w->get()->begin(), w->get()->end(),
> widget);
>
>            if(ii != w->get()->end()) {
>                found = true;
>                i     = ii;
>            }
>        }
>    }
>
>    else found = true;
>
>    if(!found) {
>        warn()
>            << "Window [" << _name
>            << "] couldn't find the Widget [" << widget->getName()
>            << "] in it's object list." << std::endl
>        ;
>
>        return false;
>    }
>
>    _setFocused(i->get());
>
>    return true;
> }
>
> bool Window::setFocused(const std::string& name) {
>    Widget* w1 = getByName(name);
>
>    bool found = false;
>
>    if(!w1) {
>        // Just like above, we couldn't find the widget in the toplevel, so
> lets see if
>        // one of our EmbeddedWindow objects has it. The difference here is
> that we
>        // search by name.
>        WindowList wl;
>
>        getEmbeddedList(wl);
>
>        for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) {
>            Widget* w2 = w->get()->getByName(name);
>
>            if(w2) {
>                found = true;
>                w1    = w2;
>            }
>        }
>    }
>
>    else found = true;
>
>    if(!found) {
>        warn()
>            << "Window [" << _name
>            << "] couldn't find a Widget named [" << name
>            << "] to set as it's focus." << std::endl
>        ;
>
>        return false;
>    }
>
>    _setFocused(w1);
>
>    return true;
> }
>
> bool Window::grabFocus() {
>    if(!_wm) return false;
>
>    return _wm->setFocused(this);
> }
>
> bool Window::setFirstFocusable() {
>    WidgetList focusList;
>
>    if(getFocusList(focusList)) {
>        _setFocused(focusList.front().get());
>
>        return true;
>    }
>
>    return false;
> }
>
> bool Window::setNextFocusable() {
>    WidgetList focusList;
>
>    if(!getFocusList(focusList)) return false;
>
>    WidgetList::iterator w = focusList.begin();
>
>    // TODO: This needs to be a more complicated object, since the focus may
> be
>    // in a child Window instead of a Widget.
>    unsigned int focusedIndex = 0;
>
>    for(unsigned int i = 0; w != focusList.end(); w++, i++) if(*w ==
> _focused) {
>        focusedIndex = i;
>
>        break;
>    }
>
>    if(focusedIndex < focusList.size() - 1) _setFocused((++w)->get());
>
>    else _setFocused(focusList.front().get());
>
>    return true;
> }
>
> XYCoord Window::localXY(double absx, double absy) const {
>    XYCoord xy = getAbsoluteOrigin();
>    double  x  = absx - xy.x();
>    double  y  = absy - xy.y();
>
>    return XYCoord(x + _visibleArea[0], y + _visibleArea[1]);
> }
>
> XYCoord Window::getAbsoluteOrigin() const {
>    XYCoord xy(0, 0);
>
>    WindowList windowList;
>
>    getParentList(windowList);
>
>    for(WindowList::iterator i = windowList.begin(); i != windowList.end();
> i++) {
>        if(!i->valid()) continue;
>
>        xy.x() += static_cast<int>(i->get()->getX());
>        xy.y() += static_cast<int>(i->get()->getY());
>    }
>
>    return xy;
> }
>
> Window::EmbeddedWindow* Window::embed(
>    const std::string& newName,
>    Widget::Layer      layer,
>    unsigned int       layerOffset
> ) {
>    EmbeddedWindow* ew = new EmbeddedWindow(
>        newName.size() > 0 ? newName : _name + "Embedded",
>        getWidth(),
>        getHeight()
>    );
>
>    ew->setWindow(this);
>    ew->setSize(getWidth(), getHeight());
>    ew->setCanFill(true);
>    ew->setLayer(layer, layerOffset);
>
>    return ew;
> }
>
> bool Window::getFocusList(WidgetList& wl) const {
>    for(ConstIterator i = begin(); i != end(); i++) if(i->valid()) {
>        EmbeddedWindow* ew = dynamic_cast<EmbeddedWindow*>(i->get());
>
>        if(!ew) {
>            if(i->get()->canFocus()) wl.push_back(i->get());
>        }
>
>        else {
>            if(ew->getWindow()) ew->getWindow()->getFocusList(wl);
>        }
>    }
>
>    return wl.size() != 0;
> }
>
> bool Window::getEmbeddedList(WindowList& wl) const {
>    for(ConstIterator i = begin(); i != end(); i++) if(i->valid()) {
>        EmbeddedWindow* ew = dynamic_cast<EmbeddedWindow*>(i->get());
>
>        if(!ew || !ew->getWindow()) continue;
>
>        else {
>            wl.push_back(ew->getWindow());
>
>            ew->getWindow()->getEmbeddedList(wl);
>        }
>    }
>
>    return wl.size() != 0;
> }
>
> void Window::getParentList(WindowList& wl) const {
>    const Window* current = this;
>
>    while(current) {
>        wl.push_back(const_cast<Window*>(current));
>
>        if(current->_parent) current = current->_parent;
>
>        else current = 0;
>    }
> }
>
> void Window::managed(WindowManager* wm) {
>    _wm = wm;
>
>    for(Iterator i = begin(); i != end(); i++) {
>        _setManaged(i->get());
>        _setStyled(i->get());
>    }
>
>    setFirstFocusable();
>    resize();
>    update();
> }
>
> void Window::unmanaged(WindowManager* wm) {
>    for(Iterator i = begin(); i != end(); i++) _setManaged(i->get(), true);
>
>    _wm = 0;
> }
>
> bool Window::addWidget(Widget* widget) {
>    return _setWidget(widget);
> }
>
> bool Window::insertWidget(Widget* widget, unsigned int pos) {
>    return _setWidget(widget, pos);
> }
>
> bool Window::removeWidget(Widget* widget) {
>    if(!widget) return false;
>
>    if(_remove(widget)) {
>        _removeFromGeode(widget);
>
>        resize();
>
>        return true;
>    }
>
>    return false;
> }
>
> bool Window::replaceWidget(Widget* oldWidget, Widget* newWidget) {
>    return false;
> }
>
> unsigned int Window::addDrawableAndGetIndex(osg::Drawable* drawable) {
>    osg::Geode* geode = _geode();
>
>    if(geode->addDrawable(drawable)) return
> geode->getDrawableIndex(drawable);
>
>    // 0 is a valid error return code here, since our background widget
> should be
>    // the first child.
>    return 0;
> }
>
> unsigned int Window::addChildAndGetIndex(osg::Node* node) {
>    if(addChild(node)) return getChildIndex(node);
>
>    return 0;
> }
>
> // All of the subsequent functions are very boring and uninteresting,
> although hopefully
> // self-explanatory. They simply wrap calls to _compare<>() with the proper
> templates, and
> // forward the optional iteration ranges...
>
> point_type Window::_getMinWidgetWidth(int begin, int end, int add) const {
>    return _compare<Less>(&Widget::getWidth, begin, end, add);
> }
>
> point_type Window::_getMinWidgetHeight(int begin, int end, int add) const {
>    return _compare<Less>(&Widget::getHeight, begin, end, add);
> }
>
> point_type Window::_getMaxWidgetWidth(int begin, int end, int add) const {
>    return _compare<Greater>(&Widget::getWidth, begin, end, add);
> }
>
> point_type Window::_getMaxWidgetHeight(int begin, int end, int add) const {
>    return _compare<Greater>(&Widget::getHeight, begin, end, add);
> }
>
> point_type Window::_getMinWidgetMinWidth(int begin, int end, int add) const
> {
>    return _compare<Less>(&Widget::getMinWidth, begin, end, add);
> }
>
> point_type Window::_getMinWidgetMinHeight(int begin, int end, int add) const
> {
>    return _compare<Less>(&Widget::getMinHeight, begin, end, add);
> }
>
> point_type Window::_getMaxWidgetMinWidth(int begin, int end, int add) const
> {
>    return _compare<Greater>(&Widget::getMinWidth, begin, end, add);
> }
>
> point_type Window::_getMaxWidgetMinHeight(int begin, int end, int add) const
> {
>    return _compare<Greater>(&Widget::getMinHeight, begin, end, add);
> }
>
> point_type Window::_getMinWidgetWidthTotal(int begin, int end, int add)
> const {
>    return _compare<Less>(&Widget::getWidthTotal, begin, end, add);
> }
>
> point_type Window::_getMinWidgetHeightTotal(int begin, int end, int add)
> const {
>    return _compare<Less>(&Widget::getHeightTotal, begin, end, add);
> }
>
> point_type Window::_getMaxWidgetWidthTotal(int begin, int end, int add)
> const {
>    return _compare<Greater>(&Widget::getWidthTotal, begin, end, add);
> }
>
> point_type Window::_getMaxWidgetHeightTotal(int begin, int end, int add)
> const {
>    return _compare<Greater>(&Widget::getHeightTotal, begin, end, add);
> }
>
> point_type Window::_getMinWidgetMinWidthTotal(int begin, int end, int add)
> const {
>    return _compare<Less>(&Widget::getMinWidthTotal, begin, end, add);
> }
>
> point_type Window::_getMinWidgetMinHeightTotal(int begin, int end, int add)
> const {
>    return _compare<Less>(&Widget::getMinHeightTotal, begin, end, add);
> }
>
> point_type Window::_getMaxWidgetMinWidthTotal(int begin, int end, int add)
> const {
>    return _compare<Greater>(&Widget::getMinWidthTotal, begin, end, add);
> }
>
> point_type Window::_getMaxWidgetMinHeightTotal(int begin, int end, int add)
> const {
>    return _compare<Greater>(&Widget::getMinHeightTotal, begin, end, add);
> }
>
> point_type Window::_getMinWidgetPadHorizontal(int begin, int end, int add)
> const {
>    return _compare<Less>(&Widget::getPadHorizontal, begin, end, add);
> }
>
> point_type Window::_getMinWidgetPadVertical(int begin, int end, int add)
> const {
>    return _compare<Less>(&Widget::getPadVertical, begin, end, add);
> }
>
> point_type Window::_getMaxWidgetPadHorizontal(int begin, int end, int add)
> const {
>    return _compare<Greater>(&Widget::getPadHorizontal, begin, end, add);
> }
>
> point_type Window::_getMaxWidgetPadVertical(int begin, int end, int add)
> const {
>    return _compare<Greater>(&Widget::getPadVertical, begin, end, add);
> }
>
> point_type Window::_getNumFill(int begin, int end, int add) const {
>    return _accumulate<Plus>(&Widget::getFillAsNumeric, begin, end, add);
> }
>
> Window::Sizes Window::_getWidthImplementation() const {
>    osg::BoundingBox bb = getGeode()->getBoundingBox();
>
>    point_type w = osg::round(bb.xMax() - bb.xMin());
>
>    return Sizes(w, 0.0f);
> }
>
> Window::Sizes Window::_getHeightImplementation() const {
>    osg::BoundingBox bb = getGeode()->getBoundingBox();
>
>    point_type h = osg::round(bb.yMax() - bb.yMin());
>
>    return Sizes(h, 0.0f);
> }
>
> }
>
> _______________________________________________
> osg-submissions mailing list
> [email protected]
> http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
>
>
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to