/* *------------------------------------------------------------------------------ * Copyright (C) 2006-2007 University of Dundee. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.util.roi.model; import java.awt.geom.Rectangle2D; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.jhotdraw.draw.AttributeKey; import org.openmicroscopy.shoola.util.roi.figures.ROIFigure; import org.openmicroscopy.shoola.util.roi.model.ROI; import org.openmicroscopy.shoola.util.roi.model.ROIShape; import org.openmicroscopy.shoola.util.roi.model.annotation.AnnotationKey; import org.openmicroscopy.shoola.util.roi.model.annotation.AnnotationKeys; import org.openmicroscopy.shoola.util.roi.model.util.Coord3D; import omero.gateway.model.ShapeData; /** * * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author Donald MacDonald      * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a> * @version 3.0 * @since OME3.0 */ public class ROIShape { /** The server side object associated to this node.*/ private ShapeData data; /** The id of the ROIShape. */ private long id; /** The ROI containing the ROIShape. */ private ROI parent; /** The plane on which the ROIShape resides. */ private Coord3D coord; /** The bounding box of the ROIShape. */ private Rectangle2D boundingBox; /** The ROIFigure that represents the on screen presence of the ROIShape. */ private ROIFigure figure; /** * Annotations are stored according to a key, object mapping, just like the * attribute objects of JHotDraw. */ private Map<AnnotationKey, Object> annotations = new HashMap<AnnotationKey,Object>(); /** * Forbidden annotations can't be set by the setAnnotation() operation. * They can only be changed by basicSetAnnotations(). */ private Set<AnnotationKey> forbiddenAnnotations; /** * Copies the attributes from one figure to another. * * @param src The figure to copy from. * @param dst The figure to copy to. */ private void copyAttributes(ROIFigure src, ROIFigure dst) { Map<AttributeKey, Object> map = src.getAttributes(); Entry entry; Iterator i = map.entrySet().iterator(); while (i.hasNext()) { entry = (Entry) i.next(); dst.setAttribute((AttributeKey) entry.getKey(), entry.getValue()); } } /** * Creates the ROIShape with parent ROI on plane coordinate and * figure aggregated. * * @param parent see above. * @param coord see above. * @param shape see above. */ public ROIShape(ROI parent, Coord3D coord, ROIShape shape) { if (shape == null) throw new IllegalArgumentException("No Shape specified."); if (parent == null) throw new IllegalArgumentException("No ROI specified."); ROIFigure src = (ROIFigure) shape.getFigure(); if (src == null) throw new IllegalArgumentException("No Figure associated to shape."); this.parent = parent; this.coord = coord; boundingBox = (Rectangle2D) shape.getBoundingBox().clone(); figure = (ROIFigure) src.clone(); figure.setROIShape(this); figure.setROI(parent); copyAttributes(src, figure); } /** * Creates the ROIShape with parent ROI on plane coordinates and * figure aggregated. The ROIShape bounds are set by boundingBox. * * @param parent see above. * @param coord see above. * @param figure see above. * @param boundingBox see above. */ public ROIShape(ROI parent, Coord3D coord, ROIFigure figure, Rectangle2D boundingBox) { if (figure == null) throw new IllegalArgumentException("No Figure specified."); if (parent == null) throw new IllegalArgumentException("No ROI specified."); this.parent = parent; this.coord = coord; this.figure = figure;//(ROIFigure) figure.clone(); //shouldn't be clone. this.figure.setROIShape(this); this.figure.setROI(parent); this.boundingBox = boundingBox; copyAttributes(figure, this.figure); } /** * This id will only be used by server objects. * @return See above. */ public long getROIShapeID() { return id; } /** * This id will only be used by server objects. * @param id The id of the */ public void setROIShapeID(long id) { this.id = id; } /** * Returns the server side shape associated to this object or * <code>null</code>. * * @return See above. */ public ShapeData getData() { return data; } /** * Sets the server side shape associated to this object or * <code>null</code>. */ public void setData(ShapeData data) { this.data = data; } /** * Get the id of the ROI the ROIShape belongs to. * @return see above. */ public long getID() { return parent.getID(); } /** * The plane on which the ROIShape belongs. * @return see above. */ public Coord3D getCoord3D() { return coord; } /** * Returns the z-section. * * @return See above. */ public int getZ() { return coord.getZSection(); } /** * Returns the timepoint. * * @return See above. */ public int getT() { return coord.getTimePoint(); } /** * Get the bounding box of the ROIShape. * @return see above. */ public Rectangle2D getBoundingBox() { return boundingBox; } /** * Get the ROIFigure which represents the ROIShape. * @return see above. */ public ROIFigure getFigure() { return figure; } /** * Get the ROI containing this ROIShape. * @return see above. */ public ROI getROI() { return parent; } /** * Set the annotation of the ROIShape with key to value. * @param key see above. * @param newValue see above. */ public void setAnnotation(AnnotationKey key, Object newValue) { if (forbiddenAnnotations == null || ! forbiddenAnnotations.contains(key)) { Object oldValue = annotations.get(key); if (! annotations.containsKey(key) || oldValue != newValue || oldValue != null && newValue != null && ! oldValue.equals(newValue)) { basicSetAnnotation(key, newValue); } } } /** * Set the ROIShape to allow annotation of type key if param b true. * @param key see above. * @param b see above. */ public void setAnnotationEnabled(AnnotationKey key, boolean b) { if (forbiddenAnnotations == null) forbiddenAnnotations = new HashSet<AnnotationKey>(); if (b) forbiddenAnnotations.remove(key); else forbiddenAnnotations.add(key); } /** * Is the annotation with key allowed. * @param key see above. * @return see above. */ public boolean isAnnotationEnabled(AnnotationKey key) { return forbiddenAnnotations == null || !forbiddenAnnotations.contains(key); } /** * Set the annotations in the ROIShape from the map. * @param map see above. */ public void basicSetAnnotations(Map<AnnotationKey, Object> map) { for (Map.Entry<AnnotationKey, Object> entry : map.entrySet()) basicSetAnnotation(entry.getKey(), entry.getValue()); } /** * Set the annoations of the ROIShape from the map provided. * @param map see above. */ public void setAnnotations(Map<AnnotationKey, Object> map) { for (Map.Entry<AnnotationKey, Object> entry : map.entrySet()) setAnnotation(entry.getKey(), entry.getValue()); } /** * Get all the annotations of the ROIShape. * @return see above. */ public Map<AnnotationKey, Object> getAnnotation() { return new HashMap<AnnotationKey,Object>(annotations); } /** * Sets an annotation of the ROIShape. * AnnotationKey name and semantics are defined by the class implementing * the ROIShape interface. * @param key see above. * @param newValue see above. */ public void basicSetAnnotation(AnnotationKey key, Object newValue) { if (forbiddenAnnotations == null || ! forbiddenAnnotations.contains(key)) annotations.put(key, newValue); } /** * Gets an annotation from the ROIShape. * @param key see above. * @return see above. */ public Object getAnnotation(AnnotationKey key) { return hasAnnotation(key) ? annotations.get(key) : key.getDefaultValue(); } /** * Get the annotation key with name. * @param name see above. * @return see above. */ protected AnnotationKey getAnnotationKey(String name) { return AnnotationKeys.supportedAnnotationMap.get(name); } /** * Applies all annotation of this ROIShape to that ROIShape. * @param that the ROIShape to take values from. */ protected void applyAnnotationsTo(ROIShape that) { for (Map.Entry<AnnotationKey, Object> entry : annotations.entrySet()) { that.setAnnotation(entry.getKey(), entry.getValue()); } } /** * Remove the annotation key from map. * @param key see above. */ public void removeAnnotation(AnnotationKey key) { if (hasAnnotation(key)) annotations.remove(key); } /** * Has the ROIShape got the annotation key. * @param key see above. * @return see above. */ public boolean hasAnnotation(AnnotationKey key) { return annotations.containsKey(key); } /** * Copies the shape. * * @param plane The plane to copy. * @return See above. */ public ROIShape copy(Coord3D plane) { if (plane == null) plane = this.coord; return new ROIShape(this.parent, plane, this.figure, this.boundingBox); } }