Cannot close dockable which appears before focused dockable

Hi,

I too ran into a while trying to hide a dockable which appears in a StackDockStation. I can reproduce this issue in DockingFrames version 1.0.6 preview release 2 as well as version 1.0.7 preview.

I think the issue may be in StackDockStation in the method
private void remove( int index, boolean fire ).

Run the code below, and select ‘workspace’ from the ‘Views’ menu to hide a dockable called ‘workspace’ and you will see a NullPointerException.

package tmp.test.docking;

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import bibliothek.gui.DockFrontend;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.DefaultDockable;
import bibliothek.gui.dock.SplitDockStation;
import bibliothek.gui.dock.station.split.SplitDockPathProperty;
import bibliothek.gui.dock.themes.BasicTheme;
import bibliothek.gui.dock.themes.NoStackTheme;

public class TestHidingStackDockComponent
{
    
    private static final String ROOT_DOCKING_STATION = "rootDockingStation";
    
    private Dockable _workspaceDockable;
    private Dockable _logDockable;
    private Dockable _dataDockable;
    
    private DockFrontend _frontend;
        
    /**
     * @param args
     */
    public static void main(String[] args)
    {
        final TestHidingStackDockComponent tdr = new TestHidingStackDockComponent();
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                JFrame frame = tdr.getFrame();
                frame.setJMenuBar(tdr.getMenuBar());
                JPanel mainPanel = new JPanel();
                mainPanel.setLayout(new BorderLayout());
                mainPanel.add(tdr.initUI(), BorderLayout.CENTER);
                frame.getContentPane().add(mainPanel);
                frame.setVisible(true);                
                frame.validate();                
            }            
        });
    }
    
    private JMenuBar getMenuBar()
    {
        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("Views");
        JCheckBoxMenuItem workspace = new JCheckBoxMenuItem("workspace", true);
        JCheckBoxMenuItem log = new JCheckBoxMenuItem("log", true);        
        JCheckBoxMenuItem data = new JCheckBoxMenuItem("data", true);
        createAndAddChangeListener(workspace, _workspaceDockable);
        createAndAddChangeListener(log, _logDockable);
        createAndAddChangeListener(data, _dataDockable);
        menu.add(workspace);
        menu.add(log);
        menu.add(data);
        menuBar.add(menu);
        return menuBar;
    }
    
    private JComponent initUI()
    {
        _frontend = getFrontend();
        SplitDockStation rootDockStation = new SplitDockStation();
        _frontend.addRoot(rootDockStation, ROOT_DOCKING_STATION);
        
        //create dockable components
        Dockable emptyDockable = createDockable("Empty Dockable");
        _workspaceDockable = createDockable("Workspace");        
        _logDockable = createDockable("Log");
        _dataDockable = createDockable("Data");                
        
        //place them in appropriate areas                
        rootDockStation.drop(emptyDockable);

        SplitDockPathProperty workspaceSdpp = new SplitDockPathProperty();
        workspaceSdpp.add(SplitDockPathProperty.Location.BOTTOM, 0.7);
        rootDockStation.drop(_workspaceDockable, workspaceSdpp);
        
        SplitDockPathProperty logSdpp = new SplitDockPathProperty();
        logSdpp.add(SplitDockPathProperty.Location.BOTTOM, 0.7);
        rootDockStation.drop(_logDockable, logSdpp);
        
        SplitDockPathProperty dataSdpp = new SplitDockPathProperty();
        dataSdpp.add(SplitDockPathProperty.Location.BOTTOM, 0.7);
        rootDockStation.drop(_dataDockable, dataSdpp);
        
        _frontend.hide(emptyDockable);
        
        return (JComponent)rootDockStation.getComponent();
    }
    
    private DockFrontend getFrontend()
    {
        DockFrontend frontend = new DockFrontend();
        frontend.getController().setTheme(new NoStackTheme(new BasicTheme()));
        return frontend;
    }

    private JFrame getFrame()
    {
        JFrame frame = new JFrame();
        frame.setSize(new Dimension(600, 400));
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        return frame;
    }
    
    private Dockable createDockable(String name)
    {
        JPanel panel = new JPanel();
        panel.add(new JLabel(name));
        Dockable dockable = new DefaultDockable(panel, name);
        _frontend.add(dockable, name);
        return dockable;
    }
    
    private void createAndAddChangeListener(JMenuItem menuItem, final Dockable dockableToHide)
    {
        menuItem.addChangeListener(new ChangeListener(){
            @Override
            public void stateChanged(ChangeEvent e)
            {
                if(!((JCheckBoxMenuItem)e.getSource()).getState())
                {
                    _frontend.hide(dockableToHide);
                }    
            }            
        });
    }
}



Thanks & Regards
Parag Shah

As I understand the mail you sent me, the preview 1 of 1.0.7 solves this problem?

But I’am thankful for your code anyway, I could never reproduce the error reliable. Maybe this helps to root out the problem, not just to supress the symptoms.