/*
* 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) 2011 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.displayer;
import bibliothek.gui.DockController;
import bibliothek.gui.DockStation;
import bibliothek.gui.DockTheme;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.station.DisplayerFactory;
import bibliothek.gui.dock.station.DockableDisplayer;
import bibliothek.gui.dock.title.DockTitle;
import bibliothek.gui.dock.util.ResourceRequest;
import bibliothek.gui.dock.util.extension.Extension;
import bibliothek.gui.dock.util.extension.ExtensionName;
import bibliothek.gui.dock.util.extension.SharedExtension;
/**
* A {@link DisplayerRequest} is an object that can create new {@link DockableDisplayer}s by
* calling several factories.
* @author Benjamin Sigg
*/
public abstract class DisplayerRequest extends ResourceRequest<DockableDisplayer>{
/** the element for which the displayer is shown */
private Dockable target;
/** the element that shows the displayer */
private DockStation parent;
/** the title that should be forwarded to the displayer, may be <code>null</code> */
private DockTitle title;
/** the controller in whose realm this request is used, can be <code>null</code> */
private DockController controller;
/** factories added by an extension */
private SharedExtension<DisplayerFactory> extensions;
/** default factory provided by the {@link DockTheme} */
private DisplayerFactory defaultFactory;
/** name forwarded to the {@link ExtensionName} */
private String displayerId;
/**
* Creates a new request.
* @param parent the station which is going to show the {@link DockableDisplayer}.
* @param target the element which is going to be shown in the displayer
* @param defaultFactory the default factory, to be used if no other way was found to create the {@link DockableDisplayer}
* @param displayerId a unique identifier that depends on the type of <code>parent</code>, this identifier will be forwarded to
* {@link Extension}s allowing them an easy way to filter uninteresting {@link DisplayerRequest}s, must not be <code>null</code>
*/
public DisplayerRequest( DockStation parent, Dockable target, DisplayerFactory defaultFactory, String displayerId ){
if( parent == null ){
throw new IllegalArgumentException( "parent must not be null" );
}
if( target == null ){
throw new IllegalArgumentException( "target must not be null" );
}
if( displayerId == null ){
throw new IllegalArgumentException( "displayerId must not be null" );
}
this.parent = parent;
this.target = target;
this.defaultFactory = defaultFactory;
this.displayerId = displayerId;
}
/**
* Sets the {@link DockController} in whose realm this {@link DisplayerRequest} is used. The {@link DockController} can
* be used to load extensions.
* @param controller the controller, can be <code>null</code>
*/
public void setController( DockController controller ){
if( this.controller != controller ){
this.controller = controller;
if( extensions != null ){
extensions.unbind();
extensions = null;
}
if( controller != null ){
extensions = controller.getExtensions().share( new ExtensionName<DisplayerFactory>( DisplayerFactory.DISPLAYER_EXTENSION, DisplayerFactory.class, DisplayerFactory.DISPLAYER_EXTENSION_ID, displayerId ) );
extensions.bind();
}
}
}
/**
* Gets the controller in whose realm this request is issued.
* @return the controller, might be <code>null</code>
*/
public DockController getController(){
return controller;
}
/**
* Creates a new {@link DockableDisplayer}.
* @param title the title that should be shown on the displayer, may be <code>null</code>
*/
public void request( DockTitle title ){
this.title = title;
try{
request();
}
finally{
this.title = null;
}
}
/**
* Gets the {@link Dockable} which is going to be shown in the {@link DockableDisplayer}.
* @return the dockable, not <code>null</code>
*/
public Dockable getTarget(){
return target;
}
/**
* Gets the {@link DockStation} which is going to show the {@link DockableDisplayer}.
* @return the station, not <code>null</code>
*/
public DockStation getParent(){
return parent;
}
/**
* Gets the title that should be shown on the displayer.
* @return the title to show, or <code>null</code>
*/
public DockTitle getTitle(){
return title;
}
/**
* Sets the {@link DockableDisplayer} which should be shown. A valid displayer must meet the following
* conditions:
* <ul>
* <li>it must not be <code>null</code></li>
* <li>the result of {@link DockableDisplayer#getDockable()} must be {@link #getTarget()}</li>
* </ul>
* @throws IllegalStateException if {@link #request()} was not called
* @throws IllegalArgumentException if <code>displayer</code> is <code>null</code>
*/
@Override
public void answer( DockableDisplayer displayer ){
super.answer( displayer );
}
@Override
protected void executeRequestList(){
target.requestDisplayer( this );
if( isAnswered() ){
return;
}
parent.requestChildDisplayer( this );
if( isAnswered() ){
return;
}
if( extensions != null ){
for( DisplayerFactory factory : extensions ){
factory.request( this );
if( isAnswered() ){
return;
}
}
}
defaultFactory.request( this );
}
@Override
protected void validate( DockableDisplayer resource ){
if( resource == null ){
throw new IllegalArgumentException( "displayer is null" );
}
if( resource.getDockable() != getTarget() ){
throw new IllegalArgumentException( "displayer.getDockable() is not target" );
}
}
}