Search in sources :

Example 21 with TemplateThing

use of ini.trakem2.tree.TemplateThing in project TrakEM2 by trakem2.

the class ProjectTiler method createRetiledSibling.

/**
 * Take a {@link Project}, a size for the image tiles, and a target directory,
 * and create a new copy of the current project in that folder but with the underlying
 * images converted to tiles with a translation-only transform (saved as zipped TIFFs,
 * with extension ".tif.zip").
 * The new, returned {@link Project} represents the given project but with much
 * simpler transformations (just translation) for the images and a defined size for
 * the latter, which helps a lot regarding storage space of the XML (and parsing and
 * saving time) and performance when browsing layers (keep in mind that, for a 32k x 32k image,
 * at 100% zoom one would have to load a 32k x 32k image and render just a tiny bit
 * of it). The copied Project preserves the ID of the {@link Layer}s of the original
 * {@link Project}, as well as the dimensions; this means the copy is a sibling of
 * the original, and it is possible to send segmentations from one to the other "as is"
 * (directly, without having to transform along with the images which would not be possible).
 *
 * Image files are stored as
 *
 * The non-image objects of the given project are copied into the new project as well.
 *
 * @param srcProject The project to create a sibling of.
 * @param targetDirectory The directory in which to create all the necessary data and mipmap folders for the new Project.
 * @param tileWidth The width of the tiles to create for the data of the new project.
 * @param tileHeight The height of the tiles.
 * @param exportImageType Any of {@link ImagePlus#GRAY8}, {@link ImagePlus#GRAY16} or {@link ImagePlus#COLOR_RGB}, otherwise an {@link IllegalArgumentException} is thrown.
 * @param onlyVisibleImages Whether to consider visible images only.
 * @param nExportThreads Number of layers to export in parallel. Use a small number when original images are huge (such as larger than 4096 x 4096 pixels).
 * @param createMipMaps Whether to generate the mipmaps when done or not.
 *
 * @throws Exception IllegalArgumentException When {@code exportImageType} is not {@link ImagePlus#GRAY16} or {@link ImagePlus#COLOR_RGB}, or when the directory exists and cannot be written to.
 */
public static final Project createRetiledSibling(final Project srcProject, final String targetDirectory, final int tileWidth, final int tileHeight, final int exportImageType, final boolean onlyVisibleImages, final int nExportThreads, final boolean createMipMaps) throws Exception {
    // Validate exportImageType
    switch(exportImageType) {
        case ImagePlus.GRAY8:
        case ImagePlus.GRAY16:
        case ImagePlus.COLOR_RGB:
            break;
        default:
            throw new IllegalArgumentException("Can only accept GRAY8, GRAY16 or COLOR_RGB as values for 'exportImageType'!");
    }
    // Validate targetDirectory
    final File fdir = new File(targetDirectory);
    if (fdir.exists()) {
        if (!fdir.isDirectory() || !fdir.canWrite())
            throw new IllegalArgumentException("Invalid directory: not a directory or cannot write to: " + targetDirectory);
    } else {
        if (!fdir.mkdirs()) {
            throw new IllegalArgumentException("Cannot create directory at: " + targetDirectory);
        }
    }
    final String targetDir = Utils.fixDir(targetDirectory);
    // Create "data" directory
    final String dataDir = new StringBuilder(targetDir).append("data/").toString();
    final File fDataDir = new File(dataDir);
    if (fDataDir.exists() && (!fDataDir.isDirectory() || !fDataDir.canWrite())) {
        throw new IllegalArgumentException("Cannot create or write to 'data' directory in the targetDirectory at: " + targetDir);
    } else {
        fDataDir.mkdir();
    }
    // Create new Project, plain, without any automatic creation of a Layer or a Display
    final Project newProject = Project.newFSProject("blank", null, targetDir, false);
    final LayerSet newLayerSet = newProject.getRootLayerSet();
    newLayerSet.setCalibration(srcProject.getRootLayerSet().getCalibrationCopy());
    if (!createMipMaps) {
        Utils.log("MipMaps are DISABLED:\n --> When done, right-click and choose 'Display - Properties...' and enable mipmaps,\n     and then run 'Project - Regenerate all mipmaps'\n");
        newProject.getLoader().setMipMapsRegeneration(false);
        Utils.log("mipmaps enabled? " + newProject.getLoader().isMipMapsRegenerationEnabled());
    }
    // Copy the Template Tree of types
    newProject.resetRootTemplateThing(srcProject.getRootTemplateThing().clone(newProject, true), null);
    for (final TemplateThing tt : newProject.getRootTemplateThing().getUniqueTypes(new HashMap<String, TemplateThing>()).values()) {
        newProject.addUniqueType(tt);
    }
    // Clone layers with the exact same IDs, so that the two projects are siblings at the layer-level:
    // (Being siblings allows for treelines, arealists, etc. to be transferred from one to another "as is").
    final List<Layer> srcLayers = srcProject.getRootLayerSet().getLayers();
    final List<Layer> newLayers = new ArrayList<Layer>();
    for (final Layer srcLayer : srcLayers) {
        final Layer newLayer = new Layer(newProject, srcLayer.getId(), srcLayer.getZ(), srcLayer.getThickness());
        // to update the ID generator in FSLoader
        newLayer.addToDatabase();
        newLayerSet.add(newLayer);
        newLayers.add(newLayer);
        newProject.getRootLayerThing().addChild(new LayerThing(newProject.getRootLayerThing().getChildTemplate("layer"), newProject, newLayer));
    }
    newProject.getLayerTree().rebuild();
    // Update the LayerSet
    newLayerSet.setDimensions(srcProject.getRootLayerSet().getLayerWidth(), srcProject.getRootLayerSet().getLayerHeight(), LayerSet.NORTHWEST);
    Display.updateLayerScroller(newLayerSet);
    Display.update(newLayerSet);
    // Copy template from the src Project
    // (It's done after creating layers so the IDs will not collide with those of the Layers)
    newProject.resetRootTemplateThing(srcProject.getRootTemplateThing().clone(newProject, false), null);
    // Export tiles as new Patch instances, creating new image files in disk
    final int numThreads = Math.max(1, Math.min(nExportThreads, Runtime.getRuntime().availableProcessors()));
    int i = 0;
    for (final Layer srcLayer : srcLayers) {
        Utils.log("Processing layer " + (i + 1) + "/" + srcLayers.size() + " -- " + new Date());
        final int layerIndex = i++;
        // Create subDirectory
        final String dir = dataDir + "/" + layerIndex + "/";
        new File(dir).mkdir();
        // Create a new Layer with the same Z and thickness
        final Layer newLayer = newLayers.get(layerIndex);
        // Export layer tiles
        final ArrayList<Patch> patches = new ArrayList<Patch>();
        if (ImagePlus.GRAY16 == exportImageType) {
            Process.progressive(ExportUnsignedShort.exportTiles(srcLayer, tileWidth, tileHeight, onlyVisibleImages), new CountingTaskFactory<Callable<ExportedTile>, Patch>() {

                public Patch process(final Callable<ExportedTile> c, final int index) {
                    try {
                        // Create the tile
                        final ExportedTile t = c.call();
                        // Store the file
                        final String title = layerIndex + "-" + index;
                        final String path = dir + title + ".tif.zip";
                        final ImagePlus imp = new ImagePlus(title, t.sp);
                        if (!new FileSaver(imp).saveAsZip(path)) {
                            throw new Exception("Could not save tile: " + path);
                        }
                        // Create a Patch
                        final Patch patch = new Patch(newProject, title, t.x, t.y, imp);
                        patch.setLocked(true);
                        newProject.getLoader().addedPatchFrom(path, patch);
                        return patch;
                    } catch (Exception e) {
                        IJError.print(e);
                        return null;
                    }
                }
            }, patches, numThreads);
        } else {
            // GRAY8 or COLOR_RGB: created from mipmaps
            Process.progressive(tileSequence(srcLayer, tileWidth, tileHeight, onlyVisibleImages), new CountingTaskFactory<Rectangle, Patch>() {

                @Override
                public Patch process(final Rectangle bounds, final int index) {
                    try {
                        // Create the tile
                        final ImagePlus imp = srcLayer.getProject().getLoader().getFlatImage(srcLayer, bounds, 1.0, -1, exportImageType, Patch.class, null, false, Color.black);
                        final String title = layerIndex + "-" + index;
                        imp.setTitle(title);
                        final String path = dir + title + ".tif.zip";
                        if (!new FileSaver(imp).saveAsZip(path)) {
                            throw new Exception("Could not save tile: " + path);
                        }
                        // Create a Patch
                        final Patch patch = new Patch(newProject, title, bounds.x, bounds.y, imp);
                        patch.setLocked(true);
                        newProject.getLoader().addedPatchFrom(path, patch);
                        return patch;
                    } catch (Exception e) {
                        IJError.print(e);
                        return null;
                    }
                }
            }, patches, numThreads);
        }
        // Add all Patches to the new Layer
        for (final Patch p : patches) {
            newLayer.add(p);
        }
    }
    // Copy all segmentations "As is"
    final ProjectThing root = srcProject.getRootProjectThing();
    if (null != root.getChildren() && !root.getChildren().isEmpty()) {
        final ProjectThing source_pt = srcProject.getRootProjectThing().getChildren().get(0);
        // "As is"
        final int transfer_mode = 0;
        final ProjectThing landing_parent = newProject.getRootProjectThing();
        srcProject.getProjectTree().rawSendToSiblingProject(source_pt, transfer_mode, newProject, landing_parent);
    }
    // Copy all floating text labels
    i = 0;
    for (final Layer srcLayer : srcLayers) {
        for (final DLabel srcLabel : srcLayer.getAll(DLabel.class)) {
            newLayers.get(i++).add(srcLabel.clone(newProject, false));
        }
    }
    if (createMipMaps) {
        final LinkedList<Future<?>> fus = new LinkedList<Future<?>>();
        final int batch = Runtime.getRuntime().availableProcessors();
        for (final Layer newLayer : newLayers) {
            for (final Patch p : newLayer.getAll(Patch.class)) {
                fus.add(p.updateMipMaps());
                // Don't build-up too much
                if (fus.size() > batch * 3) {
                    while (fus.size() > batch) {
                        try {
                            fus.removeFirst().get();
                        } catch (Exception e) {
                            IJError.print(e);
                        }
                    }
                }
            }
        }
        Utils.wait(fus);
    }
    // Save:
    newProject.saveAs(targetDir + "exported.xml", false);
    return newProject;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) Callable(java.util.concurrent.Callable) FileSaver(ij.io.FileSaver) ProjectThing(ini.trakem2.tree.ProjectThing) LayerSet(ini.trakem2.display.LayerSet) LayerThing(ini.trakem2.tree.LayerThing) Layer(ini.trakem2.display.Layer) ImagePlus(ij.ImagePlus) Date(java.util.Date) LinkedList(java.util.LinkedList) Project(ini.trakem2.Project) DLabel(ini.trakem2.display.DLabel) TemplateThing(ini.trakem2.tree.TemplateThing) Future(java.util.concurrent.Future) File(java.io.File) Patch(ini.trakem2.display.Patch) ExportedTile(mpicbg.trakem2.transform.ExportedTile)

Example 22 with TemplateThing

use of ini.trakem2.tree.TemplateThing 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;
    }
}
Also used : Project(ini.trakem2.Project) HashMap(java.util.HashMap) LayerSet(ini.trakem2.display.LayerSet) Iterator(java.util.Iterator) LayerThing(ini.trakem2.tree.LayerThing) TemplateThing(ini.trakem2.tree.TemplateThing) ProjectThing(ini.trakem2.tree.ProjectThing) Thing(ini.trakem2.tree.Thing) ProjectThing(ini.trakem2.tree.ProjectThing) SAXException(org.xml.sax.SAXException) SAXParseException(org.xml.sax.SAXParseException)

Example 23 with TemplateThing

use of ini.trakem2.tree.TemplateThing in project TrakEM2 by trakem2.

the class LayerThing method getPopupItems.

public JMenuItem[] getPopupItems(ActionListener listener) {
    JMenuItem item;
    ArrayList<JMenuItem> al_items = new ArrayList<JMenuItem>();
    JMenu menu = new JMenu("Add...");
    ArrayList<TemplateThing> tc = template.getChildren();
    if (null != tc) {
        for (Iterator<TemplateThing> it = tc.iterator(); it.hasNext(); ) {
            // changing underscores for spaces, for the 'layer_set' type to read nice
            item = new JMenuItem("new " + it.next().getType().replace('_', ' '));
            item.addActionListener(listener);
            menu.add(item);
        }
        if (template.getType().replaceAll("_", " ").equals("layer set")) {
            item = new JMenuItem("many new layers...");
            item.addActionListener(listener);
            menu.add(item);
        }
    }
    if (0 != menu.getItemCount()) {
        al_items.add(menu);
    }
    // Add a "Show" for all except the root LayerSet
    if (null != parent) {
        item = new JMenuItem("Show");
        item.addActionListener(listener);
        al_items.add(item);
    }
    if (template.getType().equals("layer")) {
        // adjust z and thickness
        item = new JMenuItem("Adjust...");
        item.addActionListener(listener);
        al_items.add(item);
    }
    item = new JMenuItem("Rename...");
    item.addActionListener(listener);
    al_items.add(item);
    if (template.getType().replaceAll("_", " ").equals("layer set")) {
        if (null != parent) {
            item = new JMenuItem("Show centered in Display");
            item.addActionListener(listener);
            al_items.add(item);
        }
        item = new JMenuItem("Resize LayerSet...");
        item.addActionListener(listener);
        al_items.add(item);
        LayerSet layer_set = (LayerSet) object;
        final boolean empty = 0 == layer_set.getLayers().size();
        item = new JMenuItem("Autoresize LayerSet");
        item.addActionListener(listener);
        al_items.add(item);
        if (empty)
            item.setEnabled(false);
        item = new JMenuItem("Translate layers in Z...");
        item.addActionListener(listener);
        al_items.add(item);
        if (empty)
            item.setEnabled(false);
        item = new JMenuItem("Reverse layer Z coords...");
        item.addActionListener(listener);
        al_items.add(item);
        if (empty)
            item.setEnabled(false);
        item = new JMenuItem("Reset layer Z and thickness");
        item.addActionListener(listener);
        al_items.add(item);
        if (empty)
            item.setEnabled(false);
        item = new JMenuItem("Search...");
        item.addActionListener(listener);
        al_items.add(item);
        if (empty)
            item.setEnabled(false);
    }
    item = new JMenuItem("Import stack...");
    // contains layers already, wouldn't know where to put it!
    if (template.getType().replaceAll("_", " ").equals("layer set") && 0 != ((LayerSet) object).getLayers().size())
        item.setEnabled(false);
    item.addActionListener(listener);
    al_items.add(item);
    if (template.getType().equals("layer")) {
        item = new JMenuItem("Import grid...");
        item.addActionListener(listener);
        al_items.add(item);
        item = new JMenuItem("Import sequence as grid...");
        item.addActionListener(listener);
        al_items.add(item);
        item = new JMenuItem("Import from text file...");
        item.addActionListener(listener);
        al_items.add(item);
    }
    // add a delete to all except the root LayerSet
    if (null != parent) {
        al_items.add(new JMenuItem(""));
        item = new JMenuItem("Delete...");
        item.addActionListener(listener);
        al_items.add(item);
    }
    JMenuItem[] items = new JMenuItem[al_items.size()];
    al_items.toArray(items);
    return items;
}
Also used : LayerSet(ini.trakem2.display.LayerSet) ArrayList(java.util.ArrayList) JMenuItem(javax.swing.JMenuItem) JMenu(javax.swing.JMenu)

Example 24 with TemplateThing

use of ini.trakem2.tree.TemplateThing in project TrakEM2 by trakem2.

the class LayerTree method addLayer.

/**
 * Used by the Loader.importStack and the "many new layers" command.
 */
public void addLayer(LayerSet layer_set, Layer layer) {
    if (null == layer_set || null == layer)
        return;
    try {
        // find the node that contains the LayerSet
        DefaultMutableTreeNode root_node = (DefaultMutableTreeNode) this.getModel().getRoot();
        LayerThing root_lt = (LayerThing) root_node.getUserObject();
        Thing thing = null;
        if (root_lt.getObject().equals(layer_set))
            thing = root_lt;
        else
            thing = root_lt.findChild(layer_set);
        DefaultMutableTreeNode parent_node = DNDTree.findNode(thing, this);
        if (null == parent_node) {
            Utils.log("LayerTree: LayerSet not found.");
            return;
        }
        LayerThing parent_thing = (LayerThing) parent_node.getUserObject();
        double z = layer.getZ();
        // find the node whose 'z' is larger than z, and add the Layer before that.
        int n = parent_node.getChildCount();
        int i = 0;
        for (; i < n; i++) {
            DefaultMutableTreeNode child_node = (DefaultMutableTreeNode) parent_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 the 'i' layer which has a larger z
            break;
        }
        TemplateThing tt = parent_thing.getChildTemplate("layer");
        if (null == tt) {
            Utils.log("LayerTree: Null template Thing!");
            return;
        }
        LayerThing new_thing = new LayerThing(tt, layer.getProject(), layer);
        // Add the new_thing to the tree
        if (null != new_thing) {
            parent_thing.addChild(new_thing);
            DefaultMutableTreeNode new_node = new DefaultMutableTreeNode(new_thing);
            // TODO when changing the Z of a layer, the insertion is proper but an empty space is left //Utils.log("LayerTree: inserting at: " + i);
            ((DefaultTreeModel) this.getModel()).insertNodeInto(new_node, parent_node, i);
            TreePath treePath = new TreePath(new_node.getPath());
            this.scrollPathToVisible(treePath);
            this.setSelectionPath(treePath);
        }
    } catch (Exception e) {
        IJError.print(e);
    }
}
Also used : DefaultMutableTreeNode(javax.swing.tree.DefaultMutableTreeNode) TreePath(javax.swing.tree.TreePath) DefaultTreeModel(javax.swing.tree.DefaultTreeModel) Layer(ini.trakem2.display.Layer)

Example 25 with TemplateThing

use of ini.trakem2.tree.TemplateThing 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);
    }
}
Also used : DefaultMutableTreeNode(javax.swing.tree.DefaultMutableTreeNode) ArrayList(java.util.ArrayList) DBObject(ini.trakem2.persistence.DBObject) GenericDialog(ij.gui.GenericDialog) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet) LayerSet(ini.trakem2.display.LayerSet) DefaultTreeModel(javax.swing.tree.DefaultTreeModel) Layer(ini.trakem2.display.Layer) TreePath(javax.swing.tree.TreePath) DBObject(ini.trakem2.persistence.DBObject) Display(ini.trakem2.display.Display)

Aggregations

TemplateThing (ini.trakem2.tree.TemplateThing)17 HashMap (java.util.HashMap)11 ArrayList (java.util.ArrayList)10 Displayable (ini.trakem2.display.Displayable)9 ZDisplayable (ini.trakem2.display.ZDisplayable)9 ProjectThing (ini.trakem2.tree.ProjectThing)9 TreePath (javax.swing.tree.TreePath)9 LayerThing (ini.trakem2.tree.LayerThing)8 Project (ini.trakem2.Project)7 Layer (ini.trakem2.display.Layer)7 DefaultMutableTreeNode (javax.swing.tree.DefaultMutableTreeNode)7 LayerSet (ini.trakem2.display.LayerSet)6 DBObject (ini.trakem2.persistence.DBObject)6 ResultSet (java.sql.ResultSet)6 GenericDialog (ij.gui.GenericDialog)5 FSLoader (ini.trakem2.persistence.FSLoader)4 LayerTree (ini.trakem2.tree.LayerTree)4 ProjectTree (ini.trakem2.tree.ProjectTree)4 TemplateTree (ini.trakem2.tree.TemplateTree)4 SQLException (java.sql.SQLException)4