use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Loader method createLazyFlyThrough.
/**
* Each slice is generated on demand, one slice per Region instance.
*/
public <I> ImagePlus createLazyFlyThrough(final List<? extends Region<I>> regions, final double magnification, final int type, final Displayable active) {
final Region<I> first = regions.get(0);
final int w = (int) (first.r.width * magnification), h = (int) (first.r.height * magnification);
final LazyVirtualStack stack = new LazyVirtualStack(w, h, regions.size());
for (final Region<I> r : regions) {
stack.addSlice(new Callable<ImageProcessor>() {
@Override
public ImageProcessor call() {
return getFlatImage(r.layer, r.r, magnification, 0xffffffff, type, Displayable.class, null, true, Color.black, active).getProcessor();
}
});
}
return new ImagePlus("Fly-Through", stack);
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Loader method getFlatAWTImage.
/**
* @param layer The layer from which to collect visible Displayable instances that intersect the srcRect.
* @param srcRect_ Rectangle in World coordinates representing the field of view to paint into the image, and defines the width and height of the image together with the scale.
* @param scale Value between 0 and 1.
* @param c_alphas Which color channels to include when painting Patch instances that hold an RGB image.
* @param type Either ImagePlus.GRAY8 or ImagePlus.COLOR_RGB
* @param clazz Include only Displayable instances of this class; use Displayable.class for all.
* @param al_displ List of Displayable instances to include. Use null to include all visible intersected by srcRect.
* @param quality Whether to attempt to create a larger image and then scale it down with area averaging for best quality.
* @param background The color of the areas of the image where no Displayable paints.
* @param active Whether to paint a particular Displayable instance in an active state (as if it was selected in the UI).
* @return
*/
public Image getFlatAWTImage(final Layer layer, final Rectangle srcRect_, final double scale, final int c_alphas, final int type, final Class<?> clazz, List<? extends Displayable> al_displ, boolean quality, final Color background, final Displayable active) {
try {
// dimensions
int w = 0;
int h = 0;
Rectangle srcRect = (null == srcRect_) ? null : (Rectangle) srcRect_.clone();
if (null != srcRect) {
w = srcRect.width;
h = srcRect.height;
} else {
w = (int) Math.ceil(layer.getLayerWidth());
h = (int) Math.ceil(layer.getLayerHeight());
srcRect = new Rectangle(0, 0, w, h);
}
Utils.log2("Loader.getFlatImage: using rectangle " + srcRect);
/*
* output size including excess space for not entirely covered
* pixels
*/
final int ww = (int) Math.ceil(w * scale);
final int hh = (int) Math.ceil(h * scale);
/* The size of the buffered image to be generated */
final int biw, bih;
final double scaleP, scalePX, scalePY;
// on scaling down to output resolution.
if (quality) {
if (ww * hh >= Math.pow(2, 30)) {
// 1 GB
// While perhaps scale could be increased to an image size of up to 2 GB, it is not advisable
scaleP = scalePX = scalePY = scale;
quality = false;
biw = ww;
bih = hh;
Utils.log("Can't use 'quality' flag for getFlatAWTImage: would be too large");
// If the image is larger than 2 GB, it will thrown a NegativeArraySizeException below and stop.
} else {
// Max area: the smallest of the srcRect at 100x magnification and 1 GB
final double max_area = Math.min(srcRect.width * srcRect.height, Math.pow(2, 30));
final double ratio = ww / (double) hh;
// area = w * h
// ratio = w / h
// w = ratio * h
// area = ratio * h * h
// h = sqrt(area / ratio)
// scaleP is then the ratio between the real-world height and the target height
// (And clamp to a maximum of 1.0: above makes no sense)
scaleP = Math.min(1.0, srcRect.height / Math.sqrt(max_area / ratio));
biw = (int) Math.ceil(ww / scale);
bih = (int) Math.ceil(hh / scale);
/* compensate for excess space due to ceiling */
scalePX = (double) biw / (double) ww * scale;
scalePY = (double) bih / (double) hh * scale;
Utils.log("getFlatAWTImage -- scale: " + scale + "; quality scale: " + scaleP);
}
} else {
scaleP = scalePX = scalePY = scale;
biw = ww;
bih = hh;
}
// estimate image size
final long n_bytes = (long) ((biw * bih * (ImagePlus.GRAY8 == type ? 1.0 : /*byte*/
4.0)));
Utils.log2("Flat image estimated size in bytes: " + Long.toString(n_bytes) + " w,h : " + (int) Math.ceil(biw) + "," + (int) Math.ceil(bih) + (quality ? " (using 'quality' flag: scaling to " + scale + " is done later with area averaging)" : ""));
releaseToFit(n_bytes);
// go
BufferedImage bi = null;
switch(type) {
case ImagePlus.GRAY8:
bi = new BufferedImage(biw, bih, BufferedImage.TYPE_BYTE_INDEXED, GRAY_LUT);
break;
case ImagePlus.COLOR_RGB:
bi = new BufferedImage(biw, bih, BufferedImage.TYPE_INT_ARGB);
break;
default:
Utils.log2("Left bi,icm as null");
break;
}
final Graphics2D g2d = bi.createGraphics();
g2d.setColor(background);
g2d.fillRect(0, 0, bi.getWidth(), bi.getHeight());
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
// TODO Stephan, test if that introduces offset vs nearest neighbor
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
// to smooth edges of the images
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
ArrayList<ZDisplayable> al_zdispl = null;
if (null == al_displ) {
al_displ = new ArrayList<Displayable>(layer.find(clazz, srcRect, true, true));
al_zdispl = new ArrayList<ZDisplayable>((Collection) layer.getParent().findZDisplayables(clazz, layer, srcRect, true, true));
} else {
// separate ZDisplayables into their own array
al_displ = new ArrayList<Displayable>(al_displ);
final HashSet<ZDisplayable> az = new HashSet<ZDisplayable>();
for (final Iterator<?> it = al_displ.iterator(); it.hasNext(); ) {
final Object ob = it.next();
if (ob instanceof ZDisplayable) {
it.remove();
az.add((ZDisplayable) ob);
}
}
// order ZDisplayables by their stack order
final ArrayList<ZDisplayable> al_zdispl2 = layer.getParent().getZDisplayables();
for (final Iterator<ZDisplayable> it = al_zdispl2.iterator(); it.hasNext(); ) {
if (!az.contains(it.next()))
it.remove();
}
al_zdispl = al_zdispl2;
}
// prepare the canvas for the srcRect and magnification
final AffineTransform at_original = g2d.getTransform();
final AffineTransform atc = new AffineTransform();
atc.scale(scalePX, scalePY);
atc.translate(-srcRect.x, -srcRect.y);
at_original.preConcatenate(atc);
g2d.setTransform(at_original);
// Utils.log2("will paint: " + al_displ.size() + " displ and " + al_zdispl.size() + " zdispl");
// int total = al_displ.size() + al_zdispl.size();
int count = 0;
boolean zd_done = false;
final List<Layer> layers = layer.getParent().getColorCueLayerRange(layer);
for (final Displayable d : al_displ) {
// paint the ZDisplayables before the first label, if any
if (!zd_done && d instanceof DLabel) {
zd_done = true;
for (final ZDisplayable zd : al_zdispl) {
if (!zd.isOutOfRepaintingClip(scaleP, srcRect, null)) {
zd.paint(g2d, srcRect, scaleP, active == zd, c_alphas, layer, layers);
}
count++;
// Utils.log2("Painted " + count + " of " + total);
}
}
if (!d.isOutOfRepaintingClip(scaleP, srcRect, null)) {
d.paintOffscreen(g2d, srcRect, scaleP, active == d, c_alphas, layer, layers);
// Utils.log("painted: " + d + "\n with: " + scaleP + ", " + c_alphas + ", " + layer);
} else {
// Utils.log2("out: " + d);
}
count++;
// Utils.log2("Painted " + count + " of " + total);
}
if (!zd_done) {
zd_done = true;
for (final ZDisplayable zd : al_zdispl) {
if (!zd.isOutOfRepaintingClip(scaleP, srcRect, null)) {
zd.paint(g2d, srcRect, scaleP, active == zd, c_alphas, layer, layers);
}
count++;
// Utils.log2("Painted " + count + " of " + total);
}
}
// ensure enough memory is available for the processor and a new awt from it
// locks on its own
releaseToFit((long) (n_bytes * 2.3));
try {
if (quality) {
// need to scale back down
Image scaled = null;
if (!isMipMapsRegenerationEnabled() || scale >= 0.499) {
// there are no proper mipmaps above 50%, so there's need for SCALE_AREA_AVERAGING.
// very slow, but best by far
scaled = bi.getScaledInstance(ww, hh, Image.SCALE_AREA_AVERAGING);
if (ImagePlus.GRAY8 == type) {
// getScaledInstance generates RGB images for some reason.
final BufferedImage bi8 = new BufferedImage(ww, hh, BufferedImage.TYPE_BYTE_GRAY);
bi8.createGraphics().drawImage(scaled, 0, 0, null);
scaled.flush();
scaled = bi8;
}
} else {
// faster, but requires gaussian blurred images (such as the mipmaps)
if (bi.getType() == BufferedImage.TYPE_BYTE_INDEXED) {
scaled = new BufferedImage(ww, hh, bi.getType(), GRAY_LUT);
} else {
scaled = new BufferedImage(ww, hh, bi.getType());
}
final Graphics2D gs = (Graphics2D) scaled.getGraphics();
// gs.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
gs.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
gs.drawImage(bi, 0, 0, ww, hh, null);
}
bi.flush();
return scaled;
} else {
// else the image was made scaled down already, and of the proper type
return bi;
}
} catch (final OutOfMemoryError oome) {
Utils.log("Not enough memory to create the ImagePlus. Try scaling it down or not using the 'quality' flag.");
}
} catch (final Exception e) {
IJError.print(e);
}
return null;
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class TMLHandler method makeLayerThing.
private LayerThing makeLayerThing(String type, final HashMap<String, String> ht_attributes) {
try {
type = type.toLowerCase();
if (0 == type.indexOf("t2_")) {
type = type.substring(3);
}
// long id = -1;
// final String sid = ht_attributes.get("id");
// if (null != sid) id = Long.parseLong(sid);
long oid = -1;
final String soid = ht_attributes.get("oid");
if (null != soid)
oid = Long.parseLong(soid);
if (type.equals("node")) {
if (null == last_tree) {
throw new NullPointerException("Can't create a node for null last_tree!");
}
final Node<?> node = last_tree.newNode(ht_attributes);
taggables.add(node);
// Put node into the list of nodes with that layer id, to update to proper Layer pointer later
final long ndlid = Long.parseLong(ht_attributes.get("lid"));
List<Node<?>> list = node_layer_table.get(ndlid);
if (null == list) {
list = new ArrayList<Node<?>>();
node_layer_table.put(ndlid, list);
}
list.add(node);
// Set node as root node or add as child to last node in the stack
if (null == last_root_node) {
last_root_node = node;
} else {
final String sconf = ht_attributes.get("c");
nodes.getLast().add((Node) node, null == sconf ? Node.MAX_EDGE_CONFIDENCE : Byte.parseByte(sconf));
}
// color?
final String scolor = ht_attributes.get("color");
if (null != scolor) {
final Color color = Utils.getRGBColorFromHex(scolor);
Collection<Node<?>> nodes = node_colors.get(color);
if (null == nodes) {
nodes = new ArrayList<Node<?>>();
node_colors.put(color, nodes);
}
nodes.add(node);
}
// Put node into stack of nodes (to be removed on closing the tag)
nodes.add(node);
} else if (type.equals("profile")) {
Profile profile = new Profile(this.project, oid, ht_attributes, ht_links);
profile.addToDatabase();
ht_displayables.put(oid, profile);
addToLastOpenLayer(profile);
last_displayable = profile;
return null;
} else if (type.equals("pipe")) {
Pipe pipe = new Pipe(this.project, oid, ht_attributes, ht_links);
pipe.addToDatabase();
ht_displayables.put(new Long(oid), pipe);
ht_zdispl.put(new Long(oid), pipe);
last_displayable = pipe;
addToLastOpenLayerSet(pipe);
return null;
} else if (type.equals("polyline")) {
Polyline pline = new Polyline(this.project, oid, ht_attributes, ht_links);
pline.addToDatabase();
last_displayable = pline;
ht_displayables.put(new Long(oid), pline);
ht_zdispl.put(new Long(oid), pline);
addToLastOpenLayerSet(pline);
return null;
} else if (type.equals("connector")) {
final Connector con = new Connector(this.project, oid, ht_attributes, ht_links);
if (ht_attributes.containsKey("origin")) {
legacy.add(new Runnable() {
public void run() {
con.readLegacyXML(al_layer_sets.get(al_layer_sets.size() - 1), ht_attributes, ht_links);
}
});
}
con.addToDatabase();
last_connector = con;
last_tree = con;
last_displayable = con;
ht_displayables.put(new Long(oid), con);
ht_zdispl.put(new Long(oid), con);
addToLastOpenLayerSet(con);
return null;
} else if (type.equals("path")) {
if (null != reca) {
reca.add(ht_attributes.get("d"));
return null;
}
return null;
} else if (type.equals("area")) {
reca = new ReconstructArea();
if (null != last_area_list) {
last_area_list_layer_id = Long.parseLong(ht_attributes.get("layer_id"));
}
return null;
} else if (type.equals("area_list")) {
AreaList area = new AreaList(this.project, oid, ht_attributes, ht_links);
// why? This looks like an onion
area.addToDatabase();
last_area_list = area;
last_displayable = area;
ht_displayables.put(new Long(oid), area);
ht_zdispl.put(new Long(oid), area);
addToLastOpenLayerSet(area);
return null;
} else if (type.equals("tag")) {
Taggable t = taggables.getLast();
if (null != t) {
Object ob = ht_attributes.get("key");
// defaults to 't'
int keyCode = KeyEvent.VK_T;
// KeyEvent.VK_U is char U, not u
if (null != ob)
keyCode = (int) ((String) ob).toUpperCase().charAt(0);
Tag tag = al_layer_sets.get(al_layer_sets.size() - 1).putTag(ht_attributes.get("name"), keyCode);
// could be null if name is not found
if (null != tag)
t.addTag(tag);
}
} else if (type.equals("ball_ob")) {
// add a ball to the last open Ball
if (null != last_ball) {
last_ball.addBall(Double.parseDouble(ht_attributes.get("x")), Double.parseDouble(ht_attributes.get("y")), Double.parseDouble(ht_attributes.get("r")), Long.parseLong(ht_attributes.get("layer_id")));
}
return null;
} else if (type.equals("ball")) {
Ball ball = new Ball(this.project, oid, ht_attributes, ht_links);
ball.addToDatabase();
last_ball = ball;
last_displayable = ball;
ht_displayables.put(new Long(oid), ball);
ht_zdispl.put(new Long(oid), ball);
addToLastOpenLayerSet(ball);
return null;
} else if (type.equals("stack")) {
Stack stack = new Stack(this.project, oid, ht_attributes, ht_links);
stack.addToDatabase();
last_stack = stack;
last_displayable = stack;
ht_displayables.put(new Long(oid), stack);
ht_zdispl.put(new Long(oid), stack);
addToLastOpenLayerSet(stack);
} else if (type.equals("treeline")) {
Treeline tline = new Treeline(this.project, oid, ht_attributes, ht_links);
tline.addToDatabase();
last_treeline = tline;
last_tree = tline;
last_treeline_data = new StringBuilder();
last_displayable = tline;
ht_displayables.put(oid, tline);
ht_zdispl.put(oid, tline);
addToLastOpenLayerSet(tline);
} else if (type.equals("areatree")) {
AreaTree art = new AreaTree(this.project, oid, ht_attributes, ht_links);
art.addToDatabase();
last_areatree = art;
last_tree = art;
last_displayable = art;
ht_displayables.put(oid, art);
ht_zdispl.put(oid, art);
addToLastOpenLayerSet(art);
} else if (type.equals("dd_item")) {
if (null != last_dissector) {
last_dissector.addItem(Integer.parseInt(ht_attributes.get("tag")), Integer.parseInt(ht_attributes.get("radius")), ht_attributes.get("points"));
}
} else if (type.equals("label")) {
DLabel label = new DLabel(project, oid, ht_attributes, ht_links);
label.addToDatabase();
ht_displayables.put(new Long(oid), label);
addToLastOpenLayer(label);
last_displayable = label;
return null;
} else if (type.equals("annot")) {
last_annotation = new StringBuilder();
return null;
} else if (type.equals("patch")) {
Patch patch = new Patch(project, oid, ht_attributes, ht_links);
patch.addToDatabase();
ht_displayables.put(new Long(oid), patch);
addToLastOpenLayer(patch);
last_patch = patch;
last_displayable = patch;
checkAlphaMasks(patch);
return null;
} else if (type.equals("filter")) {
last_patch_filters.add(newFilter(ht_attributes));
} else if (type.equals("dissector")) {
Dissector dissector = new Dissector(this.project, oid, ht_attributes, ht_links);
dissector.addToDatabase();
last_dissector = dissector;
last_displayable = dissector;
ht_displayables.put(new Long(oid), dissector);
ht_zdispl.put(new Long(oid), dissector);
addToLastOpenLayerSet(dissector);
} else if (type.equals("layer")) {
// find last open LayerSet, if any
for (int i = al_layer_sets.size() - 1; i > -1; ) {
LayerSet set = al_layer_sets.get(i);
Layer layer = new Layer(project, oid, ht_attributes);
layer.addToDatabase();
set.addSilently(layer);
al_layers.add(layer);
Object ot = ht_attributes.get("title");
return new LayerThing(template_layer_thing, project, -1, (null == ot ? null : (String) ot), layer, null);
}
} else if (type.equals("layer_set")) {
LayerSet set = new LayerSet(project, oid, ht_attributes, ht_links);
last_displayable = set;
set.addToDatabase();
ht_displayables.put(new Long(oid), set);
al_layer_sets.add(set);
addToLastOpenLayer(set);
Object ot = ht_attributes.get("title");
return new LayerThing(template_layer_set_thing, project, -1, (null == ot ? null : (String) ot), set, null);
} else if (type.equals("calibration")) {
// find last open LayerSet if any
for (int i = al_layer_sets.size() - 1; i > -1; ) {
LayerSet set = al_layer_sets.get(i);
set.restoreCalibration(ht_attributes);
return null;
}
} else if (type.equals("prop")) {
// Add property to last created Displayable
if (null != last_displayable) {
last_displayable.setProperty(ht_attributes.get("key"), ht_attributes.get("value"));
}
} else if (type.equals("linked_prop")) {
// Add linked property to last created Displayable. Has to wait until the Displayable ids have been resolved to instances.
if (null != last_displayable) {
putLinkedProperty(last_displayable, ht_attributes);
}
} else {
Utils.log2("TMLHandler Unknown type: " + type);
}
} catch (Exception e) {
IJError.print(e);
}
// default:
return null;
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class TMLHandler method startElement.
public void startElement(String namespace_URI, String local_name, String qualified_name, Attributes attributes) throws SAXException {
if (null == loader)
return;
// Utils.log2("startElement: " + qualified_name);
this.counter++;
if (0 == counter % 100) {
// davi-experimenting: don't talk so much when you have > 600,000 patches to load!
Utils.showStatus("Loading " + counter, false);
}
try {
// failsafe:
qualified_name = qualified_name.toLowerCase();
final HashMap<String, String> ht_attributes = new HashMap<String, String>();
for (int i = attributes.getLength() - 1; i > -1; i--) {
ht_attributes.put(attributes.getQName(i).toLowerCase(), attributes.getValue(i));
}
// get the id, which whenever possible it's the id of the encapsulating Thing object. The encapsulated object id is the oid
// The type is specified by the qualified_name
Thing thing = null;
if (0 == qualified_name.indexOf("t2_")) {
if (qualified_name.equals("t2_display")) {
// store for later, until the layers exist
if (open_displays)
al_displays.add(ht_attributes);
} else {
// a Layer, LayerSet or Displayable object
thing = makeLayerThing(qualified_name, ht_attributes);
if (null != thing) {
if (null == root_lt && thing.getObject() instanceof LayerSet) {
root_lt = (LayerThing) thing;
}
}
}
} else if (qualified_name.equals("project")) {
if (null != this.root_pt) {
Utils.log("WARNING: more than one project definitions.");
return;
}
// Create the project
this.project = new Project(Long.parseLong(ht_attributes.remove("id")), ht_attributes.remove("title"));
// temp, but will be the same anyway
this.project.setTempLoader(this.loader);
this.project.parseXMLOptions(ht_attributes);
// register id
this.project.addToDatabase();
String title = ht_attributes.get("title");
if (null != title)
this.project.setTitle(title);
// Add all unique TemplateThing types to the project
for (Iterator<TemplateThing> it = root_tt.getUniqueTypes(new HashMap<String, TemplateThing>()).values().iterator(); it.hasNext(); ) {
this.project.addUniqueType(it.next());
}
this.project.addUniqueType(this.project_tt);
this.root_pt = new ProjectThing(this.project_tt, this.project, this.project);
// Add a project pointer to all template things
this.root_tt.addToDatabase(this.project);
thing = root_pt;
} else if (qualified_name.startsWith("ict_transform") || qualified_name.startsWith("iict_transform")) {
makeCoordinateTransform(qualified_name, ht_attributes);
} else if (!qualified_name.equals("trakem2")) {
// Any abstract object
thing = makeProjectThing(qualified_name, ht_attributes);
}
if (null != thing) {
// get the previously open thing and add this new_thing to it as a child
int size = al_open.size();
if (size > 0) {
Thing parent = al_open.get(size - 1);
parent.addChild(thing);
// Utils.log2("Adding child " + thing + " to parent " + parent);
}
// add the new thing as open
al_open.add(thing);
}
} catch (Exception e) {
IJError.print(e);
skip = true;
}
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class LayerTree method actionPerformed.
public void actionPerformed(ActionEvent ae) {
try {
String command = ae.getActionCommand();
// commands for multiple selections:
TreePath[] paths = this.getSelectionPaths();
if (null != paths && paths.length > 1) {
if (command.equals("Reverse layer Z coords")) {
// check that all layers belong to the same layer set
// just do it
Layer[] layer = new Layer[paths.length];
LayerSet ls = null;
for (int i = 0; i < paths.length; i++) {
layer[i] = (Layer) ((LayerThing) ((DefaultMutableTreeNode) paths[i].getLastPathComponent()).getUserObject()).getObject();
if (null == ls)
ls = layer[i].getParent();
else if (!ls.equals(layer[i].getParent())) {
Utils.showMessage("To reverse, all layers must belong to the same layer set");
return;
}
}
final ArrayList<Layer> al = new ArrayList<Layer>();
for (int i = 0; i < layer.length; i++) al.add(layer[i]);
ls.addLayerEditedStep(al);
// ASSSUMING layers are already Z ordered! CHECK
for (int i = 0, j = layer.length - 1; i < layer.length / 2; i++, j--) {
double z = layer[i].getZ();
layer[i].setZ(layer[j].getZ());
layer[j].setZ(z);
}
updateList(ls);
ls.addLayerEditedStep(al);
Display.updateLayerScroller(ls);
} else if (command.equals("Translate layers in Z...")) {
GenericDialog gd = ControlWindow.makeGenericDialog("Range");
gd.addMessage("Translate selected range in the Z axis:");
gd.addNumericField("by: ", 0, 4);
gd.showDialog();
if (gd.wasCanceled())
return;
// else, displace
double dz = gd.getNextNumber();
if (Double.isNaN(dz)) {
Utils.showMessage("Invalid number");
return;
}
HashSet<LayerSet> hs_parents = new HashSet<LayerSet>();
for (int i = 0; i < paths.length; i++) {
Layer layer = (Layer) ((LayerThing) ((DefaultMutableTreeNode) paths[i].getLastPathComponent()).getUserObject()).getObject();
layer.setZ(layer.getZ() + dz);
hs_parents.add(layer.getParent());
}
for (LayerSet ls : hs_parents) {
updateList(ls);
}
// now update all profile's Z ordering in the ProjectTree
ProjectThing root_pt = project.getRootProjectThing();
for (final ProjectThing pt : root_pt.findChildrenOfType("profile_list")) {
pt.fixZOrdering();
project.getProjectTree().updateList(pt);
}
project.getProjectTree().updateUILater();
// Display.updateLayerScroller((LayerSet)((DefaultMutableTreeNode)getModel().getRoot()).getUserObject());
} else if (command.equals("Delete...")) {
if (!Utils.check("Really remove all selected layers?"))
return;
for (int i = 0; i < paths.length; i++) {
DefaultMutableTreeNode lnode = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
LayerThing lt = (LayerThing) lnode.getUserObject();
Layer layer = (Layer) lt.getObject();
if (!layer.remove(false)) {
Utils.showMessage("Could not delete layer " + layer);
this.updateUILater();
return;
}
if (lt.remove(false)) {
((DefaultTreeModel) this.getModel()).removeNodeFromParent(lnode);
}
}
this.updateUILater();
} else if (command.equals("Scale Z and thickness...")) {
GenericDialog gd = new GenericDialog("Scale Z");
gd.addNumericField("scale: ", 1.0, 2);
gd.showDialog();
double scale = gd.getNextNumber();
if (Double.isNaN(scale) || 0 == scale) {
Utils.showMessage("Imvalid scaling factor: " + scale);
return;
}
for (int i = 0; i < paths.length; i++) {
DefaultMutableTreeNode lnode = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
LayerThing lt = (LayerThing) lnode.getUserObject();
Layer layer = (Layer) lt.getObject();
layer.setZ(layer.getZ() * scale);
layer.setThickness(layer.getThickness() * scale);
}
this.updateUILater();
} else {
Utils.showMessage("Don't know what to do with command " + command + " for multiple selected nodes");
}
return;
}
// commands for single selection:
if (null == selected_node)
return;
LayerThing thing = (LayerThing) selected_node.getUserObject();
LayerThing new_thing = null;
TemplateThing tt = null;
Object ob = null;
int i_position = -1;
if (command.startsWith("new ")) {
String name = command.substring(4).toLowerCase();
if (name.equals("layer")) {
// Create new Layer and add it to the selected node
LayerSet set = (LayerSet) thing.getObject();
Layer new_layer = Layer.create(thing.getProject(), set);
if (null == new_layer)
return;
tt = thing.getChildTemplate("layer");
ob = new_layer;
Display.updateTitle(set);
} else if (name.equals("layer set")) {
// with space in the middle
// Create a new LayerSet and add it in the middle
Layer layer = (Layer) thing.getObject();
LayerSet new_set = layer.getParent().create(layer);
if (null == new_set)
return;
layer.add(new_set);
// add it at the end of the list
// with space, not underscore
tt = thing.getChildTemplate("layer set");
ob = new_set;
i_position = selected_node.getChildCount();
Display.update(layer);
} else {
Utils.log("LayerTree.actionPerformed: don't know what to do with the command: " + command);
return;
}
} else if (command.equals("many new layers...")) {
LayerSet set = (LayerSet) thing.getObject();
List<Layer> layers = Layer.createMany(set.getProject(), set);
// add them to the tree as LayerThing
if (null == layers)
return;
for (Layer la : layers) {
// null layers will be skipped
addLayer(set, la);
}
Display.updateTitle(set);
return;
} else if (command.equals("Show")) {
// create a new Display
DBObject dbo = (DBObject) thing.getObject();
// the top level LayerSet
if (thing.getType().equals("layer_set") && null == ((LayerSet) dbo).getParent())
return;
Display.createDisplay(dbo.getProject(), thing.getType().equals("layer") ? (Layer) dbo : ((LayerSet) dbo).getParent());
return;
} else if (command.equals("Show centered in Display")) {
LayerSet ls = (LayerSet) thing.getObject();
Display.showCentered(ls.getParent(), ls, false, false);
} else if (command.equals("Delete...")) {
remove(true, thing, selected_node);
return;
} else if (command.equals("Import stack...")) {
if (thing.getObject() instanceof LayerSet) {
LayerSet set = (LayerSet) thing.getObject();
Layer layer = null;
if (0 == set.getLayers().size()) {
layer = Layer.create(set.getProject(), set);
if (null == layer)
return;
tt = thing.getChildTemplate("Layer");
ob = layer;
} else
// click on a desired, existing layer.
return;
layer.getProject().getLoader().importStack(layer, null, true);
} else if (thing.getObject() instanceof Layer) {
Layer layer = (Layer) thing.getObject();
layer.getProject().getLoader().importStack(layer, null, true);
return;
}
} else if (command.equals("Import grid...")) {
if (thing.getObject() instanceof Layer) {
Layer layer = (Layer) thing.getObject();
layer.getProject().getLoader().importGrid(layer);
}
} else if (command.equals("Import sequence as grid...")) {
if (thing.getObject() instanceof Layer) {
Layer layer = (Layer) thing.getObject();
layer.getProject().getLoader().importSequenceAsGrid(layer);
}
} else if (command.equals("Import from text file...")) {
if (thing.getObject() instanceof Layer) {
Layer layer = (Layer) thing.getObject();
layer.getProject().getLoader().importImages(layer);
}
} else if (command.equals("Resize LayerSet...")) {
if (thing.getObject() instanceof LayerSet) {
LayerSet ls = (LayerSet) thing.getObject();
ij.gui.GenericDialog gd = ControlWindow.makeGenericDialog("Resize LayerSet");
gd.addNumericField("new width: ", ls.getLayerWidth(), 3);
gd.addNumericField("new height: ", ls.getLayerHeight(), 3);
gd.addChoice("Anchor: ", LayerSet.ANCHORS, LayerSet.ANCHORS[0]);
gd.showDialog();
if (gd.wasCanceled())
return;
float new_width = (float) gd.getNextNumber(), new_height = (float) gd.getNextNumber();
// will complain and prevent cropping existing Displayable objects
ls.setDimensions(new_width, new_height, gd.getNextChoiceIndex());
}
} else if (command.equals("Autoresize LayerSet")) {
if (thing.getObject() instanceof LayerSet) {
LayerSet ls = (LayerSet) thing.getObject();
ls.setMinimumDimensions();
}
} else if (command.equals("Adjust...")) {
if (thing.getObject() instanceof Layer) {
Layer layer = (Layer) thing.getObject();
ij.gui.GenericDialog gd = ControlWindow.makeGenericDialog("Adjust Layer");
gd.addNumericField("new z: ", layer.getZ(), 4);
gd.addNumericField("new thickness: ", layer.getThickness(), 4);
gd.showDialog();
if (gd.wasCanceled())
return;
double new_z = gd.getNextNumber();
layer.setThickness(gd.getNextNumber());
if (new_z != layer.getZ()) {
layer.setZ(new_z);
// move in the tree
/*
DefaultMutableTreeNode child = findNode(thing, this);
DefaultMutableTreeNode parent = (DefaultMutableTreeNode)child.getParent();
parent.remove(child);
// reinsert
int n = parent.getChildCount();
int i = 0;
for (; i < n; i++) {
DefaultMutableTreeNode child_node = (DefaultMutableTreeNode)parent.getChildAt(i);
LayerThing child_thing = (LayerThing)child_node.getUserObject();
if (!child_thing.getType().equals("Layer")) continue;
double iz = ((Layer)child_thing.getObject()).getZ();
if (iz < new_z) continue;
// else, add the layer here, after this one
break;
}
((DefaultTreeModel)this.getModel()).insertNodeInto(child, parent, i);
*/
// fix tree crappiness (empty slot ?!?)
/* // the fix doesn't work. ARGH TODO
Enumeration e = parent.children();
parent.removeAllChildren();
i = 0;
while (e.hasMoreElements()) {
//parent.add((DefaultMutableTreeNode)e.nextElement());
((DefaultTreeModel)this.getModel()).insertNodeInto(child, parent, i);
i++;
}*/
// easier and correct: overkill
updateList(layer.getParent());
// set selected
DefaultMutableTreeNode child = findNode(thing, this);
TreePath treePath = new TreePath(child.getPath());
this.scrollPathToVisible(treePath);
this.setSelectionPath(treePath);
}
}
return;
} else if (command.equals("Rename...")) {
GenericDialog gd = ControlWindow.makeGenericDialog("Rename");
gd.addStringField("new name: ", thing.getTitle());
gd.showDialog();
if (gd.wasCanceled())
return;
project.getRootLayerSet().addUndoStep(new RenameThingStep(thing));
thing.setTitle(gd.getNextString());
project.getRootLayerSet().addUndoStep(new RenameThingStep(thing));
} else if (command.equals("Translate layers in Z...")) {
// / TODO: this method should use multiple selections directly on the tree
if (thing.getObject() instanceof LayerSet) {
LayerSet ls = (LayerSet) thing.getObject();
ArrayList<Layer> al_layers = ls.getLayers();
String[] layer_names = new String[al_layers.size()];
for (int i = 0; i < layer_names.length; i++) {
layer_names[i] = ls.getProject().findLayerThing(al_layers.get(i)).toString();
}
GenericDialog gd = ControlWindow.makeGenericDialog("Range");
gd.addMessage("Translate selected range in the Z axis:");
gd.addChoice("from: ", layer_names, layer_names[0]);
gd.addChoice("to: ", layer_names, layer_names[layer_names.length - 1]);
gd.addNumericField("by: ", 0, 4);
gd.showDialog();
if (gd.wasCanceled())
return;
// else, displace
double dz = gd.getNextNumber();
if (Double.isNaN(dz)) {
Utils.showMessage("Invalid number");
return;
}
int i_start = gd.getNextChoiceIndex();
int i_end = gd.getNextChoiceIndex();
for (int i = i_start; i <= i_end; i++) {
Layer layer = (Layer) al_layers.get(i);
layer.setZ(layer.getZ() + dz);
}
// update node labels and position
updateList(ls);
}
} else if (command.equals("Reverse layer Z coords...")) {
// / TODO: this method should use multiple selections directly on the tree
if (thing.getObject() instanceof LayerSet) {
LayerSet ls = (LayerSet) thing.getObject();
ArrayList<Layer> al_layers = ls.getLayers();
String[] layer_names = new String[al_layers.size()];
for (int i = 0; i < layer_names.length; i++) {
layer_names[i] = ls.getProject().findLayerThing(al_layers.get(i)).toString();
}
GenericDialog gd = ControlWindow.makeGenericDialog("Range");
gd.addMessage("Reverse Z coordinates of selected range:");
gd.addChoice("from: ", layer_names, layer_names[0]);
gd.addChoice("to: ", layer_names, layer_names[layer_names.length - 1]);
gd.showDialog();
if (gd.wasCanceled())
return;
int i_start = gd.getNextChoiceIndex();
int i_end = gd.getNextChoiceIndex();
for (int i = i_start, j = i_end; i < i_end / 2; i++, j--) {
Layer layer1 = (Layer) al_layers.get(i);
double z1 = layer1.getZ();
Layer layer2 = (Layer) al_layers.get(j);
layer1.setZ(layer2.getZ());
layer2.setZ(z1);
}
// update node labels and position
updateList(ls);
}
} else if (command.equals("Search...")) {
Search.showWindow();
} else if (command.equals("Reset layer Z and thickness")) {
LayerSet ls = ((LayerSet) thing.getObject());
List<Layer> layers = ls.getLayers();
ls.addLayerEditedStep(layers);
int i = 0;
for (final Layer la : ls.getLayers()) {
la.setZ(i++);
la.setThickness(1);
}
ls.addLayerEditedStep(layers);
} else {
Utils.log("LayerTree.actionPerformed: don't know what to do with the command: " + command);
return;
}
if (null == tt)
return;
new_thing = new LayerThing(tt, thing.getProject(), ob);
if (-1 == i_position && new_thing.getType().equals("layer")) {
// find the node whose 'z' is larger than z, and add the Layer before that.
// (just because there could be objects other than LayerThing with a Layer in it in the future, so set.getLayers().indexOf(layer) may not be useful)
double z = ((Layer) ob).getZ();
int n = selected_node.getChildCount();
int i = 0;
for (; i < n; i++) {
DefaultMutableTreeNode child_node = (DefaultMutableTreeNode) selected_node.getChildAt(i);
LayerThing child_thing = (LayerThing) child_node.getUserObject();
if (!child_thing.getType().equals("layer")) {
continue;
}
double iz = ((Layer) child_thing.getObject()).getZ();
if (iz < z) {
continue;
}
// else, add the layer here, after this one
break;
}
i_position = i;
}
thing.addChild(new_thing);
DefaultMutableTreeNode new_node = new DefaultMutableTreeNode(new_thing);
((DefaultTreeModel) this.getModel()).insertNodeInto(new_node, selected_node, i_position);
TreePath treePath = new TreePath(new_node.getPath());
this.scrollPathToVisible(treePath);
this.setSelectionPath(treePath);
if (new_thing.getType().equals("layer set")) {
// add the first layer to it, and open it in a Display
LayerSet newls = (LayerSet) new_thing.getObject();
Layer la = new Layer(newls.getProject(), 0, 1, newls);
addLayer(newls, la);
new Display(newls.getProject(), la);
}
} catch (Exception e) {
IJError.print(e);
}
}
Aggregations