/* * 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.Dockable; import bibliothek.gui.dock.SplitDockStation; import bibliothek.gui.dock.common.intern.CDockable; import bibliothek.gui.dock.common.intern.CPlaceholderStrategy; import bibliothek.gui.dock.common.intern.CommonDockable; import bibliothek.gui.dock.common.perspective.CControlPerspective; import bibliothek.gui.dock.station.split.DockableSplitDockTree; import bibliothek.gui.dock.station.split.SplitDockGrid; import bibliothek.util.Path; /** * A {@link CGrid} is a mechanism to layout a set of {@link CDockable} on * a {@link SplitDockStation} like the one used in the center of the * {@link CContentArea} or on the {@link CWorkingArea}. <code>CGrid</code>s * also can register new {@link CDockable}s to a {@link CControl}.<br> * <br> * <b>Usage:</b><br> * A <code>CGrid</code> consists of a set of <code>entries</code> where each * <code>entry</code> consists of a set of {@link CDockable}s and a rectangle * (position= <code>x/y</code>, size=<code>width/height</code>). The rectangle * tells where the <code>CDockable</code>s and how big they are compared to the * other <code>entries</code>.<br> * A client first fills a <code>CGrid</code> with such entries. Then the client calls * {@link CGridArea#deploy(CGrid)}, {@link CWorkingArea#deploy(CGrid)} or * {@link #toTree()}. This triggers the <code>CGrid</code> to convert its entries * into a tree of <code>Dockable</code>s. This tree can then be given to a * {@link SplitDockStation}. The <code>CGrid</code> can be trashed after it created * the tree - changes to the grid will not be forwarded to the tree.<br> * <br> * If the <code>CGrid</code> was created using the constructor {@link #CGrid(CControl)}, * then the method {@link CControl#addDockable(SingleCDockable)} or {@link CControl#addDockable(MultipleCDockable)} * is called for any new {@link CDockable}. * @author Benjamin Sigg * */ public class CGrid { /** the internal representation of this grid */ private SplitDockGrid grid = new SplitDockGrid(); /** the control for which this grid is used */ private CControl control; /** * Creates a new grid. * @deprecated Use {@link #CGrid(CControl)} with an argument of <code>null</code> instead. This * method may be removed in a future release. */ @Deprecated public CGrid(){ // do nothing } /** * Creates a new grid. If {@link CDockable}s is not <code>null</code>, then new {@link CDockable}s * will be registered at <code>control</code>. While a value of <code>null</code> is valid, * for most clients a non-<code>null</code> value will be the better choice. Please note that * some methods will not work if <code>control</code> is <code>null</code>. * @param control the control where this grid should register new {@link CDockable}s, * should not be <code>null</code> for most clients */ public CGrid( CControl control ){ this.control = control; } /** * Creates and returns a tree which contains the {@link CommonDockable}s * of this {@link CGrid}. The branches of the tree are put in a way, that * the boundaries of the {@link CommonDockable}s are respected as good * as possible. * @return the contents of this grid as tree */ public DockableSplitDockTree toTree(){ return grid.toTree(); } /** * Adds a new set of {@link CDockable}s to this grid. The {@link CDockable}s * are also added to the {@link CControl} of this <code>CGrid</code>. * @param x the x-coordinate of the dockables * @param y the y-coordinate of the dockables * @param width the width of the dockables * @param height the height of the dockables * @param dockables a list of {@link SingleCDockable}s and {@link MultipleCDockable}s. */ public void add( double x, double y, double width, double height, CDockable... dockables ){ Dockable[] intern = new Dockable[ dockables.length ]; for( int i = 0; i < intern.length; i++ ){ CDockable dockable = dockables[i]; if( control != null ){ if( dockable instanceof SingleCDockable ){ control.addDockable( (SingleCDockable)dockable ); } else if( dockable instanceof MultipleCDockable ){ if( dockable.getControl() == null ){ control.addDockable( (MultipleCDockable)dockable ); } } } intern[i] = dockable.intern(); } grid.addDockable( x, y, width, height, intern ); } /** * Adds some placeholders for {@link SingleCDockable}s to this {@link CGrid}. This method does not make any checks concerning * the validity of the placeholders, the placeholders will however be checked once the {@link CGrid} is deployed.<br> * This method will assume that the {@link CPlaceholderStrategy} is installed and use the method {@link CPlaceholderStrategy#getSingleDockablePlaceholder(String)}<br> * Please note that placeholders are always placed after the real existing {@link CDockable}s, if * order is important then clients must use a {@link CControlPerspective} to create the layout. * to convert the identifiers into placeholders. * @param x the x-coordinate of the dockables * @param y the y-coordinate of the dockables * @param width the width of the dockables * @param height the height of the dockables * @param identifiers the identifiers that would be returned by {@link SingleCDockable#getUniqueId()} * @throws IllegalStateException if this {@link CGrid} does not have access to the a {@link CControl} */ public void addSingle( double x, double y, double width, double height, String... identifiers ){ if( control == null ){ throw new IllegalStateException( "This method is only available if the CGrid was constructed with a CControl" ); } Path[] placeholders = new Path[ identifiers.length ]; for( int i = 0; i < placeholders.length; i++ ){ placeholders[i] = CPlaceholderStrategy.getSingleDockablePlaceholder( control.getRegister().toSingleId( identifiers[i] ) ); } } /** * Adds some placeholders for {@link MultipleCDockable}s to this {@link CGrid}. This method does not make any checks concerning * the validity of the placeholders, the placeholders will however be checked once the {@link CGrid} is deployed.<br> * This method will assume that the {@link CPlaceholderStrategy} is installed and use the method {@link CPlaceholderStrategy#getMultipleDockablePlaceholder(String)} * to convert the identifiers into placeholders.<br> * Please note that placeholders are always placed after the real existing {@link CDockable}s, if * order is important then clients must use a {@link CControlPerspective} to create the layout. * @param x the x-coordinate of the dockables * @param y the y-coordinate of the dockables * @param width the width of the dockables * @param height the height of the dockables * @param identifiers the identifiers that are used when calling {@link CControl#addDockable(String, MultipleCDockable)} * @throws IllegalStateException if this {@link CGrid} does not have access to the a {@link CControl} */ public void addMulti( double x, double y, double width, double height, String... identifiers ){ if( control == null ){ throw new IllegalStateException( "This method is only available if the CGrid was constructed with a CControl" ); } Path[] placeholders = new Path[ identifiers.length ]; for( int i = 0; i < placeholders.length; i++ ){ placeholders[i] = CPlaceholderStrategy.getMultipleDockablePlaceholder( control.getRegister().toMultiId( identifiers[i] ) ); } } /** * Adds some placeholders to this {@link CGrid}. This method does not make any checks concerning * the validity of the placeholders, the placeholders will however be checked once the {@link CGrid} * is deployed.<br> * Please note that placeholders are always placed after the real existing {@link CDockable}s, if * order is important then clients must use a {@link CControlPerspective} to create the layout. * @param x the x-coordinate of the dockables * @param y the y-coordinate of the dockables * @param width the width of the dockables * @param height the height of the dockables * @param placeholders the list of new placeholders */ public void addPlaceholders( double x, double y, double width, double height, Path... placeholders ){ grid.addPlaceholders( x, y, width, height, placeholders ); } /** * Marks <code>dockable</code> as being selected in the stack that * has the boundaries of <code>x, y, width, height</code>. * @param x the x coordinate of the stack * @param y the y coordinate of the stack * @param width the width of the stack * @param height the height of the stack * @param dockable the element to select, not <code>null</code> * @throws IllegalArgumentException if <code>dockable</code> is not registered at location <code>x/y/width/height</code> */ public void select( double x, double y, double width, double height, CDockable dockable ){ grid.setSelected( x, y, width, height, dockable.intern() ); } /** * Informs this grid about a horizontal divider that should be inserted * into the layout. There are no guarantees that the divider really is inserted. * @param x1 the first x coordinate of the divider * @param x2 the second x coordinate of the divider * @param y the y coordinate of the divider */ public void addHorizontalDivider( double x1, double x2, double y ){ grid.addHorizontalDivider( x1, x2, y ); } /** * Informs this grid about a vertical divider that should be inserted * into the layout. There are no guarantees that the divider really is inserted. * @param x the x coordinate of the divider * @param y1 the first y coordinate of the divider * @param y2 the second y coordinate of the divider */ public void addVerticalDivider( double x, double y1, double y2 ){ grid.addVerticalDivider( x, y1, y2 ); } }