/* * 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.title; import java.util.ArrayList; import java.util.List; import bibliothek.gui.DockController; import bibliothek.gui.DockTheme; import bibliothek.gui.Dockable; import bibliothek.gui.dock.DockFactory; import bibliothek.gui.dock.event.UIListener; import bibliothek.gui.dock.util.Priority; import bibliothek.gui.dock.util.extension.Extension; import bibliothek.gui.dock.util.extension.ExtensionName; import bibliothek.util.Path; /** * A <code>DockTitleVersion</code> is a hint which {@link DockTitleFactory} has to * be used to create one or more {@link DockTitle DockTitle} for some {@link Dockable}.<br> * <code>DockTitleVersions</code> are created and registered by a {@link DockTitleManager}.<br> * Every version consists of three slots for factories, each with different * priority. If a new title is required, the factory with the highest priority * will be used.<br> * <code>DockTitleVersion</code> implements {@link DockTitleFactory} for convenience. * @author Benjamin Sigg */ public class DockTitleVersion implements DockTitleFactory{ /** * Name of the {@link ExtensionName} that allows to load additional {@link DockFactory}s into this * {@link DockTitleVersion}. These factories will be asked to create a {@link DockTitle} before * the real factory is asked. */ public static final Path DOCK_TITLE_VERSION_EXTENSION = new Path( "dock.DockTitleVersion" ); /** Name of the only property of an {@link ExtensionName}, the property points to <code>this</code> */ public static final String DOCK_TITLE_VERSION_EXTENSION_PARAMETER = "version"; /** the three slots for the factories */ private DockTitleFactory[] factories = new DockTitleFactory[3]; /** additional high priority factories created by an {@link Extension} */ private DockTitleFactory[] extensionFactories; /** the name of this version */ private String id; /** the controller for which the titles are created */ private DockController controller; /** the current requests on this version */ private List<DockTitleRequest> requests = new ArrayList<DockTitleRequest>(); /** whether the theme is currently changing, a version does automatically call {@link DockTitleRequest#request()} while the theme changes */ private boolean onThemeChange = false; /** * Creates a new version. * @param controller the controller for which titles will be created * @param id the unique name of this version */ public DockTitleVersion( DockController controller, String id ){ if( controller == null ) throw new NullPointerException( "Controller must not be null" ); if( id == null ) throw new IllegalArgumentException( "The ID must not be null" ); this.controller = controller; this.id = id; controller.getThemeManager().addUIListener( new UIListener() { public void updateUI( DockController controller ){ // ignore } public void themeWillChange( DockController controller, DockTheme oldTheme, DockTheme newTheme ){ onThemeChange = true; } public void themeChanged( DockController controller, DockTheme oldTheme, DockTheme newTheme ){ onThemeChange = false; } }); List<DockTitleFactory> list = controller.getExtensions().load( new ExtensionName<DockTitleFactory>( DOCK_TITLE_VERSION_EXTENSION, DockTitleFactory.class, DOCK_TITLE_VERSION_EXTENSION_PARAMETER, this ) ); if( !list.isEmpty() ){ extensionFactories = list.toArray( new DockTitleFactory[ list.size() ] ); } } /** * Adds <code>request</code> to this version. The <code>request</code> will * be installed on the current {@link DockTitleFactory} of this version. * This method should not be called by clients, clients should call {@link DockTitleRequest#install()}. * @param request the new request, not <code>null</code> */ public void install( DockTitleRequest request ){ if( request == null ) throw new IllegalArgumentException( "request must not be null" ); requests.add( request ); DockTitleFactory factory = getFactory(); if( factory != null ){ factory.install( request ); } } /** * Removes <code>request</code> from this version. This method should not be * called by clients, clients should call {@link DockTitleRequest#uninstall()}. * @param request the request to remove */ public void uninstall( DockTitleRequest request ){ requests.remove( request ); DockTitleFactory factory = getFactory(); if( factory != null ){ factory.uninstall( request ); } } /** * Calls {@link DockTitleFactory#request(DockTitleRequest)} for the current * factory. If there are any {@link #DOCK_TITLE_VERSION_EXTENSION extensions} installed, then * these extensions are questioned first. * @param request the request to answer */ public void request( DockTitleRequest request ){ DockTitleFactory client = getFactory( Priority.CLIENT ); if( client != null ){ client.request( request ); return; } if( extensionFactories != null ){ for( DockTitleFactory factory : extensionFactories ){ factory.request( request ); if( request.isAnswered() ){ return; } } } DockTitleFactory factory = getFactory(); if( factory != null ){ factory.request( request ); } } /** * Calls {@link DockTitleRequest#request()} for all {@link DockTitleRequest}s * that are currently installed on this version. */ public void request(){ for( DockTitleRequest request : requests ){ request.request(); } } /** * Gets the index of the slot in {@link #factories} which is used for * the factory with the given <code>priority</code>. * @param priority the priority of the slot * @return the index of the slot */ private int map( Priority priority ){ switch( priority ){ case CLIENT: return 0; case THEME: return 1; default: return 2; } } /** * Gets the factory with the highest priority * @return the factory or <code>null</code> if there is no * factory registered. */ public DockTitleFactory getFactory(){ for( int i = 0; i < factories.length; i++ ){ if( factories[i] != null ) return factories[i]; } return null; } /** * Stores <code>factory</code> at the slot <code>priority</code>. * @param factory the factory * @param priority the importance of the factory */ public void setFactory( DockTitleFactory factory, Priority priority ){ DockTitleFactory oldFactory = getFactory(); factories[ map( priority ) ] = factory; DockTitleFactory newFactory = getFactory(); if( oldFactory != newFactory ){ if( oldFactory != null ){ for( DockTitleRequest request : requests ){ oldFactory.uninstall( request ); } } if( newFactory != null ){ for( DockTitleRequest request : requests ){ newFactory.install( request ); if( !onThemeChange ){ request.request(); } } } } } /** * Gets the factory with the given priority. * @param priority the priority * @return the factory or <code>null</code> */ public DockTitleFactory getFactory( Priority priority ){ return factories[ map( priority ) ]; } /** * Tells whether there is a factory with the importance <code>priority</code>, * or not. * @param priority the searched priority * @return <code>true</code> if there is a factory */ public boolean isSet( Priority priority ){ return factories[ map( priority ) ] != null; } @Override public int hashCode() { return id.hashCode(); } @Override public boolean equals( Object obj ) { if (obj == this) { return true; } if (obj == null) { return false; } if (obj.getClass() == this.getClass()) { return (((DockTitleVersion)obj).id.equals( id )); } return false; } /** * Gets the name of this version. The name is set when this version * is created. It should be unique; it is unique if all versions are * created through the same {@link DockTitleManager}. * @return the name */ public String getID(){ return id; } /** * Gets the controller for which the titles are created. * @return the owner of this version */ public DockController getController(){ return controller; } }