/* * Bibliothek - DockingFrames * Library built on Java/Swing, allows the user to "drag and drop" * panels containing any Swing-Component the developer likes to add. * * Copyright (C) 2007 Benjamin Sigg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Benjamin Sigg * benjamin_sigg@gmx.ch * CH - Switzerland */ package bibliothek.gui.dock.action.actions; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import bibliothek.gui.Dockable; import bibliothek.gui.dock.action.ActionContentModifier; import bibliothek.gui.dock.action.DockAction; import bibliothek.gui.dock.action.StandardDockAction; import bibliothek.gui.dock.disable.ActionDisablingStrategyObserver; import bibliothek.gui.dock.disable.DisablingStrategy; import bibliothek.gui.dock.event.StandardDockActionListener; /** * An abstract implementation of the {@link DockAction}-interface. * This implementation allows to {@link #addDockActionListener(StandardDockActionListener) register} * some {@link StandardDockActionListener}, and stores the {@link Dockable Dockables} * which are using this action. * @author Benjamin Sigg */ public abstract class AbstractStandardDockAction implements StandardDockAction { /** The listeners that are registered by this action */ protected List<StandardDockActionListener> listeners = new ArrayList<StandardDockActionListener>(); /** All {@link Dockable Dockables} which can be used by this action */ private Map<Dockable, Integer> bound = new HashMap<Dockable, Integer>(); /** Keeps track of the current {@link DisablingStrategy} and informs this action when its state changed */ private ActionDisablingStrategyObserver disabling; /** * Creates a new action. * @param monitorDisabling whether the current {@link DisablingStrategy} should be monitored */ public AbstractStandardDockAction( boolean monitorDisabling ){ if( monitorDisabling ){ disabling = new ActionDisablingStrategyObserver( this ){ @Override protected void setDisabled( Set<Dockable> dockable, boolean disabled ){ fireActionEnabledChanged( dockable ); } @Override protected void setDisabled( Dockable dockable, boolean disabled ){ Set<Dockable> set = new HashSet<Dockable>( 1 ); set.add( dockable ); fireActionEnabledChanged( set ); } }; } } public void addDockActionListener( StandardDockActionListener listener ) { listeners.add( listener ); } public void removeDockActionListener( StandardDockActionListener listener ) { listeners.remove( listener ); } /** * Invoked by this {@link AbstractStandardDockAction} when a {@link Dockable} * was bound to this action the first time. * @param dockable The Dockable that was not known to this action * before the method was invoked */ protected void bound( Dockable dockable ) { // do nothing } /** * Called by this {@link AbstractStandardDockAction} when the {@link Dockable} * <code>dockable</code> will not be used in any means by this * action. Note that the {@link #bound(Dockable)}-method can be * invoked again with the <code>dockable</code>. * @param dockable The Dockable which will not by used in any way. */ protected void unbound( Dockable dockable ) { // do nothing } /** * Tells whether the <code>dockable</code> is bound with this * action, or not. * @param dockable The {@link Dockable} to test * @return <code>true</code> if it is bound, <code>false</code> * otherwise */ public boolean isBound( Dockable dockable ){ return bound.containsKey( dockable ); } /** * Gets a set of all {@link Dockable Dockables} which are currently * bound to this {@link DockAction}. * @return The bound Dockables */ public Set<Dockable> getBoundDockables(){ return Collections.unmodifiableSet( bound.keySet() ); } public void bind( Dockable dockable ) { if( disabling != null ){ disabling.bind( dockable ); } Integer old = bound.get( dockable ); if( old == null ){ bound.put( dockable, 1 ); bound( dockable ); } else bound.put( dockable, old+1 ); } public void unbind( Dockable dockable ) { if( disabling != null ){ disabling.unbind( dockable ); } Integer old = bound.get( dockable ); if( old == null ){ // that should not happen... try{ throw new NullPointerException( "Unbind called too often, omit unbind and continue" ); } catch( NullPointerException ex ){ ex.printStackTrace(); } } else{ if( old == 1 ){ bound.remove( dockable ); unbound( dockable ); } else bound.put( dockable, old-1 ); } } /** * This method chooses the result according to the current {@link DisablingStrategy}. */ public boolean isEnabled( Dockable dockable ){ if( disabling == null ){ return true; } return !disabling.isDisabled( dockable ); } /** * Invokes the * {@link StandardDockActionListener#actionTextChanged(StandardDockAction, Set) actionTextChanged}- * method of all currently registered {@link StandardDockActionListener} * @param dockables The set of dockables for which the text has been * changed. */ protected void fireActionTextChanged( Set<Dockable> dockables ){ for( StandardDockActionListener listener : listeners.toArray( new StandardDockActionListener[ listeners.size() ] )) listener.actionTextChanged( this, dockables ); } /** * Invokes the * {@link StandardDockActionListener#actionTooltipTextChanged(StandardDockAction, Set) actionTooltipTextChanged}- * method of all currently registered {@link StandardDockActionListener} * @param dockables The set of dockables for which the tooltip has been * changed. */ protected void fireActionTooltipTextChanged( Set<Dockable> dockables ){ for( StandardDockActionListener listener : listeners.toArray( new StandardDockActionListener[ listeners.size() ] )) listener.actionTooltipTextChanged( this, dockables ); } /** * Invokes the * {@link StandardDockActionListener#actionIconChanged(StandardDockAction, ActionContentModifier, Set) actionIconChanged}- * method of all currently registered {@link StandardDockActionListener} * @param modifier the context in which the changed icon was used, can be <code>null</code> to indicate that all * icons changed * @param dockables The set of dockables for which the icon has been * changed. */ protected void fireActionIconChanged( ActionContentModifier modifier, Set<Dockable> dockables ){ for( StandardDockActionListener listener : listeners.toArray( new StandardDockActionListener[ listeners.size() ] )) listener.actionIconChanged( this, modifier, dockables ); } /** * Invokes the * {@link StandardDockActionListener#actionEnabledChanged(StandardDockAction, Set) actionEnabledChanged}- * method of all currently registered {@link StandardDockActionListener} * @param dockables The set of dockables for which the enabled-state has been * changed. */ protected void fireActionEnabledChanged( Set<Dockable> dockables ){ for( StandardDockActionListener listener : listeners.toArray( new StandardDockActionListener[ listeners.size() ] )) listener.actionEnabledChanged( this, dockables ); } /** * Invokes the * {@link StandardDockActionListener#actionRepresentativeChanged(StandardDockAction, Set) actionRepresentativeChanged}- * method of all currently registered {@link StandardDockActionListener} * @param dockables The set of dockables for which the enabled-state has been * changed. */ protected void fireActionRepresentativeChanged( Set<Dockable> dockables ){ for( StandardDockActionListener listener : listeners.toArray( new StandardDockActionListener[ listeners.size() ] )) listener.actionRepresentativeChanged( this, dockables ); } }