First, just wanted to say thanks for providing such a great, open-source docking solution. It looks really nice!
I’m slowly figuring out how things work, using the common library. I had a question about creating a workspace-like panel.
I have a menu of pages that the user can select to open. I want to have a space reserved on the screen where the pages open by default, in a tab group. Once they are open there, the user can choose to dock them wherever the want.
I was able to accomplish this by creating a dockable with a blank JPanel, and then setting the location of any newly opened page to be the same as the location of the JPanel. This works well for getting the pages in the right place; however, this causes an empty tab to appear in the tab group. Is there a better way to accomplish this?
Also, what controls if a dockable is closeable or not? I see the “isCloseable” function where you can query the state, but not a corresponding “setCloseable”.
I think I know what you would like to have, but with the current version of Common this cannot yet be done without very dirty tricks. I hope to allow such things in the final version of 1.0.8, but that version will not be available soon.
The only thing I think could come near to what you want to do is a CWorkingArea. You may try the code below to see if you can use this.
import java.awt.BorderLayout;
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.CLocation;
import bibliothek.gui.dock.common.CWorkingArea;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
public class Dock {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setLayout(new BorderLayout());
final CControl control = new CControl(frame);
frame.add(control.getContentArea(), BorderLayout.CENTER);
final CWorkingArea area = control.createWorkingArea( "area" );
area.setLocation( CLocation.base().normal() );
area.setVisible( true );
JMenuBar bar = new JMenuBar();
JMenu menu = new JMenu( "Menu" );
bar.add( menu );
JMenuItem item = new JMenuItem( "Open" );
item.addActionListener( new ActionListener(){
private int i = 0;
public void actionPerformed( ActionEvent e ){
String id = String.valueOf( i++ );
DefaultSingleCDockable dockable = new DefaultSingleCDockable( id, id );
control.add( dockable );
dockable.setLocation( CLocation.working( area ) );
dockable.setVisible( true );
}
});
menu.add( item );
frame.setJMenuBar( bar );
frame.setVisible(true);
}
}```
Thanks for the sample, Beni. I considered a CWorkingArea, but the problem is that I want the user to be able to move things that are placed in the initial position to anywhere else. The working area restricts things to only be moved around within the working area, right?
I guess I’ll just stick with what i have for now then, and wait for 1.0.8 to come out!
I’m using CGridArea to accomplish this. The main trick is using the getStationLocation() method of the CGridArea. Now the question: is this a legitimate solution?
import java.awt.BorderLayout;
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.CGridArea;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
public class DefaultArea {
public static final float LEFTRIGHT_SPLIT = 0.33f;
public static final float TOPBOTTOM_SPLIT = 0.75f;
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setLayout(new BorderLayout());
final CControl control = new CControl(frame);
frame.add(control.getContentArea(), BorderLayout.CENTER);
final CGridArea area = control.createGridArea( "area" );
final CGridArea leftArea = control.createGridArea( "left" );
final CGridArea bottomRightArea = control.createGridArea( "bottom" );
CGrid grid = new CGrid();
grid.add( 0, 0, LEFTRIGHT_SPLIT*(1/LEFTRIGHT_SPLIT), 3, leftArea);
grid.add( 1, 0, (1-LEFTRIGHT_SPLIT)*(1/LEFTRIGHT_SPLIT), 2, area );
grid.add( 1, 1, (1-LEFTRIGHT_SPLIT)*(1/LEFTRIGHT_SPLIT), 1, bottomRightArea );
control.getContentArea().deploy( grid );
JMenuBar bar = new JMenuBar();
JMenu menu = new JMenu( "Menu" );
bar.add( menu );
JMenuItem item = new JMenuItem( "Open" );
item.addActionListener( new ActionListener(){
private int i = 0;
public void actionPerformed( ActionEvent e ){
String id = String.valueOf( i++ );
DefaultSingleCDockable dockable = new DefaultSingleCDockable( id, id );
control.add( dockable );
dockable.setLocation( area.getStationLocation() );
dockable.setVisible( true );
}
});
menu.add( item );
frame.setJMenuBar( bar );
frame.setVisible(true);
}
}
I tried to implement this solution, and it worked up to a point. I created a grid that had a single grid area in it, and when I open a new page at that area’s getStationLocation it shows up in the right spot. However, if I drag something from the default location to a new dock and then open a new page it no longer opens in the correct position.
keresztg, in your implementation are you only ever having things in the 3 locations mentioned?
Nope. The users can drag panels where they want. Of course this will screw up the initial layout quite a bit. Possibly your target area will shrink to a minimal size or will be hidden.
As a workaround we created a “Restore Views” function which can be used by the user to restore the original layout. I’m also thinking about a custom DockAcceptance class but currently I have no time to investigate the API…