Save before closing an application


We are using your nice framework, but we got into this issue. Is there a reliable way to detect if save is needed before closing the application? We want the save dialog to appear only if there has been any change to the layout. (we tried this by comparing the initial input xml to the one obtained on exit by calling the writeXML method, but the CControl seems to change that xml, event if we don’t do anything to the layout; some reordering seems to happen internally).


There is no property where you could ask the framework directly. The only way I can think of is to listen for events, and setting your own „boolean“.

You could use some listeners to detect changes in the layout. You would probably get most of the events, but some corner cases might be missed.

  • Add a CControlListener to CControl to learn about new CDockables
  • Add a CDockableLocationListener to all CDockable to be informed when their position or size changes.

For even more events:

  • For events like „a tab in a stack was selected“ a DockStationListener might be needed.

Thanks! I will try these.

So you are confirming that and comparing a saved xml to what writeXML generates the next time before exiting isn’t a reliable way to check for changes.

On second thought, adding and then removing the same dockable, should be a no-change event. This scenario only is more than just setting a „boolean“. What do you think? Isn’t there any easier way of knowing if the CControl has really changed since opening? We don’t need an undo functionality, but we only need to konw if anything has changed related to the initial state of the CControl.


More, I mentioned layout, thinking maybe the framework provides generic support for knowing if anything changed. The layout is only part of the equation. There are also properties related to the dockables, which could change.

There are some HashMaps and other random stuff in the layout, preventing the xml from always being the same.

The complete layout is also available as a java-object, a CPerspective (see CControl.getPerspectives()). You could iterate through all the objects there… but it is a lot of work.


I have one last question. Is there a way to find the selected dockable? I need this to be a simple method call, because I have to find it right after opening and right before closing the frame. The listener might help with the final state (before closing).

You can get the selected dockable by calling CControl.getFocusedCDockable(). There is also a CFocusListener if you want to be notified on focus changes.

Thanks for your reply.

It seems that a selected tab in a stack doesn’t necessarily mean focused. So on opening, the focused dockable returned by CControl is null. But the selected tab (the one in the StackDockStation) in not. So in the end, I think it’s the selected tab in the StackDockStation I am really after. Is there a way I could retrieve that?

That information is not available in the „common“ layer, but you can find it one layer deeper.

In the code below you see the DockableSelectionListener which will be informed when the selection changes (on any kind of station).

And the loop at the end of code just iterates over the current layout.

There is some typecasting involved here, because we are in the „core“ layer.

		CControl control = ...

		control.getController().addDockableSelectionListener( new DockableSelectionListener() {
			public void dockableSelected( DockableSelectionEvent event ) {
				if( event.getStation() instanceof StackDockStation ) {
					Dockable selected = event.getNewSelected();
					if( selected instanceof CommonDockable ) {
						CDockable dockable = ((CommonDockable) selected).getDockable();
						if( dockable instanceof SingleCDockable ) {
							SingleCDockable single = (SingleCDockable) dockable;
							System.out.println( "did select: " + single.getUniqueId() );
		} );

		int count = control.getController().getStationCount();
		for( int i = 0; i < count; i++ ) {
			DockStation station = control.getController().getStation( i );
			if( station instanceof StackDockStation ) {
				Dockable selected = ((StackDockStation) station).getFrontDockable();
				if( selected instanceof CommonDockable ) {
					CDockable dockable = ((CommonDockable) selected).getDockable();
					if( dockable instanceof SingleCDockable ) {
						SingleCDockable single = (SingleCDockable) dockable;
						System.out.println( "started with selection: " + single.getUniqueId() );