How to save layout including floating dockables?

Hello,
I just started to use DockingFrames and in the mean time everything is going well (thank you for the great software :slight_smile: ), but there is some problem that I don’t know how to solve. I was able to save and restore the layout, but I’m unable to find a way to restore dockables that were floating at the moment of saving. Below is an example of what I’m doing. I will appreciate if you’ll help me to solve this issue.

Best Regards,
Maxim Golubitsky

import bibliothek.gui.DockStation;
import bibliothek.gui.dock.DefaultDockable;
import bibliothek.gui.dock.ScreenDockStation;
import bibliothek.gui.dock.SplitDockStation;
import bibliothek.gui.dock.StackDockStation;
import bibliothek.gui.dock.layout.PredefinedDockSituation;
import bibliothek.gui.dock.station.screen.ScreenDockStationFactory;
import bibliothek.gui.dock.station.split.SplitDockProperty;
import bibliothek.util.xml.XElement;
import bibliothek.util.xml.XIO;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class Test extends JFrame{

    DockController controller = new DockController();
    SplitDockStation splitDockStation = new SplitDockStation();
    PredefinedDockSituation dockSituation = new PredefinedDockSituation();
    ScreenDockStation screenDockStation;

    public Test() throws HeadlessException {
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        controller.setRootWindow( this );
        dockSituation.put("root", splitDockStation );
        screenDockStation = new ScreenDockStation( controller.getRootWindowProvider() );
        controller.add( screenDockStation );
        screenDockStation.setShowing( true );
        dockSituation.add( new ScreenDockStationFactory( this ));

        controller.add( splitDockStation );
        add( splitDockStation, BorderLayout.CENTER );
        MyDockable dockable = new MyDockable( "Test1" );
        splitDockStation.drop( dockable, SplitDockProperty.NORTH );
        dockSituation.put("Test1", dockable);

        StackDockStation stackDockStation = new StackDockStation();
        splitDockStation.drop( stackDockStation, SplitDockProperty.SOUTH );
        for(int i = 2; i < 5; i++){
            String name = "Test" + i;
            dockable = new MyDockable( name );
            stackDockStation.drop( dockable );
            dockSituation.put(name, dockable);
        }
        createMenu();
        setSize(300, 400);
    }

    public static void main(String[] args) {
        new Test().setVisible( true );
    }

    private void save(){
        try{
            Map<String , DockStation> map = new HashMap<String , DockStation>();
            map.put( "root", splitDockStation );
            map.put( "floating", screenDockStation );

            XElement xlayout = new XElement( "layout" );
            dockSituation.writeXML(map, xlayout);

            FileOutputStream out = new FileOutputStream( "C:\\layout.xml" );
            XIO.writeUTF( xlayout, out );
            out.close() ;
        }
        catch( IOException ex ){
            ex.printStackTrace() ;
        }
    }

    private void load(){
        try{
            XElement xroot = XIO.read( new FileReader("C:\\layout.xml") );
            dockSituation.readXML(xroot);
        }
        catch( IOException ex ){
            ex.printStackTrace();
        }
    }

    private void createMenu(){
        JMenuBar menuBar = new JMenuBar();
        setJMenuBar( menuBar );
        JMenu menu = new JMenu("File");
        menuBar.add(menu);
        Action saveAction = new AbstractAction( "Save" ) {
            public void actionPerformed(ActionEvent e) {
                save();
            }
        };
        menu.add( new JMenuItem( saveAction ) );
        Action loadAction = new AbstractAction( "Load" ) {
            public void actionPerformed(ActionEvent e) {
                load();
            }
        };
        menu.add( new JMenuItem( loadAction ) );
    }

    class MyDockable extends DefaultDockable{

        MyDockable( String title ){
            super( title );
            add( new JLabel(title) );
        }
    }
}```

In this example all you need to do is to add one line of code at line 35/36:
dockSituation.put( "screen", screenDockStation );

Currently a new ScreenDockStation is created every time you load the layout, and this station is completely ignored by your example and by the framework. With the code above the existing station is reused, and the Dockables appear.

You might also consider using a DockFrontend (offers some methods to make life easier) or the Common project. The Common project is a wrapper and adds a lot of functionality, like buttons to minimize a Dockable, or automatic storage of the location of Dockables.

Thank you very much, it is working now :smiley:
Maybe you can add this example to your tutorial? I think it can help to people like me.
It is pretty easy to get lost in this world of Dockables and Stations :wink:
With regard to the Common project since I develop a web project I’m trying to keep it lightweight.
Maybe later if I’ll see that I miss some must-have functionality…
And thank you again for the fast response.