/** TrakEM2 plugin for ImageJ(C). Copyright (C) 2005-2009 Albert Cardona and Rodney Douglas. 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 (http://www.gnu.org/licenses/gpl.txt ) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. You may contact Albert Cardona at acardona at ini.phys.ethz.ch Institute of Neuroinformatics, University of Zurich / ETH, Switzerland. **/ package ini.trakem2.display; import ini.trakem2.Project; import ini.trakem2.persistence.XMLOptions; import ini.trakem2.utils.Search; import ini.trakem2.utils.Utils; import java.awt.Color; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; /** For Pipes and other objects that must be shown in all Layers of a LayerSet. */ public abstract class ZDisplayable extends Displayable { protected LayerSet layer_set; public ZDisplayable(Project project, String title, double x, double y) { super(project, title, x, y); } /** For reconstruction from the database. */ public ZDisplayable(Project project, long id, String title, boolean locked, AffineTransform at, float width, float height) { super(project, id, title, locked, at, width, height); } /** For reconstruction from an XML file. */ public ZDisplayable(Project project, long id, HashMap<String,String> ht, HashMap<Displayable,String> ht_links) { super(project, id, ht, ht_links); Object data = ht.get("layer_set_id"); if (null != data) { // construct a dummy layerset this.layer_set = new LayerSet(project, Long.parseLong((String)data)); // TODO fix this hack // -- one year later: seems like it will stay. } } public void setLayerSet(LayerSet layer_set) { setLayerSet(layer_set, true); // should check that the new LayerSet belongs to the same project } public void setLayerSet(LayerSet layer_set, boolean update_db) { if (layer_set == this.layer_set) return; this.layer_set = layer_set; if (update_db) updateInDatabase("layer_set_id"); } public LayerSet getLayerSet() { return layer_set; } // Overriding, for repainting the proper part, without updating the database public void setLayer(Layer layer) { this.layer = layer; } /** Link the Patch objects that lay underneath the part of the bounding box of this profile that shows in the current layer, so that they cannot be dragged independently. */ abstract public boolean linkPatches(); /** Returns the layer of lowest Z coordinate where this ZDisplayable has a point in. */ abstract public Layer getFirstLayer(); public void exportXML(StringBuilder sb_body, String indent, XMLOptions options) { super.exportXML(sb_body, indent, options); sb_body.append(indent).append("layer_set_id=\"").append(layer_set.getId()).append("\"\n"); } static public void exportDTD(final String type, final StringBuilder sb_header, final HashSet<String> hs, final String indent) { if (hs.contains(type)) return; Displayable.exportDTD(type, sb_header, hs, indent); sb_header.append(indent).append(TAG_ATTR1).append(type).append(" layer_set_id").append(TAG_ATTR2) ; } /** Transform points falling within the given layer; translate by dx,dy and rotate by rot relative to origin xo,yo*/ @Deprecated public void transformPoints(Layer layer, double dx, double dy, double rot, double xo, double yo) {} @Override protected boolean remove2(boolean check) { return project.getProjectTree().remove(check, project.findProjectThing(this), null); // will call remove(check) here } @Override public boolean remove(boolean check) { if (check && !Utils.check("Really remove " + this.toString() + " ?")) return false; if (layer_set.remove(this) && removeFromDatabase()) { unlink(); removeLinkedPropertiesFromOrigins(); Search.remove(this); // duplication of code from Displayable.remove, because there isn't a proper hierarchy of classes Display.flush(this); project.decache(this); return true; } return false; } /** Does not remove from the LayerSet. */ @Override public boolean softRemove() { if (removeFromDatabase()) { unlink(); removeLinkedPropertiesFromOrigins(); Search.remove(this); // duplication of code from Displayable.remove, because there isn't a proper hierarchy of classes Display.flush(this); return true; } return false; } /** Check if this instance will paint anything at the level of the given Layer. */ public boolean paintsAt(final Layer layer) { if (null == layer || layer_set != layer.getParent()) return false; return true; } /** Get the list of Layer ids on which this ZDisplayable has data on.*/ @Override public Collection<Long> getLayerIds() { // Unless overriden, return all final ArrayList<Long> l = new ArrayList<Long>(); for (final Layer la : layer_set.getLayers()) l.add(la.getId()); return l; } public void setColor(Color color) { if (null == color || color.equals(this.color)) return; this.color = color; Displayable.last_color = color; updateInDatabase("color"); Display.repaint(layer_set, this, 5); Display3D.setColor(this, color); } abstract public boolean intersects(Area area, double z_first, double z_last); public void setVisible(final boolean visible, final boolean repaint) { if (visible == this.visible) { // patching synch error //Display.updateVisibilityCheckbox(layer, this, null); return; } this.visible = visible; if (repaint) { Display.repaint(layer_set, null, getBoundingBox(), 5, true); } updateInDatabase("visible"); } public Bucketable getBucketable() { return this.layer_set; } /** Retain the data within the layer range, and through out all the rest. */ public boolean crop(List<Layer> range) { return true; } /** Update internal datastructures to reflect the fact that @param layer has been removed from the containing LayerSet.*/ protected boolean layerRemoved(Layer la) { if (null != hs_linked) { for (final Displayable d : hs_linked) if (d.layer == la) unlink(d); } return true; } public void updateBucket(final Layer la) { if (null == la) updateBucket(); // for all layers else if (null != getBucketable()) getBucketable().updateBucket(this, la); } /** Update buckets for all Layers. */ @Override public void updateBucket() { if (null == getBucketable()) return; for (final Layer layer : getLayersWithData()) { getBucketable().updateBucket(this, layer); } } abstract protected boolean calculateBoundingBox(final Layer la); }