/* * 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) 2009 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.facile.mode.status; import java.util.ArrayList; import java.util.List; import bibliothek.gui.Dockable; import bibliothek.gui.dock.common.mode.ExtendedMode; import bibliothek.gui.dock.facile.mode.Location; import bibliothek.gui.dock.facile.mode.LocationMode; import bibliothek.gui.dock.facile.mode.LocationModeManager; import bibliothek.gui.dock.support.mode.ModeManager; import bibliothek.gui.dock.support.mode.ModeManagerListener; /** * Abstract implementation of an {@link ExtendedModeEnablement}. This implementation * handles {@link ExtendedModeEnablementListener}s and tells subclasses when to * add or remove listeners to or from {@link Dockable}s.<br> * <b>Note:</b> Subclasses must call {@link #init()}. * @author Benjamin Sigg */ public abstract class AbstractExtendedModeEnablement implements ExtendedModeEnablement{ /** the listeners registered at this enablement */ private List<ExtendedModeEnablementListener> listeners = new ArrayList<ExtendedModeEnablementListener>(); /** the manager in whose realm this enablement is used */ private LocationModeManager<?> manager; /** a listener to {@link #manager} */ private ModeManagerListener<Location, LocationMode> modeManagerListener = new ModeManagerListener<Location, LocationMode>() { public void modeRemoved( ModeManager<? extends Location, ? extends LocationMode> manager, LocationMode mode ){ // ignore } public void modeChanged( ModeManager<? extends Location, ? extends LocationMode> manager, Dockable dockable, LocationMode oldMode, LocationMode newMode ){ // ignore } public void modeAdded( ModeManager<? extends Location, ? extends LocationMode> manager, LocationMode mode ){ // ignore } public void dockableRemoved( ModeManager<? extends Location, ? extends LocationMode> manager, Dockable dockable ){ disconnect( dockable ); } public void dockableAdded( ModeManager<? extends Location, ? extends LocationMode> manager, Dockable dockable ){ connect( dockable ); } }; /** * Creates a new enablement. Subclasses should call {@link #init()} afterwards. * @param manager the manager in whose realm this enablement is used, not <code>null</code> */ public AbstractExtendedModeEnablement( LocationModeManager<?> manager ){ this.manager = manager; } /** * Gets the manager in whose realm this enablement is used. * @return the manager, <code>null</code> if {@link #destroy()} has * been called. */ public LocationModeManager<?> getManager(){ return manager; } /** * Initializes this enablement: adds a listener to {@link #getManager() the manager} * and calls {@link #connect(Dockable)} for all known {@link Dockable}s. */ protected void init(){ manager.addModeManagerListener( modeManagerListener ); for( Dockable dockable : manager.listDockables() ){ connect( dockable ); } } public void addListener( ExtendedModeEnablementListener listener ){ if( listener == null ) throw new IllegalArgumentException( "listener must not be null" ); listeners.add( listener ); } public void removeListener( ExtendedModeEnablementListener listener ){ listeners.remove( listener ); } /** * Calls {@link ExtendedModeEnablementListener#availabilityChanged(Dockable, ExtendedMode, boolean)} for * all listeners that are registered. * @param dockable the element which is affected * @param mode the mode which is affected * @param available the new availability state */ protected void fire( Dockable dockable, ExtendedMode mode, boolean available ){ ExtendedModeEnablementListener[] array = listeners.toArray( new ExtendedModeEnablementListener[ listeners.size() ] ); for( ExtendedModeEnablementListener listener : array ){ listener.availabilityChanged( dockable, mode, available ); } } public void destroy(){ if( manager != null ){ manager.removeModeManagerListener( modeManagerListener ); for( Dockable dockable : manager.listDockables() ){ disconnect( dockable ); } manager = null; } } /** * Adds listeners to <code>dockable</code> in order to call {@link #fire(Dockable, ExtendedMode, boolean)} * once the availability of some mode changed. * @param dockable the element which needs new listeners */ protected abstract void connect( Dockable dockable ); /** * Removes listeners from <code>dockable</code> that were added earlier. * @param dockable the element which is no longer to be connected */ protected abstract void disconnect( Dockable dockable ); }