Action of minimized dock

hi,
i’m developing an application using 5 docks
for some reasons, i need to add/remove action on 3 of them.

my problem is, i dont find how to access to the action when dock is minimized
(especially, the minimizedHold action)

to be more precise :

  • i want to set the action MinimizedHold to false (that’s done, no problem)
  • i want the icon doing this action do not appear (remove or hide is ok for me) when the dock is minimalized

if someone can help me (sorry for not doing lot of research but german is a language i never learnt)

I’m not 100% certain what you need, but here are some suggestions where to start looking.

  • Right click on the button/title of the minimized Dockable.
  • Mark the DockActions (not the CActions!) with the annotation “ButtonContentAction”.
  • Using the properties “FlapDockStation.BUTTON_CONTENT” and “FlapDockStation.BUTTON_CONTENT_FILTER” to select what items to show.

i make 2 screeshots to explain cause i think it’s an easy problem

first, i have a dock with minimize action (i use the setMinimizable function), (defaultly with that theme, BUBBLE_THEME, there were 3 actions, minimize, maximize, externalize)

now when this dock is minimized, it looks like that :

so there are 2 actions : the one on the right is to return to normal size, the one on the left is „stick“ (i want to remove this one)
my problem is really how to access to this minimzed dock, cause i think there are some methods .setStickable, .setWhatEver, etc… on this component if i can access it

about what you say, i dont find a way to retrieve DockAction only CAction (and my actionCount is 0 …)

i cant show you some source code but it’s really basic declaration of a few SingleCDockable, add to my frame, with a CControl (as in example from the documentation) and i make a function to customize some parameters (minimalizable, maximalizable,externalizable,minimizedhold and resizedlock)

The stick-action is not yet configurable (I’ll add it to the todo-list). Currently I’m at work, but later I’ll write you an example that hides the action and at the same time allows you to show your own actions.

There are not many “setX” methods in the Dockables because most behavior is configured through factories and strategy interfaces. As they could ignore any setting I often did not create them in the first place.

That should create the behavior you asked for:


import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;

import javax.swing.Icon;
import javax.swing.JFrame;

import bibliothek.gui.Dockable;
import bibliothek.gui.dock.FlapDockStation;
import bibliothek.gui.dock.action.DefaultActionOffer;
import bibliothek.gui.dock.action.DockAction;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.action.FilteredDockActionSource;
import bibliothek.gui.dock.action.actions.AbstractStandardDockAction;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
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.DefaultCDockable;
import bibliothek.gui.dock.station.flap.FlapDockHoldToggle;
import bibliothek.gui.dock.station.flap.button.ButtonContent;
import bibliothek.gui.dock.station.flap.button.ButtonContentCondition;
import bibliothek.gui.dock.station.flap.button.DefaultButtonContentFilter;

public class Dock73 {
	/* This example shows how to play with actions and the FlapDockStation
	 * 
	 * Part 1: Filtering the content of the button of the FlapDockStation
	 * Part 2: Hiding the "hold" or "stick" action of FlapDockStation */
	public static void main( String[] args ){
		JFrame frame = new JFrame();
		CControl control = new CControl( frame );
		
		/* Part 1: by installing this filter we tell the framework which actions to show on the minimized-button-title */
		control.putProperty( FlapDockStation.BUTTON_CONTENT_FILTER, new CustomActionSelection() );
		/* Part 1: by installing these set of rules we define how exactly the minimized-button-title should look like */
		control.putProperty( FlapDockStation.BUTTON_CONTENT, createCustomContent() );
		
		/* Part 2: through a custom ActionOffer we can exchange the algorithm that collects the actions of a Dockable */
		control.getController().addActionOffer( new HoldToggleFilter() );
		
		/* setting up some dockables for testing */
		frame.add( control.getContentArea() );
		
		CGrid grid = new CGrid( control );
		grid.add( 0, 0, 1, 1, new DefaultSingleCDockable( "a", "Aaa", new CustomButton() ) );
		grid.add( 0, 1, 1, 1, new DefaultSingleCDockable( "b", "Bbb", new CustomButton() ) );
		grid.add( 1, 0, 1, 1, new DefaultSingleCDockable( "c", "Ccc", new CustomButton() ) );
		grid.add( 1, 1, 1, 1, new DefaultSingleCDockable( "d", "Ddd", new CustomButton() ) );
		control.getContentArea().deploy( grid );
		
		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		frame.setBounds( 20, 20, 400, 400 );
		frame.setVisible( true );
	}

	/* Part 1: there are different settings like "paint some text" or "paint an icon" that can be applied to
	 * the minimized-title. Important for us is "paint some actions" and "do filter these actions". */
	private static ButtonContent createCustomContent(){
		ButtonContentCondition knob = ButtonContent.TRUE;
		ButtonContentCondition icon = ButtonContent.IF_DOCKABLE;
		ButtonContentCondition text = ButtonContent.IF_DOCKABLE;
		ButtonContentCondition children = ButtonContent.IF_STATION;
		ButtonContentCondition actions = ButtonContent.TRUE;
		ButtonContentCondition filterActions = ButtonContent.TRUE;
		
		return new ButtonContent( knob, icon, text, children, actions, filterActions );
	}
	
	/* Part 1: This is a custom filter that allows us to select which actions to paint on the minimized-title. This
	 * filter can only work if filtering is enabled, see "createCustomContent". */
	private static class CustomActionSelection extends DefaultButtonContentFilter{
		@Override
		public boolean isButtonAction( DockAction action ){
			/* Because CAction is a wrapper around DockAction and DockAction does not contain a reference to
			 * the CAction, we are starting an extensive search. */
			if( action instanceof AbstractStandardDockAction ){
				/* All CActions make use of AbstractStandardDockAction */
				for( Dockable dockable : ((AbstractStandardDockAction)action).getBoundDockables() ){
					/* The action knows by which Dockable it is used */
					if( dockable instanceof CommonDockable ){
						/* CDockable is a wrapper around CommonDockable, which itself is a subinterface of Dockable */
						CDockable cdockable = ((CommonDockable)dockable).getDockable();
						if( cdockable instanceof DefaultCDockable ){
							/* We are using DefaultSingleCDockable, a subclass of DefaultCDockable */
							DefaultCDockable defDockable = (DefaultCDockable)cdockable;
							for( int i = 0, n = defDockable.getActionCount(); i < n; i++ ){
								/* And we can just iterate over all actions */
								CAction caction = defDockable.getAction( i );
								if( caction.intern() == action ){
									/* We found the CAction that wraps around "action", now we can perform a final check. */
									return isButtonAction( caction );
								}
							}
						}
					}
				}
			}
			
			return super.isButtonAction( action );
		}
		
		public boolean isButtonAction( CAction action ){
			return action instanceof CustomButton;
		}
	}
	
	/* Part 1: Some custom action that will be shown on the minimized-title. */
	private static class CustomButton extends CButton{
		public CustomButton(){
			setText( "Hello" );
			setIcon( new RectIcon() );
		}		
		
		@Override
		protected void action(){
			System.out.println( "Hello" );	
		}
	}
	
	/* Part 1: Just some stupid icon */
	private static class RectIcon implements Icon{
		public int getIconHeight(){
			return 16;
		}
		
		public int getIconWidth(){
			return 16;
		}
		
		public void paintIcon( Component c, Graphics g, int x, int y ){
			g.setColor( Color.RED );
			g.fillRect( x+2, y+2, 10, 10 );
		}
	}
	
	// ------------
	
	/* Part 2: All DockActions are collected by "ActionOffer"s. This custom implementation works like the default
	 * ActionOffer, but applies a filter to the actions. */
	private static class HoldToggleFilter extends DefaultActionOffer{
		@Override
		public DockActionSource getSource( Dockable dockable, DockActionSource source, DockActionSource[] guards, DockActionSource parent, DockActionSource[] parents ){
			DockActionSource result = super.getSource( dockable, source, guards, parent, parents );
			return new HoldToggleFilterActionSource( result ); 
		}
	}
	
	/* Part 2: This filter is applied by "HoldToggleFilter" and does not show the action that is provided by the
	 * FlapDockStation. */
	private static class HoldToggleFilterActionSource extends FilteredDockActionSource{
		public HoldToggleFilterActionSource( DockActionSource source ){
			super( source );
		}
		
		@Override
		protected boolean include( DockAction action ){
			return !(action instanceof FlapDockHoldToggle);
		}
	}
}

That’s juste perfect, thank you =)

is that possible to also remove the stick action ?
i mean the view shown when you clic on a minimized dock.

Install a custom FlapWindowFactory (using the property key FlapDockStation.WINDOW_FACTORY and CControl.putProperty). If your factory does not create a window (returns null), then no window will be shown.

is there a simple way to set the default minized location ?

Solved.


    private static class MinimizeSouthAction extends CMinimizeAction{
       
        public MinimizeSouthAction(CControl control)
        {
            super(control);
        }
       
        @Override
        public void action( CDockable dockable ){
            dockable.setLocation(CLocation.base().minimalSouth());
        }
    }

maybe there is a better solution ?

Your current version will always place the dockable at the south. You could also try the method “AbstractCDockable.setDefaultLocation” with “mode=ExtendedMode.MINIMIZED”, that will allow the framework to store the previous position.

I fail to change the text and tooltip of action like maximize and minimize
so i set it up in my own minimize/maximum etc… (as you do for the CMinimizeAction but i change the setText and setToolTip parameters)

but now i got a problem about that, here some source code to understand what happens :

import java.awt.BorderLayout;
import java.awt.Color;

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

import bibliothek.gui.Dockable;
import bibliothek.gui.dock.FlapDockStation;
import bibliothek.gui.dock.action.DefaultActionOffer;
import bibliothek.gui.dock.action.DockAction;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.action.FilteredDockActionSource;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.ColorMap;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.intern.DefaultCDockable;
import bibliothek.gui.dock.common.intern.action.CExtendedModeAction;
import bibliothek.gui.dock.common.mode.CLocationModeManager;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.common.theme.ThemeMap;
import bibliothek.gui.dock.station.flap.ButtonPane;
import bibliothek.gui.dock.station.flap.DefaultFlapWindowFactory;
import bibliothek.gui.dock.station.flap.FlapDockHoldToggle;
import bibliothek.gui.dock.station.flap.FlapWindow;


public class LostButton extends JFrame
{
    private SingleCDockable dock1;
    private SingleCDockable dock2;

    public static void main(String[] args)
    {
        new LostButton();
    }

    public LostButton()
    {
        super();
        this.enableInputMethods(true);
        ColorMap cm;
        CControl control = new CControl(this);

        control.getController().addActionOffer(new HoldToggleFilter());

        control.putProperty(FlapDockStation.WINDOW_FACTORY,
                new DefaultFlapWindowFactory()
                {
                    @Override
                    public FlapWindow create(FlapDockStation station,
                            ButtonPane buttonPane)
                    {
                        return null;
                    }
                });

        ThemeMap theme = control.getThemes();
        theme.select(ThemeMap.KEY_BUBBLE_THEME);

        this.setLayout(new BorderLayout());
        this.add(control.getContentArea());

        dock1 = create(new JPanel(), "Dock 1", Color.white);
        cm = dock1.getColors();
        cm.setColor(ColorMap.COLOR_KEY_TITLE_FOREGROUND, Color.white);
        cm.setColor(ColorMap.COLOR_KEY_TITLE_BACKGROUND, Color.black);

        dock2 = create(new JPanel(), "Dock 2", Color.white);
        cm = dock2.getColors();
        cm.setColor(ColorMap.COLOR_KEY_TITLE_FOREGROUND, Color.white);
        cm.setColor(ColorMap.COLOR_KEY_TITLE_BACKGROUND, Color.black);

        MinimizeSouthAction minimize = new MinimizeSouthAction(control);
        MaximizeAction maximize = new MaximizeAction(control);
        NormalizeAction normalize = new NormalizeAction(control);

        ((DefaultSingleCDockable) dock1).putAction(
                CDockable.ACTION_KEY_MINIMIZE, minimize);
        ((DefaultSingleCDockable) dock1).putAction(
                CDockable.ACTION_KEY_NORMALIZE, normalize);
        ((DefaultSingleCDockable) dock2).putAction(
                CDockable.ACTION_KEY_MAXIMIZE, maximize);
        ((DefaultSingleCDockable) dock2).putAction(
                CDockable.ACTION_KEY_NORMALIZE, normalize);

        control.addDockable(dock1);
        control.addDockable(dock2);

        dock1.setVisible(true);
        dock2.setVisible(true);

        removeDockAction(dock1, true, false, false, true, true, false);
        removeDockAction(dock2, true, false, true, false, true, false);

        this.setResizable(true);
        this.setSize(500, 500);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    public static SingleCDockable create(JComponent panel, String title,
            Color color)
    {
        JComponent background = panel;

        background.setOpaque(true);
        background.setBackground(color);

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

    private void removeDockAction(SingleCDockable dock, boolean resizable,
            boolean externalizable, boolean maximalizable, boolean minimizable,
            boolean showTitle, boolean stackable)
    {
        DefaultCDockable dockParam = ((DefaultCDockable) dock);

        dockParam.setResizeLocked(resizable);
        dockParam.setResizeLockedHorizontally(resizable);
        dockParam.setResizeLockedVertically(resizable);
        dockParam.setExternalizable(externalizable);
        dockParam.setMaximizable(maximalizable);
        dockParam.setMinimizable(minimizable);
        dockParam.setMinimizedHold(false);
        dockParam.setTitleShown(showTitle);
        dockParam.setStackable(stackable);
    }

    private static class HoldToggleFilter extends DefaultActionOffer
    {
        @Override
        public DockActionSource getSource(Dockable dockable,
                DockActionSource source, DockActionSource[] guards,
                DockActionSource parent, DockActionSource[] parents)
        {
            DockActionSource result = super.getSource(dockable, source, guards,
                    parent, parents);
            return new HoldToggleFilterActionSource(result);
        }
    }

    /**
     * Ce filtre est appliqué par {@link HoldToggleFilter} et ne montre pas
     * l'action qui est fourni par {@link FlapDockStation}.
     */
    private static class HoldToggleFilterActionSource extends
            FilteredDockActionSource
    {
        public HoldToggleFilterActionSource(DockActionSource source)
        {
            super(source);
        }

        @Override
        protected boolean include(DockAction action)
        {
            return !(action instanceof FlapDockHoldToggle);
        }
    }

    public class MaximizeAction extends CExtendedModeAction
    {
        public MaximizeAction(CControl control)
        {
            super(control, ExtendedMode.MAXIMIZED,
                    CLocationModeManager.ICON_MANAGER_KEY_MAXIMIZE, "", "",
                    CControl.KEY_GOTO_MAXIMIZED);
            setText("Maximize text in my language");
            setTooltip("Maximize tooltip in my language");
        }
    }

    public class MinimizeSouthAction extends CExtendedModeAction
    {
        public MinimizeSouthAction(CControl control)
        {
            super(control, ExtendedMode.MINIMIZED,
                    CLocationModeManager.ICON_MANAGER_KEY_MINIMIZE, "", "",
                    CControl.KEY_GOTO_MINIMIZED);
            setText("Minimize text in my language");
            setTooltip("Minimize tooltip in my language");
        }

        @Override
        public void action(CDockable dockable)
        {
            dockable.setLocation(CLocation.base().minimalSouth());
        }
    }

    public class NormalizeAction extends CExtendedModeAction
    {
        public NormalizeAction(CControl control)
        {
            super(control, ExtendedMode.NORMALIZED,
                    CLocationModeManager.ICON_MANAGER_KEY_NORMALIZE,
                    "normalize", "", CControl.KEY_GOTO_NORMALIZED);
            setText("Normalize text in my language");
            setTooltip("Normalize tooltip in my language");
        }
    }
}

dock1 is only minimizable.
dock2 is only maximizable.

i use my own minimize/maximize/normalize actions.

dock2 works fine on maximization and back to normal, no problem with my overriden actions.
dock1 works fine to minimize but when minimized the normalize button isnt paint (i can still right clic and do the action).

this behaviour is weird for me cause the default normalize action works fine but cant change the text/tooltip and when i use exactly the same code but change 2 strings, it failed :s

The original normalize-action is marked with the annotation “@ButtonContentAction” and only actions with this mark show up on minimized dockables.

But you should use the TextManager to change the text. It is a lot easier that way. You can either set the text directly, using the keys that are also found in the “*.properties” files. Or you can load entire ResourceBundles, which were created to handle language dependent stuff.

TextManager text = control.getController().getTexts();

text.put( Priority.CLIENT, "normalize.in", "Text in your language" );
text.put( Priority.CLIENT, "normalize.in.tooltip", "Text in your language" ); 

// ... or ...

Locale locale = <your language>;
ResourceBundle bundle= ResourceBundle.getBundle( "baseName", locale, getClassLoader() );
DefaultTextScheme scheme = new DefaultTextScheme( bundle );

text.setScheme( Priority.CLIENT, scheme );```