/* * 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.common; import bibliothek.gui.DockController; import bibliothek.gui.DockStation; import bibliothek.gui.Dockable; import bibliothek.gui.dock.common.intern.CDockable; import bibliothek.gui.dock.common.location.CBaseLocation; import bibliothek.gui.dock.common.location.CExternalizedLocation; import bibliothek.gui.dock.common.location.CFlapIndexLocation; import bibliothek.gui.dock.common.location.CGridAreaLocation; import bibliothek.gui.dock.common.location.CLocationExpandStrategy; import bibliothek.gui.dock.common.location.CMaximalExternalizedLocation; import bibliothek.gui.dock.common.location.CMaximizedLocation; import bibliothek.gui.dock.common.location.CMinimizeAreaLocation; import bibliothek.gui.dock.common.location.CWorkingAreaLocation; import bibliothek.gui.dock.common.location.DefaultExpandStrategy; import bibliothek.gui.dock.common.mode.ExtendedMode; import bibliothek.gui.dock.layout.DockableProperty; /** * A class describing the current location of a {@link CDockable}. {@link CLocation}s * are combined, and a whole path of <code>CLocation</code>s describes an actual location. * <br> * Some warnings: * <ul> * <li>A {@link CLocation} is a very short living object: it does not have any ties to the * actual layout of the application. Meaning that any change in the layout may invalidate a {@link CLocation}. For * this reason clients are strongly encouraged not to store {@link CLocation}s in any kind of collection for later use.</li> * <li>There is no code available for storing {@link CLocation} persistently. This is deliberate, as {@link CLocation}s * are only good for a momentary snapshot of the location. The framework itself provides facilities to persistently store * the location of a {@link Dockable} for a long time. You may have a look at {@link CControl#writeXML(java.io.File)} and * {@link CControl#setMissingStrategy(MissingCDockableStrategy)}.</li> * <li>While {@link CLocation} and {@link DockableProperty} both store the location of {@link CDockable} or * a {@link Dockable}, they are not exactly the same thing. A {@link CLocation} expresses the current location of a * {@link CDockable} independent from the <code>dockable</code> itself. A {@link DockableProperty} however may also * store information that is specific to a {@link Dockable}, namely the placeholder. This means that while every * {@link CLocation} can be converted to a {@link DockableProperty}, not every {@link DockableProperty} can be * converted to a {@link CLocation} without loosing some information.</li> * </ul> * Some examples showing how to create a path of locations:<br> * <pre> * // an externalized element * CLocation location = CLocation.external( 20, 20, 400, 300 ); * * // a minimized element at the left side of the default panel * CLocation location = CLocation.base().minimalWest(); * * // an element in the lower right corner on a stack (tapped pane): * CLocation location = CLocation.base().normalSouth( 0.5 ).east( 0.5 ).stack( 2 ); * * // an element in the middle on a specific CContentArea * CContentArea area = ... * CLocation location = CLocation.base( area ).normalRectangle( 0.25, 0.25, 0.5, 0.5 ); * </pre> * Two {@link CLocation}s are to be considered equal if {@link #findRoot()}, {@link #findMode()} and * {@link #findProperty()} return the same value.<br> * * @author Benjamin Sigg */ public abstract class CLocation { /** * Creates a new location that tells all children to use a station * defined on <code>center</code>. * @param center the base of all new locations, can be <code>null</code> * @return the representation of <code>center</code> */ public static CBaseLocation base( CContentArea center ){ return new CBaseLocation( center ); } /** * Creates a new location that tells all children to use the default * center. * @return the new base */ public static CBaseLocation base(){ return new CBaseLocation(); } /** * Creates a new location representing the given {@link CWorkingArea}. * @param area an area * @return the representation of <code>area</code> */ public static CWorkingAreaLocation working( CWorkingArea area ){ return new CWorkingAreaLocation( area ); } /** * Creates a new location representing a minimize area. * @param area the area to which the location refers * @return the new location */ public static CMinimizeAreaLocation minimized( CMinimizeArea area ){ return new CMinimizeAreaLocation( area ); } /** * Creates a new location representing a minimize area. * @param area the area to which the location refers * @param index the exact location on <code>area</code> * @return the new location */ public static CFlapIndexLocation minimized( CMinimizeArea area, int index ){ return new CMinimizeAreaLocation( area ).insert( index ); } /** * Creates a new location representing a grid area. * @param area the area that is represented * @return the new location */ public static CGridAreaLocation normalized( CGridArea area ){ return new CGridAreaLocation( area ); } /** * Creates a new location representing the externalized mode. * @param x the x-coordinate in pixels * @param y the y-coordinate in pixels * @param width the width in pixels * @param height the height in pixels * @return the new location */ public static CExternalizedLocation external( int x, int y, int width, int height ){ return new CExternalizedLocation( x, y, width, height ); } /** * Creates a location representing the maximized mode. * @return the maximized mode */ public static CMaximizedLocation maximized(){ return new CMaximizedLocation(); } /** * Creates a location representing the maximized mode on <code>area</code>. It is the clients * responsibility to ensure that <code>area</code> actually allows maximization. * @param area the area on which an element will be maximized * @return the new maximization location */ public static CMaximizedLocation maximized( CGridArea area ){ return new CMaximizedLocation( area.getUniqueId() ); } /** * Creates a location representing the maximized mode on <code>area</code>. It is the clients * responsibility to ensure that <code>area</code> actually allows maximization. * @param area the area on which an element will be maximized * @return the new maximization location */ public static CMaximizedLocation maximized( CContentArea area ){ return new CMaximizedLocation( area.getCenterIdentifier() ); } /** * Creates a location representing an element that is externalized and maximized. The coordinates * are used once the {@link CDockable} is no longer maximized. * @param x the x-coordinate in pixels * @param y the y-coordinate in pixels * @param width the width in pixels * @param height the height in pixels * @return the new location */ public static CMaximalExternalizedLocation maximized( int x, int y, int width, int height ){ return new CMaximalExternalizedLocation( x, y, width, height ); } /** * Gets the parent location of this location. Some root-locations may never have a parent. * @return the parent location, can be <code>null</code> */ public abstract CLocation getParent(); /** * Gets the name of the station this location belongs to. This can be the id * of any {@link CStation}. * @return the name of the station or <code>null</code> if this location * does not have enough information to find the root */ public abstract String findRoot(); /** * Gets the mode this location represents. * @return the mode or <code>null</code> */ public abstract ExtendedMode findMode(); /** * Gets a path describing this location in terms of the * DockingFrames. The method is ignoring any children of this location. * @return the path to this location or <code>null</code> */ public DockableProperty findProperty(){ return findProperty( null ); } /** * Gets a path describing this location in terms of the * DockingFrames. * @param successor the path of the elements above this location or <code>null</code> * @return the path to this location or <code>null</code>, can also be <code>successor</code> */ public abstract DockableProperty findProperty( DockableProperty successor ); /** * Tries to create a location that resembles <code>property</code>. * @param controller the controller in whose realm this method is called, may be used to load * extensions * @param property some location * @return a location whose {@link #findProperty()} would create * <code>property</code> again, or <code>null</code> in case that <code>property</code> * can't be used */ public final CLocation expandProperty( DockController controller, DockableProperty property ){ return expandProperty( property, new DefaultExpandStrategy( controller ) ); } /** * Tries to create a location that resembles <code>property</code>. * @param property some location * @param strategy a strategy helping to convert the properties * @return a location whose {@link #findProperty()} would create * <code>property</code> again, or <code>null</code> in case that <code>property</code> * can't be used */ public CLocation expandProperty( DockableProperty property, CLocationExpandStrategy strategy ){ CLocation location = strategy.expand( this, property ); if( location == null ){ return null; } property = property.getSuccessor(); if( property == null ){ return location; } return location.expandProperty( property, strategy ); } /** * Returns a {@link CLocation} that describes the location of an element * that should be inserted next to this location. * @return the new location * @deprecated Clients should make use of {@link CDockable#setLocationsAside(CDockable)} and * {@link CDockable#setLocationsAsideFocused()}, because these methods can directly modify {@link DockStation}s * and insert placeholders when necessary. */ @Deprecated public abstract CLocation aside(); @Override public boolean equals( Object obj ){ if( obj instanceof CLocation ){ CLocation that = (CLocation)obj; return equals( findRoot(), that.findRoot() ) && equals( findMode(), that.findMode() ) && equals( findProperty(), that.findProperty() ); } return false; } private boolean equals( Object a, Object b ){ if( a == b ){ return true; } if( a == null && b != null ){ return false; } return a != null && a.equals( b ); } @Override public int hashCode(){ Object root = findRoot(); Object mode = findMode(); Object property = findProperty(); int result = 0; if( root != null ){ result = root.hashCode(); } result *= 31; if( mode != null ){ result += mode.hashCode(); } result *= 31; if( property != null ){ result += property.hashCode(); } return result; } }