All Downloads are FREE. Search and download functionalities are using the official Maven repository.

bibliothek.gui.dock.common.perspective.CControlPerspective Maven / Gradle / Ivy

Go to download

DockingFrames is an open source Java Swing docking framework, licenced under LGPL 2.1. This is the same distribution as the original distribution (http://www.docking-frames.org/), only reinstalled in maven

There is a newer version: 1.1.2p20b.fix-1
Show newest version
/*
 * 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) 2010 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
 * [email protected]
 * CH - Switzerland
 */
package bibliothek.gui.dock.common.perspective;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import bibliothek.gui.DockFrontend;
import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.DockElement;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CStation;
import bibliothek.gui.dock.common.CWorkingArea;
import bibliothek.gui.dock.common.MultipleCDockable;
import bibliothek.gui.dock.common.MultipleCDockableFactory;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.intern.CControlAccess;
import bibliothek.gui.dock.common.intern.CDockFrontend;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.intern.CSetting;
import bibliothek.gui.dock.common.intern.CommonDockable;
import bibliothek.gui.dock.common.intern.CommonMultipleDockableFactory;
import bibliothek.gui.dock.common.intern.CommonSingleDockableFactory;
import bibliothek.gui.dock.common.intern.CommonSingleDockableLayout;
import bibliothek.gui.dock.common.intern.RootStationAdjacentFactory;
import bibliothek.gui.dock.common.intern.station.CommonDockStationFactory;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.facile.mode.Location;
import bibliothek.gui.dock.facile.mode.LocationSettingConverter;
import bibliothek.gui.dock.frontend.DockFrontendPerspective;
import bibliothek.gui.dock.frontend.FrontendPerspectiveCache;
import bibliothek.gui.dock.frontend.RegisteringDockFactory;
import bibliothek.gui.dock.frontend.Setting;
import bibliothek.gui.dock.layout.DockLayout;
import bibliothek.gui.dock.layout.DockLayoutComposition;
import bibliothek.gui.dock.layout.DockSituation;
import bibliothek.gui.dock.layout.DockableProperty;
import bibliothek.gui.dock.layout.PropertyTransformer;
import bibliothek.gui.dock.perspective.Perspective;
import bibliothek.gui.dock.perspective.PerspectiveElement;
import bibliothek.gui.dock.perspective.PerspectiveStation;
import bibliothek.gui.dock.perspective.PredefinedPerspective;
import bibliothek.gui.dock.support.mode.ModeSettings;
import bibliothek.gui.dock.support.mode.ModeSettingsConverter;
import bibliothek.util.ClientOnly;
import bibliothek.util.FrameworkOnly;
import bibliothek.util.Path;
import bibliothek.util.Version;
import bibliothek.util.xml.XElement;
import bibliothek.util.xml.XException;

/**
 * A {@link CControlPerspective} is a wrapper around a {@link CControl} allowing
 * access to various {@link CPerspective}s.
 * @author Benjamin Sigg
 */
@ClientOnly
public class CControlPerspective {
	private CControlAccess control;
	
	/**
	 * Creates a new wrapper
	 * @param control the control whose perspectives are modified
	 */
	public CControlPerspective( CControlAccess control ){
		if( control == null ){
			throw new IllegalArgumentException( "control must not be null" );
		}
		
		this.control = control;
	}
	
	/**
	 * Gets the {@link CControl} in whose realm this {@link CControlPerspective} operates.
	 * @return the owner of this perspective
	 */
	public CControl getControl(){
		return control.getOwner();
	}
    
    /**
     * Creates a new {@link CPerspective} that is set up with all the stations of the {@link CControl}. 
     * There are no {@link Dockable}s stored in the new perspective.
     * @return the new perspective
     */
    public CPerspective createEmptyPerspective(){
    	CPerspective perspective = new CPerspective( control );
    	for( CStation station : control.getOwner().getStations() ){
    		perspective.addStation( station.createPerspective() );
    	}
    	return perspective;
    }
    
    /**
     * Gets a perspective that matches the current layout of the application.
     * @param includeWorkingAreas whether {@link Dockable}s that are managed by a working-area should be
     * included in the layout or not
     * @return the current perspective
     */
    public CPerspective getPerspective( boolean includeWorkingAreas ){
    	Setting setting = control.getOwner().intern().getSetting( !includeWorkingAreas );
    	return convert( (CSetting)setting, includeWorkingAreas );
    }

    /**
     * Gets the names of all the perspectives that are available.
     * @return all the names
     */
    public String[] getNames(){
    	return control.getOwner().layouts();
    }
    
    /**
     * Gets the perspective which represents a layout that was stored using {@link CControl#save(String)}.
     * @param name the name of the stored layout
     * @return the perspective or null if name was not found
     */
    public CPerspective getPerspective( String name ){
    	return getPerspective( name, false );
    }

    /**
     * Gets the perspective which represents a layout that was stored using {@link CControl#save(String)}.
     * @param name the name of the stored layout
     * @param includeWorkingAreas whether the content of working areas should be included (requires that
     * the layout was saved in the first place)
     * @return the perspective or null if name was not found
     */
    public CPerspective getPerspective( String name, boolean includeWorkingAreas ){
    	Setting setting = control.getOwner().intern().getSetting( name );
    	if( setting == null ){
    		return null;
    	}
    	return convert( (CSetting)setting, includeWorkingAreas );
    }
    
    /**
     * Changes the layout of the associated {@link CControl} such that it matches perspective. 
     * @param perspective the perspective to apply, not null
     * @param includeWorkingAreas whether {@link Dockable}s that are managed by a working-area should be
     * included in the layout or not
     */
    public void setPerspective( CPerspective perspective, boolean includeWorkingAreas ){
    	control.getOwner().intern().setSetting( convert( perspective, includeWorkingAreas ), !includeWorkingAreas );
    }
    
    /**
     * Stores perspective as a layout that can be selected by the user by calling
     * {@link CControl#load(String)}.
* The contents of working areas are ignored by this method. * @param name the name of the layout * @param perspective the new layout, not null */ public void setPerspective( String name, CPerspective perspective ){ setPerspective( name, perspective, false ); } /** * Stores perspective as a layout that can be selected by the user by calling * {@link CControl#load(String)}. * @param name the name of the layout * @param perspective the new layout, not null * @param includeWorkingAreas whether the contents of working areas should be stored as well */ public void setPerspective( String name, CPerspective perspective, boolean includeWorkingAreas ){ control.getOwner().intern().setSetting( name, convert( perspective, includeWorkingAreas ) ); } /** * Deletes the perspective with name name. * @param name the name of the perspective */ public void removePerspective( String name ){ control.getOwner().delete( name ); } /** * Renames the perspective source to destination. If there is already a * layout with name destination it will be overridden. This operation works directly on the * {@link CControl}, already existing {@link CPerspective}s will not be affected by invoking this method. * @param source the name of the source * @param destination the name of the destination * @throws IllegalArgumentException if source does not point to an existing layout * @throws IllegalArgumentException if either source or destination are null */ public void renamePerspective( String source, String destination ){ if( source == null ){ throw new IllegalArgumentException( "source is null" ); } if( destination == null ){ throw new IllegalArgumentException( "destination is null" ); } CDockFrontend frontend = control.getOwner().intern(); Setting layout = frontend.getSetting( source ); if( layout == null ){ throw new IllegalArgumentException( "no perspective registered with name '" + source + "'" ); } frontend.setSetting( destination, layout ); frontend.delete( source ); if( source.equals( frontend.getCurrentSetting() )){ frontend.setCurrentSettingName( destination ); } } /** * Writes the contents of perspective into root using the factories provided * by this {@link CControlPerspective}. * @param root the element to write into, not null * @param perspective the perspective to write, not null */ public void writeXML( XElement root, CPerspective perspective ){ writeXML( root, perspective, true ); } /** * Writes the contents of perspective into root using the factories provided * by this {@link CControlPerspective}. * @param root the element to write into, not null * @param perspective the perspective to write, not null * @param includeWorkingAreas whether the output contains information about children of {@link CStation#isWorkingArea() working areas} * (includeWorkingAreas = true) or not (includeWorkingAreas = false) */ public void writeXML( XElement root, CPerspective perspective, boolean includeWorkingAreas ){ perspective.storeLocations(); DockFrontendPerspective frontend = conversion( perspective, includeWorkingAreas ); Perspective conversion = frontend.getPerspective(); Map stations = new HashMap(); for( String key : perspective.getStationKeys() ){ CStationPerspective station = perspective.getStation( key ); if( station.asDockable() == null || station.asDockable().getParent() == null ){ stations.put( key, conversion.convert( station.intern() )); } } conversion.getSituation().writeCompositionsXML( stations, root.addElement( "stations" ) ); // Store the last location of all known elements XElement xinvisible = root.addElement( "invisible" ); PropertyTransformer transformer = frontend.getPropertyTransformer(); for( String key : perspective.getDockableKeys() ){ CDockablePerspective dockable = perspective.getDockable( key ); Location location = getInvisibleLocation( dockable ); if( location != null ){ XElement xdockable = xinvisible.addElement( "dockable" ); xdockable.addString( "key", key ); if( dockable.getParent() == null ){ conversion.getSituation().writeCompositionXML( conversion.convert( dockable.intern() ), xdockable.addElement( "content" ) ); } XElement xlocation = xdockable.addElement( "location" ); xlocation.addString( "root", location.getRoot() ); xlocation.addString( "mode", dockable.getLocationHistory().getLastMode().getModeIdentifier().toString() ); xlocation.addBoolean( "applicationDefined", location.isApplicationDefined() ); transformer.writeXML( location.getLocation(), xlocation ); } } // store more location information ModeSettings settings = perspective.getLocationManager().writeModes( control ); settings.writeXML( root.addElement( "modes" ) ); } /** * Writes the contents of perspective into out using the factories provided * by this {@link CControlPerspective}. * @param out the stream to write into, not null * @param perspective the perspective to write, not null * @throws IOException if out is not writeable */ public void write( DataOutputStream out, CPerspective perspective ) throws IOException{ write( out, perspective, true ); } /** * Writes the contents of perspective into out using the factories provided * by this {@link CControlPerspective}. * @param out the stream to write into, not null * @param perspective the perspective to write, not null * @param includeWorkingAreas whether the output contains information about children of {@link CStation#isWorkingArea() working areas} * (includeWorkingAreas = true) or not (includeWorkingAreas = false) * @throws IOException if out is not writeable */ public void write( DataOutputStream out, CPerspective perspective, boolean includeWorkingAreas ) throws IOException{ perspective.storeLocations(); Version.write( out, Version.VERSION_1_1_2 ); DockFrontendPerspective frontend = conversion( perspective, includeWorkingAreas ); Perspective conversion = frontend.getPerspective(); Map stations = new HashMap(); for( String key : perspective.getStationKeys() ){ CStationPerspective station = perspective.getStation( key ); stations.put( key, conversion.convert( station.intern() )); } conversion.getSituation().writeCompositions( stations, out ); // Store the last location of all known elements String[] keys = perspective.getDockableKeys(); out.writeInt( keys.length ); PropertyTransformer transformer = frontend.getPropertyTransformer(); for( String key : keys ){ CDockablePerspective dockable = perspective.getDockable( key ); Location location = getInvisibleLocation( dockable ); if( location != null ){ out.writeBoolean( true ); out.writeUTF( key ); if( dockable.getParent() == null ){ out.writeBoolean( true ); conversion.getSituation().writeComposition( conversion.convert( dockable.intern() ), out ); } else{ out.writeBoolean( false ); } out.writeUTF( location.getRoot() ); out.writeUTF( dockable.getLocationHistory().getLastMode().getModeIdentifier().toString() ); out.writeBoolean( location.isApplicationDefined() ); transformer.write( location.getLocation(), out ); } else{ out.writeBoolean( false ); } } // write more location information ModeSettings settings = perspective.getLocationManager().writeModes( control ); settings.write( out ); } /** * Converts perspective into a {@link CSetting}. * @param perspective the perspective to convert * @param includeWorkingAreas whether the children of {@link CWorkingArea}s should be stored as well * @return the converted perspective */ public CSetting write( CPerspective perspective, boolean includeWorkingAreas ){ return convert( perspective, includeWorkingAreas ); } /** * Emulates a call to {@link CControl#readXML(XElement)} and returns all the layouts that are stored * within root. * @param root the root xml element of a file * @return all the layouts and settings stored in root * @throws XException if root is not well formed */ public CControlPerspectiveBlop readAllXML( XElement root ) throws XException{ CControlPerspectiveBlop blop = new CControlPerspectiveBlop( this ); blop.readXML( root ); return blop; } /** * Creates a new {@link CPerspective} using the information stored in root. While this method * uses the factories provided by this {@link CControlPerspective}, the new {@link CPerspective} is not registered * anywhere. It is the clients responsibility to call {@link #setPerspective(String, CPerspective)} or * {@link #setPerspective(CPerspective, boolean)} to actually use the result of this method. * @param root the element which contains information about a perspective * @return the new perspective * @throws XException if the structure of root is not as expected */ public CPerspective readXML( XElement root ) throws XException{ return readXML( root, true ); } /** * Creates a new {@link CPerspective} using the information stored in root. While this method * uses the factories provided by this {@link CControlPerspective}, the new {@link CPerspective} is not registered * anywhere. It is the clients responsibility to call {@link #setPerspective(String, CPerspective)} or * {@link #setPerspective(CPerspective, boolean)} to actually use the result of this method. * @param root the element which contains information about a perspective * @return the new perspective * @param includeWorkingAreas whether the perspective contains information about children of {@link CStation#isWorkingArea() working areas} * (includeWorkingAreas = true) or not (includeWorkingAreas = false). This parameter should have the same value as was used * when calling {@link #write(DataOutputStream, CPerspective, boolean)}. * @throws XException if the structure of root is not as expected */ public CPerspective readXML( XElement root, boolean includeWorkingAreas ) throws XException{ CPerspective perspective = createEmptyPerspective(); PerspectiveElementFactory factory = new PerspectiveElementFactory( perspective ); DockFrontendPerspective frontend = wrap( perspective, includeWorkingAreas, factory ); Perspective conversion = frontend.getPerspective(); for( Map.Entry> item : control.getRegister().getFactories().entrySet() ){ conversion.getSituation().add( new CommonMultipleDockableFactory( item.getKey(), item.getValue(), control, perspective ) ); } XElement xstations = root.getElement( "stations" ); if( xstations == null ){ throw new XException( "missing element 'stations'" ); } Map stations = conversion.getSituation().readCompositionsXML( xstations ); factory.setStations( stations ); for( DockLayoutComposition composition : stations.values() ){ PerspectiveElement station = conversion.convert( composition ); if( station instanceof CommonElementPerspective ){ CStationPerspective stationPerspective = ((CommonElementPerspective)station).getElement().asStation(); if( stationPerspective != null ){ perspective.addStation( stationPerspective ); } } } perspective.storeLocations(); // read the last known location of all elements XElement xinvisible = root.getElement( "invisible" ); if( xinvisible != null ){ PropertyTransformer transformer = frontend.getPropertyTransformer(); for( XElement xdockable : xinvisible.getElements( "dockable" )){ String key = xdockable.getString( "key" ); CDockablePerspective dockable = perspective.getDockable( key ); if( dockable == null ){ XElement xcontent = xdockable.getElement( "content" ); if( xcontent != null ){ PerspectiveElement element = conversion.convert( conversion.getSituation().readCompositionXML( xcontent ) ); if( element instanceof CommonElementPerspective ){ dockable = ((CommonElementPerspective)element).getElement().asDockable(); if( dockable != null ){ perspective.putDockable( dockable ); } } } } if( dockable != null ){ XElement xlocation = xdockable.getElement( "location" ); String locationRoot = xlocation.getString( "root" ); DockableProperty location = transformer.readXML( xlocation ); Path mode = new Path( xlocation.getString( "mode" )); boolean applicationDefined = false; if( xlocation.attributeExists( "applicationDefined" )){ applicationDefined = xlocation.getBoolean( "applicationDefined" ); } ExtendedMode extendedMode = perspective.getLocationManager().getMode( mode ); if( extendedMode != null ){ dockable.getLocationHistory().add( extendedMode, new Location( mode, locationRoot, location, applicationDefined ) ); } } } } XElement xmodes = root.getElement( "modes" ); if( xmodes == null ){ throw new XException( "missing element 'modes'" ); } ModeSettingsConverter converter = new LocationSettingConverter( control.getOwner().getController() ); ModeSettings modes = control.getOwner().getLocationManager().createModeSettings( converter ); modes.readXML( xmodes ); perspective.getLocationManager().readModes( modes, perspective, control ); return perspective; } /** * Emulates a call to {@link CControl#read(DataInputStream)} and returns all the layouts that are stored * in the stream in. * @param in the bytes of some layout file * @return all the layouts and settings that can be read from in * @throws IOException if there is a problem reading in or if in is not well formed */ public CControlPerspectiveBlop readAll( DataInputStream in ) throws IOException{ CControlPerspectiveBlop blop = new CControlPerspectiveBlop( this ); blop.read( in ); return blop; } /** * Creates a new {@link CPerspective} using the information stored in in. While this method * uses the factories provided by this {@link CControlPerspective}, the new {@link CPerspective} is not registered * anywhere. It is the clients responsibility to call {@link #setPerspective(String, CPerspective)} or * {@link #setPerspective(CPerspective, boolean)} to actually use the result of this method. * @param in the stream to read data from * @return the new perspective * @throws IOException if in is not readable or in the wrong format */ public CPerspective read( DataInputStream in ) throws IOException{ return read( in, true ); } /** * Creates a new {@link CPerspective} using the information stored in in. While this method * uses the factories provided by this {@link CControlPerspective}, the new {@link CPerspective} is not registered * anywhere. It is the clients responsibility to call {@link #setPerspective(String, CPerspective)} or * {@link #setPerspective(CPerspective, boolean)} to actually use the result of this method. * @param in the stream to read data from * @param includeWorkingAreas whether the perspective contains information about children of {@link CStation#isWorkingArea() working areas} * (includeWorkingAreas = true) or not (includeWorkingAreas = false). This parameter should have the same value as was used * when calling {@link #write(DataOutputStream, CPerspective, boolean)}. * @return the new perspective * @throws IOException if in is not readable or in the wrong format */ public CPerspective read( DataInputStream in, boolean includeWorkingAreas ) throws IOException{ Version version = Version.read( in ); boolean version111 = version.equals( Version.VERSION_1_1_1 ); boolean version111a = version.equals( Version.VERSION_1_1_1a ); boolean version112 = version.equals( Version.VERSION_1_1_2 ); if( !version111 && !version111a && !version112 ){ throw new IOException( "unknown version: " + version ); } CPerspective perspective = createEmptyPerspective(); PerspectiveElementFactory factory = new PerspectiveElementFactory( perspective ); DockFrontendPerspective frontend = wrap( perspective, includeWorkingAreas, factory ); Perspective conversion = frontend.getPerspective(); for( Map.Entry> item : control.getRegister().getFactories().entrySet() ){ conversion.getSituation().add( new CommonMultipleDockableFactory( item.getKey(), item.getValue(), control, perspective ) ); } Map stations = conversion.getSituation().readCompositions( in ); factory.setStations( stations ); for( DockLayoutComposition composition : stations.values() ){ PerspectiveElement station = conversion.convert( composition ); if( station instanceof CommonElementPerspective ){ CStationPerspective stationPerspective = ((CommonElementPerspective)station).getElement().asStation(); if( stationPerspective != null ){ perspective.addStation( stationPerspective ); } } } if( version111a || version112 ){ perspective.storeLocations(); PropertyTransformer transformer = frontend.getPropertyTransformer(); for( int i = 0, n = in.readInt(); i converter = new LocationSettingConverter( control.getOwner().getController() ); ModeSettings modes = control.getOwner().getLocationManager().createModeSettings( converter ); modes.read( in ); perspective.getLocationManager().readModes( modes, perspective, control ); return perspective; } /** * Creates a new {@link CPerspective} and fills it using the information from setting. * @param setting the layout to convert * @param includeWorkingAreas whether the layout contains information about children of {@link CWorkingArea}s * @return the layout of setting */ public CPerspective read( CSetting setting, boolean includeWorkingAreas ){ return convert( setting, includeWorkingAreas ); } private CSetting convert( CPerspective perspective, boolean includeWorkingAreas ){ perspective.storeLocations(); DockFrontendPerspective frontend = conversion( perspective, includeWorkingAreas ); Perspective conversion = frontend.getPerspective(); CSetting setting = new CSetting(); // layout for( String key : perspective.getStationKeys() ){ CStationPerspective station = perspective.getStation( key ); if( station.asDockable() == null || station.asDockable().getParent() == null ){ setting.putRoot( key, conversion.convert( station.intern() ) ); } } // invisible items (storing location of visible items as well) for( String key : perspective.getDockableKeys() ){ CDockablePerspective dockable = perspective.getDockable( key ); Location location = getInvisibleLocation( dockable ); if( location != null ){ setting.addInvisible( key, location.getRoot(), null, location.getLocation() ); } } ModeSettings settings = perspective.getLocationManager().writeModes( control ); setting.setModes( settings ); return setting; } private CPerspective convert( CSetting setting, boolean includeWorkingAreas ){ CPerspective cperspective = createEmptyPerspective(); PerspectiveElementFactory factory = new PerspectiveElementFactory( cperspective ); DockFrontendPerspective frontend = wrap( cperspective, includeWorkingAreas, factory ); Perspective conversion = frontend.getPerspective(); for( Map.Entry> item : control.getRegister().getFactories().entrySet() ){ conversion.getSituation().add( new CommonMultipleDockableFactory( item.getKey(), item.getValue(), control, cperspective ) ); } // registered dockables Map stations = new HashMap(); for( String root : setting.getRootKeys() ){ stations.put( root, setting.getRoot( root ) ); } factory.setStations( stations ); for( DockLayoutComposition composition : stations.values() ){ PerspectiveElement station = conversion.convert( composition ); if( station instanceof CommonElementPerspective ){ CStationPerspective stationPerspective = ((CommonElementPerspective)station).getElement().asStation(); if( stationPerspective != null ){ cperspective.addStation( stationPerspective ); } } } // invisible dockables for( int i = 0, n = setting.getInvisibleCount(); i < n; i++ ){ DockLayoutComposition composition = setting.getInvisibleLayout( i ); if( composition != null ){ PerspectiveElement element = conversion.convert( composition ); if( element instanceof CommonElementPerspective ){ CDockablePerspective dockable = ((CommonElementPerspective)element).getElement().asDockable(); if( dockable != null ){ DockableProperty location = setting.getInvisibleLocation( i ); String root = setting.getInvisibleRoot( i ); ExtendedMode mode = cperspective.getLocationManager().getMode( root, location ); if( mode != null ){ dockable.getLocationHistory().add( mode, new Location( mode.getModeIdentifier(), root, location, false ) ); } cperspective.putDockable( dockable ); } } } } // location information ModeSettings modes = setting.getModes(); cperspective.getLocationManager().readModes( modes, cperspective, control ); return cperspective; } private Location getInvisibleLocation( CDockablePerspective dockable ){ LocationHistory history = dockable.getLocationHistory(); List order = history.getOrder(); if( !order.isEmpty() ){ Path mode = order.get( order.size()-1 ); Location location = history.getLocations().get( mode ); return location; } return null; } /** * Creates a new {@link DockFrontendPerspective} which uses the settings from perspective to read * and write layouts. This method adds {@link CommonSingleDockableFactory}, {@link CommonMultipleDockableFactory} and * {@link CommonDockStationFactory} to the perspective.
* Clients usually have no need to call this method. * @param perspective the perspective whose settings should be used for reading or writing a layout * @param includeWorkingAreas whether the contents of {@link CStation#isWorkingArea() working areas} * should be included in the layout or not * @return the new builder */ @FrameworkOnly public DockFrontendPerspective conversion( CPerspective perspective, boolean includeWorkingAreas ){ DockFrontendPerspective conversion = wrap( perspective, includeWorkingAreas ); DockSituation situation = conversion.getPerspective().getSituation(); for( Map.Entry> item : control.getRegister().getFactories().entrySet() ){ situation.add( new CommonMultipleDockableFactory( item.getKey(), item.getValue(), control, perspective ) ); } return conversion; } private DockFrontendPerspective wrap( CPerspective perspective, boolean includeWorkingAreas ){ PerspectiveElementFactory factory = new PerspectiveElementFactory( perspective ); return wrap( perspective, includeWorkingAreas, factory ); } private DockFrontendPerspective wrap( CPerspective perspective, boolean includeWorkingAreas, PerspectiveElementFactory factory ){ DockFrontendPerspective frontend = control.getOwner().intern().getPerspective( !includeWorkingAreas, factory ); PredefinedPerspective inner = frontend.getPerspective(); factory.setBasePerspective( inner ); CommonSingleDockableFactory singleDockableFactory = new CommonSingleDockableFactory( control.getOwner(), perspective ); inner.getSituation().add( singleDockableFactory ); inner.getSituation().addBackup( new RegisteringDockFactory( control.getOwner().intern(), singleDockableFactory ) ); inner.getSituation().add( new CommonDockStationFactory( control.getOwner(), factory, singleDockableFactory ) ); return frontend; } /** * Helper class for converting {@link DockElement}s to {@link PerspectiveElement}s. * @author Benjamin Sigg */ private class PerspectiveElementFactory implements FrontendPerspectiveCache{ private CPerspective perspective; private Perspective basePerspective; private Map dockables = new HashMap(); private Map stations; /** * Creates a new factory. * @param perspective the perspective for which items are required */ public PerspectiveElementFactory( CPerspective perspective ){ this.perspective = perspective; Iterator elements = perspective.elements(); while( elements.hasNext() ){ PerspectiveElement element = elements.next(); if( element instanceof SingleCDockablePerspective ){ SingleCDockablePerspective dockable = (SingleCDockablePerspective) element; dockables.put( dockable.getUniqueId(), dockable ); } } } public void setStations( Map stations ){ this.stations = stations; } /** * Sets the {@link Perspective} which is using this cache. * @param basePerspective the perspective using this cache, not null */ public void setBasePerspective( Perspective basePerspective ){ this.basePerspective = basePerspective; } public PerspectiveElement get( String id, DockElement element, boolean isRootStation ){ if( isRootStation ){ return perspective.getStation( id ).intern(); } else if( element instanceof CommonDockable ){ CDockable dockable = ((CommonDockable)element).getDockable(); if( dockable.asStation() != null ){ CStationPerspective station = perspective.getStation( dockable.asStation().getUniqueId() ); if( station == null ){ throw new IllegalArgumentException( "Found a non-root CStation that is not registered: " + dockable.asStation().getUniqueId() ); } return station.intern(); } if( dockable instanceof SingleCDockable ){ String key = ((SingleCDockable)dockable).getUniqueId(); SingleCDockablePerspective result = dockables.get( key ); if( result == null ){ result = new SingleCDockablePerspective( key ); dockables.put( key, result ); } return result.intern(); } if( dockable instanceof MultipleCDockable ){ return null; } } throw new IllegalArgumentException( "The intern DockFrontend of the CControl has elements registered that are not SingleCDockables: " + id + "=" + element ); } @SuppressWarnings("unchecked") public PerspectiveElement get( String id, boolean rootStation ){ String key = id; if( !rootStation && control.getRegister().isSingleId( id )){ key = control.getRegister().singleToNormalId( id ); } // maybe a station DockLayoutComposition root = null; if( stations != null ){ root = stations.get( key ); } if( root == null ){ root = getPredefinedStation( key, basePerspective.getSituation() ); } Path stationType = null; if( root != null ){ // really a station DockLayout layout = (DockLayout)root.getAdjacent( RootStationAdjacentFactory.FACTORY_ID ); if( layout != null){ stationType = layout.getData(); } CStationPerspective station = perspective.getStation( key ); if( station == null ){ station = control.getOwner().getMissingPerspectiveStrategy().createStation( key, stationType ); if( station != null ){ perspective.addStation( station ); station.setRoot( rootStation ); } } if( station == null ){ return null; } return station.intern(); } else if( control.getRegister().isSingleId( id )){ // maybe a dockable SingleCDockablePerspective result = dockables.get( key ); if( result == null ){ result = new SingleCDockablePerspective( key ); dockables.put( key, result ); } return result.intern(); } return null; } /** * Tries to find the layout of a {@link DockStation} which was predefined with the unique * identifier id. This method recursively searches through the entire tree of elements and * also finds stations that are registered as {@link SingleCDockable} or {@link MultipleCDockable}. * @param id the identifier to search * @param situation algorithms used to extract information from {@link DockLayoutComposition}s * @return the layout or null if not found */ protected DockLayoutComposition getPredefinedStation( String id, DockSituation situation ){ if( stations != null ){ for( DockLayoutComposition station : stations.values() ){ DockLayoutComposition result = getPredefinedStation( id, station, situation ); if( result != null ){ return result; } } } return null; } private DockLayoutComposition getPredefinedStation( String id, DockLayoutComposition current, DockSituation situation ){ // check self String currentId = situation.getIdentifier( current ); if( currentId != null ){ if( id.length() == DockFrontend.ROOT_KEY_PREFIX.length()+id.length() && currentId.startsWith( DockFrontend.ROOT_KEY_PREFIX ) && currentId.endsWith( id )){ return current; } if( currentId.startsWith( DockFrontend.DOCKABLE_KEY_PREFIX )){ currentId = currentId.substring( DockFrontend.DOCKABLE_KEY_PREFIX.length() ); if( control.getRegister().isSingleId( currentId )){ currentId = control.getRegister().singleToNormalId( currentId ); } else if( control.getRegister().isMultiId( currentId )){ currentId = control.getRegister().multiToNormalId( currentId ); } if( currentId.equals( id )){ return current; } } } // check children List children = current.getChildren(); if( children != null ){ for( DockLayoutComposition child : children ){ DockLayoutComposition result = getPredefinedStation( id, child, situation ); if( result != null ){ return result; } } } return null; } public String get( PerspectiveElement element ){ for( String key : perspective.getStationKeys() ){ CStationPerspective station = perspective.getStation( key ); if( station.intern() == element ){ return key; } } if( element instanceof CommonElementPerspective ){ CElementPerspective celement = ((CommonElementPerspective)element).getElement(); if( celement instanceof SingleCDockablePerspective ){ return control.getRegister().toSingleId( ((SingleCDockablePerspective)celement).getUniqueId() ); } } return null; } public boolean isRootStation( PerspectiveStation element ){ for( String key : perspective.getStationKeys() ){ CStationPerspective station = perspective.getStation( key ); if( station.intern() == element ){ return true; } } return false; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy