<commit_before>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005 darkbits                        Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/widgets/window.hpp"
#include "guichan/exception.hpp"
#include "guichan/mouseinput.hpp"

namespace gcn
{
    Window::Window()
    {
        mContent = NULL;
        mMouseDrag = false;
        setBorderSize(1);
        setPadding(2);
        setTitleBarHeight(16);
        setAlignment(Graphics::CENTER);
        addMouseListener(this);
        setMovable(true);
        setOpaque(true);
    }

    Window::Window(const std::string& caption)
    {
        mContent = NULL;
        mMouseDrag = false;
        setCaption(caption);
        setBorderSize(1);
        setPadding(2);
        setTitleBarHeight(16);
        setAlignment(Graphics::CENTER);
        addMouseListener(this);
        setMovable(true);
        setOpaque(true);
    }

    Window::Window(Widget* content, const std::string& caption)
    {
        mContent = NULL;
        mMouseDrag = false;
        setContent(content);
        setCaption(caption);
        setBorderSize(1);
        setPadding(2);
        setTitleBarHeight(16);
        setAlignment(Graphics::CENTER);
        addMouseListener(this);
        setMovable(true);
        setOpaque(true);
    }

    Window::~Window()
    {
        setContent(NULL);
    }

    void Window::setPadding(unsigned int padding)
    {
        mPadding = padding;
        repositionContent();
    }

    unsigned int Window::getPadding() const
    {
        return mPadding;
    }

    void Window::setTitleBarHeight(unsigned int height)
    {
        mTitleBarHeight = height;
        repositionContent();
    }

    unsigned int Window::getTitleBarHeight()
    {
        return mTitleBarHeight;
    }

    void Window:: _announceDeath(Widget *widget)
    {
        mContent = NULL;
    }

    void Window::setContent(Widget* widget)
    {
        if (getContent() != NULL)
        {
            getContent()->_setParent(NULL);
            getContent()->_setFocusHandler(NULL);
        }

        if (widget != NULL)
        {
            widget->_setParent(this);
            widget->_setFocusHandler(_getFocusHandler());
        }

        mContent = widget;
        repositionContent();
    }

    Widget* Window::getContent() const
    {
        return mContent;
    }

    void Window::setCaption(const std::string& caption)
    {
        mCaption = caption;
    }

    const std::string& Window::getCaption() const
    {
        return mCaption;
    }

    void Window::setAlignment(unsigned int alignment)
    {
        mAlignment = alignment;
    }

    unsigned int Window::getAlignment() const
    {
        return mAlignment;
    }

    void Window::draw(Graphics* graphics)
    {
        Color faceColor = getBaseColor();
        Color highlightColor, shadowColor;
        int alpha = getBaseColor().a;
        int width = getWidth() + getBorderSize() * 2 - 1;
        int height = getHeight() + getBorderSize() * 2 - 1;
        highlightColor = faceColor + 0x303030;
        highlightColor.a = alpha;
        shadowColor = faceColor - 0x303030;
        shadowColor.a = alpha;

        Rectangle d = getContentDimension();

        // Fill the background around the content
        graphics->setColor(faceColor);
        // Fill top
        graphics->fillRectangle(Rectangle(0,0,getWidth(),d.y - 1));
        // Fill left
        graphics->fillRectangle(Rectangle(0,d.y - 1, d.x - 1, getHeight() - d.y + 1));
        // Fill right
        graphics->fillRectangle(Rectangle(d.x + d.width + 1,
                                          d.y - 1,
                                          getWidth() - d.x - d.width - 1,
                                          getHeight() - d.y + 1));
        // Fill bottom
        graphics->fillRectangle(Rectangle(d.x - 1,
                                          d.y + d.height + 1,
                                          d.width + 2,
                                          getHeight() - d.height - d.y - 1));

        if (isOpaque())
        {
            graphics->fillRectangle(d);
        }

        // Construct a rectangle one pixel bigger than the content
        d.x -= 1;
        d.y -= 1;
        d.width += 2;
        d.height += 2;

        // Draw a border around the content
        graphics->setColor(shadowColor);
        // Top line
        graphics->drawLine(d.x,
                           d.y,
                           d.x + d.width - 2,
                           d.y);

        // Left line
        graphics->drawLine(d.x,
                           d.y + 1,
                           d.x,
                           d.y + d.height - 1);

        graphics->setColor(highlightColor);
        // Right line
        graphics->drawLine(d.x + d.width - 1,
                           d.y,
                           d.x + d.width - 1,
                           d.y + d.height - 2);
        // Bottom line
        graphics->drawLine(d.x + 1,
                           d.y + d.height - 1,
                           d.x + d.width - 1,
                           d.y + d.height - 1);

        drawContent(graphics);

        int textX;
        int textY;
        textY = (getTitleBarHeight() - getFont()->getHeight()) / 2;
        switch (getAlignment())
        {
          case Graphics::LEFT:
              textX = 4;
              break;
          case Graphics::CENTER:
              textX = getWidth() / 2;
              break;
          case Graphics::RIGHT:
              textX = getWidth() - 4;
              break;
          default:
              throw GCN_EXCEPTION("Unknown alignment.");
        }

        graphics->setColor(getForegroundColor());
        graphics->setFont(getFont());
        graphics->drawText(getCaption(), textX, textY, getAlignment());
    }

    void Window::drawBorder(Graphics* graphics)
    {
        Color faceColor = getBaseColor();
        Color highlightColor, shadowColor;
        int alpha = getBaseColor().a;
        int width = getWidth() + getBorderSize() * 2 - 1;
        int height = getHeight() + getBorderSize() * 2 - 1;
        highlightColor = faceColor + 0x303030;
        highlightColor.a = alpha;
        shadowColor = faceColor - 0x303030;
        shadowColor.a = alpha;

        unsigned int i;
        for (i = 0; i < getBorderSize(); ++i)
        {
            graphics->setColor(highlightColor);
            graphics->drawLine(i,i, width - i, i);
            graphics->drawLine(i,i + 1, i, height - i - 1);
            graphics->setColor(shadowColor);
            graphics->drawLine(width - i,i + 1, width - i, height - i);
            graphics->drawLine(i,height - i, width - i - 1, height - i);
        }
    }

    void Window::drawContent(Graphics* graphics)
    {
        if (getContent() != NULL)
        {
            graphics->pushClipArea(getContentDimension());
            graphics->pushClipArea(Rectangle(0, 0, getContent()->getWidth(),
                                             getContent()->getHeight()));
            getContent()->draw(graphics);
            graphics->popClipArea();
            graphics->popClipArea();
        }
    }

    void Window::mousePress(int x, int y, int button)
    {
        if (getParent() != NULL)
        {
            getParent()->moveToTop(this);
        }

        if (isMovable() && hasMouse()
            && y < (int)(getTitleBarHeight() + getPadding()) && button == 1)
        {
            mMouseDrag = true;
            mMouseXOffset = x;
            mMouseYOffset = y;
        }
    }

    void Window::mouseRelease(int x, int y, int button)
    {
        if (button == 1)
        {
            mMouseDrag = false;
        }
    }

    void Window::mouseMotion(int x, int y)
    {
        if (mMouseDrag && isMovable())
        {
            setPosition(x - mMouseXOffset + getX(),
                        y - mMouseYOffset + getY());
        }
    }

    void Window::moveToTop(Widget* widget)
    {
        if (widget != getContent())
        {
            throw GCN_EXCEPTION("Widget is not content of window.");
        }
    }

    void Window::moveToBottom(Widget* widget)
    {
        if (widget != getContent())
        {
            throw GCN_EXCEPTION("Widget is not content of window");
        }
    }

    void Window::getDrawSize(int& width, int& height, Widget* widget)
    {
        if (widget != getContent())
        {
            throw GCN_EXCEPTION("Widget is not content of window");
        }

        Rectangle d = getContentDimension();
        width = d.width;
        height = d.height;
    }

    void Window::repositionContent()
    {
        if (getContent() == NULL)
        {
            return;
        }

        Rectangle d = getContentDimension();
        mContent->setPosition(d.x, d.y);
    }

    Rectangle Window::getContentDimension()
    {
        return Rectangle(getPadding(),
                         getTitleBarHeight(),
                         getWidth() - getPadding() * 2,
                         getHeight() - getPadding() - getTitleBarHeight());
    }

    void Window::setMovable(bool movable)
    {
        mMovable = movable;
    }

    bool Window::isMovable() const
    {
        return mMovable;
    }

    void Window::resizeToContent()
    {
        if (getContent() != NULL)
        {
            setSize(getContent()->getWidth() + 2*getPadding(),
                    getContent()->getHeight() + getPadding()
                    + getTitleBarHeight());
        }
    }

    void Window::_mouseInputMessage(const MouseInput &mouseInput)
    {
        BasicContainer::_mouseInputMessage(mouseInput);

        if (getContent() != NULL)
        {
            if (getContentDimension().isPointInRect(mouseInput.x, mouseInput.y) &&
                getContent()->getDimension().isPointInRect(mouseInput.x, mouseInput.y))
            {
                if (!getContent()->hasMouse())
                {
                    getContent()->_mouseInMessage();
                }

                MouseInput mi = mouseInput;
                mi.x -= getContent()->getX();
                mi.y -= getContent()->getY();
                getContent()->_mouseInputMessage(mi);
            }
            else if (getContent()->hasMouse())
            {
                getContent()->_mouseOutMessage();
            }
        }
    }

    void Window::_mouseOutMessage()
    {
        BasicContainer::_mouseOutMessage();

        if (getContent() != NULL && getContent()->hasMouse())
        {
            getContent()->_mouseOutMessage();
        }
    }

    void Window::_setFocusHandler(FocusHandler *focusHandler)
    {
        if (getContent() != NULL)
        {
            getContent()->_setFocusHandler(focusHandler);
        }

        BasicContainer::_setFocusHandler(focusHandler);
    }

    void Window::setOpaque(bool opaque)
    {
        mOpaque = opaque;
    }

    bool Window::isOpaque()
    {
        return mOpaque;
    }

    void Window::logic()
    {
        if (getContent() != NULL)
        {
            getContent()->logic();
        }
    }
}
<commit_msg>Content is now not drawn if not visible.<commit_after>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005 darkbits                        Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/widgets/window.hpp"
#include "guichan/exception.hpp"
#include "guichan/mouseinput.hpp"

namespace gcn
{
    Window::Window()
    {
        mContent = NULL;
        mMouseDrag = false;
        setBorderSize(1);
        setPadding(2);
        setTitleBarHeight(16);
        setAlignment(Graphics::CENTER);
        addMouseListener(this);
        setMovable(true);
        setOpaque(true);
    }

    Window::Window(const std::string& caption)
    {
        mContent = NULL;
        mMouseDrag = false;
        setCaption(caption);
        setBorderSize(1);
        setPadding(2);
        setTitleBarHeight(16);
        setAlignment(Graphics::CENTER);
        addMouseListener(this);
        setMovable(true);
        setOpaque(true);
    }

    Window::Window(Widget* content, const std::string& caption)
    {
        mContent = NULL;
        mMouseDrag = false;
        setContent(content);
        setCaption(caption);
        setBorderSize(1);
        setPadding(2);
        setTitleBarHeight(16);
        setAlignment(Graphics::CENTER);
        addMouseListener(this);
        setMovable(true);
        setOpaque(true);
    }

    Window::~Window()
    {
        setContent(NULL);
    }

    void Window::setPadding(unsigned int padding)
    {
        mPadding = padding;
        repositionContent();
    }

    unsigned int Window::getPadding() const
    {
        return mPadding;
    }

    void Window::setTitleBarHeight(unsigned int height)
    {
        mTitleBarHeight = height;
        repositionContent();
    }

    unsigned int Window::getTitleBarHeight()
    {
        return mTitleBarHeight;
    }

    void Window:: _announceDeath(Widget *widget)
    {
        mContent = NULL;
    }

    void Window::setContent(Widget* widget)
    {
        if (getContent() != NULL)
        {
            getContent()->_setParent(NULL);
            getContent()->_setFocusHandler(NULL);
        }

        if (widget != NULL)
        {
            widget->_setParent(this);
            widget->_setFocusHandler(_getFocusHandler());
        }

        mContent = widget;
        repositionContent();
    }

    Widget* Window::getContent() const
    {
        return mContent;
    }

    void Window::setCaption(const std::string& caption)
    {
        mCaption = caption;
    }

    const std::string& Window::getCaption() const
    {
        return mCaption;
    }

    void Window::setAlignment(unsigned int alignment)
    {
        mAlignment = alignment;
    }

    unsigned int Window::getAlignment() const
    {
        return mAlignment;
    }

    void Window::draw(Graphics* graphics)
    {
        Color faceColor = getBaseColor();
        Color highlightColor, shadowColor;
        int alpha = getBaseColor().a;
        int width = getWidth() + getBorderSize() * 2 - 1;
        int height = getHeight() + getBorderSize() * 2 - 1;
        highlightColor = faceColor + 0x303030;
        highlightColor.a = alpha;
        shadowColor = faceColor - 0x303030;
        shadowColor.a = alpha;

        Rectangle d = getContentDimension();

        // Fill the background around the content
        graphics->setColor(faceColor);
        // Fill top
        graphics->fillRectangle(Rectangle(0,0,getWidth(),d.y - 1));
        // Fill left
        graphics->fillRectangle(Rectangle(0,d.y - 1, d.x - 1, getHeight() - d.y + 1));
        // Fill right
        graphics->fillRectangle(Rectangle(d.x + d.width + 1,
                                          d.y - 1,
                                          getWidth() - d.x - d.width - 1,
                                          getHeight() - d.y + 1));
        // Fill bottom
        graphics->fillRectangle(Rectangle(d.x - 1,
                                          d.y + d.height + 1,
                                          d.width + 2,
                                          getHeight() - d.height - d.y - 1));

        if (isOpaque())
        {
            graphics->fillRectangle(d);
        }

        // Construct a rectangle one pixel bigger than the content
        d.x -= 1;
        d.y -= 1;
        d.width += 2;
        d.height += 2;

        // Draw a border around the content
        graphics->setColor(shadowColor);
        // Top line
        graphics->drawLine(d.x,
                           d.y,
                           d.x + d.width - 2,
                           d.y);

        // Left line
        graphics->drawLine(d.x,
                           d.y + 1,
                           d.x,
                           d.y + d.height - 1);

        graphics->setColor(highlightColor);
        // Right line
        graphics->drawLine(d.x + d.width - 1,
                           d.y,
                           d.x + d.width - 1,
                           d.y + d.height - 2);
        // Bottom line
        graphics->drawLine(d.x + 1,
                           d.y + d.height - 1,
                           d.x + d.width - 1,
                           d.y + d.height - 1);

        drawContent(graphics);

        int textX;
        int textY;
        textY = (getTitleBarHeight() - getFont()->getHeight()) / 2;
        switch (getAlignment())
        {
          case Graphics::LEFT:
              textX = 4;
              break;
          case Graphics::CENTER:
              textX = getWidth() / 2;
              break;
          case Graphics::RIGHT:
              textX = getWidth() - 4;
              break;
          default:
              throw GCN_EXCEPTION("Unknown alignment.");
        }

        graphics->setColor(getForegroundColor());
        graphics->setFont(getFont());
        graphics->drawText(getCaption(), textX, textY, getAlignment());
    }

    void Window::drawBorder(Graphics* graphics)
    {
        Color faceColor = getBaseColor();
        Color highlightColor, shadowColor;
        int alpha = getBaseColor().a;
        int width = getWidth() + getBorderSize() * 2 - 1;
        int height = getHeight() + getBorderSize() * 2 - 1;
        highlightColor = faceColor + 0x303030;
        highlightColor.a = alpha;
        shadowColor = faceColor - 0x303030;
        shadowColor.a = alpha;

        unsigned int i;
        for (i = 0; i < getBorderSize(); ++i)
        {
            graphics->setColor(highlightColor);
            graphics->drawLine(i,i, width - i, i);
            graphics->drawLine(i,i + 1, i, height - i - 1);
            graphics->setColor(shadowColor);
            graphics->drawLine(width - i,i + 1, width - i, height - i);
            graphics->drawLine(i,height - i, width - i - 1, height - i);
        }
    }

    void Window::drawContent(Graphics* graphics)
    {
        if (getContent() != NULL && getContent()->isVisible())
        {
            graphics->pushClipArea(getContentDimension());
            graphics->pushClipArea(Rectangle(0, 0, getContent()->getWidth(),
                                             getContent()->getHeight()));
            getContent()->draw(graphics);
            graphics->popClipArea();
            graphics->popClipArea();
        }
    }

    void Window::mousePress(int x, int y, int button)
    {
        if (getParent() != NULL)
        {
            getParent()->moveToTop(this);
        }

        if (isMovable() && hasMouse()
            && y < (int)(getTitleBarHeight() + getPadding()) && button == 1)
        {
            mMouseDrag = true;
            mMouseXOffset = x;
            mMouseYOffset = y;
        }
    }

    void Window::mouseRelease(int x, int y, int button)
    {
        if (button == 1)
        {
            mMouseDrag = false;
        }
    }

    void Window::mouseMotion(int x, int y)
    {
        if (mMouseDrag && isMovable())
        {
            setPosition(x - mMouseXOffset + getX(),
                        y - mMouseYOffset + getY());
        }
    }

    void Window::moveToTop(Widget* widget)
    {
        if (widget != getContent())
        {
            throw GCN_EXCEPTION("Widget is not content of window.");
        }
    }

    void Window::moveToBottom(Widget* widget)
    {
        if (widget != getContent())
        {
            throw GCN_EXCEPTION("Widget is not content of window");
        }
    }

    void Window::getDrawSize(int& width, int& height, Widget* widget)
    {
        if (widget != getContent())
        {
            throw GCN_EXCEPTION("Widget is not content of window");
        }

        Rectangle d = getContentDimension();
        width = d.width;
        height = d.height;
    }

    void Window::repositionContent()
    {
        if (getContent() == NULL)
        {
            return;
        }

        Rectangle d = getContentDimension();
        mContent->setPosition(d.x, d.y);
    }

    Rectangle Window::getContentDimension()
    {
        return Rectangle(getPadding(),
                         getTitleBarHeight(),
                         getWidth() - getPadding() * 2,
                         getHeight() - getPadding() - getTitleBarHeight());
    }

    void Window::setMovable(bool movable)
    {
        mMovable = movable;
    }

    bool Window::isMovable() const
    {
        return mMovable;
    }

    void Window::resizeToContent()
    {
        if (getContent() != NULL)
        {
            setSize(getContent()->getWidth() + 2*getPadding(),
                    getContent()->getHeight() + getPadding()
                    + getTitleBarHeight());
        }
    }

    void Window::_mouseInputMessage(const MouseInput &mouseInput)
    {
        BasicContainer::_mouseInputMessage(mouseInput);

        if (getContent() != NULL)
        {
            if (getContentDimension().isPointInRect(mouseInput.x, mouseInput.y) &&
                getContent()->getDimension().isPointInRect(mouseInput.x, mouseInput.y))
            {
                if (!getContent()->hasMouse())
                {
                    getContent()->_mouseInMessage();
                }

                MouseInput mi = mouseInput;
                mi.x -= getContent()->getX();
                mi.y -= getContent()->getY();
                getContent()->_mouseInputMessage(mi);
            }
            else if (getContent()->hasMouse())
            {
                getContent()->_mouseOutMessage();
            }
        }
    }

    void Window::_mouseOutMessage()
    {
        BasicContainer::_mouseOutMessage();

        if (getContent() != NULL && getContent()->hasMouse())
        {
            getContent()->_mouseOutMessage();
        }
    }

    void Window::_setFocusHandler(FocusHandler *focusHandler)
    {
        if (getContent() != NULL)
        {
            getContent()->_setFocusHandler(focusHandler);
        }

        BasicContainer::_setFocusHandler(focusHandler);
    }

    void Window::setOpaque(bool opaque)
    {
        mOpaque = opaque;
    }

    bool Window::isOpaque()
    {
        return mOpaque;
    }

    void Window::logic()
    {
        if (getContent() != NULL)
        {
            getContent()->logic();
        }
    }
}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2012 Heiko Strathmann
 * Copyright (C) 2012 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/base/init.h>
#include <shogun/features/SimpleFeatures.h>
#include <shogun/features/Labels.h>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/classifier/svm/LibSVM.h>
#include <shogun/evaluation/CrossValidation.h>
#include <shogun/evaluation/StratifiedCrossValidationSplitting.h>
#include <shogun/evaluation/ContingencyTableEvaluation.h>

using namespace shogun;

void print_message(FILE* target, const char* str)
{
	fprintf(target, "%s", str);
}

void test_cross_validation()
{
	/* data matrix dimensions */
	index_t num_vectors=500;
	index_t num_features=5;

	/* data means -1, 1 in all components, std deviation of 3 */
	SGVector<float64_t> mean_1(num_features);
	SGVector<float64_t> mean_2(num_features);
	CMath::fill_vector(mean_1.vector, mean_1.vlen, -1.0);
	CMath::fill_vector(mean_2.vector, mean_2.vlen, 1.0);
	float64_t sigma=3;

	/* fill data matrix around mean */
	SGMatrix<float64_t> train_dat(num_features, num_vectors);
	for (index_t i=0; i<num_vectors; ++i)
	{
		for (index_t j=0; j<num_features; ++j)
		{
			float64_t mean=i<num_vectors/2 ? mean_1.vector[0] : mean_2.vector[0];
			train_dat.matrix[i*num_features+j]=CMath::normal_random(mean, sigma);
		}
	}

	/* training features */
	CSimpleFeatures<float64_t>* features=
			new CSimpleFeatures<float64_t>(train_dat);

	/* training labels +/- 1 for each cluster */
	SGVector<float64_t> lab(num_vectors);
	for (index_t i=0; i<num_vectors; ++i)
		lab.vector[i]=i<num_vectors/2 ? -1.0 : 1.0;

	CLabels* labels=new CLabels(lab);

	/* gaussian kernel */
	int32_t kernel_cache=100;
	int32_t width=10;
	CGaussianKernel* kernel=new CGaussianKernel(kernel_cache, width);
	kernel->init(features, features);

	/* create svm via libsvm */
	float64_t svm_C=10;
	float64_t svm_eps=0.0001;
	CLibSVM* svm=new CLibSVM(svm_C, kernel, labels);
	svm->set_epsilon(svm_eps);

	/* splitting strategy */
	index_t n_folds=5;
	CStratifiedCrossValidationSplitting* splitting=
			new CStratifiedCrossValidationSplitting(labels, n_folds);

	/* evaluation criterium */
	CContingencyTableEvaluation* eval_crit=
			new CContingencyTableEvaluation(ACCURACY);

	/* cross validation instance, 10 runs, 95% confidence interval */
	CCrossValidation* cross=new CCrossValidation(svm, features, labels,
			splitting, eval_crit);

	cross->set_num_runs(10);
	cross->set_conf_int_alpha(0.05);

	/* actual evaluation */
	CrossValidationResult result=cross->evaluate();
	result.print_result();

	/* clean up */
	SG_UNREF(cross);
	mean_1.destroy_vector();
	mean_2.destroy_vector();
}

int main(int argc, char **argv)
{
	init_shogun(&print_message, &print_message, &print_message);

	test_cross_validation();

	exit_shogun();

	return 0;
}

<commit_msg>some corrections additions<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2012 Heiko Strathmann
 * Copyright (C) 2012 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/base/init.h>
#include <shogun/features/SimpleFeatures.h>
#include <shogun/features/Labels.h>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/classifier/svm/LibSVM.h>
#include <shogun/evaluation/CrossValidation.h>
#include <shogun/evaluation/StratifiedCrossValidationSplitting.h>
#include <shogun/evaluation/ContingencyTableEvaluation.h>

using namespace shogun;

void print_message(FILE* target, const char* str)
{
	fprintf(target, "%s", str);
}

void test_cross_validation()
{
	/* data matrix dimensions */
	index_t num_vectors=40;
	index_t num_features=5;

	/* data means -1, 1 in all components, std deviation of 3 */
	SGVector<float64_t> mean_1(num_features);
	SGVector<float64_t> mean_2(num_features);
	CMath::fill_vector(mean_1.vector, mean_1.vlen, -1.0);
	CMath::fill_vector(mean_2.vector, mean_2.vlen, 1.0);
	float64_t sigma=3;

	CMath::display_vector(mean_1.vector, mean_1.vlen, "mean 1");
	CMath::display_vector(mean_2.vector, mean_2.vlen, "mean 2");

	/* fill data matrix around mean */
	SGMatrix<float64_t> train_dat(num_features, num_vectors);
	for (index_t i=0; i<num_vectors; ++i)
	{
		for (index_t j=0; j<num_features; ++j)
		{
			float64_t mean=i<num_vectors/2 ? mean_1.vector[0] : mean_2.vector[0];
			train_dat.matrix[i*num_features+j]=CMath::normal_random(mean, sigma);
		}
	}

	/* training features */
	CSimpleFeatures<float64_t>* features=
			new CSimpleFeatures<float64_t>(train_dat);
	SG_REF(features);

	/* training labels +/- 1 for each cluster */
	SGVector<float64_t> lab(num_vectors);
	for (index_t i=0; i<num_vectors; ++i)
		lab.vector[i]=i<num_vectors/2 ? -1.0 : 1.0;

	CLabels* labels=new CLabels(lab);

	/* gaussian kernel */
	int32_t kernel_cache=100;
	int32_t width=10;
	CGaussianKernel* kernel=new CGaussianKernel(kernel_cache, width);
	kernel->init(features, features);

	/* create svm via libsvm */
	float64_t svm_C=10;
	float64_t svm_eps=0.0001;
	CLibSVM* svm=new CLibSVM(svm_C, kernel, labels);
	svm->set_epsilon(svm_eps);

	/* train and output */
	svm->train(features);
	CLabels* output=svm->apply(features);
	for (index_t i=0; i<num_vectors; ++i)
		SG_SPRINT("i=%d, class=%f,\n", i, output->get_label(i));

	/* evaluation criterion */
	CContingencyTableEvaluation* eval_crit=
			new CContingencyTableEvaluation(ACCURACY);

	/* evaluate training error */
	float64_t eval_result=eval_crit->evaluate(output, labels);
	SG_SPRINT("training error: %f\n", eval_result);
	SG_UNREF(output);

	/* assert that regression "works". this is not guaranteed to always work
	 * but should be a really coarse check to see if everything is going
	 * approx. right */
	ASSERT(eval_result<2);

	/* splitting strategy */
	index_t n_folds=5;
	CStratifiedCrossValidationSplitting* splitting=
			new CStratifiedCrossValidationSplitting(labels, n_folds);

	/* cross validation instance, 10 runs, 95% confidence interval */
	CCrossValidation* cross=new CCrossValidation(svm, features, labels,
			splitting, eval_crit);

	cross->set_num_runs(100);
	cross->set_conf_int_alpha(0.05);

	/* actual evaluation */
	CrossValidationResult result=cross->evaluate();
	result.print_result();

	/* clean up */
	SG_UNREF(cross);
	SG_UNREF(features);
	mean_1.destroy_vector();
	mean_2.destroy_vector();
}

int main(int argc, char **argv)
{
	init_shogun(&print_message, &print_message, &print_message);

	test_cross_validation();

	exit_shogun();

	return 0;
}

<|endoftext|>


<commit_before>/*
 * This file is part of accounts-ui
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * 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 GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include "service-selection-page.h"
#include "account-sync-handler.h"
#include "provider-plugin-process.h"
#include "service-settings-widget.h"
#include "accountsmanagersingleton.h"
#include "account-setup-finished-page.h"

//Qt
#include <QStringListModel>
#include <QItemSelection>
#include <QDebug>

//Meegotouch
#include <MLayout>
#include <MList>
#include <MGridLayoutPolicy>
#include <MLinearLayoutPolicy>
#include <MButton>
#include <MWidgetCreator>
#include <MContainer>
#include <MSeparator>
#include <MBasicListItem>
#include <MWidgetAction>
#include <MImageWidget>

//libAccounts
#include <Accounts/Provider>
#include <Accounts/Manager>

namespace AccountsUI {

M_REGISTER_WIDGET_NO_CREATE(ServiceSelectionPage)

//TODO: write the service plugins
class ServiceSelectionPagePrivate
{
public:
    ServiceSelectionPagePrivate()
        : serviceList(0),
        saveAction(0),
        cancelAction(0),
        context(0),
        syncHandler(0),
        layoutServicePolicy(0)
        {}
    ~ServiceSelectionPagePrivate() {}

    MList *serviceList;
    MAction *saveAction;
    MAction *cancelAction;
    AbstractAccountSetupContext *context;
    QList<AbstractServiceSetupContext*> serviceContextList;
    QList<AbstractSetupContext*> abstractContexts;
    AccountSyncHandler *syncHandler;
    MLinearLayoutPolicy *layoutServicePolicy;
    QString serviceType;
    QMap<QString, bool> serviceStatusMap;
};

ServiceSelectionPage::ServiceSelectionPage(AbstractAccountSetupContext *context,
                                           QList<AbstractServiceSetupContext*>
                                           &serviceContextList,
                                           QGraphicsItem *parent)
        : MApplicationPage(parent),
        d_ptr(new ServiceSelectionPagePrivate())
{
    Q_D(ServiceSelectionPage);
    setStyleName("AccountsUiPage");
    d->context = context;
    d->serviceType = context->serviceType();
    d->context->account()->selectService(NULL);
    d->context->account()->setEnabled(true);
    d->serviceContextList = serviceContextList;
    d->abstractContexts.append(d->context);

    setEscapeMode(MApplicationPageModel::EscapeManualBack);

    d->syncHandler = new AccountSyncHandler(this);
    connect(d->syncHandler, SIGNAL(syncStateChanged(const SyncState&)),
            this, SLOT(onSyncStateChanged(const SyncState&)));
}

void ServiceSelectionPage::serviceSelected(QModelIndex index)
{
    Q_UNUSED(index);
}

ServiceSelectionPage::~ServiceSelectionPage()
{
    delete d_ptr;
}

void ServiceSelectionPage::createContent()
{
    Q_D(ServiceSelectionPage);

    setComponentsDisplayMode(EscapeButton, MApplicationPageModel::Hide);

    //we need a central widget to get the right layout size under the menubar
    MWidget *centralWidget = new MWidget();
    setCentralWidget(centralWidget);
    MLayout *layout = new MLayout(centralWidget);
    MLinearLayoutPolicy *layoutPolicy = new MLinearLayoutPolicy(layout, Qt::Vertical);
    layoutPolicy->setSpacing(0);

    if (d->context) {
        MWidget *upperWidget = new MWidget(this);
        MLayout *upperLayout = new MLayout(upperWidget);
        MLinearLayoutPolicy *upperLayoutPolicy = new MLinearLayoutPolicy(upperLayout, Qt::Vertical);
        upperLayoutPolicy->setSpacing(0);

        MLayout *horizontalLayout = new MLayout();
        MLinearLayoutPolicy *horizontalLayoutPolicy = new MLinearLayoutPolicy(horizontalLayout, Qt::Horizontal);
        horizontalLayoutPolicy->setSpacing(0);

        QString providerName(d->context->account()->providerName());
        // xml file that describes the ui elements for the provider
        Accounts::Provider *provider = AccountsManager::instance()->provider(providerName);
        if (provider) {
            QDomElement root = provider->domDocument().documentElement();
            QDomElement providerIcon = root.firstChildElement("icon");
            QString providerIconId = providerIcon.text();

            // Provider info widgets
            MBasicListItem *providerInfoItem =
                    new MBasicListItem(MBasicListItem:: IconWithTitleAndSubtitle, this);
            providerInfoItem->setStyleName("CommonBasicListItemInverted");
            providerInfoItem->setObjectName("wgServiceSelectionPageBasicListItem");
            providerInfoItem->setTitle(provider->displayName());
            providerInfoItem->setSubtitle(d->context->account()->displayName());
            providerInfoItem->imageWidget()->setImage(providerIconId);
            horizontalLayoutPolicy->addItem(providerInfoItem, Qt::AlignLeft | Qt::AlignVCenter);
        }

        MSeparator *separatorTop = new MSeparator(this);
        separatorTop->setStyleName("CommonItemDividerInverted");
        separatorTop->setOrientation(Qt::Horizontal);

        upperLayoutPolicy->addItem(horizontalLayout);
        upperLayoutPolicy->addItem(separatorTop);

        layoutPolicy->addItem(upperWidget);
    }

    MWidget *serviceWidget = new MWidget();
    MLayout *serviceSettingLayout = new MLayout(serviceWidget);
    d->layoutServicePolicy = new MLinearLayoutPolicy(serviceSettingLayout, Qt::Vertical);
    d->layoutServicePolicy->setSpacing(0);

    for (int i = 0; i < d->serviceContextList.count(); i++) {
        //ServiceSettingsWidget sets the display widget of the changing settings
        ServiceSettingsWidget *settingsWidget =
            new ServiceSettingsWidget(d->serviceContextList.at(i), serviceWidget,
                                      ServiceSettingsWidget::MandatorySettings |
                                      ServiceSettingsWidget::EnableButton,
                                      true);
        const Accounts::Service *service = d->serviceContextList.at(i)->service();
        emit serviceEnabled(service->name(), true);
        d->serviceStatusMap.insert(service->name(), true);
        d->abstractContexts.append(d->serviceContextList.at(i));
        d->layoutServicePolicy->addItem(settingsWidget, Qt::AlignLeft);
        connect (settingsWidget, SIGNAL(serviceEnabled(const QString&, bool)),
                 this, SIGNAL(serviceEnabled(const QString&, bool)));
        connect (settingsWidget, SIGNAL(serviceEnabled(const QString&, bool)),
                 this, SLOT(setEnabledService(const QString&, bool)));
    }

    layoutPolicy->addItem(serviceWidget, Qt::AlignLeft);

    MSeparator *separatorBottom = new MSeparator(this);
    separatorBottom->setStyleName("CommonItemDividerInverted");
    separatorBottom->setOrientation(Qt::Horizontal);
    d->layoutServicePolicy->addItem(separatorBottom);

    //% "DONE"
    d->saveAction = new MAction(qtTrId("qtn_comm_command_done"), centralWidget);
    d->saveAction->setLocation(MAction::ToolBarLocation);
    addAction(d->saveAction);

    //% "CANCEL"
    d->cancelAction = new MAction(qtTrId("qtn_comm_cancel"), centralWidget);
    d->cancelAction->setLocation(MAction::ToolBarLocation);
    addAction(d->cancelAction);
    layoutPolicy->addStretch();

    connect(d->saveAction, SIGNAL(triggered()),
            this, SLOT(onAccountInstallButton()));
    connect(d->cancelAction, SIGNAL(triggered()),
            this, SLOT(close()));
    connect(d->serviceList, SIGNAL(itemClicked(QModelIndex)),
            this,SLOT(serviceSelected(QModelIndex)));

    connect(this, SIGNAL(backButtonClicked()),
            this, SLOT(close()));
}

void ServiceSelectionPage::onAccountInstallButton()
{
    Q_D(ServiceSelectionPage);

    disconnect(d->saveAction, SIGNAL(triggered()),
               this, SLOT(onAccountInstallButton()));
    disconnect(d->cancelAction, SIGNAL(triggered()),
               this, SLOT(close()));

    setProgressIndicatorVisible(true);
    for (int i = 0; i < d->serviceContextList.count(); i++) {
        const Accounts::Service *service = d->serviceContextList.at(i)->service();
        QMap<QString, bool>::iterator mapIterator =
                d->serviceStatusMap.find(service->name());
        if (mapIterator == d->serviceStatusMap.end())
            continue;
        d->serviceContextList.at(i)->enable(mapIterator.value());
        d->serviceStatusMap.remove(mapIterator.key());
    }
    d->syncHandler->validate(d->abstractContexts);
}

void ServiceSelectionPage::onSyncStateChanged(const SyncState &state)
{
    Q_D(ServiceSelectionPage);

    switch (state) {
        case Validated:
            d->syncHandler->store(d->abstractContexts);
            break;
        case Stored:
            if (d->serviceType.isEmpty()) {
                connect(d->context->account(), SIGNAL(synced()),
                        ProviderPluginProcess::instance(), SLOT(quit()));
                d->context->account()->sync();
            } else {
                d->context->account()->sync();
                AccountSetupFinishedPage *page = new AccountSetupFinishedPage(d->context);
                page->appear();
            }
            break;
        default:
            connect(d->saveAction, SIGNAL(triggered()),
                    this, SLOT(onAccountInstallButton()));
            connect(d->cancelAction, SIGNAL(triggered()),
                    this, SLOT(close()));
            setProgressIndicatorVisible(false);
            return;
    }
}

void ServiceSelectionPage::setWidget(MWidget *widget)
{
    Q_D(ServiceSelectionPage);

    if (d->layoutServicePolicy && widget)
        d->layoutServicePolicy->addItem(widget);
}

void ServiceSelectionPage::setEnabledService(const QString &serviceName,
                                            bool enabled)
{
    Q_D(ServiceSelectionPage);
    d->serviceStatusMap[serviceName] = enabled;
}

} //namespace
<commit_msg>Fixing:  226154 - Incorrect account provider name displayed in service selection view<commit_after>/*
 * This file is part of accounts-ui
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * 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 GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include "service-selection-page.h"
#include "account-sync-handler.h"
#include "provider-plugin-process.h"
#include "service-settings-widget.h"
#include "accountsmanagersingleton.h"
#include "account-setup-finished-page.h"

//Qt
#include <QStringListModel>
#include <QItemSelection>
#include <QDebug>

//Meegotouch
#include <MLayout>
#include <MList>
#include <MGridLayoutPolicy>
#include <MLinearLayoutPolicy>
#include <MButton>
#include <MWidgetCreator>
#include <MContainer>
#include <MSeparator>
#include <MBasicListItem>
#include <MWidgetAction>
#include <MImageWidget>

//libAccounts
#include <Accounts/Provider>
#include <Accounts/Manager>

namespace AccountsUI {

M_REGISTER_WIDGET_NO_CREATE(ServiceSelectionPage)

//TODO: write the service plugins
class ServiceSelectionPagePrivate
{
public:
    ServiceSelectionPagePrivate()
        : serviceList(0),
        saveAction(0),
        cancelAction(0),
        context(0),
        syncHandler(0),
        layoutServicePolicy(0)
        {}
    ~ServiceSelectionPagePrivate() {}

    MList *serviceList;
    MAction *saveAction;
    MAction *cancelAction;
    AbstractAccountSetupContext *context;
    QList<AbstractServiceSetupContext*> serviceContextList;
    QList<AbstractSetupContext*> abstractContexts;
    AccountSyncHandler *syncHandler;
    MLinearLayoutPolicy *layoutServicePolicy;
    QString serviceType;
    QMap<QString, bool> serviceStatusMap;
};

ServiceSelectionPage::ServiceSelectionPage(AbstractAccountSetupContext *context,
                                           QList<AbstractServiceSetupContext*>
                                           &serviceContextList,
                                           QGraphicsItem *parent)
        : MApplicationPage(parent),
        d_ptr(new ServiceSelectionPagePrivate())
{
    Q_D(ServiceSelectionPage);
    setStyleName("AccountsUiPage");
    d->context = context;
    d->serviceType = context->serviceType();
    d->context->account()->selectService(NULL);
    d->context->account()->setEnabled(true);
    d->serviceContextList = serviceContextList;
    d->abstractContexts.append(d->context);

    setEscapeMode(MApplicationPageModel::EscapeManualBack);

    d->syncHandler = new AccountSyncHandler(this);
    connect(d->syncHandler, SIGNAL(syncStateChanged(const SyncState&)),
            this, SLOT(onSyncStateChanged(const SyncState&)));
}

void ServiceSelectionPage::serviceSelected(QModelIndex index)
{
    Q_UNUSED(index);
}

ServiceSelectionPage::~ServiceSelectionPage()
{
    delete d_ptr;
}

void ServiceSelectionPage::createContent()
{
    Q_D(ServiceSelectionPage);

    setComponentsDisplayMode(EscapeButton, MApplicationPageModel::Hide);

    //we need a central widget to get the right layout size under the menubar
    MWidget *centralWidget = new MWidget();
    setCentralWidget(centralWidget);
    MLayout *layout = new MLayout(centralWidget);
    MLinearLayoutPolicy *layoutPolicy = new MLinearLayoutPolicy(layout, Qt::Vertical);
    layoutPolicy->setSpacing(0);

    if (d->context) {
        MWidget *upperWidget = new MWidget(this);
        MLayout *upperLayout = new MLayout(upperWidget);
        MLinearLayoutPolicy *upperLayoutPolicy = new MLinearLayoutPolicy(upperLayout, Qt::Vertical);
        upperLayoutPolicy->setSpacing(0);

        MLayout *horizontalLayout = new MLayout();
        MLinearLayoutPolicy *horizontalLayoutPolicy = new MLinearLayoutPolicy(horizontalLayout, Qt::Horizontal);
        horizontalLayoutPolicy->setSpacing(0);

        QString providerName(d->context->account()->providerName());
        // xml file that describes the ui elements for the provider
        Accounts::Provider *provider = AccountsManager::instance()->provider(providerName);
        if (provider) {
            QDomElement root = provider->domDocument().documentElement();
            QDomElement providerIcon = root.firstChildElement("icon");
            QString providerIconId = providerIcon.text();

            // Provider info widgets
            MBasicListItem *providerInfoItem =
                    new MBasicListItem(MBasicListItem:: IconWithTitleAndSubtitle, this);
            providerInfoItem->setStyleName("CommonBasicListItemInverted");
            providerInfoItem->setObjectName("wgServiceSelectionPageBasicListItem");
            providerInfoItem->setTitle(qtTrId(provider->displayName().toLatin1()));
            providerInfoItem->setSubtitle(qtTrId(d->context->account()->displayName().toLatin1()));
            providerInfoItem->imageWidget()->setImage(providerIconId);
            horizontalLayoutPolicy->addItem(providerInfoItem, Qt::AlignLeft | Qt::AlignVCenter);
        }

        MSeparator *separatorTop = new MSeparator(this);
        separatorTop->setStyleName("CommonItemDividerInverted");
        separatorTop->setOrientation(Qt::Horizontal);

        upperLayoutPolicy->addItem(horizontalLayout);
        upperLayoutPolicy->addItem(separatorTop);

        layoutPolicy->addItem(upperWidget);
    }

    MWidget *serviceWidget = new MWidget();
    MLayout *serviceSettingLayout = new MLayout(serviceWidget);
    d->layoutServicePolicy = new MLinearLayoutPolicy(serviceSettingLayout, Qt::Vertical);
    d->layoutServicePolicy->setSpacing(0);

    for (int i = 0; i < d->serviceContextList.count(); i++) {
        //ServiceSettingsWidget sets the display widget of the changing settings
        ServiceSettingsWidget *settingsWidget =
            new ServiceSettingsWidget(d->serviceContextList.at(i), serviceWidget,
                                      ServiceSettingsWidget::MandatorySettings |
                                      ServiceSettingsWidget::EnableButton,
                                      true);
        const Accounts::Service *service = d->serviceContextList.at(i)->service();
        emit serviceEnabled(service->name(), true);
        d->serviceStatusMap.insert(service->name(), true);
        d->abstractContexts.append(d->serviceContextList.at(i));
        d->layoutServicePolicy->addItem(settingsWidget, Qt::AlignLeft);
        connect (settingsWidget, SIGNAL(serviceEnabled(const QString&, bool)),
                 this, SIGNAL(serviceEnabled(const QString&, bool)));
        connect (settingsWidget, SIGNAL(serviceEnabled(const QString&, bool)),
                 this, SLOT(setEnabledService(const QString&, bool)));
    }

    layoutPolicy->addItem(serviceWidget, Qt::AlignLeft);

    MSeparator *separatorBottom = new MSeparator(this);
    separatorBottom->setStyleName("CommonItemDividerInverted");
    separatorBottom->setOrientation(Qt::Horizontal);
    d->layoutServicePolicy->addItem(separatorBottom);

    //% "DONE"
    d->saveAction = new MAction(qtTrId("qtn_comm_command_done"), centralWidget);
    d->saveAction->setLocation(MAction::ToolBarLocation);
    addAction(d->saveAction);

    //% "CANCEL"
    d->cancelAction = new MAction(qtTrId("qtn_comm_cancel"), centralWidget);
    d->cancelAction->setLocation(MAction::ToolBarLocation);
    addAction(d->cancelAction);
    layoutPolicy->addStretch();

    connect(d->saveAction, SIGNAL(triggered()),
            this, SLOT(onAccountInstallButton()));
    connect(d->cancelAction, SIGNAL(triggered()),
            this, SLOT(close()));
    connect(d->serviceList, SIGNAL(itemClicked(QModelIndex)),
            this,SLOT(serviceSelected(QModelIndex)));

    connect(this, SIGNAL(backButtonClicked()),
            this, SLOT(close()));
}

void ServiceSelectionPage::onAccountInstallButton()
{
    Q_D(ServiceSelectionPage);

    disconnect(d->saveAction, SIGNAL(triggered()),
               this, SLOT(onAccountInstallButton()));
    disconnect(d->cancelAction, SIGNAL(triggered()),
               this, SLOT(close()));

    setProgressIndicatorVisible(true);
    for (int i = 0; i < d->serviceContextList.count(); i++) {
        const Accounts::Service *service = d->serviceContextList.at(i)->service();
        QMap<QString, bool>::iterator mapIterator =
                d->serviceStatusMap.find(service->name());
        if (mapIterator == d->serviceStatusMap.end())
            continue;
        d->serviceContextList.at(i)->enable(mapIterator.value());
        d->serviceStatusMap.remove(mapIterator.key());
    }
    d->syncHandler->validate(d->abstractContexts);
}

void ServiceSelectionPage::onSyncStateChanged(const SyncState &state)
{
    Q_D(ServiceSelectionPage);

    switch (state) {
        case Validated:
            d->syncHandler->store(d->abstractContexts);
            break;
        case Stored:
            if (d->serviceType.isEmpty()) {
                connect(d->context->account(), SIGNAL(synced()),
                        ProviderPluginProcess::instance(), SLOT(quit()));
                d->context->account()->sync();
            } else {
                d->context->account()->sync();
                AccountSetupFinishedPage *page = new AccountSetupFinishedPage(d->context);
                page->appear();
            }
            break;
        default:
            connect(d->saveAction, SIGNAL(triggered()),
                    this, SLOT(onAccountInstallButton()));
            connect(d->cancelAction, SIGNAL(triggered()),
                    this, SLOT(close()));
            setProgressIndicatorVisible(false);
            return;
    }
}

void ServiceSelectionPage::setWidget(MWidget *widget)
{
    Q_D(ServiceSelectionPage);

    if (d->layoutServicePolicy && widget)
        d->layoutServicePolicy->addItem(widget);
}

void ServiceSelectionPage::setEnabledService(const QString &serviceName,
                                            bool enabled)
{
    Q_D(ServiceSelectionPage);
    d->serviceStatusMap[serviceName] = enabled;
}

} //namespace
<|endoftext|>


<commit_before>#ifdef WINDOWS

#include <windows.h>
#include <fstream>
#include "util/system.h"

namespace System{

bool isDirectory(const std::string & path){
    unsigned int f = GetFileAttributes(path.c_str());
    if (f == INVALID_FILE_ATTRIBUTES){
        return false;
    }
    return f & FILE_ATTRIBUTE_DIRECTORY;
}

bool readableFile(const std::string & path){
    return !isDirectory(path) && readable(path);
}

bool readable(const std::string & path){
    if (isDirectory(path)){
        return true;
    }

    std::ifstream stream(path.c_str());
    bool ok = stream.good();
    if (stream.is_open()){
        stream.close();
    }
    return ok;
}

void makeDirectory(const std::string & path){
    _mkdir(path.c_str());
}

uint64_t currentMicroseconds(){
    LARGE_INTEGER ticksPerSecond;
    LARGE_INTEGER tick;
    QueryPerformanceFrequency(&ticksPerSecond);
    QueryPerformanceCounter(&tick);
    return (tick.QuadPart)/(ticksPerSecond.QuadPart/1000000);
}

}

#endif
<commit_msg>add header<commit_after>#ifdef WINDOWS

#include <windows.h>
#include <fstream>
#include "util/system.h"
#include <dirent.h>

namespace System{

bool isDirectory(const std::string & path){
    unsigned int f = GetFileAttributes(path.c_str());
    if (f == INVALID_FILE_ATTRIBUTES){
        return false;
    }
    return f & FILE_ATTRIBUTE_DIRECTORY;
}

bool readableFile(const std::string & path){
    return !isDirectory(path) && readable(path);
}

bool readable(const std::string & path){
    if (isDirectory(path)){
        return true;
    }

    std::ifstream stream(path.c_str());
    bool ok = stream.good();
    if (stream.is_open()){
        stream.close();
    }
    return ok;
}

void makeDirectory(const std::string & path){
    _mkdir(path.c_str());
}

uint64_t currentMicroseconds(){
    LARGE_INTEGER ticksPerSecond;
    LARGE_INTEGER tick;
    QueryPerformanceFrequency(&ticksPerSecond);
    QueryPerformanceCounter(&tick);
    return (tick.QuadPart)/(ticksPerSecond.QuadPart/1000000);
}

}

#endif
<|endoftext|>


<commit_before>/**
 * This file is part of node-kdtree, a node.js Addon for working with kd-trees.
 * Copyright (C) 2011 Justin Ethier <justinethier@github>
 *
 * Please use github to submit patches and bug reports:
 * https://github.com/justinethier/node-kdtree
 */

// TODO: publish via npm. see: https://github.com/isaacs/npm/blob/master/doc/developers.md#readme
//
#include <v8.h>
#include <node.h>
#include <node_events.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <kdtree.h>

using namespace v8;
using namespace node;

class KDTree : public ObjectWrap {
  public:
    static void
    Initialize (v8::Handle<v8::Object> target){
        HandleScope scope;

        Local<FunctionTemplate> t = FunctionTemplate::New(New);

        t->InstanceTemplate()->SetInternalFieldCount(1);
        t->SetClassName(String::NewSymbol("KDTree"));

        NODE_SET_PROTOTYPE_METHOD(t, "test", Test); // TODO: this will go away...
        NODE_SET_PROTOTYPE_METHOD(t, "insert", Insert);
        NODE_SET_PROTOTYPE_METHOD(t, "nearest", Nearest);
//        NODE_SET_PROTOTYPE_METHOD(t, "nearestRange", NearestRange); // kd_nearest_range

        target->Set(String::NewSymbol("KDTree"), t->GetFunction());
    }

    // TODO: allow insertion of (string?) data
    bool Insert(const double *pos, Handle<Value> data){
      return (kd_insert(kd_, pos, *data) == 0);
    }

    // Allow retrieval of (string?) data
    Handle<Value>
    Nearest(const double *pos){
      int rpos;
      char *pdata;
      kdres *results = kd_nearest(kd_, pos);
      Local<Array> rv = Array::New(dim_ + 1);

      if (results == NULL){}
      else{
        double *respos = (double *)(malloc(sizeof(double) * dim_));
        pdata = (char *)kd_res_item(results, respos);

        for(rpos = 0; rpos < dim_; rpos++){
          rv->Set(rpos, Number::New(respos[rpos]));
        }

        rv->Set(dim_, // TODO: append data element here
        Number::New(respos[rpos]));

        free(respos);
        kd_res_free(results);
      }
      return rv;
    }

    int Test()
    {
       int i, vcount = 10;
       kdtree *kd;
       kdres *set;
    //   unsigned int msec, start;

       printf("inserting %d random vectors... ", vcount);
       fflush(stdout);

       kd = kd_create(3);

    //   start = get_msec();
       for(i=0; i<vcount; i++) {
               float x, y, z;
               x = ((float)rand() / RAND_MAX) * 200.0 - 100.0;
               y = ((float)rand() / RAND_MAX) * 200.0 - 100.0;
               z = ((float)rand() / RAND_MAX) * 200.0 - 100.0;

               assert(kd_insert3(kd, x, y, z, 0) == 0);
       }
    //   msec = get_msec() - start;
    //   printf("%.3f sec\n", (float)msec / 1000.0);

    //   start = get_msec();
       set = kd_nearest_range3(kd, 0, 0, 0, 100);
    //   msec = get_msec() - start;
    //
       i = kd_res_size(set);
       printf("range query returned %d items\n", kd_res_size(set));
       kd_res_free(set);

       kd_free(kd);
       return i;
    }

  protected:

    static Handle<Value>
    Insert(const Arguments& args){
        KDTree *kd = ObjectWrap::Unwrap<KDTree>(args.This());
        HandleScope scope;

      double *pos = (double *)(malloc(sizeof(double) * args.Length()));
      for (int i = 0; i < args.Length(); i++){
        pos[i] = args[i]->NumberValue();
      }

// TODO: pass data parameter down using a persistent handle?
// http://izs.me/v8-docs/classv8_1_1Persistent.html#_details
//
// TODO:
// if this is the case, need to pass as arg, then in Insert() need to
// validate that num args == dim_
//
      // TODO: may want to pass Length down, so class can assert == dim_
      Handle<Value> result = Boolean::New( kd->Insert(pos,
          Persistent<Value>::New(args[0]) // Test code, just stuff number as data for now...
                                    // Eventually will want API to allow an optional data arg.
                                    // If not specified, will default to something (null?)
          ) );
      free(pos);
      return result;
    }

    static Handle<Value>
    Nearest(const Arguments& args){
      KDTree *kd = ObjectWrap::Unwrap<KDTree>(args.This());
      HandleScope scope;

      double *pos = (double *)(malloc(sizeof(double) * args.Length()));
      for (int i = 0; i < args.Length(); i++){
        pos[i] = args[i]->NumberValue();
      }

      // TODO: may want to pass Length down, so class can assert == dim_
      Handle<Value> result = kd->Nearest(pos);

      free(pos);
      return result;
    }

// TODO:
//    static Handle<Value>
//    NearestRange(const Arguments& args){}

    static Handle<Value>
    New (const Arguments& args){
        HandleScope scope;

// TODO: an example of how to handle arguments to constructor
//Async *async = new Async(args[0]->Int32Value(), args[1]->Int32Value());

        int dimension = 3; // Default
        if (args.Length() > 0){
          dimension = args[3]->Int32Value();
        }

        KDTree *kd = new KDTree(dimension);
        kd->Wrap(args.This());

        return args.This();
    }

    KDTree (int dim) : ObjectWrap (){
        kd_ = kd_create(dim);
        dim_ = dim;
    }

    ~KDTree(){
      // TODO: need to call this to clean up allocated 'data' elements
      //       see the kdtree docs:
//      void kd_data_destructor(struct kdtree *tree, void (*destr)(void*));
        if (kd_ != NULL){
            kd_free(kd_);
        }
    }

    static Handle<Value>
    Test (const Arguments& args){
        KDTree *kd = ObjectWrap::Unwrap<KDTree>(args.This());

        HandleScope scope;

        int num = kd->Test();

        return Integer::New(num); // Undefined();
    }

  private:
    kdtree* kd_;
    int dim_;
};

extern "C" void
init (Handle<Object> target)
{
    HandleScope scope;
    KDTree::Initialize(target);
}

<commit_msg>Added notes about saving/loading the data parameter.<commit_after>/**
 * This file is part of node-kdtree, a node.js Addon for working with kd-trees.
 * Copyright (C) 2011 Justin Ethier <justinethier@github>
 *
 * Please use github to submit patches and bug reports:
 * https://github.com/justinethier/node-kdtree
 */

// TODO: publish via npm. see: https://github.com/isaacs/npm/blob/master/doc/developers.md#readme
//
#include <v8.h>
#include <node.h>
#include <node_events.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <kdtree.h>

using namespace v8;
using namespace node;

class KDTree : public ObjectWrap {
  public:
    static void
    Initialize (v8::Handle<v8::Object> target){
        HandleScope scope;

        Local<FunctionTemplate> t = FunctionTemplate::New(New);

        t->InstanceTemplate()->SetInternalFieldCount(1);
        t->SetClassName(String::NewSymbol("KDTree"));

        NODE_SET_PROTOTYPE_METHOD(t, "test", Test); // TODO: this will go away...
        NODE_SET_PROTOTYPE_METHOD(t, "insert", Insert);
        NODE_SET_PROTOTYPE_METHOD(t, "nearest", Nearest);
//        NODE_SET_PROTOTYPE_METHOD(t, "nearestRange", NearestRange); // kd_nearest_range

        target->Set(String::NewSymbol("KDTree"), t->GetFunction());
    }

    // TODO: allow insertion of (string?) data
    bool Insert(const double *pos, Handle<Value> data){
      return (kd_insert(kd_, pos, *data) == 0);
    }

    // Allow retrieval of (string?) data
    Handle<Value>
    Nearest(const double *pos){
      int rpos;
      void *pdata;
      kdres *results = kd_nearest(kd_, pos);
      Local<Array> rv = Array::New(dim_ + 1);

      if (results == NULL){}
      else{
        double *respos = (double *)(malloc(sizeof(double) * dim_));
        pdata = (void *)kd_res_item(results, respos);

        for(rpos = 0; rpos < dim_; rpos++){
          rv->Set(rpos, Number::New(respos[rpos]));
        }

// TODO: any way to get that data back?
//Handle<Value> hdata = Handle::Cast((Value *)pdata);
//        rv->Set(dim_, // TODO: append data element here
//         Number::New( (void *)pdata ));
//        Number::New(respos[rpos]));

        free(respos);
        kd_res_free(results);
      }
      return rv;
    }

    int Test()
    {
       int i, vcount = 10;
       kdtree *kd;
       kdres *set;
    //   unsigned int msec, start;

       printf("inserting %d random vectors... ", vcount);
       fflush(stdout);

       kd = kd_create(3);

    //   start = get_msec();
       for(i=0; i<vcount; i++) {
               float x, y, z;
               x = ((float)rand() / RAND_MAX) * 200.0 - 100.0;
               y = ((float)rand() / RAND_MAX) * 200.0 - 100.0;
               z = ((float)rand() / RAND_MAX) * 200.0 - 100.0;

               assert(kd_insert3(kd, x, y, z, 0) == 0);
       }
    //   msec = get_msec() - start;
    //   printf("%.3f sec\n", (float)msec / 1000.0);

    //   start = get_msec();
       set = kd_nearest_range3(kd, 0, 0, 0, 100);
    //   msec = get_msec() - start;
    //
       i = kd_res_size(set);
       printf("range query returned %d items\n", kd_res_size(set));
       kd_res_free(set);

       kd_free(kd);
       return i;
    }

  protected:

    static Handle<Value>
    Insert(const Arguments& args){
        KDTree *kd = ObjectWrap::Unwrap<KDTree>(args.This());
        HandleScope scope;

      double *pos = (double *)(malloc(sizeof(double) * args.Length()));
      for (int i = 0; i < args.Length(); i++){
        pos[i] = args[i]->NumberValue();
      }

// TODO: pass data parameter down using a persistent handle?
// http://izs.me/v8-docs/classv8_1_1Persistent.html#_details
//
// TODO:
// if this is the case, need to pass as arg, then in Insert() need to
// validate that num args == dim_
//
      // TODO: may want to pass Length down, so class can assert == dim_
      Handle<Value> result = Boolean::New( kd->Insert(pos,
          Persistent<Value>::New(args[0]) // Test code, just stuff number as data for now...
                                    // Eventually will want API to allow an optional data arg.
                                    // If not specified, will default to something (null?)
          ) );
      free(pos);
      return result;
    }

    static Handle<Value>
    Nearest(const Arguments& args){
      KDTree *kd = ObjectWrap::Unwrap<KDTree>(args.This());
      HandleScope scope;

      double *pos = (double *)(malloc(sizeof(double) * args.Length()));
      for (int i = 0; i < args.Length(); i++){
        pos[i] = args[i]->NumberValue();
      }

      // TODO: may want to pass Length down, so class can assert == dim_
      Handle<Value> result = kd->Nearest(pos);

      free(pos);
      return result;
    }

// TODO:
//    static Handle<Value>
//    NearestRange(const Arguments& args){}

    static Handle<Value>
    New (const Arguments& args){
        HandleScope scope;

// TODO: an example of how to handle arguments to constructor
//Async *async = new Async(args[0]->Int32Value(), args[1]->Int32Value());

        int dimension = 3; // Default
        if (args.Length() > 0){
          dimension = args[3]->Int32Value();
        }

        KDTree *kd = new KDTree(dimension);
        kd->Wrap(args.This());

        return args.This();
    }

    KDTree (int dim) : ObjectWrap (){
        kd_ = kd_create(dim);
        dim_ = dim;
    }

    ~KDTree(){
      // TODO: need to call this to clean up allocated 'data' elements
      //       see the kdtree docs:
//      void kd_data_destructor(struct kdtree *tree, void (*destr)(void*));
        if (kd_ != NULL){
            kd_free(kd_);
        }
    }

    static Handle<Value>
    Test (const Arguments& args){
        KDTree *kd = ObjectWrap::Unwrap<KDTree>(args.This());

        HandleScope scope;

        int num = kd->Test();

        return Integer::New(num); // Undefined();
    }

  private:
    kdtree* kd_;
    int dim_;
};

extern "C" void
init (Handle<Object> target)
{
    HandleScope scope;
    KDTree::Initialize(target);
}

<|endoftext|>


<commit_before>/*
 * Copyright © 2012 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "main/core.h"
#include "ir.h"
#include "linker.h"
#include "ir_uniform.h"

/* These functions are put in a "private" namespace instead of being marked
 * static so that the unit tests can access them.  See
 * http://code.google.com/p/googletest/wiki/AdvancedGuide#Testing_Private_Code
 */
namespace linker {

gl_uniform_storage *
get_storage(gl_uniform_storage *storage, unsigned num_storage,
	    const char *name)
{
   for (unsigned int i = 0; i < num_storage; i++) {
      if (strcmp(name, storage[i].name) == 0)
	 return &storage[i];
   }

   return NULL;
}

void
copy_constant_to_storage(union gl_constant_value *storage,
			 const ir_constant *val,
			 const enum glsl_base_type base_type,
                         const unsigned int elements,
                         unsigned int boolean_true)
{
   for (unsigned int i = 0; i < elements; i++) {
      switch (base_type) {
      case GLSL_TYPE_UINT:
	 storage[i].u = val->value.u[i];
	 break;
      case GLSL_TYPE_INT:
      case GLSL_TYPE_SAMPLER:
	 storage[i].i = val->value.i[i];
	 break;
      case GLSL_TYPE_FLOAT:
	 storage[i].f = val->value.f[i];
	 break;
      case GLSL_TYPE_DOUBLE:
         /* XXX need to check on big-endian */
         storage[i * 2].u = *(uint32_t *)&val->value.d[i];
         storage[i * 2 + 1].u = *(((uint32_t *)&val->value.d[i]) + 1);
         break;
      case GLSL_TYPE_BOOL:
	 storage[i].b = val->value.b[i] ? boolean_true : 0;
	 break;
      case GLSL_TYPE_ARRAY:
      case GLSL_TYPE_STRUCT:
      case GLSL_TYPE_IMAGE:
      case GLSL_TYPE_ATOMIC_UINT:
      case GLSL_TYPE_INTERFACE:
      case GLSL_TYPE_VOID:
      case GLSL_TYPE_SUBROUTINE:
      case GLSL_TYPE_FUNCTION:
      case GLSL_TYPE_ERROR:
	 /* All other types should have already been filtered by other
	  * paths in the caller.
	  */
	 assert(!"Should not get here.");
	 break;
      }
   }
}

/**
 * Initialize an opaque uniform from the value of an explicit binding
 * qualifier specified in the shader.  Atomic counters are different because
 * they have no storage and should be handled elsewhere.
 */
void
set_opaque_binding(void *mem_ctx, gl_shader_program *prog,
                   const glsl_type *type, const char *name, int *binding)
{

   if (type->is_array() && type->fields.array->is_array()) {
      const glsl_type *const element_type = type->fields.array;

      for (unsigned int i = 0; i < type->length; i++) {
	 const char *element_name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i);

	 set_opaque_binding(mem_ctx, prog, element_type,
                            element_name, binding);
      }
   } else {
      struct gl_uniform_storage *const storage =
         get_storage(prog->UniformStorage, prog->NumUniformStorage, name);

      if (storage == NULL) {
         assert(storage != NULL);
         return;
      }

      const unsigned elements = MAX2(storage->array_elements, 1);

      /* Section 4.4.4 (Opaque-Uniform Layout Qualifiers) of the GLSL 4.20 spec
       * says:
       *
       *     "If the binding identifier is used with an array, the first element
       *     of the array takes the specified unit and each subsequent element
       *     takes the next consecutive unit."
       */
      for (unsigned int i = 0; i < elements; i++) {
         storage->storage[i].i = (*binding)++;
      }

      for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
        gl_shader *shader = prog->_LinkedShaders[sh];

         if (shader) {
            if (storage->type->base_type == GLSL_TYPE_SAMPLER &&
                storage->opaque[sh].active) {
               for (unsigned i = 0; i < elements; i++) {
                  const unsigned index = storage->opaque[sh].index + i;
                  shader->SamplerUnits[index] = storage->storage[i].i;
               }

            } else if (storage->type->base_type == GLSL_TYPE_IMAGE &&
                    storage->opaque[sh].active) {
               for (unsigned i = 0; i < elements; i++) {
                  const unsigned index = storage->opaque[sh].index + i;
                  shader->ImageUnits[index] = storage->storage[i].i;
               }
            }
         }
      }
   }
}

void
set_block_binding(gl_shader_program *prog, const char *block_name,
                  unsigned mode, int binding)
{
   unsigned num_blocks = mode == ir_var_uniform ? prog->NumUniformBlocks :
      prog->NumShaderStorageBlocks;
   struct gl_uniform_block *blks = mode == ir_var_uniform ?
      prog->UniformBlocks : prog->ShaderStorageBlocks;

   for (unsigned i = 0; i < num_blocks; i++) {
      if (!strcmp(blks[i].Name, block_name)) {
         blks[i].Binding = binding;
         return;
      }
   }

   unreachable("Failed to initialize block binding");
}

void
set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
			const char *name, const glsl_type *type,
                        ir_constant *val, unsigned int boolean_true)
{
   const glsl_type *t_without_array = type->without_array();
   if (type->is_record()) {
      ir_constant *field_constant;

      field_constant = (ir_constant *)val->components.get_head();

      for (unsigned int i = 0; i < type->length; i++) {
	 const glsl_type *field_type = type->fields.structure[i].type;
	 const char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name,
					    type->fields.structure[i].name);
	 set_uniform_initializer(mem_ctx, prog, field_name,
                                 field_type, field_constant, boolean_true);
	 field_constant = (ir_constant *)field_constant->next;
      }
      return;
   } else if (t_without_array->is_record() ||
              (type->is_array() && type->fields.array->is_array())) {
      const glsl_type *const element_type = type->fields.array;

      for (unsigned int i = 0; i < type->length; i++) {
	 const char *element_name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i);

	 set_uniform_initializer(mem_ctx, prog, element_name,
                                 element_type, val->array_elements[i],
                                 boolean_true);
      }
      return;
   }

   struct gl_uniform_storage *const storage =
      get_storage(prog->UniformStorage,
                  prog->NumUniformStorage,
		  name);
   if (storage == NULL) {
      assert(storage != NULL);
      return;
   }

   if (val->type->is_array()) {
      const enum glsl_base_type base_type =
	 val->array_elements[0]->type->base_type;
      const unsigned int elements = val->array_elements[0]->type->components();
      unsigned int idx = 0;
      unsigned dmul = (base_type == GLSL_TYPE_DOUBLE) ? 2 : 1;

      assert(val->type->length >= storage->array_elements);
      for (unsigned int i = 0; i < storage->array_elements; i++) {
	 copy_constant_to_storage(& storage->storage[idx],
				  val->array_elements[i],
				  base_type,
                                  elements,
                                  boolean_true);

	 idx += elements * dmul;
      }
   } else {
      copy_constant_to_storage(storage->storage,
			       val,
			       val->type->base_type,
                               val->type->components(),
                               boolean_true);

      if (storage->type->is_sampler()) {
         for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
            gl_shader *shader = prog->_LinkedShaders[sh];

            if (shader && storage->opaque[sh].active) {
               unsigned index = storage->opaque[sh].index;

               shader->SamplerUnits[index] = storage->storage[0].i;
            }
         }
      }
   }
}
}

void
link_set_uniform_initializers(struct gl_shader_program *prog,
                              unsigned int boolean_true)
{
   void *mem_ctx = NULL;

   for (unsigned int i = 0; i < MESA_SHADER_STAGES; i++) {
      struct gl_shader *shader = prog->_LinkedShaders[i];

      if (shader == NULL)
	 continue;

      foreach_in_list(ir_instruction, node, shader->ir) {
	 ir_variable *const var = node->as_variable();

	 if (!var || (var->data.mode != ir_var_uniform &&
	     var->data.mode != ir_var_shader_storage))
	    continue;

	 if (!mem_ctx)
	    mem_ctx = ralloc_context(NULL);

         if (var->data.explicit_binding) {
            const glsl_type *const type = var->type;

            if (type->without_array()->is_sampler() ||
                type->without_array()->is_image()) {
               int binding = var->data.binding;
               linker::set_opaque_binding(mem_ctx, prog, var->type,
                                          var->name, &binding);
            } else if (var->is_in_buffer_block()) {
               const glsl_type *const iface_type = var->get_interface_type();

               /* If the variable is an array and it is an interface instance,
                * we need to set the binding for each array element.  Just
                * checking that the variable is an array is not sufficient.
                * The variable could be an array element of a uniform block
                * that lacks an instance name.  For example:
                *
                *     uniform U {
                *         float f[4];
                *     };
                *
                * In this case "f" would pass is_in_buffer_block (above) and
                * type->is_array(), but it will fail is_interface_instance().
                */
               if (var->is_interface_instance() && var->type->is_array()) {
                  for (unsigned i = 0; i < var->type->length; i++) {
                     const char *name =
                        ralloc_asprintf(mem_ctx, "%s[%u]", iface_type->name, i);

                     /* Section 4.4.3 (Uniform Block Layout Qualifiers) of the
                      * GLSL 4.20 spec says:
                      *
                      *     "If the binding identifier is used with a uniform
                      *     block instanced as an array then the first element
                      *     of the array takes the specified block binding and
                      *     each subsequent element takes the next consecutive
                      *     uniform block binding point."
                      */
                     linker::set_block_binding(prog, name, var->data.mode,
                                               var->data.binding + i);
                  }
               } else {
                  linker::set_block_binding(prog, iface_type->name,
                                            var->data.mode,
                                            var->data.binding);
               }
            } else if (type->contains_atomic()) {
               /* we don't actually need to do anything. */
            } else {
               assert(!"Explicit binding not on a sampler, UBO or atomic.");
            }
         } else if (var->constant_initializer) {
            linker::set_uniform_initializer(mem_ctx, prog, var->name,
                                            var->type, var->constant_initializer,
                                            boolean_true);
         }
      }
   }

   ralloc_free(mem_ctx);
}
<commit_msg>glsl/images: bounds check image unit assignment<commit_after>/*
 * Copyright © 2012 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "main/core.h"
#include "ir.h"
#include "linker.h"
#include "ir_uniform.h"

/* These functions are put in a "private" namespace instead of being marked
 * static so that the unit tests can access them.  See
 * http://code.google.com/p/googletest/wiki/AdvancedGuide#Testing_Private_Code
 */
namespace linker {

gl_uniform_storage *
get_storage(gl_uniform_storage *storage, unsigned num_storage,
	    const char *name)
{
   for (unsigned int i = 0; i < num_storage; i++) {
      if (strcmp(name, storage[i].name) == 0)
	 return &storage[i];
   }

   return NULL;
}

void
copy_constant_to_storage(union gl_constant_value *storage,
			 const ir_constant *val,
			 const enum glsl_base_type base_type,
                         const unsigned int elements,
                         unsigned int boolean_true)
{
   for (unsigned int i = 0; i < elements; i++) {
      switch (base_type) {
      case GLSL_TYPE_UINT:
	 storage[i].u = val->value.u[i];
	 break;
      case GLSL_TYPE_INT:
      case GLSL_TYPE_SAMPLER:
	 storage[i].i = val->value.i[i];
	 break;
      case GLSL_TYPE_FLOAT:
	 storage[i].f = val->value.f[i];
	 break;
      case GLSL_TYPE_DOUBLE:
         /* XXX need to check on big-endian */
         storage[i * 2].u = *(uint32_t *)&val->value.d[i];
         storage[i * 2 + 1].u = *(((uint32_t *)&val->value.d[i]) + 1);
         break;
      case GLSL_TYPE_BOOL:
	 storage[i].b = val->value.b[i] ? boolean_true : 0;
	 break;
      case GLSL_TYPE_ARRAY:
      case GLSL_TYPE_STRUCT:
      case GLSL_TYPE_IMAGE:
      case GLSL_TYPE_ATOMIC_UINT:
      case GLSL_TYPE_INTERFACE:
      case GLSL_TYPE_VOID:
      case GLSL_TYPE_SUBROUTINE:
      case GLSL_TYPE_FUNCTION:
      case GLSL_TYPE_ERROR:
	 /* All other types should have already been filtered by other
	  * paths in the caller.
	  */
	 assert(!"Should not get here.");
	 break;
      }
   }
}

/**
 * Initialize an opaque uniform from the value of an explicit binding
 * qualifier specified in the shader.  Atomic counters are different because
 * they have no storage and should be handled elsewhere.
 */
void
set_opaque_binding(void *mem_ctx, gl_shader_program *prog,
                   const glsl_type *type, const char *name, int *binding)
{

   if (type->is_array() && type->fields.array->is_array()) {
      const glsl_type *const element_type = type->fields.array;

      for (unsigned int i = 0; i < type->length; i++) {
	 const char *element_name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i);

	 set_opaque_binding(mem_ctx, prog, element_type,
                            element_name, binding);
      }
   } else {
      struct gl_uniform_storage *const storage =
         get_storage(prog->UniformStorage, prog->NumUniformStorage, name);

      if (storage == NULL) {
         assert(storage != NULL);
         return;
      }

      const unsigned elements = MAX2(storage->array_elements, 1);

      /* Section 4.4.4 (Opaque-Uniform Layout Qualifiers) of the GLSL 4.20 spec
       * says:
       *
       *     "If the binding identifier is used with an array, the first element
       *     of the array takes the specified unit and each subsequent element
       *     takes the next consecutive unit."
       */
      for (unsigned int i = 0; i < elements; i++) {
         storage->storage[i].i = (*binding)++;
      }

      for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
        gl_shader *shader = prog->_LinkedShaders[sh];

         if (shader) {
            if (storage->type->base_type == GLSL_TYPE_SAMPLER &&
                storage->opaque[sh].active) {
               for (unsigned i = 0; i < elements; i++) {
                  const unsigned index = storage->opaque[sh].index + i;
                  shader->SamplerUnits[index] = storage->storage[i].i;
               }

            } else if (storage->type->base_type == GLSL_TYPE_IMAGE &&
                    storage->opaque[sh].active) {
               for (unsigned i = 0; i < elements; i++) {
                  const unsigned index = storage->opaque[sh].index + i;
                  if (index >= ARRAY_SIZE(shader->ImageUnits))
                     break;
                  shader->ImageUnits[index] = storage->storage[i].i;
               }
            }
         }
      }
   }
}

void
set_block_binding(gl_shader_program *prog, const char *block_name,
                  unsigned mode, int binding)
{
   unsigned num_blocks = mode == ir_var_uniform ? prog->NumUniformBlocks :
      prog->NumShaderStorageBlocks;
   struct gl_uniform_block *blks = mode == ir_var_uniform ?
      prog->UniformBlocks : prog->ShaderStorageBlocks;

   for (unsigned i = 0; i < num_blocks; i++) {
      if (!strcmp(blks[i].Name, block_name)) {
         blks[i].Binding = binding;
         return;
      }
   }

   unreachable("Failed to initialize block binding");
}

void
set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
			const char *name, const glsl_type *type,
                        ir_constant *val, unsigned int boolean_true)
{
   const glsl_type *t_without_array = type->without_array();
   if (type->is_record()) {
      ir_constant *field_constant;

      field_constant = (ir_constant *)val->components.get_head();

      for (unsigned int i = 0; i < type->length; i++) {
	 const glsl_type *field_type = type->fields.structure[i].type;
	 const char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name,
					    type->fields.structure[i].name);
	 set_uniform_initializer(mem_ctx, prog, field_name,
                                 field_type, field_constant, boolean_true);
	 field_constant = (ir_constant *)field_constant->next;
      }
      return;
   } else if (t_without_array->is_record() ||
              (type->is_array() && type->fields.array->is_array())) {
      const glsl_type *const element_type = type->fields.array;

      for (unsigned int i = 0; i < type->length; i++) {
	 const char *element_name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i);

	 set_uniform_initializer(mem_ctx, prog, element_name,
                                 element_type, val->array_elements[i],
                                 boolean_true);
      }
      return;
   }

   struct gl_uniform_storage *const storage =
      get_storage(prog->UniformStorage,
                  prog->NumUniformStorage,
		  name);
   if (storage == NULL) {
      assert(storage != NULL);
      return;
   }

   if (val->type->is_array()) {
      const enum glsl_base_type base_type =
	 val->array_elements[0]->type->base_type;
      const unsigned int elements = val->array_elements[0]->type->components();
      unsigned int idx = 0;
      unsigned dmul = (base_type == GLSL_TYPE_DOUBLE) ? 2 : 1;

      assert(val->type->length >= storage->array_elements);
      for (unsigned int i = 0; i < storage->array_elements; i++) {
	 copy_constant_to_storage(& storage->storage[idx],
				  val->array_elements[i],
				  base_type,
                                  elements,
                                  boolean_true);

	 idx += elements * dmul;
      }
   } else {
      copy_constant_to_storage(storage->storage,
			       val,
			       val->type->base_type,
                               val->type->components(),
                               boolean_true);

      if (storage->type->is_sampler()) {
         for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
            gl_shader *shader = prog->_LinkedShaders[sh];

            if (shader && storage->opaque[sh].active) {
               unsigned index = storage->opaque[sh].index;

               shader->SamplerUnits[index] = storage->storage[0].i;
            }
         }
      }
   }
}
}

void
link_set_uniform_initializers(struct gl_shader_program *prog,
                              unsigned int boolean_true)
{
   void *mem_ctx = NULL;

   for (unsigned int i = 0; i < MESA_SHADER_STAGES; i++) {
      struct gl_shader *shader = prog->_LinkedShaders[i];

      if (shader == NULL)
	 continue;

      foreach_in_list(ir_instruction, node, shader->ir) {
	 ir_variable *const var = node->as_variable();

	 if (!var || (var->data.mode != ir_var_uniform &&
	     var->data.mode != ir_var_shader_storage))
	    continue;

	 if (!mem_ctx)
	    mem_ctx = ralloc_context(NULL);

         if (var->data.explicit_binding) {
            const glsl_type *const type = var->type;

            if (type->without_array()->is_sampler() ||
                type->without_array()->is_image()) {
               int binding = var->data.binding;
               linker::set_opaque_binding(mem_ctx, prog, var->type,
                                          var->name, &binding);
            } else if (var->is_in_buffer_block()) {
               const glsl_type *const iface_type = var->get_interface_type();

               /* If the variable is an array and it is an interface instance,
                * we need to set the binding for each array element.  Just
                * checking that the variable is an array is not sufficient.
                * The variable could be an array element of a uniform block
                * that lacks an instance name.  For example:
                *
                *     uniform U {
                *         float f[4];
                *     };
                *
                * In this case "f" would pass is_in_buffer_block (above) and
                * type->is_array(), but it will fail is_interface_instance().
                */
               if (var->is_interface_instance() && var->type->is_array()) {
                  for (unsigned i = 0; i < var->type->length; i++) {
                     const char *name =
                        ralloc_asprintf(mem_ctx, "%s[%u]", iface_type->name, i);

                     /* Section 4.4.3 (Uniform Block Layout Qualifiers) of the
                      * GLSL 4.20 spec says:
                      *
                      *     "If the binding identifier is used with a uniform
                      *     block instanced as an array then the first element
                      *     of the array takes the specified block binding and
                      *     each subsequent element takes the next consecutive
                      *     uniform block binding point."
                      */
                     linker::set_block_binding(prog, name, var->data.mode,
                                               var->data.binding + i);
                  }
               } else {
                  linker::set_block_binding(prog, iface_type->name,
                                            var->data.mode,
                                            var->data.binding);
               }
            } else if (type->contains_atomic()) {
               /* we don't actually need to do anything. */
            } else {
               assert(!"Explicit binding not on a sampler, UBO or atomic.");
            }
         } else if (var->constant_initializer) {
            linker::set_uniform_initializer(mem_ctx, prog, var->name,
                                            var->type, var->constant_initializer,
                                            boolean_true);
         }
      }
   }

   ralloc_free(mem_ctx);
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <set>
#include "util/buffer.h"
#include "kernel/trace.h"

namespace lean {
void trace_cell::add_pos_info(format & r, expr const & e, pos_info_provider const * p) {
    if (!p || !e)
        return;
    format f = p->pp(e);
    if (!f)
        return;
    r += f;
    r += space();
}

format trace_cell::pp(formatter const & fmt, options const & opts, pos_info_provider const * p, bool display_children) const {
    format r;
    add_pos_info(r, get_main_expr(), p);
    r += pp_header(fmt, opts);
    if (display_children) {
        buffer<trace_cell *> children;
        get_children(children);
        unsigned indent = get_pp_indent(opts);
        for (trace_cell * child : children) {
            r += nest(indent, compose(line(), child->pp(fmt, opts, p, display_children)));
        }
    }
    return r;
}

bool trace::has_children() const {
    buffer<trace_cell *> r;
    get_children(r);
    return !r.empty();
}

bool depends_on(trace const & t, trace const & d) {
    buffer<trace_cell *>   todo;
    std::set<trace_cell *> visited;
    buffer<trace_cell *>   children;
    todo.push_back(t.raw());
    while (todo.empty()) {
        trace_cell * curr = todo.back();
        todo.pop_back();
        if (curr == d.raw()) {
            return true;
        } else {
            children.clear();
            curr->get_children(children);
            for (trace_cell * child : children) {
                if (child->is_shared()) {
                    if (visited.find(child) == visited.end()) {
                        visited.insert(child);
                        todo.push_back(child);
                    }
                } else {
                    todo.push_back(child);
                }
            }
        }
    }
    return false;
}
}
<commit_msg>fix(kernel/trace): fix typo in depends_on<commit_after>/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <set>
#include "util/buffer.h"
#include "kernel/trace.h"

namespace lean {
void trace_cell::add_pos_info(format & r, expr const & e, pos_info_provider const * p) {
    if (!p || !e)
        return;
    format f = p->pp(e);
    if (!f)
        return;
    r += f;
    r += space();
}

format trace_cell::pp(formatter const & fmt, options const & opts, pos_info_provider const * p, bool display_children) const {
    format r;
    add_pos_info(r, get_main_expr(), p);
    r += pp_header(fmt, opts);
    if (display_children) {
        buffer<trace_cell *> children;
        get_children(children);
        unsigned indent = get_pp_indent(opts);
        for (trace_cell * child : children) {
            r += nest(indent, compose(line(), child->pp(fmt, opts, p, display_children)));
        }
    }
    return r;
}

bool trace::has_children() const {
    buffer<trace_cell *> r;
    get_children(r);
    return !r.empty();
}

bool depends_on(trace const & t, trace const & d) {
    buffer<trace_cell *>   todo;
    std::set<trace_cell *> visited;
    buffer<trace_cell *>   children;
    todo.push_back(t.raw());
    while (!todo.empty()) {
        trace_cell * curr = todo.back();
        todo.pop_back();
        if (curr == d.raw()) {
            return true;
        } else {
            children.clear();
            curr->get_children(children);
            for (trace_cell * child : children) {
                if (child->is_shared()) {
                    if (visited.find(child) == visited.end()) {
                        visited.insert(child);
                        todo.push_back(child);
                    }
                } else {
                    todo.push_back(child);
                }
            }
        }
    }
    return false;
}
}
<|endoftext|>


<commit_before><commit_msg>`Universe::screenshot`: reordered code lines.<commit_after><|endoftext|>