Package bibliothek.gui.dock.common.intern.layout

Source Code of bibliothek.gui.dock.common.intern.layout.CLayoutChangeStrategy$CSettingAccess

/*
* 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.intern.layout;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import bibliothek.gui.Dockable;
import bibliothek.gui.DockFrontend.DockInfo;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.MultipleCDockable;
import bibliothek.gui.dock.common.MultipleCDockableFactory;
import bibliothek.gui.dock.common.MultipleCDockableLayout;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.event.CVetoClosingEvent;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.intern.CommonDockable;
import bibliothek.gui.dock.common.intern.CommonMultipleDockableLayout;
import bibliothek.gui.dock.frontend.DefaultLayoutChangeStrategy;
import bibliothek.gui.dock.frontend.DockFrontendInternals;
import bibliothek.gui.dock.frontend.Setting;
import bibliothek.gui.dock.layout.DockLayout;
import bibliothek.gui.dock.layout.DockLayoutComposition;
import bibliothek.gui.dock.layout.DockLayoutInfo;
import bibliothek.gui.dock.layout.DockSituation;
import bibliothek.gui.dock.layout.PredefinedDockSituation;
import bibliothek.gui.dock.station.support.PlaceholderStrategy;
import bibliothek.util.FrameworkOnly;

/**
* Strategy that pays attention to {@link MultipleCDockableFactory#match(bibliothek.gui.dock.common.MultipleCDockable, bibliothek.gui.dock.common.MultipleCDockableLayout)}
* and that fires {@link CVetoClosingEvent}s for {@link MultipleCDockable}s as well.
* @author Benjamin Sigg
*/
@FrameworkOnly
public class CLayoutChangeStrategy extends DefaultLayoutChangeStrategy {
  /** the control in whose realm this strategy is used */
  private CControl control;
 
  /** the internal name of the {@link ReplacementDockFactory} */
  private static final String REPLACEMENT_FACTORY_ID = PredefinedDockSituation.convertFactoryID( ReplacementDockFactory.REPLACEMENT_FACTORY_ID );
 
  /**
   * Creates a new strategy.
   * @param control the control in whose realm this strategy will be used
   */
  public CLayoutChangeStrategy( CControl control ){
    this.control = control;
  }
 
  @Override
  protected PredefinedDockSituation createSituation( DockFrontendInternals frontend, boolean entry, boolean onSetLayout ){
    PredefinedDockSituation situation = super.createSituation( frontend, entry, onSetLayout );
    if( onSetLayout ){
      situation.add( new ReplacementDockFactory() );
    }
    situation.setPlaceholderStrategy( control.getProperty( PlaceholderStrategy.PLACEHOLDER_STRATEGY ) );
    return situation;
  }
 
  @Override
  protected boolean shouldPredefine( Dockable dockable ){
    if( dockable instanceof CommonDockable ){
      return ((CommonDockable)dockable).getDockable() instanceof SingleCDockable;
    }
    else{
      return true;
    }
  }
 
  @Override
  protected Set<Dockable> estimateVisible( DockFrontendInternals frontend, DockSituation situation, DockLayoutComposition layout ){
        if( situation instanceof PredefinedDockSituation ){
            Set<Dockable> allDockables = new HashSet<Dockable>();
            for( DockInfo info : frontend.getDockables() ){
              Dockable dockable = info.getDockable();
              if( dockable != null ){
                allDockables.add( dockable );
              }
            }
            for( MultipleCDockable dockable : control.getRegister().getMultipleDockables() ){
              allDockables.add( dockable.intern() );
            }
           
            PredefinedDockSituation predefined = (PredefinedDockSituation)situation;
            Set<Dockable> visible = predefined.listVisible( allDockables, layout );
           
            findVisible( visible, layout );
           
            return visible;
        }
       
        return null;
  }
 
  @Override
  protected Collection<Dockable> getClosingDockables( DockFrontendInternals frontend, Set<Dockable> visible ){
    Collection<Dockable> result = super.getClosingDockables( frontend, visible );
   
    for( MultipleCDockable dockable : control.getRegister().getMultipleDockables() ){
      CommonDockable intern = dockable.intern();
      if( !visible.contains( intern )){
        result.add( intern );
      }
    }
   
    return result;
  }
 
  private void findVisible( Set<Dockable> visible, DockLayoutComposition layout ){
    DockLayoutInfo info = layout.getLayout();
    if( info != null ){
      DockLayout<?> data = info.getDataLayout();
      if( data != null ){
        if( REPLACEMENT_FACTORY_ID.equals( data.getFactoryID() )){
          CDockable dockable = (CDockable)data.getData();
          visible.add( dockable.intern() );
        }
      }
    }
   
    for( DockLayoutComposition child : layout.getChildren() ){
      findVisible( visible, child );
    }
  }
 
  /**
   * Checks the {@link DockLayout} that is associated with <code>composition</code> and may replace
   * the layout by another layout if a {@link MultipleCDockableFactory} finds a match between an existing
   * item and meta-data about an item.
   * @param frontend the caller of this method
   * @param setting the layout that is about to be applied
   * @param composition the composition to modify, may be <code>null</code>
   * @return the replacement composition or <code>null</code>
   */
  protected DockLayoutComposition replaceMultipleDockables( DockFrontendInternals frontend, CSettingAccess setting, DockLayoutComposition composition ){
    if( composition == null ){
      return null;
    }
   
    DockLayoutInfo info = composition.getLayout();
    if( info != null ){
      DockLayout<?> layout = info.getDataLayout();
      if( layout != null ){
        MultipleCDockable match = setting.findMatch( layout );
        if( match != null ){
          DockLayout<?> newLayout = new DockLayout<MultipleCDockable>( REPLACEMENT_FACTORY_ID, match );
          DockLayoutInfo newInfo = new DockLayoutInfo( newLayout );
          newInfo.setLocation( info.getLocation() );
          info = newInfo;
        }
      }
    }
 
    List<DockLayoutComposition> oldChildren = composition.getChildren();
    List<DockLayoutComposition> newChildren = new ArrayList<DockLayoutComposition>( oldChildren.size() );
   
    for( DockLayoutComposition child : oldChildren ){
      newChildren.add( replaceMultipleDockables( frontend, setting, child ) );
    }
   
    return new DockLayoutComposition( info, composition.getAdjacent(), newChildren, composition.isIgnoreChildren() );
  }
 
  @Override
  protected SettingAccess createAccess( DockFrontendInternals frontend, Setting setting ){
    return new CSettingAccess( frontend, setting );
  }
 
  /**
   * A {@link bibliothek.gui.dock.frontend.DefaultLayoutChangeStrategy.SettingAccess} that modifies the roots by calling
   * {@link CLayoutChangeStrategy#replaceMultipleDockables(DockFrontendInternals, CSettingAccess, DockLayoutComposition)}.
   * @author Benjamin Sigg
   */
  protected class CSettingAccess extends SettingAccess{
    private DockFrontendInternals frontend;
    private Map<String, DockLayoutComposition> modifiedRoots = new HashMap<String, DockLayoutComposition>();
   
    /** all the factories that might be used to create a match */
    private Map<String, MultipleCDockableFactory<?, ?>> factories;
   
    /** the dockables which have not yet been paired off ordered by their factories */
    private Map<String, List<MultipleCDockable>> remainingDockables;
   
    public CSettingAccess( DockFrontendInternals frontend, Setting setting ){
      super( setting );
      this.frontend = frontend;
     
      Map<String, MultipleCDockableFactory<?, ?>> factories = control.getRegister().getFactories();
      this.factories = new HashMap<String, MultipleCDockableFactory<?,?>>();
      for( Map.Entry<String, MultipleCDockableFactory<?, ?>> entry : factories.entrySet() ){
        this.factories.put( PredefinedDockSituation.convertFactoryID( entry.getKey() ), entry.getValue() );
      }
     
      remainingDockables = new HashMap<String, List<MultipleCDockable>>();
     
      for( MultipleCDockable dockable : control.getRegister().getMultipleDockables() ){
        for( Map.Entry<String, MultipleCDockableFactory<?, ?>> entry : factories.entrySet() ){
          if( entry.getValue() == dockable.getFactory() ){
            String key = PredefinedDockSituation.convertFactoryID( entry.getKey() );
            List<MultipleCDockable> list  = remainingDockables.get( key );
            if( list == null ){
              list = new LinkedList<MultipleCDockable>();
              remainingDockables.put( key, list );
            }
            list.add( dockable );
            break;
          }
        }
      }
    }
   
    /**
     * Searches a match for the meta-data <code>layout</code>. The result of this method will
     * never be result again for this {@link CSettingAccess}.
     * @param layout the element whose match is searched
     * @return the match or <code>null</code> if none was found
     */
    @SuppressWarnings("unchecked")
    public MultipleCDockable findMatch( DockLayout<?> layout ){
      String factoryId = layout.getFactoryID();
      Object data = layout.getData();
     
      if( data instanceof CommonMultipleDockableLayout ){
        MultipleCDockableLayout multipleLayout = ((CommonMultipleDockableLayout) data).getLayout();
        MultipleCDockableFactory<MultipleCDockable, MultipleCDockableLayout> factory = (MultipleCDockableFactory<MultipleCDockable, MultipleCDockableLayout>) factories.get( factoryId );
        if( factory != null ){
          List<MultipleCDockable> list = remainingDockables.get( factoryId );
          if( list != null ){
            Iterator<MultipleCDockable> iterator = list.iterator();
            while( iterator.hasNext() ){
              MultipleCDockable next = iterator.next();
              if( factory.match( next, multipleLayout )){
                iterator.remove();
                if( list.isEmpty() ){
                  remainingDockables.remove( factoryId );
                }
                return next;
              }
            }
          }
        }
      }
     
      return null;
    }
   
    @Override
    public DockLayoutComposition getRoot( String root ){
      DockLayoutComposition result = modifiedRoots.get( root );
      if( result == null ){
        result = replaceMultipleDockables( frontend, this, super.getRoot( root ) );
        modifiedRoots.put( root, result );
      }
      return result;
    }
  }
}
TOP

Related Classes of bibliothek.gui.dock.common.intern.layout.CLayoutChangeStrategy$CSettingAccess

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.