CControl read/write layout file problem

Hi Byte,

I meet a problem with restore layout. If the user has three Dockables, the first time the main window is opened normally, I will save the current layout to the file when I close the main window. When the administrator modifies the privileges, the current user can see the contents of the four Dockables, there is no problem with the initial loading, and the four Dockables are loaded into the CControl. When I call the CControl.readXML() method to restore, There is a problem: it will make only three Dockables visible in the main window, and the other one is already in the Dockable CControl, but it is not displayed.

How do I make that hidden Dockable visible or incremental restore interface layout?

Best regards,
Scott.

1 „Gefällt mir“

I would just check if this 4th Dockable is visible or not, and make it visible.

In the example below I used setLocationAside to ensure the missing Dockable is displayed at the same location as some other “friendly Dockable” (I’m assuming some Dockables are usually grouped together).

package test;

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

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.perspective.CContentPerspective;
import bibliothek.gui.dock.common.perspective.CControlPerspective;
import bibliothek.gui.dock.common.perspective.CGridPerspective;
import bibliothek.gui.dock.common.perspective.CPerspective;
import bibliothek.gui.dock.common.perspective.SingleCDockablePerspective;

public class PermissionsTest {
	public static void main( String[] args ) {
		new PermissionsTest();
	}

	private JFrame frame = new JFrame( "Test" );
	private DefaultSingleCDockable friend = new DefaultSingleCDockable( "c", "Cccc" );
	private DefaultSingleCDockable dockable = new DefaultSingleCDockable( "d", "Dddd" );
	private CControl control;

	public PermissionsTest() {
		control = new CControl( frame );
		frame.setContentPane( control.getContentArea() );
		frame.setBounds( 20, 20, 1000, 1000 );

		CGrid grid = new CGrid( control );
		grid.add( 0, 0, 1, 1, new DefaultSingleCDockable( "a", "Aaaa" ) );
		grid.add( 0, 0, 1, 1, new DefaultSingleCDockable( "b", "Bbbb" ) );
		grid.add( 1, 0, 1, 1, friend );
		grid.add( 1, 0, 1, 1, dockable );
		control.getContentArea().deploy( grid );

		addMenuBar();

		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		frame.setVisible( true );
	}

	private void addMenuBar() {
		JMenuBar bar = new JMenuBar();
		frame.setJMenuBar( bar );

		JMenu menu = new JMenu( "Testing" );
		bar.add( menu );

		JMenuItem issue = new JMenuItem( "Load layout without repair" );
		menu.add( issue );
		issue.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent e ) {
				loadBaseLayout( false );
			}
		} );

		JMenuItem fix = new JMenuItem( "Load layout and repair" );
		menu.add( fix );
		fix.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent e ) {
				loadBaseLayout( true );
				repair();
			}
		} );
	}

	private CPerspective baseLayout() {
		CControlPerspective perspectives = control.getPerspectives();
		CPerspective perspective = perspectives.createEmptyPerspective();

		CContentPerspective contentArea = perspective.getContentArea();
		CGridPerspective center = contentArea.getCenter();
		center.gridAdd( 0, 0, 1, 1,
				new SingleCDockablePerspective( "a" ),
				new SingleCDockablePerspective( "b" ) );
		center.gridAdd( 0, 1, 1, 1,
				new SingleCDockablePerspective( "c" ) );

		center.gridDeploy();

		return perspective;
	}

	private void loadBaseLayout( boolean withPlaceholder ) {
		control.getPerspectives().setPerspective( baseLayout(), true );
	}

	/*
	 * Here we make the missing dockable visible
	 */
	private void repair() {
		if( !dockable.isVisible() ) {
			// just inherit the locations from another dockable
			dockable.setLocationsAside( friend );
			dockable.setVisible( true );
		}
	}
}

You could also use try using the DockableGrouping to access any placeholder that is still stored in the layout file. But this will only work if the Dockable was visible at least once (because otherwise the layout does not contain any placeholders).

Hm… It is an option but not a good one. We are misusing the grouping-feature. I would recommend using the solution from my first answer.

package test;

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

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.grouping.PlaceholderGrouping;
import bibliothek.gui.dock.common.intern.CPlaceholderStrategy;
import bibliothek.util.xml.XElement;

public class PermissionsTest {
	public static void main( String[] args ) {
		new PermissionsTest();
	}

	private JFrame frame = new JFrame( "Test" );
	private DefaultSingleCDockable friend = new DefaultSingleCDockable( "c", "Cccc" );
	private DefaultSingleCDockable dockable = new DefaultSingleCDockable( "d", "Dddd" );
	private CControl control;

	private XElement layout;

	public PermissionsTest() {
		control = new CControl( frame );
		frame.setContentPane( control.getContentArea() );
		frame.setBounds( 20, 20, 1000, 1000 );

		CGrid grid = new CGrid( control );
		grid.add( 0, 0, 1, 1, new DefaultSingleCDockable( "a", "Aaaa" ) );
		grid.add( 0, 0, 1, 1, new DefaultSingleCDockable( "b", "Bbbb" ) );
		grid.add( 1, 0, 1, 1, friend );
		grid.add( 1, 0, 1, 1, dockable );
		control.getContentArea().deploy( grid );

		addMenuBar();

		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		frame.setVisible( true );
	}

	private void addMenuBar() {
		JMenuBar bar = new JMenuBar();
		frame.setJMenuBar( bar );

		JMenu menu = new JMenu( "Testing" );
		bar.add( menu );

		JMenuItem hide = new JMenuItem( "1. Remove permission" );
		menu.add( hide );
		hide.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent e ) {
				hide();
			}
		} );

		JMenuItem save = new JMenuItem( "2. Save" );
		menu.add( save );
		save.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent e ) {
				save();
			}
		} );

		JMenuItem load = new JMenuItem( "3. Load" );
		menu.add( load );
		load.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent e ) {
				load();
			}
		} );

		JMenuItem show = new JMenuItem( "4. Add permission" );
		menu.add( show );
		show.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent e ) {
				show();
			}
		} );
	}

	private void save() {
		layout = new XElement( "layout" );
		control.writeXML( layout );
	}

	private void load() {
		control.readXML( layout );
	}

	private void hide() {
		dockable.setVisible( false );
	}

	private void show() {
		if( !dockable.isVisible() ) {
			// by setting the grouping behavior we make the dockable visible at the placeholder that is still stored in the layout
			dockable.setGrouping( new PlaceholderGrouping( control, CPlaceholderStrategy.getSingleDockablePlaceholder( "d" ) ) );
			dockable.setVisible( true );
			dockable.setGrouping( null );
		}
	}
}

thanks a lot.

regards,
Scott.