MultiDocumentPanel bug


#1

Hi Jules,

I’ve found a nasty bug in Juce - a fast fix would be really appreciated. :smiley:

  • Create an app with tabbed-based interfaces (I’ve got two different apps that both do this…)
    i.e. based on MultiDocumentPanel …
  • Start the app, add a tab
  • Close one of the tabs - it doesn’t matter which one - the remaining revealed tabbed Window
    displays blank (!) though the tab itself is OK; press that tab to the underlying component
    to be repained properly!
    … simply resizing the container window doesn’t cause the ‘revealed’ tabbed Component to
    repaint (!!)

TIA! :slight_smile:

Pete


#2

Thanks - fixed!


#3

Hi Jules!

Just checking to see if you’ve pushed this to the repo or not - the most recent commit I can see in master is 3 Jun 2013 - “WASPI: used mix format channel mask.” (14ec53de2e5d7e493c973ac0a2b91a8fb912e170)

Once I can pull it, I’ll be very happy to test it for you. :slight_smile:

Best wishes,

Pete


#4

You need to use the new git URL
git clone --depth 1 git://github.com/julianstorer/JUCE.git
and Sourceforge RSS if you use it
http://sourceforge.net/p/juce/code/feed


#5

Wilco!

However, while I get all the code just fine, there is almost no history…?!

This is the only history I get…?!

$ git log
commit a0e292bdaff851bbf9e73f98a4874f5ad57feee6
Author: jules <jules@rawmaterialsoftware.com>
Date:   Tue Jul 9 17:25:04 2013 +0100

    TabbedComponent::removeTab fix.

commit 82d305a2a2d2cd8262512af0c25c9f63a9c10eb7
Author: jules <jules@rawmaterialsoftware.com>
Date:   Tue Jul 9 16:09:28 2013 +0100

    Introjucer: added exporter for VS2013

HTH! :slight_smile:

Pete


#6

Sorry, I now understand.

This truncated history was caused by --depth 1

Panic over. :slight_smile:

Pete


#7

Hi Jules,

I’ve pulled-down the very latest code from the latest repo :slight_smile: … and have stepped through your changes to TabbedButtonBar::removeTab (just to verify that your code changes were pulled-in properly) … but the problem remains.

Let me know if there is anything I can check from my side!

Best wishes,

Pete


#8

Well, I reproduced it in the juce demo widgets page, and fixed it there. If you can give me some test-case code that still fails, I’ll take another look!


#9

Hi Jules,

OK, that gives me some serious hacking around to do, in order to create a test case for you, I guess!

The problem might be related to FileBasedDocument based apps that are based on multi-document panels - which the Jucer Demo isn’t, of course?
Have you got any internal test-bed apps that work like that? It is going to take a lot of work otherwise to get a stripped-down test app for you to build with. :slight_smile:

Pete


#10

Hi Jules,

Good news - I’ve fixed it for you! The fix is here … as you can see, it is pretty trivial.

It’d be great if you could check this in to the main repo!

bool MultiDocumentPanel::closeDocument (Component* component,
                                        const bool checkItsOkToCloseFirst)
{
    if (components.contains (component))
    {
        if (checkItsOkToCloseFirst && ! tryToCloseDocument (component))
            return false;

        component->removeComponentListener (this);

        const bool shouldDelete = MultiDocHelpers::shouldDeleteComp (component);
        component->getProperties().remove ("mdiDocumentDelete_");
        component->getProperties().remove ("mdiDocumentBkg_");

        if (mode == FloatingWindows)
        {
            for (int i = getNumChildComponents(); --i >= 0;)
            {
                if (MultiDocumentPanelWindow* const dw = dynamic_cast <MultiDocumentPanelWindow*> (getChildComponent (i)))
                {
                    if (dw->getContentComponent() == component)
                    {
                        ScopedPointer<MultiDocumentPanelWindow> (dw)->clearContentComponent();
                        break;
                    }
                }
            }

            if (shouldDelete)
                delete component;

            components.removeFirstMatchingValue (component);

            if (isFullscreenWhenOneDocument() && components.size() == 1)
            {
                for (int i = getNumChildComponents(); --i >= 0;)
                {
                    ScopedPointer<MultiDocumentPanelWindow> dw (dynamic_cast <MultiDocumentPanelWindow*> (getChildComponent (i)));

                    if (dw != nullptr)
                        dw->clearContentComponent();
                }

                addAndMakeVisible (components.getFirst());
            }
        }
        else
        {
            jassert (components.indexOf (component) >= 0);

            if (tabComponent != nullptr)
            {
                for (int i = tabComponent->getNumTabs(); --i >= 0;)
                    if (tabComponent->getTabContentComponent (i) == component)
                        tabComponent->removeTab (i);
            }
            else
            {
                removeChildComponent (component);
            }

            if (shouldDelete)
                delete component;

            if (tabComponent != nullptr && tabComponent->getNumTabs() <= numDocsBeforeTabsUsed)
                tabComponent = nullptr;

            components.removeFirstMatchingValue (component);

            if (components.size() > 0 && tabComponent == nullptr)
                addAndMakeVisible (components.getFirst());
        }

        resized();
   
        // MPC Close tab fix... (BEGIN)
        // This ensures that the active tab is painted properly when a tab is closed!
        Component *activeComponent = getActiveDocument();
        if (activeComponent != nullptr) {
            setActiveDocument(activeComponent);
        }
        // MPC Close tab fix... (END)
      
        activeDocumentChanged();
    }
    else
    {
        jassertfalse;
    }

    return true;
}

Best wishes,

Pete


#11

aha! Thanks, will throw that into the pot!


#12

Top man! :wink: