Common - finding dockables positioned relative to dockable

Using the common API, is there a way to get the list of all dockables that are strictly on some side of some dockable? In my application, where a main window is surrounded by dockables, I’d like to be able to hide all dockables that are strictly on either side of the main window, e.g. all dockables whose left x coordinate is larger than the right x coordinate of the main window.
I guess I can iterate all dockables in the system and check for this, but is there a better way using the layout information?

Ask the CContentArea for its SplitDockStation and analyze its tree (SplitDockStation#getRoot). That is however not far away from testing all Dockables.

I tried to do this (checking the position of one component relative to another) using the JComponent’s x,y,width and height properties. To calculate the x&y I wrote a loop that adds all the parents’ x & y until the topmost parent.

I encountered a strange situation in which a window that was docked at the bottom had a ‘y’ coordinate that was smaller than the main window’s y + height. I don’t understand how this can happen.

Nevertheless, I need to be able to know which side of the main window a dockable is docked. How can I get this info from the CLocation? (i.e. how to I compare the CLocation of the main window with the CLocation of the dockable to find which side of the main window the dockable is located?)

Thanks,
Shlomy

I encountered a strange situation in which a window that was docked at the bottom had a ‚y‘ coordinate that was smaller than the main window’s y + height. I don’t understand how this can happen.

If it was not visible then its boundaries might not be updated.

CLocation: you could transform it into a DockableProperty (using the method „findProperty“). Then search for SplitDockProperty and SplitDockPathProperty (the later can be transformed into a SplitDockProperty using „toLocation“), finally analyse its content…

Something like this:

DockableProperty dp = location.findProperty();
if( dp instanceof SplitDockPathProperty )
  dp = ((SplitDockPathProperty)dp).toLocation();

if( dp instanceof SplitDockProperty ){
  double x = ((SplitDockProperty)dp).getX();  // value between 0 and 1 !!
  ...
}```

Thanks. I found out that my computation of the x,y of the dockable was done incorrectly. After fixing it, it seems to be working fine. I don’t want to get into the DockingFrames layout, since I need to learn a lot for that.

Sorry, I was wrong. Even the new way to compute x,y does not always work.
I don’t understand how I can find out from your example the relative position between two CDockables a & b. What do the x/y between 0 and 1 in your example indicate?
Can you give me a sample code, for example, that returns true if CDockable ‘a’ is on the left of CDockable ‘b’? (By ‘on the left’, I mean that the rightmost pixel of dockable ‘a’ is on the left of the leftmost pixel of dockable ‘b’, i.e. “a.right < b.left”.

Sure. The x/width-values are the relative coordinates of the dockables on the SplitDockStation (relative coordinates: where the Dockables would be, would the station have a size of 1/1). In the example below “a” is left of “b1” and “b2”.


import javax.swing.JFrame;

import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.layout.DockableProperty;
import bibliothek.gui.dock.station.split.SplitDockPathProperty;
import bibliothek.gui.dock.station.split.SplitDockProperty;

public class Dock1 {
	public static void main( String[] args ){
		JFrame frame = new JFrame();

		// setup a controller and a few dockables

		CControl control = new CControl( frame );
		frame.add( control.getContentArea() );
		
		CGrid grid = new CGrid( control );
		grid.add( 0, 0, 25, 75, new DefaultSingleCDockable( "a", "a" ) );
		grid.add( 25, 0, 75, 75, new DefaultSingleCDockable( "b1", "b1" ), new DefaultSingleCDockable( "b2", "b2" ) );
		grid.add( 0, 75, 100, 25, new DefaultSingleCDockable( "c", "c" ) );

		control.getContentArea().deploy( grid );

		frame.setBounds( 20, 20, 500, 300 );
		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

		frame.setVisible( true );
		
		for( int i = control.getCDockableCount()-1; i >= 0; i-- ){
			for( int j = control.getCDockableCount()-1; j >= 0; j-- ){
				DefaultSingleCDockable a = (DefaultSingleCDockable)control.getCDockable( i );
				DefaultSingleCDockable b = (DefaultSingleCDockable)control.getCDockable( j );
				
				System.out.println( a.getTitleText() + " < " + b.getTitleText() + " = " + isLeftOf( a, b ) );
			}
		}
	}

	public static boolean isLeftOf( CDockable left, CDockable right ){
		SplitDockProperty pLeft = get( left );
		SplitDockProperty pRight = get( right );
		
		if( pLeft == null || pRight == null )
			throw new IllegalStateException( "sorry, one dockable is not on a SplitDockStation" );
		
		return pLeft.getX() + pLeft.getWidth() <= pRight.getX();
	}
	
	public static SplitDockProperty get( CDockable dockable ){
		CLocation location = dockable.getBaseLocation();
		DockableProperty dp = location.findProperty();
		if( dp instanceof SplitDockPathProperty )
			dp = ((SplitDockPathProperty)dp).toLocation();

		if( dp instanceof SplitDockProperty )
			return (SplitDockProperty)dp;

		return null;
	}
}```

Does this only work for dockables that are current visible? Or that belong to the same split dock station? For some reason, I get the following data for my dockables (extracted from a debugger):
main editor window: x=0.0, y=0.0, width=1.0, height=1.0
dockable window at the bottom (not currently visible): x=0.0, y=0.7119645494830132, width=1.0, height=0.28803545051698676

To find if the dockable is at the bottom, I check that “dockable.y >= main.y + main.height”, but since main.height=1.0, this evaluates to false (when I’d expect true).

Only if they belong to the same SplitDockStation. Invisible CDockables do not have a location (unless set by the client through “setLocation”). Perhaps you mean something else with invisible than I do, for me invisible means calling “setVisible( false )”.

There are basic things I don’t understand. As the user drags the dockables around, can I make sure they continue to belong to the same SplitDockStation, so that this relative-position check can work? Otherwise, is there a way to apply this check globally, regardless of the SplitDockStation? Suppose I drag some dockable to the left of the main window, I want to know for sure that the dockable is on the left of the main window. One reason I need to know this is that if the dockable is minimized, I want it to go to the minimization area that’s closest to its position on screen, but there are other reasons as well.
What I meant by “invisible” is dockables that are currently hidden because they are stacked with another dockable which is currently visible.

It is possible to place restrictions to where a user may drag a Dockable *1. But I think in this case it would not help, as Dockables are also moved around if the user clicks on certain buttons, like the „minimize“-button.

In the standard setup of an application using Common there is only one SplitDockStation present (surrounded by four FlapDockStation for the four minimize-areas). Each new CWorkingArea introduces one additional SplitDockStation and each new CContentArea introduces one additional SplitDockStation.

This (or these) SplitDockStation(s) are „root“-stations. A CLocation always references one root-station. If Dockables are stacked (and perhaps invisible) they are not directly child of a SplitDockStation but of a StackDockStation. This StackDockStation is not a root-station, hence the CLocation of stacked/invisible CDockables still references the SplitDockStation. As a result our problem remains the same, independent of whether a CDockable runs around alone, or is grouped with others.

The FlapDockStations (showing minimized CDockables) are also root-stations, so the CLocation of their children does not reference a SplitDockStation.

How does this help? CLocation offers the method „findRoot“ which returns the unique identifier of the root-station. If you have access to a CContentArea the unique identifier of the different stations can be found through methods like „getNorthIdentifier“. This allows you to find out on which station a CDockable lies, and react differently to this information.

I assume this is also part of your jEditor-plugin? Since I have to look at it any way, perhaps I can give you an answer that helps more later, or can write a little class which tells such things. But not before the weekend :wink: .

*1 in this case a AcceptanceDockRelocatorMode would do the trick, I can write you one if you really want it.

Thanks, it will be great if you can help by looking at the code.
The jEdit plugin for DockingFrames functions as an adapter between DockingFrames and the jEdit docking API. jEdit comes with a docking framework (that is considered very primitive nowadays, but was great 9 years ago), that provides an API for dockable window queries and operations (e.g. show/hide/isVisible). jEdit contains some dialogs for configuring the docking framework, that is implemented using this API. A while ago I added the capability of a pluggable docking framework,where plugins can implement this API on their own (e.g. by adapting it to DockingFrames). With modern docking frameworks, this API is not always well-defined, because it is based on restrictions that existed in the primitive docking framework of jEdit but do not exist in modern frameworks. Nevertheless, this API must be satisfied as many (non-docking-related) plugins are using them.

Regarding the relative position of dockables, I’ve noticed some strange behavior; if I have several dockables stacked together in the same SplitDockStation (at least visually they seem to be stacked together), switching between them can change their size. E.g. if the dockables are stacked at the bottom, below the main window, clicking the tab of dockable A brings dockable A to the front, and may also increase its size compared to the dockable that was previously in front (so I see less of the main window). Then clicking dockable B may decrease the size (so I see more of the main window). Is it supposed to be this way?

You have some strange things going on… clicking on the tab should not affect the size of the StackDockStation and its children.