screenDockable

Hi Byte,

I’m sorry to bother you again, There is an interface implementation I would like to ask you when clicking the docking button (Disconnects this panel from the frame) in the stackDockable layout, can I just separate the currently selected tab? Can I change the response event of the docking Button? thanks in advance.

best regards,
Scott.

Hi scott,

The general idea to separate a Dockable from a stack is just to drag&drop the Dockable away.

But… Dockables stick together due to the CGroupBehavior. The behavior can be modified by invoking CControl.setGroupBehavior. I suggest you try out CGroupBehavior.TOPMOST.

If CGroupBehavior.TOPMOST is too heavy, you might want to build your own CGroupBehavior. Depending on the target ExtendedMode you could then forward the calls to CGroupBehavior.TOPMOST or CGroupBehavior.STACKED (=the default behavior).

Let me know if these modifications help your.

Thanks for your answer, it does work.

best regards,
Scott.

Hi Beni,

Solving use this way,I have a small problem that I have not found a way to solve it.
When I dragging a dockable to make it a screenStation, it can be returned to the dragged position when the undocking button is clicked. If it is a stackStation, when you click undocking, they will not all go to the original location in the main window.

public class DMGroupBehavior implements CGroupBehavior {

@Override
public CGroupMovement prepare( LocationModeManager<? extends LocationMode> manager, Dockable dockable, ExtendedMode target ){
    if( isGrouped( dockable, target, manager ) ) {
        return new StackGroupMovement( (StackDockStation)dockable.getDockParent(), dockable, target );
    }
    return new SingleGroupMovement( dockable, target );
}

private boolean isGrouped( Dockable dockable, ExtendedMode target, LocationModeManager<?> manager , boolean ... fal){
    DockStation parent = dockable.getDockParent();
    if( parent instanceof StackDockStation ) {
        for( int i = 0, n = parent.getDockableCount(); i < n; i++ ) {
            if( !manager.isModeAvailable( parent.getDockable( i ), target ) ) {
                return false;
            }
        }
        boolean disConnection = target.getModeIdentifier().equals(ExternalizedMode.IDENTIFIER);
        return true && !disConnection;
    }
    return false;
}

@Override
public Dockable getGroupElement( LocationModeManager<? extends LocationMode> manager, Dockable dockable, ExtendedMode mode ) {
    return getBehaviorForTarget( mode ).getGroupElement( manager, dockable, mode );
}

@Override
public Dockable getReplaceElement( LocationModeManager<? extends LocationMode> manager, Dockable old, Dockable dockable, ExtendedMode mode ) {
    return getBehaviorForTarget( mode ).getReplaceElement( manager, old, dockable, mode );
}

@Override
public boolean shouldForwardActions( LocationModeManager<? extends LocationMode> manager, DockStation station, Dockable dockable, ExtendedMode mode ) {
    return getBehaviorForTarget( mode ).shouldForwardActions( manager, station, dockable, mode );
}

private CGroupBehavior getBehaviorForTarget( ExtendedMode target ) {
    if( target == ExtendedMode.EXTERNALIZED ) {
        return CGroupBehavior.TOPMOST;
    } else {
        return CGroupBehavior.STACKED;
    }
}
}

I tried to modify the dockable back to the main window one by one and I didn’t succeed.

This is a small problem. I just want to use it perfectly.

regards,
Scott.

Just to make sure I understand your idea:

  • The user drags some Dockables to the screen
  • Then he stacks them together
  • He clicks on the “return back to not beeing floating” button, and all the Dockables should separate from the stack and go back to their original place?

I’ll have to test your code. I’ll give you an answer in the next few days.

That’s right. you got my point.

Try out this example. It is just another CGroupBehavior, you can add it to the list of behaviors you already return in getBehaviorForTarget.
The most important thing in this code, is the for loop in th e apply method. It moves one Dockable after each other back to the center area.

package test;

import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.StackDockStation;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.group.CGroupBehavior;
import bibliothek.gui.dock.common.group.CGroupBehaviorCallback;
import bibliothek.gui.dock.common.group.CGroupMovement;
import bibliothek.gui.dock.common.group.SingleGroupMovement;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.facile.mode.LocationMode;
import bibliothek.gui.dock.facile.mode.LocationModeManager;

public class SplitGroupBehaviorTest {
	public static void main( String[] args ) {
		JFrame frame = new JFrame( "Test" );
		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

		CControl control = new CControl( frame );

		// custom behavior for moving around dockables
		control.setGroupBehavior( new SplittingGroupBehavior() );

		frame.add( control.getContentArea() );

		CGrid grid = new CGrid( control );
		grid.add( 0, 0, 1, 1, new DefaultSingleCDockable( "a", "Aaaa" ) );
		grid.add( 0, 1, 1, 1, new DefaultSingleCDockable( "b", "Bbbb" ) );
		grid.add( 1, 0, 1, 1, new DefaultSingleCDockable( "c", "Cccc" ) );
		grid.add( 1, 1, 1, 1, new DefaultSingleCDockable( "d", "Dddd" ) );
		control.getContentArea().deploy( grid );

		frame.setBounds( 50, 50, 1000, 800 );
		frame.setVisible( true );
	}

	public static class SplittingGroupBehavior implements CGroupBehavior {
		@Override
		public CGroupMovement prepare( LocationModeManager<? extends LocationMode> manager, Dockable dockable, ExtendedMode target ) {
			if( isStackedAndExternalized( manager, dockable ) && target == ExtendedMode.NORMALIZED ) {
				// for this test, we are just interested in the action of moving stacked floating dockables back to the
				// normalized mode.
				return new SplittingGroupMovement( dockable.getDockParent() );
			} else {
				return new SingleGroupMovement( dockable, target );
			}
		}

		private boolean isStackedAndExternalized( LocationModeManager<? extends LocationMode> manager, Dockable dockable ) {
			return dockable.getDockParent() instanceof StackDockStation &&
					manager.getCurrentMode( dockable ).getExtendedMode() == ExtendedMode.EXTERNALIZED;
		}

		@Override
		public Dockable getGroupElement( LocationModeManager<? extends LocationMode> manager, Dockable dockable, ExtendedMode mode ) {
			return dockable;
		}

		@Override
		public Dockable getReplaceElement( LocationModeManager<? extends LocationMode> manager, Dockable old, Dockable dockable, ExtendedMode mode ) {
			if( dockable == old )
				return null;
			return old;
		}

		@Override
		public boolean shouldForwardActions( LocationModeManager<? extends LocationMode> manager, DockStation station, Dockable dockable, ExtendedMode mode ) {
			return false;
		}
	}

	private static class SplittingGroupMovement implements CGroupMovement {
		private final DockStation station;

		public SplittingGroupMovement( DockStation station ) {
			this.station = station;
		}

		@Override
		public void apply( CGroupBehaviorCallback callback ) {
			// just iterate through all the dockables. It's like clicking on the "normalize" button mutiple times.
			for( Dockable dockable : dockablesToMove() ) {
				callback.setMode( dockable, ExtendedMode.NORMALIZED );
			}
		}

		private List<Dockable> dockablesToMove() {
			List<Dockable> result = new ArrayList<>();
			for( int i = 0, n = station.getDockableCount(); i < n; i++ ) {
				result.add( station.getDockable( i ) );
			}
			return result;
		}

		@Override
		public boolean forceAccept( DockStation parent, Dockable child ) {
			return true;
		}
	}
}

I use the scheme you gave, there is a small problem, it will only appear in the following situations:

  1. I dragged the Dockable A out and then maximized it.
    2.I dragged the dockable B out and merged it with Dockable A.
    3.clicks on the “return back to not beeing floating” button, Either there is no response or only the selected Dockable returns to the main window.(“Back to the normal size” Button event has the same problem)

Repeat the above problematic operation multiple times, there will be the following exception.

java.lang.IllegalStateException: the parent of 'DefaultCommonDockable[dockable=DefaultSingleCDockable[unique id=single d]]' is not 'bibliothek.gui.dock.common.intern.station.CScreenDockStation@4149c063' but 'null'
at bibliothek.gui.dock.DockHierarchyLock.ensureLinked(DockHierarchyLock.java:342)
at bibliothek.gui.dock.DockHierarchyLock.access$400(DockHierarchyLock.java:45)
at bibliothek.gui.dock.DockHierarchyLock$Token.release(DockHierarchyLock.java:417)
at bibliothek.gui.dock.ScreenDockStation.addDockable(ScreenDockStation.java:1399)
at bibliothek.gui.dock.ScreenDockStation.executeDrop(ScreenDockStation.java:1579)
at bibliothek.gui.dock.ScreenDockStation.drop(ScreenDockStation.java:1455)
at bibliothek.gui.dock.common.mode.station.CScreenDockStationHandle$Maximal.setMaximized(CScreenDockStationHandle.java:388)
at bibliothek.gui.dock.common.mode.station.CScreenDockStationHandle$Maximal.onApply(CScreenDockStationHandle.java:330)
at bibliothek.gui.dock.facile.mode.MaximizedMode.applyStarting(MaximizedMode.java:554)
at bibliothek.gui.dock.facile.mode.MaximizedMode$Listener.applyStarting(MaximizedMode.java:788)
at bibliothek.gui.dock.facile.mode.AbstractLocationMode.apply(AbstractLocationMode.java:401)
at bibliothek.gui.dock.facile.mode.AbstractLocationMode.apply(AbstractLocationMode.java:55)
at bibliothek.gui.dock.support.mode.ModeManager$4.run(ModeManager.java:700)
at bibliothek.gui.dock.support.mode.ModeManager.runTransaction(ModeManager.java:514)
at bibliothek.gui.dock.support.mode.ModeManager.runTransaction(ModeManager.java:493)
at bibliothek.gui.dock.support.mode.ModeManager.apply(ModeManager.java:694)
at bibliothek.gui.dock.facile.mode.LocationModeManager.apply(LocationModeManager.java:376)
at bibliothek.gui.dock.facile.mode.LocationModeManager.apply(LocationModeManager.java:82)
at bibliothek.gui.dock.support.mode.ModeManager.apply(ModeManager.java:625)
at bibliothek.gui.dock.support.mode.ModeManager.apply(ModeManager.java:561)
at bibliothek.gui.dock.support.mode.ModeManager.apply(ModeManager.java:541)
at bibliothek.gui.dock.facile.mode.LocationModeManager$6$1.setMode(LocationModeManager.java:296)
at bibliothek.gui.dock.common.group.SingleGroupMovement.apply(SingleGroupMovement.java:52)
at bibliothek.gui.dock.facile.mode.LocationModeManager$6.run(LocationModeManager.java:294)
at bibliothek.gui.dock.support.mode.ModeManager$3.run(ModeManager.java:476)
at bibliothek.gui.dock.support.mode.ModeManager.runTransaction(ModeManager.java:514)
at bibliothek.gui.dock.support.mode.ModeManager.runTransaction(ModeManager.java:474)
at bibliothek.gui.dock.support.mode.ModeManager.runTransaction(ModeManager.java:455)
at bibliothek.gui.dock.facile.mode.LocationModeManager.apply(LocationModeManager.java:289)
at bibliothek.gui.dock.facile.mode.LocationModeManager$5.run(LocationModeManager.java:265)
at bibliothek.gui.dock.support.mode.ModeManager.runTransaction(ModeManager.java:514)