/* * 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) 2010 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.mode.station; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import bibliothek.gui.DockController; import bibliothek.gui.DockStation; import bibliothek.gui.Dockable; import bibliothek.gui.dock.ScreenDockStation; import bibliothek.gui.dock.common.CLocation; import bibliothek.gui.dock.common.CStation; import bibliothek.gui.dock.common.intern.station.CScreenDockStation; import bibliothek.gui.dock.common.location.CExternalizedLocation; import bibliothek.gui.dock.common.location.CMaximalExternalizedLocation; import bibliothek.gui.dock.common.mode.CExternalizedModeArea; import bibliothek.gui.dock.common.mode.CLocationMode; import bibliothek.gui.dock.common.mode.CLocationModeManager; import bibliothek.gui.dock.common.mode.CMaximizedMode; import bibliothek.gui.dock.common.mode.CMaximizedModeArea; import bibliothek.gui.dock.facile.mode.ExternalizedMode; import bibliothek.gui.dock.facile.mode.Location; import bibliothek.gui.dock.facile.mode.LocationMode; import bibliothek.gui.dock.facile.mode.LocationModeEvent; import bibliothek.gui.dock.facile.mode.MaximizedMode; import bibliothek.gui.dock.facile.mode.MaximizedModeArea; import bibliothek.gui.dock.facile.mode.ModeArea; import bibliothek.gui.dock.facile.mode.ModeAreaListener; import bibliothek.gui.dock.layout.DockableProperty; import bibliothek.gui.dock.station.screen.ScreenDockProperty; import bibliothek.gui.dock.station.screen.ScreenDockStationListener; import bibliothek.gui.dock.station.screen.ScreenDockWindow; import bibliothek.gui.dock.support.mode.AffectedSet; import bibliothek.gui.dock.util.DockUtilities; /** * Connection between a {@link ScreenDockStation} and the {@link CExternalizedModeArea} interface. * @author Benjamin Sigg */ public class CScreenDockStationHandle { /** the station handled by this handle */ private CStation<CScreenDockStation> station; /** Representation of this as {@link CExternalizedModeArea} */ private External external = new External(); /** Representation of this as {@link CMaximizedModeArea} */ private Maximal maximal = new Maximal(); /** the mode owning {@link #external} */ private LocationMode externalMode; /** the mode owning {@link #maximal} */ private CMaximizedMode maximizedMode; /** the manager handling all modes */ private CLocationModeManager manager; /** * Creates a new handle * @param station the station which is handled by this handle, not <code>null</code> * @param manager the manager handling all modes, not <code>null</code> */ public CScreenDockStationHandle( CStation<CScreenDockStation> station, CLocationModeManager manager ){ this.station = station; this.manager = manager; station.getStation().addScreenDockStationListener( new ScreenDockStationListener() { public void windowRegistering( ScreenDockStation station, Dockable dockable, ScreenDockWindow window ) { // ignore } public void windowDeregistering( ScreenDockStation station, Dockable dockable, ScreenDockWindow window ) { // ignore } public void fullscreenChanged( ScreenDockStation station, Dockable dockable ) { ModeAreaListener[] listeners; ModeArea source; if( station.isFullscreen( dockable )){ source = maximal; listeners = maximal.listeners(); } else{ source = external; listeners = external.listeners(); } Set<Dockable> dockables = new HashSet<Dockable>(); dockables.add( dockable ); for( ModeAreaListener listener : listeners ){ listener.internalLocationChange( source, dockables ); } } }); } /** * Gets the representation of this as {@link CExternalizedModeArea}. * @return the representation */ public CExternalizedModeArea getExternalizedModeArea(){ return external; } /** * Gets the representation of this as {@link CMaximizedModeArea}. * @return the representation */ public CMaximizedModeArea getMaximizedModeArea(){ return maximal; } /** * Gets a {@link CLocation} describing the location of <code>dockable</code> on the station of this handle. * @param dockable some child * @return the location */ public CLocation getCLocation( Dockable dockable ){ DockableProperty property = DockUtilities.getPropertyChain( station.getStation(), dockable ); return expand( property ); } /** * Assuming dockable would be at location <code>location</code> if it would be a child of this station, * returns the CLocation that matches <code>location</code>. * @param dockable some element which may or may not be a child of this station * @param location the location dockable would have if it would be a child of this station * @return the location or <code>null</code> if <code>location.getLocation()</code> is not valid */ public CLocation getCLocation( Dockable dockable, Location location ){ DockableProperty property = location.getLocation(); if( property == null ) return null; return expand( property ); } private CLocation expand( DockableProperty property ){ if( property instanceof ScreenDockProperty ){ ScreenDockProperty screen = (ScreenDockProperty)property; CLocation result; if( screen.isFullscreen() ){ result = new CMaximalExternalizedLocation( screen.getX(), screen.getY(), screen.getWidth(), screen.getHeight() ); } else{ result = new CExternalizedLocation( screen.getX(), screen.getY(), screen.getWidth(), screen.getHeight() ); } if( property.getSuccessor() != null ){ return result.expandProperty( station.getStation().getController(), property.getSuccessor() ); } else{ return result; } } return null; } /** * Represents a {@link CScreenDockStationHandle} as {@link CExternalizedModeArea}. * @author Benjamin Sigg */ protected class External implements CExternalizedModeArea{ private List<ModeAreaListener> listeners = new ArrayList<ModeAreaListener>(); public DockableProperty getLocation( Dockable child ) { return DockUtilities.getPropertyChain( getStation(), child ); } public boolean autoDefaultArea() { return true; } public boolean isLocationRoot(){ return true; } public boolean setLocation( Dockable dockable, DockableProperty location, AffectedSet set ) { set.add( dockable ); if( isChild( dockable )){ if( location != null ){ station.getStation().move( dockable, location ); } return true; } else{ boolean acceptable = DockUtilities.acceptable( getStation(), dockable ); if( !acceptable ){ return false; } if( location != null ){ if( !station.getStation().drop( dockable, location )){ location = null; } } if( location == null ){ station.getStation().drop( dockable ); } return true; } } public void addModeAreaListener( ModeAreaListener listener ) { listeners.add( listener ); } public void removeModeAreaListener( ModeAreaListener listener ) { listeners.remove( listener ); } /** * Gets all the listeners that are registered at this area. * @return all listeners */ public ModeAreaListener[] listeners(){ return listeners.toArray( new ModeAreaListener[ listeners.size() ] ); } public DockStation getStation() { return station.getStation(); } public String getUniqueId() { return station.getUniqueId(); } public boolean isChild( Dockable dockable ) { return dockable.getDockParent() == station.getStation() && !station.getStation().isFullscreen( dockable ); } public boolean respectWorkingAreas() { return false; } public void setController( DockController controller ) { // ignore } public void setMode( LocationMode mode ){ externalMode = mode; } public CLocation getCLocation( Dockable dockable ) { return CScreenDockStationHandle.this.getCLocation( dockable ); } public CLocation getCLocation( Dockable dockable, Location location ) { return CScreenDockStationHandle.this.getCLocation( dockable, location ); } } /** * A representation of {@link CScreenDockStationHandle} as {@link CMaximizedModeArea}. * @author Benjamin Sigg */ protected class Maximal implements CMaximizedModeArea{ private List<ModeAreaListener> listeners = new ArrayList<ModeAreaListener>(); public Dockable[] getMaximized() { return station.getStation().getFullscreenChildren(); } public boolean isRepresenting( DockStation station ) { return CScreenDockStationHandle.this.station.getStation() == station; } public boolean autoDefaultArea() { return false; } public boolean isLocationRoot(){ return true; } public DockableProperty getLocation( Dockable child ){ return DockUtilities.getPropertyChain( getStation(), child ); } public Runnable onApply( LocationModeEvent event ) { if( event.isDone() ) return null; Location location = event.getLocation(); Dockable dockable = event.getDockable(); if( event.getMode().getUniqueIdentifier().equals( ExternalizedMode.IDENTIFIER )){ CLocationMode last = manager.getCurrentMode( dockable ); CLocationMode secondLast = manager.getPreviousMode( dockable ); if( last != null && secondLast != null ){ if( ExternalizedMode.IDENTIFIER.equals( secondLast.getUniqueIdentifier() ) && MaximizedMode.IDENTIFIER.equals( last.getUniqueIdentifier() )){ MaximizedModeArea area = maximizedMode.get( location.getRoot() ); if( area == this ){ dockable = maximizedMode.getMaximizingElement( dockable ); area.setMaximized( dockable, false, null, event.getAffected() ); event.done(true); return null; } } } } return null; } public Runnable onApply( LocationModeEvent event, Dockable replacement ) { return null; } public void prepareApply( Dockable dockable, Location history, AffectedSet set ){ // ignore } public LocationMode getUnmaximizedMode(){ return externalMode; } public void setMaximized( Dockable dockable, boolean maximized, Location history, AffectedSet set ){ ScreenDockStation station = getStation(); DockStation parent = dockable.getDockParent(); if( maximized ){ if( parent == station ){ station.setFullscreen( dockable, true ); } else{ Dockable child = DockUtilities.getDirectChild( station, dockable ); if( child == null ){ throw new IllegalArgumentException( "dockable not a child of this station" ); } if( !parent.canDrag( dockable )){ throw new IllegalArgumentException( "cannot drag dockable from its parent" ); } parent.drag( dockable ); if( !station.drop( dockable, child ) ){ throw new IllegalStateException( "cannot drop dockable on this station" ); } station.setFullscreen( dockable, true ); } } else{ if( parent == station ){ station.setFullscreen( dockable, false ); } else{ Dockable child = DockUtilities.getDirectChild( station, dockable ); ScreenDockProperty location = station.getLocation( child, dockable ); if( !parent.canDrag( dockable )){ throw new IllegalArgumentException( "cannot drag dockable from its current parent" ); } location.setFullscreen( false ); if( !station.drop( dockable, location, true )){ throw new IllegalStateException( "could not drop dockable on this station" ); } } } } public void addModeAreaListener( ModeAreaListener listener ) { listeners.add( listener ); } public void removeModeAreaListener( ModeAreaListener listener ) { listeners.remove( listener ); } /** * Gets all the listeners that are registered at this area. * @return all listeners */ public ModeAreaListener[] listeners(){ return listeners.toArray( new ModeAreaListener[ listeners.size() ] ); } public ScreenDockStation getStation() { return station.getStation(); } public String getUniqueId() { return station.getUniqueId(); } public boolean isChild( Dockable dockable ) { ScreenDockStation station = getStation(); return dockable.getDockParent() == station && station.isFullscreen( dockable ); } public boolean respectWorkingAreas() { return false; } public void setController( DockController controller ) { // ignore } public void setMode( LocationMode mode ){ maximizedMode = (CMaximizedMode)mode; } public CLocation getCLocation( Dockable dockable ) { return CScreenDockStationHandle.this.getCLocation( dockable ); } public CLocation getCLocation( Dockable dockable, Location location ) { return CScreenDockStationHandle.this.getCLocation( dockable, location ); } } }