Package bibliothek.gui.dock.common.mode.station

Source Code of bibliothek.gui.dock.common.mode.station.CSplitDockStationHandle$Maximal

/*
* 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.common.mode.station;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import bibliothek.gui.DockController;
import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.SplitDockStation;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.CStation;
import bibliothek.gui.dock.common.group.CGroupMovement;
import bibliothek.gui.dock.common.intern.CommonDockable;
import bibliothek.gui.dock.common.intern.station.CSplitDockStation;
import bibliothek.gui.dock.common.location.CMaximizedLocation;
import bibliothek.gui.dock.common.mode.CLocationMode;
import bibliothek.gui.dock.common.mode.CLocationModeManager;
import bibliothek.gui.dock.common.mode.CMaximizedModeArea;
import bibliothek.gui.dock.common.mode.CNormalModeArea;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.common.util.CDockUtilities;
import bibliothek.gui.dock.control.relocator.DockRelocatorEvent;
import bibliothek.gui.dock.control.relocator.VetoableDockRelocatorAdapter;
import bibliothek.gui.dock.control.relocator.VetoableDockRelocatorListener;
import bibliothek.gui.dock.event.SplitDockListener;
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.facile.mode.NormalModeArea;
import bibliothek.gui.dock.layout.DockableProperty;
import bibliothek.gui.dock.station.split.DockableSplitDockTree;
import bibliothek.gui.dock.station.split.SplitDockFullScreenProperty;
import bibliothek.gui.dock.support.mode.AffectedSet;
import bibliothek.gui.dock.support.mode.AffectingRunnable;
import bibliothek.gui.dock.util.DockUtilities;
import bibliothek.util.Path;

/**
* Combination of {@link CMaximizedModeArea}, {@link CNormalModeArea} and a
* {@link SplitDockStation}.
* @author Benjamin Sigg
*/
public class CSplitDockStationHandle{
  /** the station which is handled by this handle */
  private CStation<CSplitDockStation> station;
 
  /** normal-mode */
  private Normal normal = new Normal();
  /** maximized-mode */
  private Maximal maximal = new Maximal();
 
  /** the mode which is accessing this handler */
  private LocationMode normalMode;
 
  /** the mode which is accessing this handler */
  private MaximizedMode<?> maximizedMode;
 
  /** the manager in whose realm this handle is used */
  private CLocationModeManager manager;
 
  /** the listeners added to this {@link ModeArea} */
  private List<ModeAreaListenerWrapper> listeners = new ArrayList<ModeAreaListenerWrapper>();
 
  private SplitDockListener fullScreenListener = new SplitDockListener() {
    public void fullScreenDockableChanged( SplitDockStation station, Dockable oldFullScreen, Dockable newFullScreen ){
      Set<Dockable> affected = new HashSet<Dockable>();
      if( oldFullScreen != null )
        affected.add( oldFullScreen );
      if( newFullScreen != null )
        affected.add( newFullScreen );
     
      ModeAreaListenerWrapper[] array = listeners.toArray( new ModeAreaListenerWrapper[ listeners.size() ] );
      for( ModeAreaListenerWrapper listener : array ){
        listener.fire( affected );
      }
    }
  };
 
  /**
   * This listener calls {@link MaximizedMode#unmaximize(Dockable, AffectedSet)} if some element is dropped
   * onto this station.
   */
  private VetoableDockRelocatorListener relocatorListener = new VetoableDockRelocatorAdapter() {
    @Override
    public void dropped( DockRelocatorEvent event ){
      if( !event.isMove() ){
        MaximizedModeArea next = maximizedMode.getNextMaximizeArea( event.getTarget() );
        if( next == maximal ){
          manager.runTransaction( new AffectingRunnable() {
            public void run( AffectedSet set ){
              maximizedMode.unmaximize( (DockStation)getStation(), set );   
            }
          });
        }
      }
    }
  };
 
  /**
   * Creates a new handle.
   * @param station the station to handle
   * @param manager the manager in whose realm this handle is used
   */
  public CSplitDockStationHandle( CStation<CSplitDockStation> station, CLocationModeManager manager ){
    this.station = station;
    this.manager = manager;
  }
 
  /**
   * Adds <code>listener</code> to this handle, the listener will be invoked if the current
   * fullscreen-Dockable of the {@link SplitDockStation} changed.
   * @param listener the new listener
   */
  protected void add( ModeAreaListenerWrapper listener ){
    if( listener == null )
      throw new IllegalArgumentException( "listener must not be empty" );
    if( listeners.isEmpty() ){
      station.getStation().addSplitDockStationListener( fullScreenListener );
    }
    listeners.add( listener );
  }
 
  /**
   * Removes <code>listener</code> from this handle.
   * @param listener the listener to remove
   */
  protected void remove( ModeAreaListenerWrapper listener ){
    listeners.remove( listener );
    if( listeners.isEmpty() ){
      station.getStation().removeSplitDockStationListener( fullScreenListener );
    }
  }
 
  /**
   * Gets the station which is managed by this handle.
   * @return the station
   */
  public SplitDockStation getStation(){
    return station.getStation();
  }
 
  /**
   * Gets the {@link CStation} which is managed by this handle.
   * @return the station
   */
  public CStation<CSplitDockStation> getCStation(){
    return station;
  }
 
  /**
   * Returns this as {@link NormalModeArea}
   * @return a representation of <code>this</code>
   */
  public CNormalModeArea asNormalModeArea(){
    return normal;
  }
 
  /**
   * Returns this as {@link MaximizedModeArea}
   * @return a representation of <code>this</code>
   */
  public CMaximizedModeArea asMaximziedModeArea(){
    return maximal;
  }
 
  /**
   * Gets the mode which should be used to unmaximize children.
   * @return the mode to unmaximize children
   */
  protected LocationMode getNormalMode(){
    return normalMode;
  }
 
  private Path normalModeIdentifier(){
    return normalExtendedMode().getModeIdentifier();
  }
 
  private ExtendedMode normalExtendedMode(){
    return getNormalMode().getExtendedMode();
  }
 
 
  /**
   * Ensures that <code>dockable</code> is a child of this
   * station.
   * @param dockable the element to drop, must not yet be a child of this station
   * @throws IllegalStateException if <code>dockable</code> already
   * is a child of this station.
   */
  public void dropAside( Dockable dockable ){
    if( dockable.getDockParent() == station.getStation() )
      throw new IllegalStateException( "dockable already a child" );
   
    DockableSplitDockTree tree = getStation().createTree();
    if( tree.getRoot() == null )
      tree.root( dockable );
    else{
      tree.root( tree.horizontal( tree.put( dockable ), tree.unroot() ) );
    }
    getStation().dropTree( tree, false );
  }
 
  /**
   * A wrapper for a {@link ModeAreaListener}.
   * @author Benjamin Sigg
   */
  protected static class ModeAreaListenerWrapper{
    /** the listener */
    private ModeAreaListener listener;
    /** the area */
    private ModeArea area;
   
    public ModeAreaListenerWrapper( ModeArea area, ModeAreaListener listener ){
      this.area = area;
      this.listener = listener;
    }
   
    /**
     * Calls {@link ModeAreaListener#internalLocationChange(ModeArea, Set)} with
     * <code>dockables</code> as set and {@link #area} as area.
     * @param dockables the set of changed elements
     */
    public void fire( Set<Dockable> dockables ){
      listener.internalLocationChange( area, dockables );
    }
   
    @Override
    public boolean equals( Object obj ){
      if( obj == this )
        return true;
      if( obj instanceof ModeAreaListenerWrapper ){
        ModeAreaListenerWrapper other = (ModeAreaListenerWrapper)obj;
        return other.area.equals( area ) && other.listener.equals( listener );
      }
      return false;
    }
   
    @Override
    public int hashCode(){
      return area.hashCode() ^ listener.hashCode();
    }
  }
 
  /**
   * Represents the {@link SplitDockStation} as {@link CNormalModeArea}.
   * @author Benjamin Sigg
   */
  protected class Normal implements CNormalModeArea{
    public void setMode( LocationMode mode ){
      normalMode = mode;
    }
   
    public void addModeAreaListener( ModeAreaListener listener ){
      add( new ModeAreaListenerWrapper( this, listener ) );
    }
   
    public void removeModeAreaListener( ModeAreaListener listener ){
      removenew ModeAreaListenerWrapper( this, listener ) )
    }
   
    public boolean autoDefaultArea() {
      return true;
    }
   
    public boolean isLocationRoot(){
      return true;
    }
   
    public void setController( DockController controller ){
      // ignore 
    }
   
    public boolean isNormalModeChild( Dockable dockable ){
      if( !isChild( dockable )){
        return false;
      }
      if( getStation().getFullScreen() == dockable){
        return false;
      }
      if( !isWorkingAreaValid( dockable )){
        return false;
      }
      return true;
    }
   
    private boolean isWorkingAreaValid( Dockable dockable ){
      if( dockable instanceof CommonDockable ){
        CStation<?> workingArea = ((CommonDockable)dockable).getDockable().getWorkingArea();
        if( workingArea == null ){
          return CDockUtilities.getFirstWorkingArea( station ) == null;
        }
        else{
          return CDockUtilities.getFirstWorkingArea( station ) == workingArea;
        }
      }
      return true;
    }

    public DockableProperty getLocation( Dockable child ){
      return DockUtilities.getPropertyChain( getStation(), child );
    }

    public String getUniqueId(){
      return station.getUniqueId();
    }

    public boolean isChild( Dockable dockable ){
      return dockable.getDockParent() == getStation() && !maximal.isChild( dockable );
    }

    public SplitDockStation getStation(){
      return station.getStation();
    }
   
    public boolean respectWorkingAreas(){
      return true;
    }
   
    public boolean setLocation( Dockable dockable, DockableProperty location, AffectedSet set ){
      set.add( dockable );
     
      if( dockable.getDockParent() == station.getStation() ){
        if( location != null ){
          cleanFullscreen( set );
          getStation().move( dockable, location );
          return true;
        }
      }
      else{
        boolean acceptable = DockUtilities.acceptable( getStation(), dockable );
        if( acceptable ){
          if( dockable.getDockParent() != null ){
            dockable.getDockParent().drag( dockable );
          }
         
          cleanFullscreen( set );
         
          if( location != null ){
            if( !getStation().drop( dockable, location )){
              location = null;
            }
          }
          if( location == null ){
            if( !DockUtilities.isAncestor( station.getStation(), dockable )){
              getStation().drop( dockable );
            }
          }
          return true;
        }
      }
      return false;
    }
   
    private void cleanFullscreen( AffectedSet set ){
      Dockable fullscreen = getStation().getFullScreen();
      if( fullscreen != null ){
        maximal.setMaximized( fullscreen, false, null, set );
      }
    }
   
    public CLocation getCLocation( Dockable dockable ){
      DockableProperty property = DockUtilities.getPropertyChain( getStation(), dockable );
      return station.getStationLocation().expandProperty( station.getStation().getController(), property );
    }
   
   
    public CLocation getCLocation( Dockable dockable, Location location ){
      DockableProperty property = location.getLocation();
      if( property == null )
        return station.getStationLocation();
     
      return station.getStationLocation().expandProperty( station.getStation().getController(), property );
    }
   
    public CLocation getBaseLocation(){
      return station.getStationLocation();
    }
   
    public boolean isWorkingArea(){
      return station.isWorkingArea();
    }
  }
 
  /**
   * Represents a {@link SplitDockStation} as a {@link CMaximizedModeArea}.
   * @author Benjamin Sigg
   */
  protected class Maximal implements CMaximizedModeArea{
    /** the controller in whose realm this area works */
    private DockController controller;
   
    public void addModeAreaListener( ModeAreaListener listener ){
      add( new ModeAreaListenerWrapper( this, listener ) );
    }
   
    public void removeModeAreaListener( ModeAreaListener listener ){
      remove( new ModeAreaListenerWrapper( this, listener ) )
    }
   
    public void setMode( LocationMode mode ){
      if( maximizedMode != null && mode != null )
        throw new IllegalStateException( "handle already in use" );
      maximizedMode = (MaximizedMode<?>)mode;
    }
   
    public void setController( DockController controller ){
      if( this.controller != null ){
        this.controller.getRelocator().removeVetoableDockRelocatorListener( relocatorListener );
      }
      this.controller = controller;
      if( controller != null ){
        controller.getRelocator().addVetoableDockRelocatorListener( relocatorListener );
      }
    }
   
    public DockableProperty getLocation( Dockable child ){
      DockableProperty property = DockUtilities.getPropertyChain( getStation(), child );
      SplitDockFullScreenProperty result = new SplitDockFullScreenProperty();
      result.setSuccessor( property.getSuccessor() );
      return result;
    }
   
    public boolean autoDefaultArea() {
      return true;
    }
   
    public boolean isLocationRoot(){
      return true;
    }
   
    public LocationMode getUnmaximizedMode(){
      return getNormalMode();
    }
   
    public void prepareApply( Dockable dockable, AffectedSet affected ){
      CLocationMode normal = manager.getMode( normalModeIdentifier() );
      if( normal != null ){
        manager.apply( dockable, normal, affected, false );
      }
    }
   
    public void prepareApply( Dockable dockable, Location history, AffectedSet set ){
      boolean remaximize = history != null && history.getLocation() instanceof SplitDockFullScreenProperty;
     
      if( !remaximize ){
        if( manager.getMode( dockable ) != normalExtendedMode() ){
          CLocationMode normal = manager.getMode( normalModeIdentifier() );
          if( normal != null ){
            CGroupMovement movement = maximizedMode.getManager().getGroupBehavior().prepare( manager, dockable, normal.getExtendedMode() );
            if( movement != null ){
              manager.apply( dockable, normal.getExtendedMode(), movement );
            }
          }
        }
      }
    }
   
    public Runnable onApply( LocationModeEvent event ){
      if( event.isDone() )
        return null;
     
      Location location = event.getLocation();
          Dockable dockable = event.getDockable();
         
      DockableProperty property = location == null ? null : location.getLocation();
     
      if( event.getMode().getUniqueIdentifier().equals( normalModeIdentifier() )){
        // try to set the mode prematurely
            if( property != null ){
              if( property.getSuccessor() == null ){
                  CLocationMode last = manager.getCurrentMode( dockable );
                  CLocationMode secondLast = manager.getPreviousMode( dockable );
                 
                    if( last != null && secondLast != null ){
                      if( normalModeIdentifier().equals( secondLast.getUniqueIdentifier() ) &&
                          MaximizedMode.IDENTIFIER.equals( last.getUniqueIdentifier() )){
                       
                        MaximizedModeArea area = maximizedMode.get( location.getRoot() );
                       
                            if( area == this ){
                                area.setMaximized( dockable, false, null, event.getAffected() );
                                event.done(true);
                                return null;
                            }
                        }
                    }
                }
            }
        }
     
          // if the element is about to become a child of this station, ensure
          // this station does not show a maximized element
          if( location != null && getMaximized() != null ){
            Map<ExtendedMode, DockStation> roots = manager.getRepresentations( location.getRoot() );
            for( DockStation station : roots.values() ){
              if( DockUtilities.isAncestor( getStation(), station )){
                maximizedMode.unmaximize( this, event.getAffected() )
                break;
              }
            }
          }
         
          // if this station currently shows dockable as maximized element, ensure it is no longer maximized
      if( maximizedMode != null && event.getMode().getUniqueIdentifier().equals( normalModeIdentifier() )){
        MaximizedModeArea area = maximizedMode.getMaximizeArea( dockable );
        if( area == this ){
          maximizedMode.unmaximize( dockable, event.getAffected() );
        }
      }
         
          return null;
    }
   
    public Runnable onApply( final LocationModeEvent event, final Dockable replacement ){
      if( event.isDone() )
        return null;
     
      if( !event.getMode().getUniqueIdentifier().equals( normalModeIdentifier() )){
        maximizedMode.unmaximize( getStation().getFullScreen(), event.getAffected() );

            return new Runnable() {
          public void run(){
            if( replacement != null && replacement.getDockParent() != null ){
              maximizedMode.maximize( Maximal.this, replacement, event.getAffected() );
            }   
          }
        };
      }
     
      return null;
    }
   
    public String getUniqueId(){
      return station.getUniqueId();
    }
   
    public boolean isChild( Dockable dockable ){
      return getStation().getFullScreen() == dockable;
    }
   
    public SplitDockStation getStation(){
      return station.getStation();
    }
   
    public boolean respectWorkingAreas(){
      return false;
    }
   
    public Dockable[] getMaximized(){
      Dockable dockable = getStation().getFullScreen();
      if( dockable == null ){
        return null;
      }
      return new Dockable[]{ dockable };
    }

    public void setMaximized( Dockable dockable, boolean maximized, Location location, AffectedSet set ){
      SplitDockStation station = getStation();
     
      if( !maximized ){
        if( station.getFullScreen() != null && DockUtilities.isAncestor( station.getFullScreen(), dockable )){
          station.setFullScreen( null );
        }
      }
      else{
        DockableProperty property = location == null ? null : location.getLocation();
       
        if( property instanceof SplitDockFullScreenProperty ){
          if( getMaximized() != null ){
            if( getStation().drop( dockable, property ) ){
                  return;
                }
          }
        }
       
        if( dockable.getDockParent() == station ){
          station.setFullScreen( dockable );
            }
            else{
                if( dockable.getDockParent() != null )
                    dockable.getDockParent().drag( dockable );
 
                dropAside( dockable );
                station.setFullScreen( dockable );
            }
      }
     
      set.add( dockable );
    }
   
    public boolean isRepresenting( DockStation station ){
      return station == CSplitDockStationHandle.this.station.getStation();
    }
   
    public CLocation getCLocation( Dockable dockable ){
      DockableProperty property = DockUtilities.getPropertyChain( getStation(), dockable );
      return getCLocation( property );
    }
   
    public CLocation getCLocation( Dockable dockable, Location location ){
      DockableProperty property = location.getLocation();
      return getCLocation( property );
    }
   
    private CLocation getCLocation( DockableProperty property ){
      CLocation stationLocation = station.getStationLocation();
      CMaximizedLocation result = new CMaximizedLocation( stationLocation.findRoot() );
     
      if( property != null ){
        property = property.getSuccessor();
      }
      if( property != null ){
        return result.expandProperty( station.getStation().getController(), property );
      }
      else{
        return result;
      }
    }
  }
}
TOP

Related Classes of bibliothek.gui.dock.common.mode.station.CSplitDockStationHandle$Maximal

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-20639858-1', 'auto'); ga('send', 'pageview');