Disable drag and drop to/from ScreenDockStation

I am trying to disable drag and drop of dockables into and out of the ScreenDockStation. My customer has requested that the externalize button must explicitly be pressed to move a dockable out of the main application frame, and the unexternalize button must be pressed to return the dockable to the application frame.

I was able to disable dragging out of the ScreenDockStation using the following code:


CControl dockControl = new CControl(frame);
dockControl.putProperty(ScreenDockStation.WINDOW_CONFIGURATION, (screenDockStation, dockable) -> {
	WindowConfiguration config = new WindowConfiguration();
	config.setMoveOnTitleGrab(true);
	config.setMoveOnBorder(false);
	config.setAllowDragAndDropOnTitle(false);
	return config;
});

However, I have not found a way to disable drag and drop into the ScreenDockStation without disabling dockables from being accepted to that location at all via DockAcceptance. Any help would be appreciated.

DockAcceptance is probably not going to help, because a DockAcceptance is a very hard boundary. The “VetoableDockRelocatorListener” on the other hand is only called during drag and drop operations, and hence should be the right place to prevent unwanted drag and drop operations. The listener will not be triggered if the user clicks a button. The listener can suppress events from happening by calling “event.forbid”, in the example below we forbid any event that would change the “floating” state of a Dockable.


import javax.swing.JFrame;

import bibliothek.gui.Dockable;
import bibliothek.gui.dock.DockElement;
import bibliothek.gui.dock.ScreenDockStation;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.control.relocator.DockRelocatorEvent;
import bibliothek.gui.dock.control.relocator.VetoableDockRelocatorAdapter;

public class DisableMoveTo {
	public static void main(String[] args) {
		JFrame frame = new JFrame("Title");
		CControl control = new CControl(frame);
		frame.add(control.getContentArea());
		
		
		DefaultSingleCDockable d1 = new DefaultSingleCDockable("id", "Hello");
		DefaultSingleCDockable d2 = new DefaultSingleCDockable("id2", "Hello2");
		control.addDockable(d1);
		control.addDockable(d2);
		d1.setVisible(true);
		d2.setVisible(true);
	
		control.getController().getRelocator().addVetoableDockRelocatorListener(new VetoableDockRelocatorAdapter() {
			@Override
			public void searched(DockRelocatorEvent event) {
				boolean dockableExt = isExt(event.getDockable());
				boolean stationExt = isExt(event.getTarget());
				
				if( dockableExt != stationExt ){
					event.forbid();
				}
			}
			
			private boolean isExt(DockElement element){
				if( element == null){
					return false;
				}
				
				if( element.asDockStation() instanceof ScreenDockStation ){
					return true;
				}
				Dockable dockable = element.asDockable();
				return dockable != null && isExt(dockable.getDockParent());
			}
		});
		
		frame.setBounds(200, 200, 1000, 1000);
		frame.setVisible(true);
	}
}

*** Edit ***

You could also use the VetoableDockRelocatorListener to find out when a drag and drop operation starts/stops, and enable/disable the DockAcceptance you already wrote. I guess the UI would look a bit better, because that would stop the framework from creating unwanted events in the first place. Calling “forbid” basically says to the framework “forget the last MouseEvent”, a DockAcceptance however says “do something else with the MouseEvent”, where “something else” could mean “select another parent for the Dockable”.