CDockablePropertyListener

Hi,
I’m searching for an option when my component in DefaultSingleCDockable is hidden or shown.
I’m using Docking Frames 1.0.8.
To clarify my need I changed the Example of the common.pdf and added some listeners.
If I drag red, green and blue to one SplitStation, so I only can see one of the Panels in a single “TabbedPane”, I would like to listen to these hiding and showing events. But CDockableStateListener and ComponentListener did not recognize the change.
Are there any other options how I can determine such changes?

Thanks,
Martin


import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;

import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.event.CDockableStateListener;
import bibliothek.gui.dock.common.intern.CDockable;

public class Example {

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

		CControl control = new CControl(frame);

		frame.setLayout(new GridLayout(1, 1));
		frame.add(control.getContentArea());

		SingleCDockable red = create("Red", Color.RED);
		SingleCDockable green = create("Green", Color.GREEN);
		SingleCDockable blue = create("Blue", Color.BLUE);

		red.addCDockableStateListener(new CDockableStateListener() {

			@Override
			public void externalized(CDockable arg0) {
				// TODO Auto-generated method stub

			}

			@Override
			public void maximized(CDockable arg0) {
				// TODO Auto-generated method stub

			}

			@Override
			public void minimized(CDockable arg0) {
				// TODO Auto-generated method stub

			}

			@Override
			public void normalized(CDockable arg0) {
				// TODO Auto-generated method stub

			}

			@Override
			public void visibilityChanged(CDockable arg0) {
				System.out.println("visibilityChanged");
			}
		});

		control.add(red);
		control.add(green);
		control.add(blue);

		red.setVisible(true);

		green.setLocation(CLocation.base().normalSouth(0.4));
		green.setVisible(true);

		blue.setLocation(CLocation.base().normalEast(0.3));
		blue.setVisible(true);

		frame.setBounds(20, 20, 400, 400);
		frame.setVisible(true);
	}

	public static SingleCDockable create(String title, Color color) {

		JPanel background = new JPanel();
		background.setOpaque(true);
		background.setBackground(color);

		background.addComponentListener(new ComponentAdapter() {

			@Override
			public void componentShown(ComponentEvent e) {
				System.out.println("componentShown");
			}

			@Override
			public void componentHidden(ComponentEvent e) {
				System.out.println("componentHidden");
			}
		});

		return new DefaultSingleCDockable(title, title, background);
	}
}

There is a distinction between two kinds of visibility:

[ul]
[li]“basic visibility”: tells whether a Dockable has a parent and is somehow accessible to the user. But it could be hidden behind another Dockable and still be “basically visible”.
[/li][li]“true visibility”: tells whether the user can see the Dockable right now.
[/li][/ul]

(Yes, the terms are confusing and not applied consistently. It’s on my list of things to change.)

1.0.8
There are no methods offered by Dockable and CDockable to get the true visibility. You have to use code from the Core project in order to get to the information: DockStations know whether their children (Dockables) are visible. Code to ask the current state would look like this.

Dockable dockable = cdockable.intern();
DockStation parent = dockable.getDockParent();
boolean trueVisibility = parent.isVisible( dockable );

You can add a DockStationListener to the parent, the listener is informed when the true visibility of a child changes. And by adding a DockHierarchyListener to a Dockable you can find out when the parent changes (e.g. after a drag n drop operation).

1.1.0
Common project: The method CDockable.isDockableVisible gives the “true visibility”. And the CDockableLocationListener informs when the visibility changed.

Core project: The method Dockable.isDockableVisible gives the “true visibility”. And visibility is monitored with a DockableStateListener.

Hi Beni,

the information helps a lot.

Since I interested in the true visibility and in 1.0.8 CDockableLocationListener is only called when the basic visibility is changed I migrated to 1.1.0 but behavior is the same.

The current solution is that I added a DockHierarchyListener to the Dockables of the Core Project as you proposed and call the isDockableVisible method of all known CDockables if a HierarchyChanged Event occurs.

Thanks,
Martin

Updated Example:

import java.awt.Color;
import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;

import bibliothek.gui.Dockable;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.event.DockHierarchyEvent;
import bibliothek.gui.dock.event.DockHierarchyListener;

public class Example {

	private static SingleCDockable red;
	private static SingleCDockable green;
	private static SingleCDockable blue;

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

		CControl control = new CControl(frame);

		frame.setLayout(new GridLayout(1, 1));
		frame.add(control.getContentArea());

		red = create("Red", Color.RED);
		green = create("Green", Color.GREEN);
		blue = create("Blue", Color.BLUE);

		control.addDockable(red);
		control.addDockable(green);
		control.addDockable(blue);

		red.setVisible(true);

		green.setLocation(CLocation.base().normalSouth(0.4));
		green.setVisible(true);

		blue.setLocation(CLocation.base().normalEast(0.3));
		blue.setVisible(true);

		frame.setBounds(20, 20, 400, 400);
		frame.setVisible(true);
	}

	public static SingleCDockable create(final String title, Color color) {

		JPanel background = new JPanel();
		background.setOpaque(true);
		background.setBackground(color);

		final DefaultSingleCDockable cDockable = new DefaultSingleCDockable(
				title, title, background);

		final Dockable dockable = cDockable.intern();
		dockable.addDockHierarchyListener(new DockHierarchyListener() {

			@Override
			public void controllerChanged(DockHierarchyEvent event) {
			}

			@Override
			public void hierarchyChanged(DockHierarchyEvent event) {

				System.out.println(" red isVisible =  "
						+ red.isDockableVisible());
				System.out.println(" blue isVisible =  "
						+ blue.isDockableVisible());
				System.out.println(" green isVisible =  "
						+ green.isDockableVisible());

			}
		});

		return cDockable;
	}
}

That’s called „backward compatibility“. It’s a pain to keep it, but you would not want your application to break with every update… :wink:

Since you are using 1.1.0 now, make use of the CDockableLocationListener. This will cover all cases that lead to a visibility change:



import java.awt.Color;
import java.awt.GridLayout;
 
import javax.swing.JFrame;
import javax.swing.JPanel;
 
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.event.CDockableLocationEvent;
import bibliothek.gui.dock.common.event.CDockableLocationListener;
import bibliothek.gui.dock.event.DockHierarchyEvent;
import bibliothek.gui.dock.event.DockHierarchyListener;
 
public class Example {
 
    private static SingleCDockable red;
    private static SingleCDockable green;
    private static SingleCDockable blue;
 
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
        CControl control = new CControl(frame);
 
        frame.setLayout(new GridLayout(1, 1));
        frame.add(control.getContentArea());
 
        red = create("Red", Color.RED);
        green = create("Green", Color.GREEN);
        blue = create("Blue", Color.BLUE);
 
        control.addDockable(red);
        control.addDockable(green);
        control.addDockable(blue);
 
        red.setVisible(true);
 
        green.setLocation(CLocation.base().normalSouth(0.4));
        green.setVisible(true);
 
        blue.setLocation(CLocation.base().normalEast(0.3));
        blue.setVisible(true);
 
        frame.setBounds(20, 20, 400, 400);
        frame.setVisible(true);
    }
 
    public static SingleCDockable create(final String title, Color color) {
 
        JPanel background = new JPanel();
        background.setOpaque(true);
        background.setBackground(color);
 
        final DefaultSingleCDockable cDockable = new DefaultSingleCDockable(
                title, title, background);
 
        cDockable.addCDockableLocationListener( new CDockableLocationListener(){
			@Override
			public void changed( CDockableLocationEvent event ){
				System.out.println( title + ": " + event.getNewVisible() );
			}
		});
        
        return cDockable;
    }
}```

Okay, I should read the manual or the post in detail.
You proposed the CDockableLocationListener not the CDockableListener, so there is no need to create a DockHierarchyListener.

Thanks,
Martin


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

		CControl control = new CControl(frame);

		frame.setLayout(new GridLayout(1, 1));
		frame.add(control.getContentArea());

		SingleCDockable red = create("Red", Color.RED);
		SingleCDockable green = create("Green", Color.GREEN);
		SingleCDockable blue = create("Blue", Color.BLUE);

		control.addDockable(red);
		control.addDockable(green);
		control.addDockable(blue);

		red.setVisible(true);

		green.setLocation(CLocation.base().normalSouth(0.4));
		green.setVisible(true);

		blue.setLocation(CLocation.base().normalEast(0.3));
		blue.setVisible(true);

		frame.setBounds(20, 20, 400, 400);
		frame.setVisible(true);
	}

	public static SingleCDockable create(final String title, Color color) {

		JPanel background = new JPanel();
		background.setOpaque(true);
		background.setBackground(color);

		final DefaultSingleCDockable cDockable = new DefaultSingleCDockable(
				title, title, background);

		cDockable.addCDockableLocationListener(new CDockableLocationListener() {
			@Override
			public void changed(CDockableLocationEvent arg0) {
				System.out.println(title + " isVisible =  "
						+ cDockable.isDockableVisible());
			}

		});
		return cDockable;
	}
}```