Dockable maximum problem in StackDockable layout


#1

Hi Byte,

When I click the maximize button in the stackDockable layout, only the currently selected dockable is maximized. How can I maximize the entire stackDockable?

When I add a CButton to the title, how do I put a portion of the Button’s position to the right of the maximize/minimize button?

Best regards,
Scott.


#2

Are you using the code from this thread: screenDockable ?

If so the CGroupBehavior prevents stacks from being maximed. This can be solved by providing a more customized CGroupBehavior.

Try out the example below. Stacks can be maximized, but the user is prevented from making an entire stack floating.

package test;

import javax.swing.JFrame;

import bibliothek.gui.DockStation;
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.group.CGroupBehavior;
import bibliothek.gui.dock.common.group.CGroupMovement;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.facile.mode.LocationMode;
import bibliothek.gui.dock.facile.mode.LocationModeManager;

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

		CControl control = new CControl( frame );
		frame.add( control.getContentArea() );

		// custom grouping behavior is set here
		control.setGroupBehavior( new MyGroupBehavior() );

		for( int i = 0; i < 4; i++ ) {
			DefaultSingleCDockable dockable = new DefaultSingleCDockable( "id" + i );
			dockable.setTitleText( "Title " + i );
			control.addDockable( dockable );
			dockable.setLocation( CLocation.base().normal().stack() );
			dockable.setVisible( true );
		}

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

	private static class MyGroupBehavior implements CGroupBehavior {
		@Override
		public CGroupMovement prepare( LocationModeManager<? extends LocationMode> manager, Dockable dockable, ExtendedMode target ) {
			return getBehaviorForTarget( target ).prepare( manager, dockable, target );
		}

		@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;
			}
		}
	}
}


#3

There is more than one way to change the order of the buttons.

Actions (a button is an Action) are collected in thematically organized DockActionSources. There is a source for the maximize/minimize/etc buttons, there is a source for the close button, there is a source for the clients custom actions. Sources are collected in CommonDockable.

In addition, DockStations and customizable ActionGuards may provide additional DockActionSources.

All these sources are collected, and forwarded to an ActionOffer. The ActionOffer combines all the actions, and creates one combined DockActionSource which is forwarded to the DockTitles and thus shown to the user.

Providing a new ActionGuard is a good way to introduce special actions. Like in the example below. Note the “special” button showing up on the very right side of the title.

package test;

import javax.swing.JFrame;

import bibliothek.gui.Dockable;
import bibliothek.gui.dock.action.ActionGuard;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.action.LocationHint;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.action.CAction;
import bibliothek.gui.dock.common.action.CButton;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.intern.CommonDockable;
import bibliothek.gui.dock.common.intern.action.CActionSource;

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

		CControl control = new CControl( frame );
		frame.add( control.getContentArea() );

		// register additional source of actions
		control.getController().addActionGuard( new MoreActionsGuard() );

		MoreActionsDockable dockable = new MoreActionsDockable( "id" );
		dockable.setTitleText( "Title" );
		dockable.setCloseable( true );

		dockable.addAction( button( "normal" ) );

		// now there is a special method for buttons that should be on the right side
		dockable.addActionRight( button( "special" ) );

		control.addDockable( dockable );
		dockable.setVisible( true );

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

	private static CButton button( String name ) {
		CButton button = new CButton();
		button.setText( name );
		button.setShowTextOnButtons( true );
		return button;
	}

	// extracts the additional source of actions from MoreActionsDockable
	private static class MoreActionsGuard implements ActionGuard {
		@Override
		public boolean react( Dockable dockable ) {
			return toCDockable( dockable ) instanceof MoreActionsDockable;
		}

		@Override
		public DockActionSource getSource( Dockable dockable ) {
			return ((MoreActionsDockable) toCDockable( dockable )).moreActions;
		}

		private CDockable toCDockable( Dockable dockable ) {
			if( dockable instanceof CommonDockable ) {
				return ((CommonDockable) dockable).getDockable();
			} else {
				return null;
			}
		}
	}

	private static class MoreActionsDockable extends DefaultSingleCDockable {
		// list of actions that should be on the right side of the title.
		private CActionSource moreActions = new CActionSource( new LocationHint( LocationHint.DOCKABLE, LocationHint.RIGHT_OF_ALL ) );

		public MoreActionsDockable( String id ) {
			super( id );
		}

		public void addActionRight( CAction action ) {
			moreActions.add( action );
		}
	}
}

#4

Thanks for your detailed answer.
I will try the solution you said.

Best regards,
Scott.


#5

The solution you gave solves my problem. Thanks again.


Regarding the title of the dockable, I found that only a

dockable.setEnabled(EnableableItem.ALL, false );

method, can I remove the context menu on the Dockable title?

Best regards,
Scott.


#6

There is an interface called ActionPopupSuppressor, which allows clients to analyze and to suppress popup menus.

Try this code:

CControl control = ...
control.getController().setPopupSuppressor( ActionPopupSuppressor.SUPPRESS_ALWAYS )

… this should disable all popup menus.

Or you implement your own ActionPopupSuppressor, with a custom filter.