/* * 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.station.split; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import bibliothek.gui.DockStation; import bibliothek.gui.Dockable; import bibliothek.gui.dock.SplitDockStation; import bibliothek.gui.dock.station.support.PlaceholderMap; import bibliothek.gui.dock.station.support.PlaceholderStrategy; import bibliothek.util.FrameworkOnly; import bibliothek.util.Path; /** * Keeps track of the various placeholders and {@link Dockable}s of a {@link SplitDockStation} * and makes sure that a placeholder is used by no more than one {@link SplitNode}. * @author Benjamin Sigg */ @FrameworkOnly public class SplitPlaceholderSet { /** access to the owner of this set */ private SplitDockAccess access; /** * Creates a new set. * @param access Access to the owner of this set, not <code>null</code> */ public SplitPlaceholderSet( SplitDockAccess access ){ this.access = access; } /** * Ensures that <code>node</code> is associated with the placeholder for <code>dockable</code>. * @param node the owner of <code>dockable</code>, can be <code>null</code> to indicate * that no-one must use the placeholder of <code>dockable</code> * @param dockable the item whose placeholder is updated * @param protectedNodes nodes that will not be removed even if they are no longer {@link SplitNode#isOfUse() useful} */ public void set( SplitNode node, Dockable dockable, SplitNode... protectedNodes ){ PlaceholderStrategy strategy = access.getOwner().getPlaceholderStrategy(); if( strategy != null ){ Path placeholder = strategy.getPlaceholderFor( dockable ); if( placeholder != null ){ set( node, placeholder, protectedNodes ); } } } /** * Ensures that <code>node</code> is associated with <code>placeholder</code> * but no other node has <code>placeholder</code>. * @param node the node which must have <code>placeholder</code>, <code>null</code> to * indicate that no-one must use <code>placeholder</code> * @param placeholder the placeholder to set or to move * @param protectedNodes nodes that will not be removed even if they are no longer {@link SplitNode#isOfUse() useful} */ public void set( final SplitNode node, final Path placeholder, final SplitNode... protectedNodes ){ final List<SplitNode> nodesToDelete = new ArrayList<SplitNode>(); Root root = access.getOwner().getRoot(); root.visit( new SplitNodeVisitor() { public void handleRoot( Root root ){ handle( root ); } public void handlePlaceholder( Placeholder placeholder ){ handle( placeholder ); } public void handleNode( Node node ){ handle( node ); } public void handleLeaf( Leaf leaf ){ handle( leaf ); } private void handle( SplitNode check ){ if( check != node ){ check.removePlaceholder( placeholder ); PlaceholderMap map = check.getPlaceholderMap(); if( map != null ){ map.removeAll( placeholder, true ); } if( !check.isOfUse() ){ nodesToDelete.add( check ); } } } }); if( node != null ){ node.addPlaceholder( placeholder ); } if( access.isTreeAutoCleanupEnabled() ){ for( SplitNode protectedNode : protectedNodes ){ nodesToDelete.remove( protectedNode ); } for( SplitNode delete : nodesToDelete ){ delete.delete( true ); } } } /** * Removes any placeholder from <code>placeholderMap</code> that is stored in another node * than <code>node</code>. * @param node the node which must not be searched, can be <code>null</code> * @param map the map from which placeholders will be removed */ public void removeDoublePlaceholders( final SplitNode node, final PlaceholderMap map ){ final Set<Path> placeholdersToRemove = new HashSet<Path>(); final PlaceholderStrategy strategy = access.getOwner().getPlaceholderStrategy(); Root root = access.getOwner().getRoot(); root.visit( new SplitNodeVisitor() { public void handleRoot( Root root ){ handle( root ); } public void handlePlaceholder( Placeholder placeholder ){ handle( placeholder ); } public void handleNode( Node node ){ handle( node ); } public void handleLeaf( Leaf leaf ){ if( leaf != node ){ handle( leaf ); handle( leaf.getDockable() ); } } private void handle( SplitNode check ){ if( check != node ){ for( Path placeholder : check.getPlaceholders() ){ placeholdersToRemove.add( placeholder ); } } } private void handle( Dockable dockable ){ if( strategy != null && dockable != null ){ Path placeholder = strategy.getPlaceholderFor( dockable ); if( placeholder != null ){ placeholdersToRemove.add( placeholder ); } DockStation station = dockable.asDockStation(); if( station != null ){ for( int i = 0, n = station.getDockableCount(); i<n; i++ ){ handle( station.getDockable( i ) ); } } } } }); map.removeAll( placeholdersToRemove, true ); } }