/* * 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) 2012 Herve Guillaume, 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 * * Herve Guillaume * rvguillaume@hotmail.com * FR - France * * Benjamin Sigg * benjamin_sigg@gmx.ch * CH - Switzerland */ package bibliothek.gui.dock.toolbar.perspective; import java.util.HashMap; import java.util.Map; import bibliothek.gui.DockStation; import bibliothek.gui.dock.perspective.PerspectiveDockable; import bibliothek.gui.dock.perspective.PerspectiveElement; import bibliothek.gui.dock.station.toolbar.ToolbarDockPerspective; import bibliothek.gui.dock.station.toolbar.ToolbarGroupDockPerspective; import bibliothek.gui.dock.station.toolbar.ToolbarStrategy; import bibliothek.gui.dock.station.toolbar.group.ToolbarColumn; /** * A wrapper around a {@link ToolbarGroupDockPerspective}, offers features that are * useful in the Common project only.<br> * A group of toolbars is organized similar to a table: there are columns of toolbars, and each * column has its own size.<br> * <b>Important note:</b> "columns" is an abstract idea, they do not exist as {@link DockStation}s. The {@link CToolbarGroupPerspective} * tries to keep its abstract representation of columns valid, if however two {@link CToolbarGroupPerspective}s point * to the same {@link ToolbarGroupDockPerspective} one perspective can modify the underlying data structure without * the other perspective noticing the changes immediately. * @author Benjamin Sigg */ public class CToolbarGroupPerspective { private ToolbarGroupDockPerspective delegate; /** all the columns that are currently alive */ private Map<ToolbarColumn<PerspectiveDockable, PerspectiveDockable>, Column> columns = new HashMap<ToolbarColumn<PerspectiveDockable, PerspectiveDockable>, CToolbarGroupPerspective.Column>(); /** * Creates a new perspective wrapping around <code>delegate</code>. * @param delegate the internal representation, not <code>null</code> */ public CToolbarGroupPerspective( ToolbarGroupDockPerspective delegate ){ if( delegate == null ) { throw new IllegalArgumentException( "delegate must not be null" ); } this.delegate = delegate; } @Override public boolean equals( Object obj ){ if( obj.getClass() == getClass() ) { return ((CToolbarGroupPerspective) obj).delegate == delegate; } return false; } /** * Allows access to the internal representation of this perspective. * @return the internal representation, not <code>null</code> */ public ToolbarGroupDockPerspective getDelegate(){ return delegate; } /** * Gets the total number of toolbars in this group. This method assumes that the * client did not modify the {@link ToolbarStrategy}. * @return the total number of toolbars */ public int getToolbarCount(){ return delegate.getDockableCount(); } /** * Gets the toolbar at location <code>index</code>. * @param index the location of the toolbar * @return the toolbar or <code>null</code> if the child at <code>index</code> has the wrong * type. A result of <code>null</code> is only to be expected if the client modified the * {@link ToolbarStrategy}. */ public CToolbarPerspective getToolbar( int index ){ PerspectiveElement child = delegate.getDockable( index ); if( child instanceof ToolbarDockPerspective ) { return new CToolbarPerspective( (ToolbarDockPerspective) child ); } else { return null; } } /** * Gets the total number of columns. * @return the number of columns */ public int getColumnCount(){ return delegate.getColumnCount(); } /** * Gets or creates the {@link Column} at <code>index</code>. Note that a {@link Column} requires * at least one child, a new {@link Column} will not appear until one child has been added. * @param index the index of an existing column, <code>-1</code> or {@link #getColumnCount()} * @return the column, note that this method may create a new {@link Column} object every time * it is called * @see #insert(int) * @see Column */ public Column column( int index ){ if( index < 0 ) { return insert( 0 ); } else if( index >= getColumnCount() ) { return insert( getColumnCount() ); } ToolbarColumn<PerspectiveDockable, PerspectiveDockable> column = delegate.getModel().getColumn( index ); Column result = columns.get( column ); if( result == null ) { result = new Column( index, column ); } result.validate(); return result; } /** * Creates a new, empty column. Only when the client adds a child to the {@link Column} the * column will insert itself at <code>index</code>. Creating a list of empty columns, and adding * children afterwards, will actually change the order of the columns to the order in which * the children were added. * @param index the location where to insert the new column * @return the new empty column * @see Column */ public Column insert( int index ){ return new Column( index ); } /** * Gets or creates a toolbar in column <code>column</code> at location <code>index</code>. * @param column the column in which to search or add the toolbar * @param index the location of the toolbar * @return the toolbar or <code>null</code> if a child of this station has the wrong type */ public CToolbarPerspective toolbar( int column, int index ){ return column( column ).toolbar( index ); } private void validateAll(){ for( Column column : columns.values().toArray( new Column[ columns.size() ] )){ column.validate(); } } /** * Represents a single column of toolbars in a group of toolbars. A column is a concept of the * user interface, as a result a column must contain at least one child. If a column does not * have children, it is not part of the group. It will however store its last index and can * insert itself at that last index again if new children are added. If several columns have * no children, then their order can change depending on the order in which new children are * added. * @author Benjamin Sigg */ public class Column { private int index; private ToolbarColumn<PerspectiveDockable, PerspectiveDockable> column; private Column( int index, ToolbarColumn<PerspectiveDockable, PerspectiveDockable> column ){ this.index = index; this.column = column; if( column != null ) { columns.put( column, this ); } } private Column( int index ){ this.index = index; } private void validate(){ if( column != null ){ int index = column.getColumnIndex(); if( index == -1 ){ columns.remove( column ); column = null; validateAll(); } else{ this.index = index; } } } /** * Gets the number of {@link CToolbarPerspective toolbars} in this column. * @return the number of toolbars */ public int getToolbarCount(){ validate(); if( column == null ) { return 0; } else { return column.getDockableCount(); } } /** * Gets or creates the toolbar at <code>index</code>. * @param index the location of the toolbar, <code>-1</code> or {@link #getToolbarCount()} * @return the toolbar or <code>null</code>. A value of <code>null</code> is only returned * if the child has a wrong type, this happens only if the client changed the {@link ToolbarStrategy} */ public CToolbarPerspective toolbar( int index ){ validate(); if( index < 0 ) { return insert( 0 ); } else if( index >= getToolbarCount() ) { return insert( getToolbarCount() ); } PerspectiveElement child = column.getDockable( index ); if( child instanceof ToolbarDockPerspective ) { return new CToolbarPerspective( (ToolbarDockPerspective) child ); } else { return null; } } /** * Creates a new toolbar at <code>index</code>. * @param index the location of the new toolbar * @return the new toolbar */ public CToolbarPerspective insert( int index ){ validate(); ToolbarDockPerspective toolbar = new ToolbarDockPerspective(); if( column == null ) { delegate.insert( this.index, toolbar ); column = delegate.getModel().getColumn( toolbar ); columns.put( column, this ); } else { delegate.insert( column.getColumnIndex(), index, toolbar ); } return new CToolbarPerspective( toolbar ); } /** * Removes the toolbar at location <code>index</code> from this column. * @param index the index of the toolbar to remove */ public void remove( int index ){ validate(); if( column != null ){ delegate.remove( column.getDockable( index ) ); } } /** * Removes <code>toolbar</code> from this column. * @param toolbar the toolbar to remove */ public void remove( CToolbarPerspective toolbar ){ validate(); delegate.remove( toolbar.getDelegate() ); } } }