Thank you so much Beni for the sample application! This is exactly what I was looking for. I still have a couple of questions if you don’t mind.
Question 1:
I tried commenting out the factory, as you pointed, and noticed how it is the factory that is telling the framework to store the meta-information for the dockable with the given id. What I didn’t understand though is the implementation of createBackup. The fact that createGreen() is explicitly called inside grid.add (line 67) and then again inside actionPerformed of the ‚replace‘ button (line 82) made me wonder when would it be called inside createBackup? So I debugged and couldn’t detect any call of the createBackup method. So can you please clarify this point?
Question 2:
I have a mixture of standalone dockables but also dockStations. As you can see, I use CStack and CStackDockStation to create dockStations. I modified the sample application such that one of the dockables becomes a dockStation. I need to implement the same REPLACE behavior on the dockStation. I prepared its own ‚replace‘ button to remove it and add it back. There’s only the factory part for the dockStation that is missing. Can you please tell me what should I do to achieve the same effect as ‚addSingleDockableFactory‘ on my dockStation?
Thanks a lot,
Shant
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.JPanel;
import bibliothek.gui.DockController;
import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.StackDockStation;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.CStation;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.SingleCDockableFactory;
import bibliothek.gui.dock.common.intern.AbstractDockableCStation;
import bibliothek.gui.dock.common.intern.CControlAccess;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.intern.CommonDockable;
import bibliothek.gui.dock.common.intern.station.CommonDockStation;
import bibliothek.gui.dock.common.intern.station.CommonDockStationFactory;
import bibliothek.gui.dock.common.mode.CNormalModeArea;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.common.perspective.CStationPerspective;
import bibliothek.gui.dock.event.DockStationAdapter;
import bibliothek.gui.dock.facile.mode.Location;
import bibliothek.gui.dock.facile.mode.LocationMode;
import bibliothek.gui.dock.facile.mode.ModeAreaListener;
import bibliothek.gui.dock.layout.DockableProperty;
import bibliothek.gui.dock.support.mode.AffectedSet;
import bibliothek.gui.dock.util.DockUtilities;
import bibliothek.util.Path;
public class Dock20 {
private static int count = 0;
public static void main( String[] args ){
JFrame frame = new JFrame();
final CControl control = new CControl( frame );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
// register a factory for "green". This tells the framework, that there can be a dockable
// with id "green", and thus all meta-information needs to be/remain stored.
control.addSingleDockableFactory( "green", new SingleCDockableFactory(){
@Override
public SingleCDockable createBackup( String id ){
//When is this needed?
return createGreen();
}
} );
// This is how you could have the same results with a MissingCDockableStrategy
// control.setMissingStrategy( new MissingCDockableStrategy(){
// @Override
// public boolean shouldStoreSingle( String id ){
// return id.equals( "green" );
// }
//
// @Override
// public boolean shouldStoreMulti( String id ){
// return false;
// }
//
// @Override
// public <L extends MultipleCDockableLayout> boolean shouldCreate( String id, MultipleCDockableFactory<?, L> factory, String uniqueId, L data ){
// return false;
// }
//
// @Override
// public boolean shouldCreate( String id, MultipleCDockableFactory<?, ?> factory ){
// return false;
// }
// } );
frame.add( control.getContentArea() );
CStack stack = createStack(control);
CGrid grid = new CGrid( control );
grid.add( 0, 0, 1, 1, create( "a", "Aaaa" ) );
grid.add( 0, 1, 1, 1, create( "b", "Bbbb" ) );
grid.add( 1, 0, 1, 1, create( "c", "Cccc" ) );
grid.add( 1, 1, 1, 1, create( "d", "Dddd" ) );
grid.add( 3, 0, 1, 1, create( "e", "Eeee" ) );
grid.add( 3, 1, 1, 1, stack );
grid.add( 2, 0, 1, 2, createGreen() );
control.getContentArea().deploy( grid );
JButton replaceGreen = new JButton( "Replace Green Dockable" );
frame.add( replaceGreen, BorderLayout.SOUTH );
replaceGreen.addActionListener( new ActionListener(){
@Override
public void actionPerformed( ActionEvent e ){
// remove the old dockable...
DefaultSingleCDockable green = (DefaultSingleCDockable)control.getSingleDockable( "green" );
green.setVisible( false );
control.removeDockable( green );
// ... create and add the new one
green = createGreen();
control.addDockable( green );
green.setVisible( true );
}
} );
JButton replaceStack = new JButton( "Replace Stack" );
frame.add( replaceStack, BorderLayout.NORTH );
replaceStack.addActionListener( new ActionListener(){
@Override
public void actionPerformed( ActionEvent e ){
CStack stack = (CStack)control.getStation("dockStation");
stack.setVisible(false);
control.removeDockable(stack);
control.remove(stack.asStation());
stack = createStack(control);
control.addDockable(stack);
stack.setVisible(true);
}
} );
frame.setBounds( 20, 20, 400, 400 );
frame.setVisible( true );
}
private static DefaultSingleCDockable createGreen(){
DefaultSingleCDockable green = new DefaultSingleCDockable( "green", "Green " + count );
count++;
JPanel panel = new JPanel();
panel.setOpaque( true );
panel.setBackground( Color.GREEN );
green.add( panel );
return green;
}
private static CStack createStack(CControl control){
CStack stack = new CStack("dockStation");
control.addStation(stack, true);
SingleCDockable tab1 = create( "tab1", "tab1" );
stack.getStation().add(tab1.intern(), 0);
SingleCDockable tab2 = create( "tab2", "tab2" );
stack.getStation().add(tab2.intern(), 1);
return stack;
}
private static SingleCDockable create(String key, String title){
DefaultSingleCDockable dockable = new DefaultSingleCDockable( key, title );
return dockable;
}
static class CStack extends AbstractDockableCStation<CStackDockStation> implements CNormalModeArea, SingleCDockable {
private boolean hideIfEmpty;
public CStack(String id) {
CStackDockStation delegate = new CStackDockStation(this);
CLocation stationLocation = new CLocation() {
@Override
public CLocation getParent() {
return null;
}
@Override
public String findRoot() {
return getUniqueId();
}
@Override
public DockableProperty findProperty(DockableProperty successor) {
return successor;
}
@Override
public ExtendedMode findMode() {
return ExtendedMode.NORMALIZED;
}
@Override
public CLocation aside() {
return this;
}
};
init(delegate, id, stationLocation, delegate);
}
public void setHideIfEmpty(boolean hideIfEmpty) {
this.hideIfEmpty = hideIfEmpty;
}
@Override
public CStationPerspective createPerspective() {
throw new IllegalStateException("not implemented");
}
@Override
public boolean isNormalModeChild(Dockable dockable) {
return isChild(dockable);
}
@Override
public DockableProperty getLocation(Dockable child) {
return DockUtilities.getPropertyChain(getStation(), child);
}
@Override
public void setLocation(Dockable dockable, DockableProperty location, AffectedSet set) {
set.add(dockable);
if (isChild(dockable)) {
getStation().move(dockable, location);
} else {
if (!getStation().drop(dockable, location)) {
getStation().drop(dockable);
}
}
}
@Override
public void addModeAreaListener(ModeAreaListener listener) {
}
@Override
public Path getTypeId() {
return null;
}
@Override
public boolean autoDefaultArea() {
return true;
}
@Override
public boolean isChild(Dockable dockable) {
return dockable.getDockParent() == getStation();
}
@Override
public void removeModeAreaListener(ModeAreaListener listener) {
}
@Override
public void setController(DockController controller) {
}
@Override
public void setMode(LocationMode mode) {
}
@Override
public CLocation getCLocation(Dockable dockable) {
DockableProperty property = DockUtilities.getPropertyChain(getStation(), dockable);
return getStationLocation().expandProperty(property);
}
@Override
public CLocation getCLocation(Dockable dockable, Location location) {
DockableProperty property = location.getLocation();
if (property == null) {
return getStationLocation();
}
return getStationLocation().expandProperty(property);
}
@Override
public boolean respectWorkingAreas() {
return false;
}
@Override
public boolean isCloseable() {
return false;
}
@Override
public boolean isExternalizable() {
return false;
}
@Override
public boolean isMaximizable() {
return false;
}
@Override
public boolean isMinimizable() {
return false;
}
@Override
public boolean isStackable() {
return false;
}
@Override
public boolean isWorkingArea() {
return false;
}
public boolean hideIfEmpty() {
return hideIfEmpty;
}
public DockActionSource[] getSources() {
return new DockActionSource[] { getClose() };
}
@Override
protected void install(CControlAccess access) {
access.getLocationManager().getNormalMode().add(this);
}
@Override
protected void uninstall(CControlAccess access) {
access.getLocationManager().getNormalMode().remove(getUniqueId());
}
}
static class CStackDockStation extends StackDockStation implements CommonDockStation<StackDockStation, CStackDockStation>, CommonDockable {
private CStack delegate;
public CStackDockStation(CStack stack) {
this.delegate = stack;
final Runnable makeVisible = new Runnable() {
@Override
public void run() {
delegate.setVisible(true);
}
};
DockUtilities.disableCheckLayoutLocked();
addDockStationListener(new DockStationAdapter() {
@Override
public void dockableAdded(DockStation station, Dockable dockable) {
DockController controller = delegate.getControl().getController();
controller.getHierarchyLock().onRelease(makeVisible);
}
});
}
@Override
public CDockable getDockable() {
return delegate;
}
@Override
public DockActionSource[] getSources() {
return delegate.getSources();
}
@Override
public CStation<CStackDockStation> getStation() {
return delegate;
}
@Override
public StackDockStation getDockStation() {
return this;
}
@Override
public CStackDockStation asDockStation() {
return this;
}
@Override
public CommonDockable asDockable() {
return this;
}
@Override
public String getConverterID() {
return super.getFactoryID();
}
@Override
public String getFactoryID() {
return CommonDockStationFactory.FACTORY_ID;
}
}
}```