Persistent layout for multiple windows

Hi,

First of all, thanks for dockingframes, because its an excellent library!

I have an application that uses different windows and loads dockables as mutliplecdockables. I am capable of storing the layout of the application with different windows, but when I try to load the layout (and content), only the layout related to the “main” window is read, so it is the only layout loaded.

Is there an easy way to handle persistent layout for different windows?
In addition, why when calling CControl.load(layout) only the elements of one window are read, even when the whole layout is stored in the same layout name?
Is there a way to store the layout of only one window?

Regards

Can you please explain a bit how you are creating and managing these “different windows”. How do they look like? Because right now I do not fully understand your application - and that makes answering your questions impossible.

For managing all the windows I have used your tutorial for multiple windows, mainly using FocusedWindowProvider. There is one CControl that manages all the windows and capabilities and sync of the application, and one CControl for each window to control the window specific functions (enable / disable editing, titles for example). There is a factory that creates MultipleCDockables and in each CDockable a custom JPanel is added.

We use the application for monitoring / sending commands. The user should be able to view / create as many panels as is allowed to, arrange them in any position or window (specially for multiple monitors); in addition, the user should be able to store different layouts, supporting multiple windows. ie: the user creates 2 windows with 2 multiplecdockables inside each window, then stores the layout; when he launches again the application and loads the layout, the application should load the 2 windows with the 2 panels inside each.

Right now the only issue we have is the storage/load of the layout for multiple windows, because if the user had 2 or more windows, when loading the layout only one window is restored instead of two. Trying to debug I saw that in the layout.xml, everything is stored as desired, but when reading it, only reads the information for one window, not 2, in other words, the function read(layout) from the factory, is only called two times (one for each element inside the first window) but none for the second window.

I use the following function for the factory

@Override
	public UCSMultipleCDockable read(UCSMultipleCDockableLayout layout) {
		String[] info = layout.getId().split("@");
		String panel = info[0];
		String frameName = info[1];
		boolean exists = false;
		UCSFrame frame = null;
		//checks if the frame is already created
		for(UCSFrame ucsFrame : frames){
			if(ucsFrame.getTitle().equals(frameName)){
				exists = true;
				frame = ucsFrame;
			}
		}
		if(!exists){
			this.global.addFrame(adapter);
			frame = frames.get(frames.size()-1);
		}
		return createDockable(panel, frames.indexOf(frame));
	}

In addition I attached the layout.xml

Thanks for your patience!

Hm, I am still not quite certain how all of this fits together. But my initial guess would be that the layout is read before the root-stations are available. If for example you read the layout before creating the windows, then the root-stations for the windows are not yet created - and thus cannot be layouted. (or there is some strange bug in the framework that I am not yet aware of).

To test this theory: if you call “CControl.getStations()” right before loading the layout, are you getting all the stations you would expect? According to the xml file you attached, you should get 11 entries.

Right before loading the layout „test“ (the one attached in my previous post), „CControl.getStations()“ returns only 6 stations


[0]	CExternalizeArea  (id=5264)	
[1]	CContentArea$MinimizeStation  (id=5265)	
[2]	CContentArea$MinimizeStation  (id=5266)	
[3]	CContentArea$MinimizeStation  (id=5267)	
[4]	CContentArea$MinimizeStation  (id=5268)	
[5]	CContentArea$CenterStation  (id=5271)	

And only the last one ([5] CContentArea$CenterStation (id=5271)), has a name identifier, in this case is „CenterStation[id=ccontrol center]“

Is this the expected behaviour?

Thanks for your time again :slight_smile:

When loading a layout-file, the framework iterates over all known root-stations and updates their layouts. Since you have 6 stations registered, the layout of those 6 stations is updated. If other stations are added to a later date, then those other stations are not updated.

What you need to ensure, is that all the stations that are referenced in the layout.xml-file are present before actually loading the file. As I understand you, you are using more than one CControl - one of them is used to create the „windows“. So you would have to ensure that this window-CControl loads the layout first, because the windows contain more root stations?

If that does not help: please provide me a little application with which I can reproduce the issue. Because I am still guessing the innards of your application :wink:

Ok, didn’t know that, now if I have the content area created (in this case in another window) all the saved layout is displayed as desired :).

Now I came up with another problem, is there a way to get the ID of the content areas stored in a specific layout?. So, for the given layout „test“, I would like to get the ID’s „window2“ and „CControl“. Is there in the framework any way to do so, or do I have to search the layout.xml manually?

Thanks for your time :slight_smile:

The layout is saved in a “Settings” object. Hm, I have to search through some code, but that has to wait until the weekend because of some deadlines I have to meet in another project.

Ok, I’ll wait. Thanks again for your time :slight_smile:

I almost forgot the API I wrote… there is a tool called the “Blop” for exactly this kind of question:


import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.perspective.CControlPerspective;
import bibliothek.gui.dock.common.perspective.CControlPerspectiveBlop;
import bibliothek.util.xml.XElement;
import bibliothek.util.xml.XIO;

public class ReadTest {
	public static void main( String[] args ) {
		CControl control = new CControl();
		CControlPerspective perspectives = control.getPerspectives();

		try (InputStream in = new BufferedInputStream( new FileInputStream( "layout.xml" ) )) {
			XElement xlayout = XIO.readUTF( in );
			CControlPerspectiveBlop blop = perspectives.readAllXML( xlayout );
			System.out.println( Arrays.toString( blop.getPerspective().getStationKeys() ) );

			System.out.println( Arrays.toString( blop.getPerspective( "test" ).getStationKeys() ) );
		} catch( IOException e ) {
			e.printStackTrace();
		}
	}
}

Works like a charm, thanks for everything!