Moving components and their children


#1

I solved my other OpenGL component problem. The problem I have now is that if I put the OpenGLComponent into a parent component, and then I move that parent, the openGL component does not move with it.

If I overide my parent component’s mouse dragged event, I can directly set the lcoation on the opengl component.

ANy ideas?


#2

Probably just a good old fashioned bug. I’ll investigate asap.


#3

Yeah, sorry - if you patch your juce_OpenGLComponent.cpp file with this new class it should work:

//==============================================================================
class InternalGLContextHolder  : public ComponentListener
{
private:
    OpenGLComponent* owner;
    Component* lastTopLevelComp;
    bool reentrant;
    void* context;
    VoidArray registeredParentComps;

public:
    //==============================================================================
    InternalGLContextHolder (OpenGLComponent* const owner_)
        : owner (owner_),
          lastTopLevelComp (0),
          reentrant (false),
          context (0)
    {
        owner->addComponentListener (this);
    }

    virtual ~InternalGLContextHolder()
    {
        owner->removeComponentListener (this);
        release();

        unregisterAsListener();
    }

    //==============================================================================
    void release()
    {
        if (context != 0)
        {
            juce_deleteOpenGLContext (context);
            context = 0;
        }
    }

    void initialise()
    {
        jassert (context == 0);

        if (context == 0)
            context = juce_createOpenGLContext (owner);
    }

    //==============================================================================
    bool makeCurrent() const
    {
        return context != 0 && juce_makeOpenGLContextCurrent (context);
    }

    void swapBuffers() const
    {
        if (context != 0)
            juce_swapOpenGLBuffers (context);
    }

    void repaint() const
    {
        if (context != 0)
            juce_repaintOpenGLWindow (context);
    }

    //==============================================================================
    void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized)
    {
        if (context != 0 && ! reentrant)
        {
            reentrant = true;

            Component* const topComp = owner->getTopLevelComponent();
            jassert (lastTopLevelComp == topComp);

            if (topComp->getNativeWindow() != 0)
            {
                juce_updateOpenGLWindowPos (context, owner, topComp);

                if (makeCurrent())
                    glViewport (0, 0, owner->getWidth(), owner->getHeight());
            }

            reentrant = false;
        }
    }

    void componentVisibilityChanged (Component& component)
    {
        componentParentHierarchyChanged (component);

        if (context != 0)
            owner->resized();
    }

    void componentParentHierarchyChanged (Component& component)
    {
        if (! reentrant)
        {
            reentrant = true;

            Component* const topComp = owner->getTopLevelComponent();

            if (topComp != lastTopLevelComp)
            {
                release();
                lastTopLevelComp = topComp;

                NativeDesktopWindow* topNW = topComp->getNativeWindow();

                if (owner->isShowing() && topNW != 0)
                    initialise();
            }

            unregisterAsListener();

            Component* p = owner->getParentComponent();

            while (p != 0)
            {
                p->addComponentListener (this);
                registeredParentComps.add (p);
                p = p->getParentComponent();
            }

            reentrant = false;

            componentMovedOrResized (component, true, true);
            owner->resized();
        }
    }

private:
    void unregisterAsListener()
    {
        for (int i = registeredParentComps.size(); --i >= 0;)
            ((Component*) registeredParentComps.getUnchecked(i))->removeComponentListener (this);

        registeredParentComps.clear();
    }
};

#4

Great stuff, that fixes the problem.

The only outstanding problem I see is when trying to use this opengl component on another component that is floating on the desktop. The opengl viewport area becomes black until you drag the parent component back onto the main window, where it will re-appear and paint properly.

Any ideas on that? I know that one has been reported before. Possibly something to do with the win32 style bits being set on the native window class?


#5

yes, probably something like that. I’ll have a look when I get a moment.


#6