/*
* 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.station;
import java.io.IOException;
import javax.swing.Icon;
import bibliothek.gui.DockController;
import bibliothek.gui.DockStation;
import bibliothek.gui.DockTheme;
import bibliothek.gui.DockUI;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.DockFactory;
import bibliothek.gui.dock.accept.DockAcceptance;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.displayer.DisplayerRequest;
import bibliothek.gui.dock.dockable.AbstractDockable;
import bibliothek.gui.dock.event.DockStationListener;
import bibliothek.gui.dock.station.layer.DefaultDropLayer;
import bibliothek.gui.dock.station.layer.DockStationDropLayer;
import bibliothek.gui.dock.station.support.DockStationListenerManager;
import bibliothek.gui.dock.title.ActivityDockTitleEvent;
import bibliothek.gui.dock.title.DockTitle;
import bibliothek.gui.dock.title.DockTitleRequest;
import bibliothek.gui.dock.util.DockUtilities;
import bibliothek.gui.dock.util.PropertyKey;
import bibliothek.gui.dock.util.icon.DockIcon;
import bibliothek.util.Todo;
import bibliothek.util.Todo.Compatibility;
import bibliothek.util.Todo.Priority;
import bibliothek.util.Todo.Version;
/**
* An abstract combination between {@link DockStation} and {@link Dockable}. This
* station has no functionality except the ability to store and call
* {@link DockStationListener DockStationListeners}.
* @author Benjamin Sigg
*
*/
public abstract class AbstractDockableStation extends AbstractDockable implements DockStation {
/**
* The list of {@link DockStationListener DockStationListeners} which
* can be used to send events to all listeners.
*/
protected DockStationListenerManager listeners = new DockStationListenerManager( this );
/** The theme of this station */
private DockTheme theme;
/**
* Constructs a new station, but does nothing more
*/
public AbstractDockableStation(){
super( PropertyKey.DOCK_STATION_TITLE, PropertyKey.DOCK_STATION_TOOLTIP );
}
@Override
protected DockIcon createTitleIcon(){
return new DockStationIcon( "dockStation.default", this ){
protected void changed( Icon oldValue, Icon newValue ){
fireTitleIconChanged( oldValue, newValue );
}
};
}
/**
* Constructs a new station and sets the theme.
* @param theme the theme, may be <code>null</code>
*/
public AbstractDockableStation( DockTheme theme ){
this();
this.theme = theme;
}
public DockStation asDockStation() {
return this;
}
public DockTheme getTheme() {
return theme;
}
public void updateTheme() {
DockController controller = getController();
if( controller != null ){
DockTheme newTheme = controller.getTheme();
if( newTheme != theme ){
theme = newTheme;
try{
callDockUiUpdateTheme();
}
catch( IOException ex ){
throw new RuntimeException( ex );
}
}
}
}
/**
* Calls the method {@link DockUI}.{@link DockUI#updateTheme(DockStation, DockFactory)}
* with <code>this</code> as the first argument, and an appropriate factory
* as the second argument.
* @throws IOException if the DockUI throws an exception
*/
protected abstract void callDockUiUpdateTheme() throws IOException;
public DockActionSource getDirectActionOffers( Dockable dockable ) {
return null;
}
public DockActionSource getIndirectActionOffers( Dockable dockable ) {
return null;
}
public void addDockStationListener( DockStationListener listener ) {
listeners.addListener( listener );
}
public void removeDockStationListener( DockStationListener listener ) {
listeners.removeListener( listener );
}
@Deprecated
@Todo( compatibility=Compatibility.BREAK_MAJOR, priority=Priority.ENHANCEMENT, target=Version.VERSION_1_1_3, description="remove this method" )
public boolean isVisible( Dockable dockable ) {
return isStationShowing();
}
public boolean isChildShowing( Dockable dockable ){
return isVisible( dockable );
}
public boolean isStationShowing(){
return isStationVisible();
}
@Deprecated
@Todo( compatibility=Compatibility.BREAK_MAJOR, priority=Priority.ENHANCEMENT, target=Version.VERSION_1_1_3, description="remove this method" )
public boolean isStationVisible() {
boolean visible = isDockableShowing();
if( visible ){
return true;
}
if( getController() != null ){
return getComponent().isShowing();
}
return false;
}
public boolean accept( Dockable child ) {
return true;
}
/**
* Tells whether this station accepts <code>child</code> as new child. This is a shortcut
* asking {@link #accept(Dockable)}, {@link Dockable#accept(DockStation)} and
* {@link DockAcceptance#accept(DockStation, Dockable)} in one go.
* @param child the child to add
* @return <code>true</code> if acceptable
*/
public boolean acceptable( Dockable child ){
return DockUtilities.acceptable( this, child );
}
/**
* Tells whether this station accepts <code>child</code> as combination with <code>old</code>.
* @param old some child of this station
* @param next a new child
* @return <code>true</code> if <code>old</code> and <code>next</code> can be combined
*/
public boolean acceptable( Dockable old, Dockable next ){
return DockUtilities.acceptable( this, old, next );
}
public void changed( Dockable dockable, DockTitle title, boolean active ) {
title.changed( new ActivityDockTitleEvent( this, dockable, active ));
}
public void requestChildDockTitle( DockTitleRequest request ){
// ignore
}
public void requestChildDisplayer( DisplayerRequest request ){
// ignore
}
public DockStationDropLayer[] getLayers(){
return new DockStationDropLayer[]{
new DefaultDropLayer( this )
};
}
/**
* Invokes {@link DockStationListenerManager#fireDockablesRepositioned(Dockable...)} for
* all children starting at index <code>fromIndex</code>.
* @param fromIndex the index of the first moved child
*/
protected void fireDockablesRepositioned( int fromIndex ){
fireDockablesRepositioned( fromIndex, getDockableCount()-1 );
}
/**
* Invokes {@link DockStationListenerManager#fireDockablesRepositioned(Dockable...)} for
* all children starting at index <code>fromIndex</code> to index <code>toIndex</code>.
* @param fromIndex the index of the first moved child
* @param toIndex the index of the last moved child
*/
protected void fireDockablesRepositioned( int fromIndex, int toIndex ){
int count = toIndex - fromIndex + 1;
if( count > 0 ){
Dockable[] moved = new Dockable[count];
for( int i = 0; i < count; i++ ){
moved[i] = getDockable( i+fromIndex );
}
listeners.fireDockablesRepositioned( moved );
}
}
/**
* Creates a generic set of algorithms.
* @return the algorithms, not <code>null</code>
*/
protected DockStationDelegate delegate(){
return new DockStationDelegate();
}
}