/*
* 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.station.toolbar.layout;
import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.DockElement;
import bibliothek.gui.dock.station.support.ConvertedPlaceholderListItem;
import bibliothek.gui.dock.station.support.PlaceholderList;
import bibliothek.gui.dock.station.support.PlaceholderListItem;
import bibliothek.gui.dock.station.support.PlaceholderListItemConverter;
import bibliothek.gui.dock.station.support.PlaceholderMap;
import bibliothek.gui.dock.station.toolbar.layout.GridPlaceholderList.Column;
import bibliothek.gui.dock.station.toolbar.layout.GridPlaceholderList.ColumnItem;
import bibliothek.util.Path;
/**
* This {@link PlaceholderList} stores {@link Column}s as items, where one
* {@link Column} is just another {@link PlaceholderList}.
*
* @author Benjamin Sigg
* @param <D>
* the kind of object that should be treated as {@link Dockable}
* @param <S>
* the kind of object that should be treated as {@link DockStation}
* @param <P>
* the type of item which represents a {@link Dockable}
*/
public abstract class GridPlaceholderList<D, S, P extends PlaceholderListItem<D>> extends PlaceholderList<ColumnItem<D, S, P>, ColumnItem<D, S, P>, Column<D, S, P>> {
/**
* This {@link PlaceholderListItemConverter} is used to read and write
* {@link Column}s, the default setting just ignores any reference to any
* {@link Dockable}.
*/
private PlaceholderListItemConverter<D, P> converter;
public GridPlaceholderList(){
setConverter( null );
}
/**
* Factory method creating an new {@link Column} that can be added to this
* list.
*
* @param content
* the content of the column, not <code>null</code>
* @return a new, empty column that is yet unknown to this list
*/
public Column<D, S, P> createColumn( PlaceholderList<D, S, P> content ){
if( content == null ) {
throw new IllegalArgumentException( "content must not be null" );
}
return new ColumnList( content );
}
/**
* Sets the {@link PlaceholderListItemConverter} which should be used to
* convert the internal lists of this grid.
*
* @param converter
* the converter to use, can be <code>null</code>
*/
public void setConverter( PlaceholderListItemConverter<D, P> converter ){
if( converter == null ) {
converter = new PlaceholderListItemConverter<D, P>(){
@Override
public ConvertedPlaceholderListItem convert( int index, P dockable ){
return null;
}
@Override
public P convert( ConvertedPlaceholderListItem item ){
return null;
}
@Override
public void added( P dockable ){
// ignore
}
};
}
this.converter = converter;
}
/**
* Gets the converter that is used to read and write {@link Column}s.
*
* @return the converter, never <code>null</code>
*/
public PlaceholderListItemConverter<D, P> getConverter(){
return converter;
}
@Override
protected Path getPlaceholder( ColumnItem<D, S, P> dockable ){
return dockable.getPlaceholder();
}
@Override
protected String toString( ColumnItem<D, S, P> dockable ){
return dockable.toString();
}
@Override
protected ColumnItem<D, S, P> toStation( ColumnItem<D, S, P> dockable ){
return dockable.asStation();
}
@Override
protected PlaceholderMap getPlaceholders( ColumnItem<D, S, P> station ){
return station.getPlaceholders();
}
@Override
protected void setPlaceholders( ColumnItem<D, S, P> station, PlaceholderMap map ){
station.setPlaceholders( map );
}
@Override
protected ColumnItem<D, S, P>[] getChildren( ColumnItem<D, S, P> station ){
return station.getChildren();
}
/**
* Converts the item <code>dockable</code> to a station.
*
* @param dockable
* the item to convert
* @return the converted item or <code>null</code>
*/
protected abstract S itemToStation( D dockable );
/**
* Gets all the children of <code>station</code>
*
* @param station
* the station whose children are searched
* @return all the children
*/
protected abstract D[] getItemChildren( S station );
/**
* Gest the placeholder of <code>dockable</code>.
*
* @param dockable
* some element of this grid
* @return the placeholder or <code>null</code>
*/
protected abstract Path getItemPlaceholder( D dockable );
/**
* Gets all the placeholders of <code>station</code>
*
* @param station
* some station
* @return all the placeholders, can be <code>null</code>
*/
protected abstract PlaceholderMap getItemPlaceholders( S station );
/**
* Sets the placeholders that are to be used by <code>station</code>
*
* @param station
* the station whose layout is to be updated
* @param map
* the new placeholders, never <code>null</code>
*/
protected abstract void setItemPlaceholders( S station, PlaceholderMap map );
/**
* An class representing either a {@link Column} or a {@link DockElement}.
*
* @author Benjamin Sigg
*/
public interface ColumnItem<D, S, P extends PlaceholderListItem<D>> {
/**
* Converts this item into an item that represents a {@link DockStation}
*
* @return the station, can be <code>null</code>
*/
public ColumnItem<D, S, P> asStation();
/**
* Gets a placeholder for this item.
*
* @return the placeholder or <code>null</code>
*/
public Path getPlaceholder();
/**
* Gets the children of this station
*
* @return the children
*/
public ColumnItem<D, S, P>[] getChildren();
/**
* Gets all the placeholders of this item.
*
* @return all the placeholders, can be <code>null</code>
*/
public PlaceholderMap getPlaceholders();
/**
* Sets all the placeholders of this station.
*
* @param map
* the new placeholders
*/
public void setPlaceholders( PlaceholderMap map );
}
/**
* Represents some kind of {@link Dockable}.
*
* @author Benjamin Sigg
*/
private class DockableItem implements ColumnItem<D, S, P> {
private final D item;
public DockableItem( D item ){
this.item = item;
}
@Override
public String toString(){
return item.toString();
}
/**
* Gets <code>this</code> if {@link #item} is some kind of station.
*
* @return
*/
@Override
public ColumnItem<D, S, P> asStation(){
final S station = itemToStation( item );
if( station == null ) {
return null;
}
return new StationItem( station );
}
@Override
public Path getPlaceholder(){
return getItemPlaceholder( item );
}
@Override
public ColumnItem<D, S, P>[] getChildren(){
throw new IllegalStateException( "a " + getClass().getSimpleName() + " must not be asked for its children" );
}
@Override
public PlaceholderMap getPlaceholders(){
return null;
}
@Override
public void setPlaceholders( PlaceholderMap map ){
// ignore
}
}
/**
* Represents some kind of {@link DockStation}.
*
* @author Benjamin Sigg
*/
private class StationItem implements ColumnItem<D, S, P> {
private final S item;
public StationItem( S item ){
this.item = item;
}
@Override
public ColumnItem<D, S, P> asStation(){
return this;
}
@Override
public Path getPlaceholder(){
throw new IllegalStateException( "a " + getClass().getSimpleName() + " must not be asked for its placeholder" );
}
@SuppressWarnings("unchecked")
@Override
public ColumnItem<D, S, P>[] getChildren(){
final D[] children = getItemChildren( item );
final ColumnItem<D, S, P>[] result = new ColumnItem[children.length];
for( int i = 0; i < result.length; i++ ) {
result[i] = new DockableItem( children[i] );
}
return result;
}
@Override
public PlaceholderMap getPlaceholders(){
return getItemPlaceholders( item );
}
@Override
public void setPlaceholders( PlaceholderMap map ){
setItemPlaceholders( item, map );
}
}
/**
* Represents one list of {@link Dockable}s.
*
* @author Benjamin Sigg
*
* @param <D>
* the kind of object that should be treated as {@link Dockable}
* @param <S>
* the kind of object that should be treated as
* {@link DockStation}
* @param <P>
* the type of item which represents a {@link Dockable}
*/
public interface Column<D, S, P extends PlaceholderListItem<D>> extends ColumnItem<D, S, P>, PlaceholderListItem<ColumnItem<D, S, P>> {
/**
* Gets the list of dockables.
*
* @return the list that is represented by this column
*/
public PlaceholderList<D, S, P> getList();
}
private class ColumnList implements Column<D, S, P> {
private final PlaceholderList<D, S, P> list;
public ColumnList( PlaceholderList<D, S, P> list ){
this.list = list;
}
@Override
public ColumnItem<D, S, P> asDockable(){
return this;
}
@Override
public ColumnItem<D, S, P> asStation(){
return this;
}
@SuppressWarnings("unchecked")
@Override
public ColumnItem<D, S, P>[] getChildren(){
final ColumnItem<D, S, P>[] result = new ColumnItem[list.dockables().size()];
int index = 0;
for( final P item : list.dockables() ) {
result[index++] = new DockableItem( item.asDockable() );
}
return result;
}
@Override
public PlaceholderMap getPlaceholders(){
return list.toMap( converter );
}
@Override
public void setPlaceholders( PlaceholderMap map ){
list.clear();
list.read( map, converter );
}
/**
* Gets the list of {@link Dockable}s of this column.
*
* @return the list of items
*/
@Override
public PlaceholderList<D, S, P> getList(){
return list;
}
@Override
public Path getPlaceholder(){
return null;
}
}
}