Cache locations?

Hi,
i did a application which consists of many dockables. I also save the layout into a string to have the same layout when the application starts up.
My problem is that the dockables which got closed before saving, do not show up at the same position they were shown on the previous startup if i choose to show them again.
Is there any way to cache the locations of closed dockables and apply them at the next startup of the application?

Thanks for any help!
Greetings -chris-

Depends on what exactly you are doing.

As long as a Dockable remains registered at a CControl its position remains in memory, even if the Dockable is not visible (calling CControl.remove or DockFrontend.remove clears the position).
This position information gets stored if you use one of the standard methods to create your config-file, like CControl.writeXML.

If you load the layout this information gets loaded if

  • the Dockable is known to the CControl (you called “add”),
    or if
  • you added a SingleCDockableBackupFactory to the CControl
    or if
  • you did set a MissingCDockableStrategy which tells the CControl explicitly to store the information.

Did you do any of these things? How do you store the layout exactly?

Hi Beni,
thanks for your reply!

I load the perspective as follows on an application start


XElement xml = XIO.read(new StringReader(userProfile.getPerspectiveXML()));
m_dockControl.readXML(xml);
m_dockControl.load("current");

and i also registered a SingleCDockableBackupFactory.
But i don’t now how to apply the MissingCDockableStrategy, maybe this is the missing link.
Can you provide a small example on how to use this MissingCDockableStrategy?
Many thanks in advance.

Greetings, -chris-

Could you please post the xml-file itself? It may contain valuable information. I would also need to know the id (key) of some of the Dockables whose location does not get cached.

You can try calling “m_dockControl.setMissingStrategy( MissingCDockableStrategy.STORE );” directly after you created your “CControl”. This will tell “m_dockControl” not to throw away any layout information. If this does not help, then the layout information never got stored in the first place.

I wrote some small application to check and make absolutely sure that location-caching works - yes it does.

Would you please copy the following lines (line 66 to 82 in my test application) to your application and:
[ul]
[li]Replace the keys “red”, “green”, etc… in the array by keys used by your application.
[/li][li]Call the code directly before “m_dockControl.load(“current”);” and again directly after. What is the output?
[/li][/ul]

Lines to copy:

    	 * Print out the position of a few selected Dockables. Only invisible Dockables
    	 * will print out something else than "null null" 
    	 */
        DockFrontend frontend = control.intern();
        String[] keys = new String[]{ "red", "green", "blue", "yellow" };
        
        for( String key : keys ){
        	DefaultCControlRegister register = (DefaultCControlRegister) control.getRegister();
        	key = register.toSingleId( key );
        	FrontendEntry entry =  frontend.getFrontendEntry( key );
        	if( entry == null ){
        		System.out.println( key + ": missing" );
        	}
        	else{
        		System.out.println( key + ": " + entry.getRoot() + " " + entry.getLocation() );
        	}
        }
        /*
         * End printing
         */```

Entire application
```package test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;

import bibliothek.gui.DockFrontend;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.intern.DefaultCControlRegister;
import bibliothek.gui.dock.common.menu.SingleCDockableListMenuPiece;
import bibliothek.gui.dock.facile.menu.RootMenuPiece;
import bibliothek.gui.dock.frontend.FrontendEntry;
import bibliothek.util.xml.XElement;

public class Dock12 extends JFrame{

    public static void main(String[] args) {
        JFrame frame = new Dock12( null );
        frame.setVisible( true );
    }
    
    private CControl control;
    
    public Dock12(XElement xml){
    	JButton reload = new JButton( "Reload" );
    	reload.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent e ){
				reload();
			}
		});
    	
    	add(reload, BorderLayout.SOUTH);
    	load( xml );
    	
    	JMenuBar bar = new JMenuBar();
    	RootMenuPiece menu = new RootMenuPiece( "Layout", true );
    	menu.add( new SingleCDockableListMenuPiece( control ) );
    	bar.add( menu.getMenu() );
    	setJMenuBar( bar );
    	
    	setSize( 600, 500 );
    	setDefaultCloseOperation( EXIT_ON_CLOSE );
    }
    
    private void load(XElement xml){
    	control = new CControl( this );
    	getContentPane().add( control.getContentArea() );
    	loadInitialLayout();
    	
    	if( xml != null ){
    		control.readXML( xml );
    	}
    	
    	/*
    	 * Print out the position of a few selected Dockables. Only invisible Dockables
    	 * will print out something else than "null null" 
    	 */
        DockFrontend frontend = control.intern();
        String[] keys = new String[]{ "red", "green", "blue", "yellow" };
        
        for( String key : keys ){
        	DefaultCControlRegister register = (DefaultCControlRegister) control.getRegister();
        	key = register.toSingleId( key );
        	FrontendEntry entry =  frontend.getFrontendEntry( key );
        	if( entry == null ){
        		System.out.println( key + ": missing" );
        	}
        	else{
        		System.out.println( key + ": " + entry.getRoot() + " " + entry.getLocation() );
        	}
        }
        /*
         * End printing
         */
    }

    private void reload(){
    	XElement xml = null;
    	
    	if( control != null ){
    		xml = new XElement( "settings" );
    		control.writeXML( xml );
    		getContentPane().remove( control.getContentArea() );
    		control.destroy();
    		setVisible( false );
    	}
    	
    	Dock12 dock = new Dock12( xml );
    	dock.setVisible( true );
    }

    private void loadInitialLayout(){
    	CGrid grid = new CGrid( control );
    	grid.add(  0,  0, 10, 10, get( "red", Color.RED ) );
    	grid.add(  0, 10, 10, 10, get( "green", Color.GREEN ) );
    	grid.add( 10,  0, 10, 10, get( "blue", Color.BLUE ) );
    	grid.add( 10, 10, 10, 10, get( "yellow", Color.YELLOW ) );
    	control.getContentArea().deploy( grid );
    }
    
    private DefaultSingleCDockable get(String id, Color color){
    	JPanel panel = new JPanel();
    	panel.setBackground( color );
    	panel.setOpaque( true );
    	
    	DefaultSingleCDockable result = new DefaultSingleCDockable( id, id, panel );
    	result.setCloseable( true );
    	return result;
    }
}

Hi Beni,
i pasted your code as you described. Here’s the outcome


###Before calling dockControl.load("current");###
single library: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f
single main: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f
single remote: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f
single rfb: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@3e1
single srv: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f
single tvcontrol: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f
single cfg: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f
single sched: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f

###After calling dockControl.load("current");###
single library: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f
single main: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f
single remote: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f
single rfb: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@3e1
single srv: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f
single tv: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f
single cfg: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f
single sched: ccontrol center bibliothek.gui.dock.station.split.SplitDockPlaceholderProperty@1f

So i guess, that the locations are cached. I then took a deeper look into my code and saw, that if the view is not shown i do a
view.setLocation(view.getPreferredLocation());
I commented this line and now the dockables get restored where i closed them, even after a restart of my application.
So this was my fault. I’m very sorry for that.

Thanks again very much for all your help!!
Greetings, -chris-

Well… such things happen to all of us :smiley: