/*
* 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.intern;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Map;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.DockFactory;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CStation;
import bibliothek.gui.dock.common.MultipleCDockable;
import bibliothek.gui.dock.common.MultipleCDockableFactory;
import bibliothek.gui.dock.common.MultipleCDockableLayout;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.perspective.CPerspective;
import bibliothek.gui.dock.common.perspective.CPerspectiveMultipleIdentifierCollection;
import bibliothek.gui.dock.common.perspective.CommonElementPerspective;
import bibliothek.gui.dock.common.perspective.MultipleCDockablePerspective;
import bibliothek.gui.dock.layout.LocationEstimationMap;
import bibliothek.gui.dock.perspective.PerspectiveDockable;
import bibliothek.gui.dock.station.support.PlaceholderStrategy;
import bibliothek.util.Version;
import bibliothek.util.xml.XElement;
/**
* A factory used to create {@link CommonDockable}s. This factory is only
* used to create {@link MultipleCDockable}s because {@link SingleCDockable}s
* are stored by the client.
* @author Benjamin Sigg
*/
public class CommonMultipleDockableFactory implements DockFactory<CommonDockable, CommonElementPerspective, CommonMultipleDockableLayout> {
/** the unique identifier of this factory */
private String id;
/** the factory used to read and write {@link MultipleCDockable}s */
private MultipleCDockableFactory<MultipleCDockable, MultipleCDockableLayout> delegate;
/** access to private properties of {@link CControl} */
private CControlAccess controlAccess;
/** access to private properties of {@link CPerspective} */
private CPerspectiveMultipleIdentifierCollection perspectiveIdentifiers;
/**
* Creates a new factory.
* @param id the identifier of this factory
* @param delegate the factory that should be used to load the contents of the
* new {@link CommonDockable}
* @param access access to the internal affairs of a {@link CControl}
*/
@SuppressWarnings("unchecked")
public CommonMultipleDockableFactory( String id, MultipleCDockableFactory<?,?> delegate, CControlAccess access ){
this.id = id;
this.delegate = (MultipleCDockableFactory<MultipleCDockable, MultipleCDockableLayout>)delegate;
this.controlAccess = access;
}
/**
* Creates a new factory.
* @param id the identifier of this factory
* @param delegate the factory that should be used to load the contents of the
* new {@link CommonDockable}
* @param access access to the internal affairs of a {@link CControl}
* @param perspective the {@link CPerspective} for which this factory is going to read and write elements
*/
@SuppressWarnings("unchecked")
public CommonMultipleDockableFactory( String id, MultipleCDockableFactory<?, ?> delegate, CControlAccess access, CPerspective perspective ){
this.id = id;
this.delegate = (MultipleCDockableFactory<MultipleCDockable, MultipleCDockableLayout>)delegate;
this.controlAccess = access;
this.perspectiveIdentifiers = new CPerspectiveMultipleIdentifierCollection( id, perspective );
}
public String getID() {
return id;
}
/**
* Gets the delegate of this factory.
* @return the delegate, not <code>null</code>
*/
public MultipleCDockableFactory<?, ?> getFactory(){
return delegate;
}
public void estimateLocations( CommonMultipleDockableLayout layout, LocationEstimationMap children ){
// currently not supported
}
public CommonMultipleDockableLayout getLayout( CommonDockable element, Map<Dockable, Integer> children ) {
MultipleCDockable dockable = (MultipleCDockable)element.getDockable();
MultipleCDockableLayout layout = delegate.write( dockable );
CommonMultipleDockableLayout flayout = new CommonMultipleDockableLayout();
flayout.setLayout( layout );
String uniqueId = controlAccess.access( element.getDockable() ).getUniqueId();
uniqueId = controlAccess.getRegister().multiToNormalId( uniqueId );
flayout.setId( uniqueId );
if( element.getDockable().getWorkingArea() != null )
flayout.setArea( element.getDockable().getWorkingArea().getUniqueId() );
return flayout;
}
public CommonMultipleDockableLayout getPerspectiveLayout( CommonElementPerspective element, Map<PerspectiveDockable, Integer> children ){
MultipleCDockablePerspective dockable = (MultipleCDockablePerspective)element.getElement();
MultipleCDockableLayout layout = dockable.getLayout();
CommonMultipleDockableLayout flayout = new CommonMultipleDockableLayout();
flayout.setLayout( layout );
String uniqueId = perspectiveIdentifiers.getUniqueId( dockable );
flayout.setId( uniqueId );
if( dockable.getWorkingArea() != null )
flayout.setArea( dockable.getWorkingArea().getUniqueId() );
return flayout;
}
public void layoutPerspective( CommonElementPerspective perspective, CommonMultipleDockableLayout layout, Map<Integer, PerspectiveDockable> children ){
MultipleCDockablePerspective multiple = (MultipleCDockablePerspective) perspective.getElement();
multiple.setLayout( layout.getLayout() );
perspectiveIdentifiers.putDockable( layout.getId(), multiple );
// working area
String areaId = layout.getArea();
if( areaId != null ){
multiple.setWorkingArea( perspectiveIdentifiers.getPerspective().getStation( areaId ) );
}
}
public CommonElementPerspective layoutPerspective( CommonMultipleDockableLayout layout, Map<Integer, PerspectiveDockable> children ){
MultipleCDockablePerspective perspective = new MultipleCDockablePerspective( getID(), layout.getId(), layout.getLayout() );
layoutPerspective( perspective.intern(), layout, children );
return perspective.intern();
}
public CommonDockable layout( CommonMultipleDockableLayout layout, Map<Integer, Dockable> children, PlaceholderStrategy placeholders ) {
return layout( layout, placeholders );
}
public CommonDockable layout( CommonMultipleDockableLayout layout, PlaceholderStrategy placeholders ) {
// base
MultipleCDockable dockable = delegate.read( layout.getLayout() );
if( dockable == null )
return null;
// id
String id = layout.getId();
MultipleCDockable oldDockable = controlAccess.getOwner().getMultipleDockable( id );
if( oldDockable != null ){
controlAccess.getOwner().replace( oldDockable, dockable );
}
else{
controlAccess.getOwner().addDockable( id, dockable );
}
// working area
String areaId = layout.getArea();
if( areaId != null ){
CStation<?> station = controlAccess.getOwner().getStation( areaId );
if( station != null ){
if( station.isWorkingArea() ){
dockable.setWorkingArea( station );
}
}
else{
for( int i = 0, n = controlAccess.getOwner().getCDockableCount(); i<n; i++ ){
CDockable check = controlAccess.getOwner().getCDockable( i );
CStation<?> checkStation = check.asStation();
if( checkStation != null && checkStation.isWorkingArea() ){
if( checkStation.getUniqueId().equals( areaId )){
// found
dockable.setWorkingArea( checkStation );
break;
}
}
}
}
}
return dockable.intern();
}
public void setLayout( CommonDockable element, CommonMultipleDockableLayout layout, Map<Integer, Dockable> children, PlaceholderStrategy placeholders ) {
// not supported
}
public void setLayout( CommonDockable element, CommonMultipleDockableLayout layout, PlaceholderStrategy placeholders ) {
// not supported
}
public CommonMultipleDockableLayout read( DataInputStream in, PlaceholderStrategy placeholders ) throws IOException {
Version version = Version.read( in );
version.checkCurrent();
CommonMultipleDockableLayout layout = new CommonMultipleDockableLayout();
layout.setLayout( delegate.create() );
layout.getLayout().readStream( in );
layout.setId( in.readUTF() );
if( in.readBoolean() )
layout.setArea( in.readUTF() );
return layout;
}
public CommonMultipleDockableLayout read( XElement element, PlaceholderStrategy placeholders ) {
CommonMultipleDockableLayout layout = new CommonMultipleDockableLayout();
layout.setLayout( delegate.create() );
layout.getLayout().readXML( element.getElement( "multiple" ) );
layout.setId( element.getElement( "id" ).getString() );
XElement xarea = element.getElement( "area" );
if( xarea != null )
layout.setArea( xarea.getString() );
return layout;
}
public void write( CommonMultipleDockableLayout layout, DataOutputStream out ) throws IOException {
Version.write( out, Version.VERSION_1_0_4 );
layout.getLayout().writeStream( out );
out.writeUTF( layout.getId() );
if( layout.getArea() == null ){
out.writeBoolean( false );
}
else{
out.writeBoolean( true );
out.writeUTF( layout.getArea() );
}
}
public void write( CommonMultipleDockableLayout layout, XElement element ) {
element.addElement( "id" ).setString( layout.getId() );
if( layout.getArea() != null )
element.addElement( "area" ).setString( layout.getArea() );
layout.getLayout().writeXML( element.addElement( "multiple" ) );
}
}