/*
*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2009 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 omero.gateway.model;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import omero.RBool;
import omero.rtypes;
import omero.RInt;
import omero.RString;
import omero.model.IObject;
import omero.model.Polygon;
import omero.model.Polyline;
import omero.model.Shape;
/**
* Hosts a shape.
*
* @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 3.0-Beta4
*/
public abstract class ShapeData
extends DataObject
{
/** Flag stating that the ROI is read only. */
public static boolean READONLY_FLAG = true;
/** The representation of the shape. */
protected ShapeSettingsData settings;
/** Flag indicating that the shape been created client side. */
private boolean clientObject;
/**
* Converts the passed collection of points.
*
* @param pts The points to convert.
* @param type The value in the list to parse.
* @return See above.
*/
private String convertPoints(String pts, String type)
{
if (pts.length() == 0) return "";
if (!pts.contains(type)) {//data inserted following the schema
return pts;
}
String exp = type+'[';
int typeStr = pts.indexOf(exp, 0);
int start = pts.indexOf('[', typeStr);
int end = pts.indexOf(']', start);
return pts.substring(start+1,end);
}
/**
* Parses out the type from the points string.
*
* @param type The value in the list to parse.
* @return See above.
*/
protected String fromPoints(String type)
{
IObject o = asIObject();
if (o instanceof Polygon) {
Polygon shape = (Polygon) asIObject();
return convertPoints(shape.getPoints().getValue(), type);
} else if (o instanceof Polyline) {
Polyline shape = (Polyline) asIObject();
return convertPoints(shape.getPoints().getValue(), type);
}
throw new IllegalArgumentException("No shape specified.");
}
/**
* Parses the points list from the string to a list of point2d objects.
*
* @param str the string to convert to points.
*/
protected List<Point2D.Double> parsePointsToPoint2DList(String str)
{
List<Point2D.Double> points = new ArrayList<Point2D.Double>();
if (str == null) return points;
StringTokenizer tt = new StringTokenizer(str, " ");
int numTokens = tt.countTokens();
StringTokenizer t;
int n;
for (int i = 0; i < numTokens; i++) {
t = new StringTokenizer(tt.nextToken(), ",");
n = t.countTokens()/2;
for (int j = 0; j < n; j++) {
points.add(
new Point2D.Double(new Double(t.nextToken()), new Double(
t.nextToken())));
}
}
return points;
}
/**
* Parses the points list from the string to a list of integer objects.
*
* @param str the string to convert to points.
*/
protected List<Integer> parsePointsToIntegerList(String str)
{
List<Integer> points = new ArrayList<Integer>();
if (str == null) return points;
StringTokenizer tt = new StringTokenizer(str, ",");
int numTokens = tt.countTokens();
StringTokenizer t;
int n;
for (int i = 0; i< numTokens; i++) {
t = new StringTokenizer(tt.nextToken(), " ");
n = t.countTokens();
for (int j = 0; j < n; j++) {
points.add(Double.valueOf(t.nextToken()).intValue());
}
}
return points;
}
/**
* Returns a Point2D.Double array as a Points attribute value. as specified
* in http://www.w3.org/TR/SVGMobile12/shapes.html#PointsBNF
*/
protected static String toPoints(Point2D.Double[] points)
{
StringBuilder buf = new StringBuilder();
for (int i = 0; i < points.length; i++)
{
if (i != 0)
{
buf.append(", ");
}
buf.append(toNumber(points[i].x));
buf.append(',');
buf.append(toNumber(points[i].y));
}
return buf.toString();
}
/** Returns a double array as a number attribute value. */
protected static String toNumber(double number)
{
String str = Double.toString(number);
if (str.endsWith(".0"))
str = str.substring(0, str.length()-2);
return str;
}
/**
* Creates a new instance.
*
* @param shape The shape to host.
* @param clientObject Pass <code>true</code> if it is a client object,
* <code>false</code> otherwise.
*/
protected ShapeData(Shape shape, boolean clientObject)
{
super();
setClientObject(clientObject);
setValue(shape);
shape.setLocked(rtypes.rbool(false));
settings = new ShapeSettingsData(shape);
}
/**
* Creates a new instance.
*
* @param shape The shape to host.
*/
protected ShapeData(Shape shape)
{
this(shape, false);
}
/**
* Returns the settings associated to the shape.
*
* @return See above.
*/
public ShapeSettingsData getShapeSettings()
{
return settings;
}
/**
* Set the settings associated to the shape.
*
* @param shape See above.
*/
protected void setShapeSettings(Shape shape)
{
settings = new ShapeSettingsData(shape);
}
/**
* Returns <code>true</code> if the object a read-only object,
* <code>false</code> otherwise.
*
* @return See above.
*/
public boolean isReadOnly()
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
return (shape.getLocked().getValue()==READONLY_FLAG);
}
/**
* Sets to <code>true</code> if the object is a read-only object,
* <code>false</code> otherwise.
*
* @param readOnly The value to set.
*/
public void setReadOnly(boolean readOnly)
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
shape.setLocked(rtypes.rbool(readOnly));
}
/**
* Returns <code>true</code> if the object one that has been created client
* side. If so the id will be <code></code>null, or invalid.
*
* @return See above.
*/
public boolean isClientObject() { return clientObject; }
/**
* Sets to <code>true</code> if the object one that has been created client
* side, <code>false</code> otherwise.
*
* @param clientObject The value to set..
*/
public void setClientObject(boolean clientObject)
{
this.clientObject = clientObject;
}
/**
* Returns the z-section.
*
* @return See above.
*/
public int getZ()
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
RInt value = shape.getTheZ();
if (value == null) return -1;
return value.getValue();
}
/**
* Sets the z-section.
*
* @param z The value to set.
*/
public void setZ(int z)
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
if (z < 0) z = 0;
shape.setTheZ(rtypes.rint(z));
setDirty(true);
}
/**
* Returns the channel.
*
* @return See above.
*/
public int getC()
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
RInt value = shape.getTheC();
if (value == null) return -1;
return value.getValue();
}
/**
* Sets the channel.
*
* @param c The value to set.
*/
public void setC(int c)
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
if (c < 0) c = 0;
shape.setTheC(rtypes.rint(c));
setDirty(true);
}
/**
* Returns the time-point.
*
* @return See above.
*/
public int getT()
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
RInt value = shape.getTheT();
if (value == null) return -1;
return value.getValue();
}
/**
* Sets the time-point.
*
* @param t The value to set.
*/
public void setT(int t)
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
if (t < 0) t = 0;
shape.setTheT(rtypes.rint(t));
setDirty(true);
}
/**
* Sets the ROICoordinate for the ShapeData.
*
* @param coord The value to set.
*/
public void setROICoordinate(ROICoordinate coord)
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
if (coord == null)
throw new IllegalArgumentException("No Coordinate specified.");
setZ(coord.getZSection());
setT(coord.getTimePoint());
setDirty(true);
}
/**
* Returns the ROICoordinate for the ShapeData.
*
* @return See above.
*/
public ROICoordinate getROICoordinate()
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
int z = getZ();
int t = getT();
if (z < 0 || t < 0) return null;
return new ROICoordinate(z, t);
}
/**
* Returns the transformation.
*
* @return See above.
*/
public String getTransform()
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
RString value = shape.getTransform();
if (value == null) return "";
return value.getValue();
}
/**
* Sets the Affine transform of the shape.
*
* @param transform The transform to set.
*/
public void setTransform(String transform)
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
if (transform == null) return;
shape.setTransform(rtypes.rstring(transform));
setDirty(true);
}
/**
* Sets to <code>true</code> if the figure been changed from the server
* side version, <code>false</code> otherwise.
*
* @param dirty The value to set.
*/
public void setDirty(boolean dirty)
{
super.setDirty(dirty);
}
/**
* Returns <code>true</code> if the shape is visible, <code>false</code>
* otherwise.
*
* @return See above.
*/
public boolean isVisible()
{
Shape shape = (Shape) asIObject();
if (shape == null) return false;
RBool b = shape.getVisibility();
if (b == null) return true;
return b.getValue();
}
/**
* Sets to <code>true</code> if the shape is visible, <code>false</code>
* otherwise.
*
* @param visible The value to set.
*/
public void setVisible(boolean visible)
{
Shape shape = (Shape) asIObject();
if (shape == null)
throw new IllegalArgumentException("No shape specified.");
shape.setVisibility(rtypes.rbool(visible));
setDirty(true);
}
}