Search in sources :

Example 1 with Thing

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

the class Display3D method show.

/**
 * Scan the {@link ProjectThing} children and assign the renderable ones to an existing {@link Display3D} for their {@link LayerSet}, or open a new one. If {@code true == wait && -1 != resample}, then the method returns only when the mesh/es have been added.
 */
public static Future<Vector<Future<Content>>> show(final ProjectThing pt, final boolean wait, final int resample) {
    if (null == pt)
        return null;
    final Future<Vector<Future<Content>>> fu = launchers.submit(new Callable<Vector<Future<Content>>>() {

        @Override
        public Vector<Future<Content>> call() {
            // Scan the given ProjectThing for 3D-viewable items
            // So: find arealist, pipe, ball, and profile_list types
            final HashSet<ProjectThing> hs = pt.findBasicTypeChildren();
            if (null == hs || 0 == hs.size()) {
                Utils.logAll("Node " + pt + " does not contain any 3D-displayable children");
                return null;
            }
            // Remove profile if it lives under a profile_list
            for (final Iterator<ProjectThing> it = hs.iterator(); it.hasNext(); ) {
                final ProjectThing pt = it.next();
                if (null != pt.getObject() && pt.getObject().getClass() == Profile.class && pt.getParent().getType().equals("profile_list")) {
                    it.remove();
                }
            }
            setWaitingCursor();
            // Start new scheduler to publish/add meshes to the 3D Viewer every 5 seconds and when done.
            final Hashtable<Display3D, Vector<Content>> contents = new Hashtable<Display3D, Vector<Content>>();
            final ScheduledExecutorService updater = Executors.newScheduledThreadPool(1);
            final AtomicInteger counter = new AtomicInteger();
            updater.scheduleWithFixedDelay(new Runnable() {

                @Override
                public void run() {
                    // Obtain a copy of the contents queue
                    final HashMap<Display3D, Vector<Content>> m = new HashMap<Display3D, Vector<Content>>();
                    synchronized (contents) {
                        m.putAll(contents);
                        contents.clear();
                    }
                    if (m.isEmpty())
                        return;
                    // Add all to the corresponding Display3D
                    for (final Map.Entry<Display3D, Vector<Content>> e : m.entrySet()) {
                        e.getKey().universe.addContentLater(e.getValue());
                        counter.getAndAdd(e.getValue().size());
                    }
                    Utils.showStatus(new StringBuilder("Rendered ").append(counter.get()).append('/').append(hs.size()).toString());
                }
            }, 100, 4000, TimeUnit.MILLISECONDS);
            // A list of all generated Content objects
            final Vector<Future<Content>> list = new Vector<Future<Content>>();
            for (final Iterator<ProjectThing> it = hs.iterator(); it.hasNext(); ) {
                // obtain the Displayable object under the node
                final ProjectThing child = it.next();
                final Object obc = child.getObject();
                final Displayable displ = obc.getClass().equals(String.class) ? null : (Displayable) obc;
                if (null != displ) {
                    if (displ.getClass().equals(Profile.class)) {
                        // handled by profile_list Thing
                        continue;
                    }
                    if (!displ.isVisible()) {
                        Utils.log("Skipping non-visible node " + displ);
                        continue;
                    }
                }
                // obtain the containing LayerSet
                final Display3D d3d;
                if (null != displ)
                    d3d = Display3D.get(displ.getLayerSet());
                else if (child.getType().equals("profile_list")) {
                    final ArrayList<ProjectThing> al_children = child.getChildren();
                    if (null == al_children || 0 == al_children.size())
                        continue;
                    // else, get the first Profile and get its LayerSet
                    d3d = Display3D.get(((Displayable) ((ProjectThing) al_children.get(0)).getObject()).getLayerSet());
                } else {
                    Utils.log("Don't know what to do with node " + child);
                    d3d = null;
                }
                if (null == d3d) {
                    Utils.log("Could not get a proper 3D display for node " + displ);
                    // java3D not installed most likely
                    return null;
                }
                boolean already;
                synchronized (d3d.ht_pt_meshes) {
                    already = d3d.ht_pt_meshes.containsKey(child);
                }
                if (already) {
                    if (child.getObject() instanceof ZDisplayable) {
                        Utils.log("Updating 3D view of " + child.getObject());
                    } else {
                        Utils.log("Updating 3D view of " + child);
                    }
                }
                list.add(d3d.executors.submit(new Callable<Content>() {

                    @Override
                    public Content call() {
                        Content c = null;
                        try {
                            c = d3d.createMesh(child, displ, resample).call();
                            Vector<Content> vc;
                            synchronized (contents) {
                                vc = contents.get(d3d);
                                if (null == vc)
                                    vc = new Vector<Content>();
                                contents.put(d3d, vc);
                            }
                            vc.add(c);
                        } catch (final Exception e) {
                            IJError.print(e);
                        }
                        return c;
                    }
                }));
                // If it's the last one:
                if (!it.hasNext()) {
                    // Add the concluding task, that waits on all and shuts down the scheduler
                    d3d.executors.submit(new Runnable() {

                        @Override
                        public void run() {
                            // Wait until all are done
                            for (final Future<Content> c : list) {
                                try {
                                    c.get();
                                } catch (final Throwable t) {
                                    IJError.print(t);
                                }
                            }
                            try {
                                // Shutdown scheduler and execute remaining tasks
                                for (final Runnable r : updater.shutdownNow()) {
                                    r.run();
                                }
                            } catch (final Throwable e) {
                                IJError.print(e);
                            }
                            // Reset cursor
                            doneWaiting();
                            Utils.showStatus(new StringBuilder("Done rendering ").append(counter.get()).append('/').append(hs.size()).toString());
                        }
                    });
                }
            }
            return list;
        }
    });
    if (wait && -1 != resample) {
        try {
            fu.get();
        } catch (final Throwable t) {
            IJError.print(t);
        }
    }
    return fu;
}
Also used : HashMap(java.util.HashMap) Iterator(java.util.Iterator) Vector(java.util.Vector) ProjectThing(ini.trakem2.tree.ProjectThing) HashSet(java.util.HashSet) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) Hashtable(java.util.Hashtable) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Content(ij3d.Content) Future(java.util.concurrent.Future) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with Thing

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

the class Loader method importImages.

/**
 * <p>Import images from the given text file, which is expected to contain 4 columns or optionally 9 columns:</p>
 * <ul>
 * <li>column 1: image file path (if base_dir is not null, it will be prepended)</li>
 * <li>column 2: x coord [px]</li>
 * <li>column 3: y coord [px]</li>
 * <li>column 4: z coord [px] (layer_thickness will be multiplied to it if not zero)</li>
 * </ul>
 * <p>optional columns, if a property is not known, it can be set to "-" which makes TrakEM2 open the file and find out by itself</p>
 * <ul>
 * <li>column 5: width [px]</li>
 * <li>column 6: height [px]</li>
 * <li>column 7: min intensity [double] (for screen display)</li>
 * <li>column 8: max intensity [double] (for screen display)</li>
 * <li>column 9: type [integer] (pixel types according to ImagepPlus types: 0=8bit int gray, 1=16bit int gray, 2=32bit float gray, 3=8bit indexed color, 4=32-bit RGB color</li>
 * </ul>
 *
 * <p>This function implements the "Import from text file" command.</p>
 *
 * <p>Layers will be automatically created as needed inside the LayerSet to which the given ref_layer belongs.</p>
 * <p>
 * The text file can contain comments that start with the # sign.
 * </p>
 * <p>
 * Images will be imported in parallel, using as many cores as your machine has.
 * </p>
 * @param calibration_ transforms the read coordinates into pixel coordinates, including x,y,z, and layer thickness.
 * @param scale_ Between 0 and 1. When lower than 1, a preprocessor script is created for the imported images, to scale them down.
 */
public Bureaucrat importImages(Layer ref_layer, String abs_text_file_path_, String column_separator_, double layer_thickness_, double calibration_, boolean homogenize_contrast_, float scale_, int border_width_) {
    // check parameters: ask for good ones if necessary
    if (null == abs_text_file_path_) {
        final String[] file = Utils.selectFile("Select text file");
        // user canceled dialog
        if (null == file)
            return null;
        abs_text_file_path_ = file[0] + file[1];
    }
    if (null == column_separator_ || 0 == column_separator_.length() || Double.isNaN(layer_thickness_) || layer_thickness_ <= 0 || Double.isNaN(calibration_) || calibration_ <= 0) {
        final Calibration cal = ref_layer.getParent().getCalibrationCopy();
        final GenericDialog gdd = new GenericDialog("Options");
        final String[] separators = new String[] { "tab", "space", "comma (,)" };
        gdd.addMessage("Choose a layer to act as the zero for the Z coordinates:");
        Utils.addLayerChoice("Base layer", ref_layer, gdd);
        gdd.addChoice("Column separator: ", separators, separators[0]);
        // default: 60 nm
        gdd.addNumericField("Layer thickness: ", cal.pixelDepth, 2);
        gdd.addNumericField("Calibration (data to pixels): ", 1, 2);
        gdd.addCheckbox("Homogenize contrast layer-wise", homogenize_contrast_);
        gdd.addSlider("Scale:", 0, 100, 100);
        gdd.addNumericField("Hide border with alpha mask", 0, 0, 6, "pixels");
        gdd.showDialog();
        if (gdd.wasCanceled())
            return null;
        layer_thickness_ = gdd.getNextNumber();
        if (layer_thickness_ < 0 || Double.isNaN(layer_thickness_)) {
            Utils.log("Improper layer thickness value.");
            return null;
        }
        calibration_ = gdd.getNextNumber();
        if (0 == calibration_ || Double.isNaN(calibration_)) {
            Utils.log("Improper calibration value.");
            return null;
        }
        // not pixelDepth!
        layer_thickness_ /= cal.pixelWidth;
        ref_layer = ref_layer.getParent().getLayer(gdd.getNextChoiceIndex());
        column_separator_ = "\t";
        switch(gdd.getNextChoiceIndex()) {
            case 1:
                column_separator_ = " ";
                break;
            case 2:
                column_separator_ = ",";
                break;
            default:
                break;
        }
        homogenize_contrast_ = gdd.getNextBoolean();
        final double sc = gdd.getNextNumber();
        if (Double.isNaN(sc))
            scale_ = 1.0f;
        else
            scale_ = ((float) sc) / 100.0f;
        final int border = (int) gdd.getNextNumber();
        if (border < 0) {
            Utils.log("Nonsensical border value: " + border);
            return null;
        }
        border_width_ = border;
    }
    if (Float.isNaN(scale_) || scale_ < 0 || scale_ > 1) {
        Utils.log("Non-sensical scale: " + scale_ + "\nUsing scale of 1 instead.");
        scale_ = 1;
    }
    // make vars accessible from inner threads:
    final Layer base_layer = ref_layer;
    final String abs_text_file_path = abs_text_file_path_;
    final String column_separator = column_separator_;
    final double layer_thickness = layer_thickness_;
    final double calibration = calibration_;
    final boolean homogenize_contrast = homogenize_contrast_;
    final float scale = (float) scale_;
    final int border_width = border_width_;
    return Bureaucrat.createAndStart(new Worker.Task("Importing images", true) {

        @Override
        public void exec() {
            try {
                // 1 - read text file
                final String[] lines = Utils.openTextFileLines(abs_text_file_path);
                if (null == lines || 0 == lines.length) {
                    Utils.log2("No images to import from " + abs_text_file_path);
                    return;
                }
                ContrastEnhancerWrapper cew = null;
                if (homogenize_contrast) {
                    cew = new ContrastEnhancerWrapper();
                    cew.showDialog();
                }
                final String sep2 = column_separator + column_separator;
                // 2 - set a base dir path if necessary
                String base_dir = null;
                // to wait on mipmap regeneration
                final Vector<Future<?>> fus = new Vector<Future<?>>();
                final LayerSet layer_set = base_layer.getParent();
                final double z_zero = base_layer.getZ();
                final AtomicInteger n_imported = new AtomicInteger(0);
                final Set<Layer> touched_layers = new HashSet<Layer>();
                final int NP = Runtime.getRuntime().availableProcessors();
                int np = NP;
                switch(np) {
                    case 1:
                    case 2:
                        break;
                    default:
                        np = np / 2;
                        break;
                }
                final ExecutorService ex = Utils.newFixedThreadPool(np, "import-images");
                final List<Future<?>> imported = new ArrayList<Future<?>>();
                final Worker wo = this;
                final String script_path;
                // If scale is at least 1/100 lower than 1, then:
                if (Math.abs(scale - (int) scale) > 0.01) {
                    // Assume source and target sigma of 0.5
                    final double sigma = Math.sqrt(Math.pow(1 / scale, 2) - 0.25);
                    final String script = new StringBuilder().append("import ij.ImagePlus;\n").append("import ij.process.ImageProcessor;\n").append("import ij.plugin.filter.GaussianBlur;\n").append("GaussianBlur blur = new GaussianBlur();\n").append(// as in ij.plugin.filter.GaussianBlur
                    "double accuracy = (imp.getType() == ImagePlus.GRAY8 || imp.getType() == ImagePlus.COLOR_RGB) ? 0.002 : 0.0002;\n").append("imp.getProcessor().setInterpolationMethod(ImageProcessor.NONE);\n").append("blur.blurGaussian(imp.getProcessor(),").append(sigma).append(',').append(sigma).append(",accuracy);\n").append("imp.setProcessor(imp.getTitle(), imp.getProcessor().resize((int)(imp.getWidth() * ").append(scale).append("), (int)(imp.getHeight() * ").append(scale).append(")));").toString();
                    File f = new File(getStorageFolder() + "resize-" + scale + ".bsh");
                    int v = 1;
                    while (f.exists()) {
                        f = new File(getStorageFolder() + "resize-" + scale + "." + v + ".bsh");
                        v++;
                    }
                    script_path = Utils.saveToFile(f, script) ? f.getAbsolutePath() : null;
                    if (null == script_path) {
                        Utils.log("Could NOT save a preprocessor script for image scaling\nat path " + f.getAbsolutePath());
                    }
                } else {
                    script_path = null;
                }
                Utils.log("Scaling script path is " + script_path);
                final AtomicReference<Triple<Integer, Integer, ByteProcessor>> last_mask = new AtomicReference<Triple<Integer, Integer, ByteProcessor>>();
                // 3 - parse each line
                for (int i = 0; i < lines.length; i++) {
                    if (Thread.currentThread().isInterrupted() || hasQuitted()) {
                        this.quit();
                        return;
                    }
                    // process line
                    // first thing is the backslash removal, before they get processed at all
                    String line = lines[i].replace('\\', '/').trim();
                    final int ic = line.indexOf('#');
                    // remove comment at end of line if any
                    if (-1 != ic)
                        line = line.substring(0, ic);
                    if (0 == line.length() || '#' == line.charAt(0))
                        continue;
                    // reduce line, so that separators are really unique
                    while (-1 != line.indexOf(sep2)) {
                        line = line.replaceAll(sep2, column_separator);
                    }
                    final String[] column = line.split(column_separator);
                    if (column.length < 4) {
                        Utils.log("Less than 4 columns: can't import from line " + i + " : " + line);
                        continue;
                    }
                    // obtain coordinates
                    double x = 0, y = 0, z = 0;
                    try {
                        x = Double.parseDouble(column[1].trim());
                        y = Double.parseDouble(column[2].trim());
                        z = Double.parseDouble(column[3].trim());
                    } catch (final NumberFormatException nfe) {
                        Utils.log("Non-numeric value in a numeric column at line " + i + " : " + line);
                        continue;
                    }
                    x *= calibration;
                    y *= calibration;
                    z = z * calibration + z_zero;
                    // obtain path
                    String path = column[0].trim();
                    if (0 == path.length())
                        continue;
                    // check if path is relative
                    if ((!IJ.isWindows() && '/' != path.charAt(0)) || (IJ.isWindows() && 1 != path.indexOf(":/"))) {
                        // path is relative.
                        if (null == base_dir) {
                            // may not be null if another thread that got the lock first set it to non-null
                            // Ask for source directory
                            final DirectoryChooser dc = new DirectoryChooser("Choose source directory");
                            final String dir = dc.getDirectory();
                            if (null == dir) {
                                // quit all threads
                                return;
                            }
                            base_dir = Utils.fixDir(dir);
                        }
                    }
                    if (null != base_dir)
                        path = base_dir + path;
                    final File f = new File(path);
                    if (!f.exists()) {
                        Utils.log("No file found for path " + path);
                        continue;
                    }
                    // will create a new Layer if necessary
                    final Layer layer = layer_set.getLayer(z, layer_thickness, true);
                    touched_layers.add(layer);
                    final String imagefilepath = path;
                    final double xx = x * scale;
                    final double yy = y * scale;
                    final Callable<Patch> creator;
                    if (column.length >= 9) {
                        creator = new Callable<Patch>() {

                            private final int parseInt(final String t) {
                                if (t.equals("-"))
                                    return -1;
                                return Integer.parseInt(t);
                            }

                            private final double parseDouble(final String t) {
                                if (t.equals("-"))
                                    return Double.NaN;
                                return Double.parseDouble(t);
                            }

                            @Override
                            public Patch call() throws Exception {
                                int o_width = parseInt(column[4].trim());
                                int o_height = parseInt(column[5].trim());
                                double min = parseDouble(column[6].trim());
                                double max = parseDouble(column[7].trim());
                                int type = parseInt(column[8].trim());
                                if (-1 == type || -1 == o_width || -1 == o_height) {
                                    // Read them from the file header
                                    final ImageFileHeader ifh = new ImageFileHeader(imagefilepath);
                                    o_width = ifh.width;
                                    o_height = ifh.height;
                                    type = ifh.type;
                                    if (!ifh.isSupportedType()) {
                                        Utils.log("Incompatible image type: " + imagefilepath);
                                        return null;
                                    }
                                }
                                ImagePlus imp = null;
                                if (Double.isNaN(min) || Double.isNaN(max)) {
                                    imp = openImagePlus(imagefilepath);
                                    min = imp.getProcessor().getMin();
                                    max = imp.getProcessor().getMax();
                                }
                                final Patch patch = new Patch(layer.getProject(), new File(imagefilepath).getName(), o_width, o_height, o_width, o_height, type, 1.0f, Color.yellow, false, min, max, new AffineTransform(1, 0, 0, 1, xx, yy), imagefilepath);
                                if (null != script_path && null != imp) {
                                    // For use in setting the preprocessor script
                                    cacheImagePlus(patch.getId(), imp);
                                }
                                return patch;
                            }
                        };
                    } else {
                        creator = new Callable<Patch>() {

                            @Override
                            public Patch call() throws Exception {
                                IJ.redirectErrorMessages();
                                final ImageFileHeader ifh = new ImageFileHeader(imagefilepath);
                                final int o_width = ifh.width;
                                final int o_height = ifh.height;
                                final int type = ifh.type;
                                if (!ifh.isSupportedType()) {
                                    Utils.log("Incompatible image type: " + imagefilepath);
                                    return null;
                                }
                                double min = 0;
                                double max = 255;
                                switch(type) {
                                    case ImagePlus.GRAY16:
                                    case ImagePlus.GRAY32:
                                        // Determine suitable min and max
                                        // TODO Stream through the image, do not load it!
                                        final ImagePlus imp = openImagePlus(imagefilepath);
                                        if (null == imp) {
                                            Utils.log("Ignoring unopenable image from " + imagefilepath);
                                            return null;
                                        }
                                        min = imp.getProcessor().getMin();
                                        max = imp.getProcessor().getMax();
                                        break;
                                }
                                // add Patch
                                final Patch patch = new Patch(layer.getProject(), new File(imagefilepath).getName(), o_width, o_height, o_width, o_height, type, 1.0f, Color.yellow, false, min, max, new AffineTransform(1, 0, 0, 1, xx, yy), imagefilepath);
                                return patch;
                            }
                        };
                    }
                    // Otherwise, images would end up loaded twice for no reason
                    if (0 == (i % (NP + NP))) {
                        final ArrayList<Future<?>> a = new ArrayList<Future<?>>(NP + NP);
                        synchronized (fus) {
                            // .add is also synchronized, fus is a Vector
                            int k = 0;
                            while (!fus.isEmpty() && k < NP) {
                                a.add(fus.remove(0));
                                k++;
                            }
                        }
                        for (final Future<?> fu : a) {
                            try {
                                if (wo.hasQuitted())
                                    return;
                                fu.get();
                            } catch (final Throwable t) {
                                t.printStackTrace();
                            }
                        }
                    }
                    imported.add(ex.submit(new Runnable() {

                        @Override
                        public void run() {
                            if (wo.hasQuitted())
                                return;
                            /* */
                            IJ.redirectErrorMessages();
                            Patch patch;
                            try {
                                patch = creator.call();
                            } catch (final Exception e) {
                                e.printStackTrace();
                                Utils.log("Could not load patch from " + imagefilepath);
                                return;
                            }
                            // Set the script if any
                            if (null != script_path) {
                                try {
                                    patch.setPreprocessorScriptPath(script_path);
                                } catch (final Throwable t) {
                                    Utils.log("FAILED to set a scaling preprocessor script to patch " + patch);
                                    IJError.print(t);
                                }
                            }
                            // Set an alpha mask to crop away the borders
                            if (border_width > 0) {
                                final Triple<Integer, Integer, ByteProcessor> m = last_mask.get();
                                if (null != m && m.a == patch.getOWidth() && m.b == patch.getOHeight()) {
                                    // Reuse
                                    patch.setAlphaMask(m.c);
                                } else {
                                    // Create new mask
                                    final ByteProcessor mask = new ByteProcessor(patch.getOWidth(), patch.getOHeight());
                                    mask.setValue(255);
                                    mask.setRoi(new Roi(border_width, border_width, mask.getWidth() - 2 * border_width, mask.getHeight() - 2 * border_width));
                                    mask.fill();
                                    patch.setAlphaMask(mask);
                                    // Store as last
                                    last_mask.set(new Triple<Integer, Integer, ByteProcessor>(mask.getWidth(), mask.getHeight(), mask));
                                }
                            }
                            if (!homogenize_contrast) {
                                fus.add(regenerateMipMaps(patch));
                            }
                            synchronized (layer) {
                                layer.add(patch, true);
                            }
                            wo.setTaskName("Imported " + (n_imported.incrementAndGet() + 1) + "/" + lines.length);
                        }
                    }));
                }
                Utils.wait(imported);
                ex.shutdown();
                if (0 == n_imported.get()) {
                    Utils.log("No images imported.");
                    return;
                }
                base_layer.getParent().setMinimumDimensions();
                Display.repaint(base_layer.getParent());
                recreateBuckets(touched_layers);
                if (homogenize_contrast) {
                    setTaskName("Enhance contrast");
                    // layer-wise (layer order is irrelevant):
                    cew.applyLayerWise(touched_layers);
                    cew.shutdown();
                }
                Utils.wait(fus);
            } catch (final Exception e) {
                IJError.print(e);
            }
        }
    }, base_layer.getProject());
}
Also used : ByteProcessor(ij.process.ByteProcessor) Set(java.util.Set) HashSet(java.util.HashSet) LayerSet(ini.trakem2.display.LayerSet) ArrayList(java.util.ArrayList) Callable(java.util.concurrent.Callable) GenericDialog(ij.gui.GenericDialog) Worker(ini.trakem2.utils.Worker) AreaList(ini.trakem2.display.AreaList) ArrayList(java.util.ArrayList) List(java.util.List) Vector(java.util.Vector) LayerSet(ini.trakem2.display.LayerSet) AtomicReference(java.util.concurrent.atomic.AtomicReference) ImageFileHeader(ini.trakem2.io.ImageFileHeader) Calibration(ij.measure.Calibration) Layer(ini.trakem2.display.Layer) ImagePlus(ij.ImagePlus) Roi(ij.gui.Roi) IOException(java.io.IOException) FormatException(loci.formats.FormatException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Triple(mpicbg.trakem2.util.Triple) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future) AffineTransform(java.awt.geom.AffineTransform) ContrastEnhancerWrapper(ini.trakem2.imaging.ContrastEnhancerWrapper) File(java.io.File) Patch(ini.trakem2.display.Patch) DirectoryChooser(ij.io.DirectoryChooser)

Example 3 with Thing

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

the class TMLHandler method endElement.

public void endElement(String namespace_URI, String local_name, String qualified_name) {
    if (null == loader)
        return;
    if (skip) {
        // reset
        skip = false;
        return;
    }
    String orig_qualified_name = qualified_name;
    // Utils.log2("endElement: " + qualified_name);
    // iterate over all open things and find the one that matches the qualified_name, and set it closed (pop it out of the list):
    qualified_name = qualified_name.toLowerCase().trim();
    if (0 == qualified_name.indexOf("t2_")) {
        qualified_name = qualified_name.substring(3);
    }
    for (int i = al_open.size() - 1; i > -1; i--) {
        Thing thing = al_open.get(i);
        if (thing.getType().toLowerCase().equals(qualified_name)) {
            al_open.remove(i);
            break;
        }
    }
    if (null != last_annotation && null != last_displayable) {
        last_displayable.setAnnotation(last_annotation.toString().trim().replaceAll("&lt;", "<"));
        last_annotation = null;
    }
    // terminate non-single clause objects
    if (orig_qualified_name.equals("t2_node")) {
        // Remove one node from the stack
        nodes.removeLast();
        taggables.removeLast();
    } else if (orig_qualified_name.equals("t2_connector")) {
        if (null != last_connector) {
            tree_root_nodes.put(last_connector, last_root_node);
            last_root_node = null;
            last_connector = null;
            last_tree = null;
            nodes.clear();
        }
        last_displayable = null;
    } else if (orig_qualified_name.equals("t2_area_list")) {
        last_area_list = null;
        last_displayable = null;
    } else if (orig_qualified_name.equals("t2_area")) {
        if (null != reca) {
            if (null != last_area_list) {
                // it's local
                last_area_list.addArea(last_area_list_layer_id, reca.getArea());
            } else {
                ((AreaTree.AreaNode) nodes.getLast()).setData(reca.getArea());
            }
            reca = null;
        }
    } else if (orig_qualified_name.equals("ict_transform_list")) {
        ct_list_stack.remove(ct_list_stack.size() - 1);
    } else if (orig_qualified_name.equals("t2_patch")) {
        if (last_patch_filters.size() > 0) {
            last_patch.setFilters(last_patch_filters.toArray(new IFilter[last_patch_filters.size()]));
        }
        if (null != last_ct) {
            last_patch.setCoordinateTransformSilently(last_ct);
            last_ct = null;
        } else if (!last_patch.checkCoordinateTransformFile()) {
            Utils.log("ERROR: could not find a file for the coordinate transform #" + last_patch.getCoordinateTransformId() + " of Patch #" + last_patch.getId());
        }
        if (!last_patch.checkAlphaMaskFile()) {
            Utils.log("ERROR: could not find a file for the alpha mask #" + last_patch.getAlphaMaskId() + " of Patch #" + last_patch.getId());
        }
        last_patch = null;
        last_patch_filters.clear();
        last_displayable = null;
    } else if (orig_qualified_name.equals("t2_ball")) {
        last_ball = null;
        last_displayable = null;
    } else if (orig_qualified_name.equals("t2_dissector")) {
        last_dissector = null;
        last_displayable = null;
    } else if (orig_qualified_name.equals("t2_treeline")) {
        if (null != last_treeline) {
            // old format:
            if (null == last_root_node && null != last_treeline_data && last_treeline_data.length() > 0) {
                last_root_node = parseBranch(Utils.trim(last_treeline_data));
                last_treeline_data = null;
            }
            // new
            tree_root_nodes.put(last_treeline, last_root_node);
            last_root_node = null;
            // always:
            last_treeline = null;
            last_tree = null;
            nodes.clear();
        }
        last_displayable = null;
    } else if (orig_qualified_name.equals("t2_areatree")) {
        if (null != last_areatree) {
            tree_root_nodes.put(last_areatree, last_root_node);
            last_root_node = null;
            last_areatree = null;
            last_tree = null;
            // the absence of this line would have made the nodes list grow with all nodes of all areatrees, which is ok but consumes memory
            nodes.clear();
        }
        last_displayable = null;
    } else if (orig_qualified_name.equals("t2_stack")) {
        if (null != last_ict) {
            last_stack.setInvertibleCoordinateTransformSilently(last_ict);
            last_ict = null;
        }
        last_stack = null;
        last_displayable = null;
    } else if (in(orig_qualified_name, all_displayables)) {
        last_displayable = null;
    }
}
Also used : AreaTree(ini.trakem2.display.AreaTree) LayerThing(ini.trakem2.tree.LayerThing) TemplateThing(ini.trakem2.tree.TemplateThing) ProjectThing(ini.trakem2.tree.ProjectThing) Thing(ini.trakem2.tree.Thing)

Example 4 with Thing

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

the class DefaultTreeTransferHandler method canPerformAction.

public boolean canPerformAction(DNDTree target, DefaultMutableTreeNode dragged_node, int action, Point location) {
    // prevent drags from non-tree components
    if (null == dragged_node)
        return false;
    // Can't drop onto a TemplateTree
    if (target instanceof TemplateTree) {
        return false;
    }
    // Can't drag a node that contains a Project!
    if (dragged_node.getUserObject() instanceof ProjectThing && ((ProjectThing) dragged_node.getUserObject()).getObject() instanceof Project) {
        return false;
    }
    // Can't drag basic object nodes from a template tree RECONSIDERED, I like it even if it looks inconsistent (but types are types!)
    /*
		if (dragged_node.getUserObject() instanceof TemplateThing && project.isBasicType(((Thing)dragged_node.getUserObject()).getType())) {
			return false;
		}
		*/
    // else, the target has to be not null
    TreePath pathTarget = target.getPathForLocation(location.x, location.y);
    if (pathTarget == null) {
        target.setSelectionPath(null);
        return false;
    }
    /* // debug
		if (action == DnDConstants.ACTION_COPY) {
			Utils.log("can drop: Action copy");
		} else if (action == DnDConstants.ACTION_MOVE) {
			Utils.log("can drop: Action move");
		} else {
			Utils.log("can drop: Unexpected action: " + action);
		}
		*/
    target.setSelectionPath(pathTarget);
    DefaultMutableTreeNode parent_node = (DefaultMutableTreeNode) pathTarget.getLastPathComponent();
    // can be a Thing or an Attribute
    Object parent_ob = parent_node.getUserObject();
    Thing child_thing = (Thing) dragged_node.getUserObject();
    if (DnDConstants.ACTION_MOVE == action || DnDConstants.ACTION_COPY == action) {
        if (parent_ob instanceof ProjectThing) {
            ProjectThing parent_thing = (ProjectThing) parent_ob;
            // check if it's allowed to give to this parent such a child:
            if (!parent_thing.uniquePathExists(child_thing.getType()) && !parent_thing.canHaveAsChild(child_thing)) {
                // Utils.log("Not possible.");
                return false;
            }
            // - the leaf that is going to be dropped into itself or any of its descendants.
            if (parent_node == dragged_node.getParent() || dragged_node.isNodeDescendant(parent_node)) {
                // Utils.log("preventing dragging onto itself or any of the self children.");
                return false;
            } else {
                return true;
            }
        }
    }
    // default:
    return false;
}
Also used : Project(ini.trakem2.Project) TreePath(javax.swing.tree.TreePath) DefaultMutableTreeNode(javax.swing.tree.DefaultMutableTreeNode)

Example 5 with Thing

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

the class ProjectThing method setTitle.

public void setTitle(String title) {
    // A Thing has a title as the object when it has no object, because the object gives it the title (the Thing only defines the type)
    if (null == title || title.length() < 1) {
        // reset title
        if (object != null && object instanceof String)
            this.object = template.getType();
        return;
    }
    if (null == object || object instanceof String) {
        object = title;
        updateInDatabase("title");
        // find any children that are using this title in addition to their own for the DisplayablePanel, and update it.
        if (null != al_children) {
            synchronized (al_children) {
                for (ProjectThing pt : al_children) {
                    if (pt.object instanceof Displayable) {
                        Displayable d = (Displayable) pt.object;
                        Display.updateTitle(d.getLayer(), d);
                    } else if (pt.getType().equals("profile_list")) {
                        if (null == pt.al_children)
                            continue;
                        for (ProjectThing pd : pt.al_children) {
                            Displayable d = (Displayable) pd.object;
                            Display.updateTitle(d.getLayer(), d);
                        }
                    }
                }
            }
        }
    } else {
        try {
            Method setTitle = null;
            if (object instanceof Displayable) {
                ((Displayable) object).setTitle(title);
            } else {
                setTitle = object.getClass().getDeclaredMethod("setTitle", new Class[] { String.class });
                setTitle.invoke(object, new Object[] { title });
            }
        } catch (NoSuchMethodException nsme) {
            Utils.log("No such method: setTitle, for object " + object);
        } catch (Exception e) {
            Utils.log("ProjectThing.setTitle: no such method setTitle or can't access it, in the object " + object);
            IJError.print(e);
        }
    }
}
Also used : ZDisplayable(ini.trakem2.display.ZDisplayable) Displayable(ini.trakem2.display.Displayable) Method(java.lang.reflect.Method)

Aggregations

DBObject (ini.trakem2.persistence.DBObject)16 ProjectThing (ini.trakem2.tree.ProjectThing)15 TemplateThing (ini.trakem2.tree.TemplateThing)9 DefaultMutableTreeNode (javax.swing.tree.DefaultMutableTreeNode)9 LayerThing (ini.trakem2.tree.LayerThing)8 TreePath (javax.swing.tree.TreePath)8 HashMap (java.util.HashMap)7 Displayable (ini.trakem2.display.Displayable)6 ZDisplayable (ini.trakem2.display.ZDisplayable)6 Thing (ini.trakem2.tree.Thing)6 GenericDialog (ij.gui.GenericDialog)5 Layer (ini.trakem2.display.Layer)5 LayerSet (ini.trakem2.display.LayerSet)5 ArrayList (java.util.ArrayList)5 HashSet (java.util.HashSet)5 ProjectTree (ini.trakem2.tree.ProjectTree)4 JPopupMenu (javax.swing.JPopupMenu)4 DefaultTreeModel (javax.swing.tree.DefaultTreeModel)4 Project (ini.trakem2.Project)3 Profile (ini.trakem2.display.Profile)3