/*
* The University of Wales, Cardiff Triana Project Software License (Based
* on the Apache Software License Version 1.1)
*
* Copyright (c) 2007 University of Wales, Cardiff. All rights reserved.
*
* Redistribution and use of the software in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any,
* must include the following acknowledgment: "This product includes
* software developed by the University of Wales, Cardiff for the Triana
* Project (http://www.trianacode.org)." Alternately, this
* acknowledgment may appear in the software itself, if and wherever
* such third-party acknowledgments normally appear.
*
* 4. The names "Triana" and "University of Wales, Cardiff" must not be
* used to endorse or promote products derived from this software
* without prior written permission. For written permission, please
* contact triana@trianacode.org.
*
* 5. Products derived from this software may not be called "Triana," nor
* may Triana appear in their name, without prior written permission of
* the University of Wales, Cardiff.
*
* 6. This software may not be sold, used or incorporated into any product
* for sale to third parties.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL UNIVERSITY OF WALES, CARDIFF OR ITS CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* ------------------------------------------------------------------------
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Triana Project. For more information on the
* Triana Project, please see. http://www.trianacode.org.
*
* This license is based on the BSD license as adopted by the Apache
* Foundation and is governed by the laws of England and Wales.
*
*/
package org.trianacode.gui.components.map;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.Point;
import java.util.Enumeration;
import java.util.Hashtable;
import org.trianacode.taskgraph.TDimension;
import org.trianacode.taskgraph.TaskLayoutDetails;
/**
* The layout manager responsible for positioning components on the map.
*
* @author Ian Wang
* @version $Revision: 4048 $
*/
public class MapLayout implements LayoutManager, TaskLayoutDetails {
/**
* the default size of the map
*/
private Dimension mapsize;
/**
* the size factor for the components (<1 = smaller >1 = larger)
*/
private double compfactor = 1;
/**
* a hashtable for the point on the map of each location
*/
private Hashtable loctable = new Hashtable();
/**
* a hashtable for the location of each component
*/
private Hashtable comptable = new Hashtable();
/**
* the current x/y scale for components
*/
private double cscale = 1.0;
/**
* Constructs a map layout for the specified mapsize
*/
public MapLayout(Dimension mapsize) {
this.mapsize = mapsize;
}
/**
* Constructs a map layout for the specified mapsize
*
* @param compfactor a scale factor for the components (default = 1).
*/
public MapLayout(Dimension mapsize, double compfactor) {
this.mapsize = mapsize;
this.compfactor = compfactor;
}
/**
* Sets the map size used by this layout manager
*/
public void setMapSize(Dimension mapsize) {
this.mapsize = mapsize;
}
/**
* @return the current map size
*/
public Dimension getMapsize() {
return mapsize;
}
/**
* Sets the poin on the map for the specified location
*/
public void setMapPoint(String location, Point point) {
loctable.put(location, point);
}
/**
* @return the point (0<=x<=1, 0<=y<=1) on the map for the specified location
*/
public Point getMapPoint(String location) {
if (loctable.containsKey(location)) {
return (Point) loctable.get(location);
} else {
return null;
}
}
/**
* @return true if there is a point registered for the specified location
*/
public boolean isMapPoint(String location) {
return loctable.containsKey(location);
}
/**
* @return the size of the left border of the workspace
*/
public int getLeftBorder() {
return 0;
}
/**
* @return the size of the right border of the workspace
*/
public int getTopBorder() {
return 0;
}
/**
* @return the dimensions of a standard triana task
*/
public TDimension getTaskDimensions() {
Dimension defsize = MapLayoutConstants.DEFAULT_TOOL_SIZE;
return new TDimension((int) (defsize.width * compfactor * cscale),
(int) (defsize.height * compfactor * cscale));
}
/**
* If the layout manager uses a per-component string, adds the component <code>comp</code> to the layout,
* associating it with the string specified by <code>name</code>.
*
* @param name the string to be associated with the component
* @param comp the component to be added
*/
public void addLayoutComponent(String name, Component comp) {
comptable.put(comp, name);
}
/**
* Removes the specified component from the layout.
*
* @param comp the component to be removed
*/
public void removeLayoutComponent(Component comp) {
comptable.remove(comp);
}
/**
* Calculates the minimum size dimensions for the specified container, given the components it contains.
*
* @param parent the component to be laid out
* @see #preferredLayoutSize
*/
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
/**
* Calculates the preferred size dimensions for the specified container, given the components it contains.
*
* @param parent the container to be laid out
* @see #minimumLayoutSize
*/
public Dimension preferredLayoutSize(Container parent) {
return mapsize;
}
/**
* Lays out the specified container.
*
* @param parent the container to be laid out
*/
public void layoutContainer(Container parent) {
Enumeration enumeration = comptable.keys();
Dimension parentsize = parent.getSize();
cscale = Math.min(((double) parentsize.width) / mapsize.width, ((double) parentsize.height) / mapsize.height);
TDimension compsize = getTaskDimensions();
Component comp;
Point pos;
int noloc = 0;
while (enumeration.hasMoreElements()) {
comp = (Component) enumeration.nextElement();
comp.setSize(new Dimension((int) compsize.getWidth(), (int) compsize.getHeight()));
pos = getLocation((String) comptable.get(comp));
if (pos != null) {
comp.setLocation((int) ((parentsize.width * (pos.getX() / mapsize.width) - (compsize.getWidth() / 2))),
(int) ((parentsize.height * (pos.getY() / mapsize.height) - (compsize.getHeight() / 2))));
} else {
comp.setLocation((int) compsize.getWidth() * noloc++, 0);
}
}
}
/**
* @return the location for the specified comp, or null if not known
*/
private Point getLocation(String location) {
Enumeration enumeration = loctable.keys();
String key;
Point loc = null;
int matchlen = 0;
while (enumeration.hasMoreElements()) {
key = (String) enumeration.nextElement();
if ((key.length() > matchlen) && (location.startsWith(key))) {
loc = (Point) loctable.get(key);
matchlen = key.length();
}
}
return loc;
}
}