Search in sources :

Example 16 with Display

use of ini.trakem2.display.Display in project TrakEM2 by trakem2.

the class ProjectTree method selectInDisplay.

public void selectInDisplay(final ProjectThing thing, final boolean shift_down) {
    Object obd = thing.getObject();
    if (obd instanceof Displayable) {
        Displayable d = (Displayable) obd;
        if (!d.isVisible())
            d.setVisible(true);
        Display display = Display.getFront(d.getProject());
        if (null == display)
            return;
        display.select(d, shift_down);
    } else {
        // select all basic types under this leaf
        final List<Displayable> ds = thing.findChildrenOfType(Displayable.class);
        Display display = null;
        for (final Iterator<Displayable> it = ds.iterator(); it.hasNext(); ) {
            final Displayable d = it.next();
            if (null == display) {
                display = Display.getFront(d.getProject());
                if (null == display)
                    return;
            }
            if (!d.isVisible()) {
                Utils.log("Skipping non-visible object " + d);
                it.remove();
            }
        }
        if (null == display)
            return;
        if (!shift_down)
            display.getSelection().clear();
        display.getSelection().selectAll(ds);
    }
}
Also used : Displayable(ini.trakem2.display.Displayable) ZDisplayable(ini.trakem2.display.ZDisplayable) DBObject(ini.trakem2.persistence.DBObject) Display(ini.trakem2.display.Display)

Example 17 with Display

use of ini.trakem2.display.Display in project TrakEM2 by trakem2.

the class Search method createCoordinate.

private Coordinate<Displayable> createCoordinate(final Displayable d) {
    Rectangle r = d.getBoundingBox();
    Layer la = d instanceof ZDisplayable ? ((ZDisplayable) d).getFirstLayer() : d.getLayer();
    if (null == la) {
        Display display = Display.getFront(d.getProject());
        if (null == display)
            la = d.getProject().getRootLayerSet().getLayer(0);
        else
            la = display.getLayer();
    }
    return new Coordinate<Displayable>(r.x + r.width / 2, r.y + r.height / 2, la, d);
}
Also used : ZDisplayable(ini.trakem2.display.ZDisplayable) Coordinate(ini.trakem2.display.Coordinate) Rectangle(java.awt.Rectangle) Layer(ini.trakem2.display.Layer) Display(ini.trakem2.display.Display)

Example 18 with Display

use of ini.trakem2.display.Display in project TrakEM2 by trakem2.

the class Compare method variabilityAnalysis.

/**
 * @param reference_project If null, then the first one found in the Project.getProjects() lists is used.
 * @param regex A String (can be null) to filter objects by, to limit what gets processed.
 *              If regex is not null, then only ProjectThing nodes with the matching regex are analyzed (shallow: none of their children are questioned, but pipes will be built from them all).
 * @param generate_plots Whether to generate the variability plots at all.
 * @param show_plots If generate_plots, whether to show the plots in a stack image window or to save them.
 * @param show_3D Whether to show any 3D data.
 * @param show_condensed_3D If show_3D, whether to show the condensed vector strings, i.e. the "average" pipes.
 * @param show_sources_3D If show_3D, whether to show the source pipes from which the condensed vector string was generated.
 * @param sources_color_table Which colors to give to the pipes of which Project.
 * @param show_envelope_3D If show_3D, whether to generate the variability envelope.
 * @param envelope_alpha If show_envelope_3D, the envelope takes an alpha value between 0 (total transparency) and 1 (total opacity)
 * @param delta_envelope The delta to resample the envelope to. When smaller than or equal to 1, no envelope resampling occurs.
 * @param show_axes_3D If show_3D, whether to display the reference axes as well.
 * @param heat_map If show_3D, whether to color the variability with a Fire LUT.
 *                 If not show_condensed_3D, then the variability is shown in color-coded 3D spheres placed at the entry point to the neuropile.
 * @param map_condensed If not null, all VectorString3D are put into this map.
 * @param projects The projects to use.
 */
public static Bureaucrat variabilityAnalysis(final Project reference_project, final String regex, final String[] ignore, final boolean show_cata_dialog, final boolean generate_plots, final boolean show_plots, final String plot_dir_, final boolean show_3D, final boolean show_condensed_3D, final boolean show_sources_3D, final Map<Project, Color> sources_color_table, final boolean show_envelope_3D, final float envelope_alpha, final double delta_envelope, final int envelope_type, final boolean show_axes_3D, final boolean heat_map, final Map<String, VectorString3D> map_condensed, final Project[] projects) {
    // gather all open projects
    final Project[] p = null == projects ? Project.getProjects().toArray(new Project[0]) : projects;
    // make the reference_project be the first in the array
    if (null != reference_project && reference_project != p[0]) {
        for (int i = 0; i < p.length; i++) {
            if (reference_project == p[i]) {
                p[i] = p[0];
                p[0] = reference_project;
                break;
            }
        }
    }
    final Worker worker = new Worker("Comparing all to all") {

        @Override
        public void run() {
            startedWorking();
            try {
                Utils.log2("Asking for CATAParameters...");
                final CATAParameters cp = new CATAParameters();
                cp.regex = regex;
                cp.delta_envelope = delta_envelope;
                cp.envelope_type = envelope_type;
                if (show_cata_dialog && !cp.setup(false, regex, true, true)) {
                    finishedWorking();
                    return;
                }
                // so source points are stored in VectorString3D for each resampled and interpolated point
                cp.with_source = true;
                // Store a series of results, depending on options
                final HashMap<String, Display3D> results = new HashMap<String, Display3D>();
                String plot_dir = plot_dir_;
                if (generate_plots && !show_plots) {
                    // Save plots
                    if (null == plot_dir) {
                        final DirectoryChooser dc = new DirectoryChooser("Choose plots directory");
                        plot_dir = dc.getDirectory();
                        if (null == plot_dir) {
                            finishedWorking();
                            return;
                        }
                    }
                    if (IJ.isWindows())
                        plot_dir = plot_dir.replace('\\', '/');
                    if (!plot_dir.endsWith("/"))
                        plot_dir += "/";
                }
                Utils.log2("Gathering chains...");
                // Gather chains that do not match the ignore regexes
                // will transform them as well to the reference found in the first project in the p array
                Object[] ob = gatherChains(p, cp, ignore);
                ArrayList<Chain> chains = (ArrayList<Chain>) ob[0];
                // to keep track of each project's chains
                final ArrayList[] p_chains = (ArrayList[]) ob[1];
                ob = null;
                if (null == chains) {
                    finishedWorking();
                    return;
                }
                Utils.log2("Collecting bundles...");
                final HashMap<Project, HashMap<String, VectorString3D>> axes = new HashMap<Project, HashMap<String, VectorString3D>>();
                // Sort out into groups by unique names of lineage bundles
                final HashMap<String, ArrayList<Chain>> bundles = new HashMap<String, ArrayList<Chain>>();
                for (final Chain chain : chains) {
                    String title = chain.getCellTitle();
                    final String t = title.toLowerCase();
                    // unnamed
                    if (0 == t.indexOf('[') || 0 == t.indexOf('#'))
                        continue;
                    Utils.log("Accepting " + title);
                    title = title.substring(0, title.indexOf(' '));
                    // lineage bundle instance chains
                    ArrayList<Chain> bc = bundles.get(title);
                    if (null == bc) {
                        bc = new ArrayList<Chain>();
                        bundles.put(title, bc);
                    }
                    bc.add(chain);
                }
                Utils.log2("Found " + bundles.size() + " bundles.");
                chains = null;
                if (null != cp.regex && show_axes_3D && axes.size() < 3) {
                    // Must find the Mushroom Body lobes separately
                    final String cp_regex = cp.regex;
                    cp.regex = "mb";
                    final Object[] o = gatherChains(p, cp, ignore);
                    final ArrayList<Chain> lobes = (ArrayList<Chain>) o[0];
                    Utils.logAll("Found " + lobes.size() + " chains for lobes");
                    for (final Chain chain : lobes) {
                        final String t = chain.getCellTitle().toLowerCase();
                        if (-1 != t.indexOf("peduncle") || -1 != t.indexOf("medial lobe") || -1 != t.indexOf("dorsal lobe")) {
                            Utils.logAll("adding " + t);
                            final Project pr = chain.pipes.get(0).getProject();
                            HashMap<String, VectorString3D> m = axes.get(pr);
                            if (null == m) {
                                m = new HashMap<String, VectorString3D>();
                                axes.put(pr, m);
                            }
                            m.put(t, chain.vs);
                            continue;
                        }
                    }
                    cp.regex = cp_regex;
                } else {
                    Utils.logAll("Not: cp.regex = " + cp.regex + "  show_axes_3D = " + show_axes_3D + "  axes.size() = " + axes.size());
                }
                final HashMap<String, VectorString3D> condensed = new HashMap<String, VectorString3D>();
                Utils.log2("Condensing each bundle...");
                // Condense each into a single VectorString3D
                for (final Map.Entry<String, ArrayList<Chain>> entry : bundles.entrySet()) {
                    final ArrayList<Chain> bc = entry.getValue();
                    if (bc.size() < 2) {
                        Utils.log2("Skipping single: " + entry.getKey());
                        continue;
                    }
                    final VectorString3D[] vs = new VectorString3D[bc.size()];
                    for (int i = 0; i < vs.length; i++) vs[i] = bc.get(i).vs;
                    final VectorString3D c = condense(cp, vs, this);
                    c.setCalibration(p[0].getRootLayerSet().getCalibrationCopy());
                    condensed.put(entry.getKey(), c);
                    if (this.hasQuitted())
                        return;
                }
                // Store:
                if (null != map_condensed) {
                    map_condensed.putAll(condensed);
                }
                if (generate_plots) {
                    Utils.log2("Plotting stdDev for each condensed bundle...");
                    // Y axis: the stdDev at each point, computed from the group of points that contribute to each
                    for (final Map.Entry<String, VectorString3D> e : condensed.entrySet()) {
                        final String name = e.getKey();
                        final VectorString3D c = e.getValue();
                        final Plot plot = makePlot(cp, name, c);
                        // FAILS//plot.addLabel(10, cp.plot_height-5, name); // must be added after setting size
                        if (show_plots)
                            plot.show();
                        else if (null != plot_dir)
                            new FileSaver(plot.getImagePlus()).saveAsPng(plot_dir + name.replace('/', '-') + ".png");
                    }
                }
                if (show_3D) {
                    final HashMap<String, Color> heat_table = new HashMap<String, Color>();
                    if (heat_map || show_envelope_3D) {
                        // Create a Fire LUT
                        final ImagePlus lutimp = new ImagePlus("lut", new ByteProcessor(4, 4));
                        IJ.run(lutimp, "Fire", "");
                        final IndexColorModel icm = (IndexColorModel) lutimp.getProcessor().getColorModel();
                        final byte[] reds = new byte[256];
                        final byte[] greens = new byte[256];
                        final byte[] blues = new byte[256];
                        icm.getReds(reds);
                        icm.getGreens(greens);
                        icm.getBlues(blues);
                        final List<String> names = new ArrayList<String>(bundles.keySet());
                        Collections.sort(names);
                        // find max stdDev
                        double max = 0;
                        final HashMap<String, Double> heats = new HashMap<String, Double>();
                        for (final String name : names) {
                            final VectorString3D vs_merged = condensed.get(name);
                            if (null == vs_merged) {
                                Utils.logAll("WARNING could not find a condensed pipe for " + name);
                                continue;
                            }
                            final double[] stdDev = vs_merged.getStdDevAtEachPoint();
                            // double avg = 0;
                            // for (int i=0; i<stdDev.length; i++) avg += stdDev[i];
                            // avg = avg/stdDev.length;
                            Arrays.sort(stdDev);
                            // median is more representative than average
                            final double median = stdDev[stdDev.length / 2];
                            if (max < median)
                                max = median;
                            heats.put(name, median);
                        }
                        for (final Map.Entry<String, Double> e : heats.entrySet()) {
                            final String name = e.getKey();
                            final double median = e.getValue();
                            // scale between 0 and max to get a Fire LUT color:
                            int index = (int) ((median / max) * 255);
                            if (index > 255)
                                index = 255;
                            final Color color = new Color(0xff & reds[index], 0xff & greens[index], 0xff & blues[index]);
                            Utils.log2(new StringBuilder(name).append('\t').append(median).append('\t').append(reds[index]).append('\t').append(greens[index]).append('\t').append(blues[index]).toString());
                            heat_table.put(name, color);
                        }
                    }
                    final LayerSet common_ls = new LayerSet(p[0], -1, "Common", 10, 10, 0, 0, 0, 512, 512, false, 2, new AffineTransform());
                    final Display3D d3d = Display3D.get(common_ls);
                    float env_alpha = envelope_alpha;
                    if (env_alpha < 0) {
                        Utils.log2("WARNING envelope_alpha is invalid: " + envelope_alpha + "\n    Using 0.4f instead");
                        env_alpha = 0.4f;
                    } else if (env_alpha > 1)
                        env_alpha = 1.0f;
                    for (final String name : bundles.keySet()) {
                        final ArrayList<Chain> bc = bundles.get(name);
                        final VectorString3D vs_merged = condensed.get(name);
                        if (null == vs_merged) {
                            Utils.logAll("WARNING: could not find a condensed vs for " + name);
                            continue;
                        }
                        if (show_sources_3D) {
                            if (null != sources_color_table) {
                                final HashSet<String> titles = new HashSet<String>();
                                for (final Chain chain : bc) {
                                    final Color c = sources_color_table.get(chain.getRoot().getProject());
                                    final String title = chain.getCellTitle();
                                    String t = title;
                                    int i = 2;
                                    while (titles.contains(t)) {
                                        t = title + "-" + i;
                                        i += 1;
                                    }
                                    titles.add(t);
                                    Display3D.addMesh(common_ls, chain.vs, t, null != c ? c : Color.gray);
                                }
                            } else {
                                for (final Chain chain : bc) Display3D.addMesh(common_ls, chain.vs, chain.getCellTitle(), Color.gray);
                            }
                        }
                        if (show_condensed_3D) {
                            Display3D.addMesh(common_ls, vs_merged, name + "-condensed", heat_map ? heat_table.get(name) : Color.red);
                        }
                        if (show_envelope_3D) {
                            double[] widths = makeEnvelope(cp, vs_merged);
                            if (cp.delta_envelope > 1) {
                                vs_merged.addDependent(widths);
                                vs_merged.resample(cp.delta_envelope);
                                widths = vs_merged.getDependent(0);
                            }
                            Display3D.addMesh(common_ls, vs_merged, name + "-envelope", heat_map ? heat_table.get(name) : Color.red, widths, env_alpha);
                        } else if (heat_map) {
                            // Show spheres in place of envelopes, at the starting tip (neuropile entry point)
                            final double x = vs_merged.getPoints(0)[0];
                            final double y = vs_merged.getPoints(1)[0];
                            final double z = vs_merged.getPoints(2)[0];
                            final double r = 10;
                            final Color color = heat_table.get(name);
                            if (null == color) {
                                Utils.logAll("WARNING: heat table does not have a color for " + name);
                                continue;
                            }
                            final Content sphere = d3d.getUniverse().addMesh(ij3d.Mesh_Maker.createSphere(x, y, z, r), new Color3f(heat_table.get(name)), name + "-sphere", 1);
                        }
                    }
                    if (show_axes_3D) {
                        for (int i = 0; i < p.length; i++) {
                            final Map<String, VectorString3D> m = axes.get(p[i]);
                            if (null == m) {
                                Utils.log2("No axes found for project " + p[i]);
                                continue;
                            }
                            for (final Map.Entry<String, VectorString3D> e : m.entrySet()) {
                                Display3D.addMesh(common_ls, e.getValue(), e.getKey() + "-" + i, Color.gray);
                            }
                        }
                    }
                    results.put("d3d", Display3D.get(common_ls));
                }
                this.result = results;
                Utils.log2("Done.");
            } catch (final Exception e) {
                IJError.print(e);
            } finally {
                finishedWorking();
            }
        }
    };
    return Bureaucrat.createAndStart(worker, p[0]);
}
Also used : CATAParameters(ini.trakem2.analysis.Compare.CATAParameters) ByteProcessor(ij.process.ByteProcessor) HashMap(java.util.HashMap) Color3f(org.scijava.vecmath.Color3f) ArrayList(java.util.ArrayList) FileSaver(ij.io.FileSaver) Worker(ini.trakem2.utils.Worker) IndexColorModel(java.awt.image.IndexColorModel) HashSet(java.util.HashSet) LayerSet(ini.trakem2.display.LayerSet) Display3D(ini.trakem2.display.Display3D) Plot(ij.gui.Plot) Color(java.awt.Color) ImagePlus(ij.ImagePlus) Project(ini.trakem2.Project) VectorString3D(ini.trakem2.vector.VectorString3D) Content(ij3d.Content) AffineTransform(java.awt.geom.AffineTransform) Map(java.util.Map) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap) DirectoryChooser(ij.io.DirectoryChooser)

Example 19 with Display

use of ini.trakem2.display.Display in project TrakEM2 by trakem2.

the class Project method newFSProject.

public static Project newFSProject(String arg, TemplateThing template_root, String storage_folder, boolean autocreate_one_layer) {
    if (Utils.wrongImageJVersion())
        return null;
    FSLoader loader = null;
    try {
        String dir_project = storage_folder;
        if (null == dir_project || !new File(dir_project).isDirectory()) {
            DirectoryChooser dc = new DirectoryChooser("Select storage folder");
            dir_project = dc.getDirectory();
            // user cancelled dialog
            if (null == dir_project)
                return null;
            if (!Loader.canReadAndWriteTo(dir_project)) {
                Utils.showMessage("Can't read/write to the selected storage folder.\nPlease check folder permissions.");
                return null;
            }
            if (IJ.isWindows())
                dir_project = dir_project.replace('\\', '/');
        }
        loader = new FSLoader(dir_project);
        Project project = createNewProject(loader, !("blank".equals(arg) || "amira".equals(arg)), template_root);
        // help the helpless users:
        if (autocreate_one_layer && null != project && ControlWindow.isGUIEnabled()) {
            Utils.log2("Creating automatic Display.");
            // add a default layer
            Layer layer = new Layer(project, 0, 1, project.layer_set);
            project.layer_set.add(layer);
            project.layer_tree.addLayer(project.layer_set, layer);
            layer.recreateBuckets();
            Display.createDisplay(project, layer);
        }
        try {
            // waiting cheaply for asynchronous swing calls
            Thread.sleep(200);
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }
        if ("amira".equals(arg) || "stack".equals(arg)) {
            // forks into a task thread
            loader.importStack(project.layer_set.getLayer(0), null, true);
        }
        project.restartAutosaving();
        return project;
    } catch (Exception e) {
        IJError.print(e);
        if (null != loader)
            loader.destroy();
    }
    return null;
}
Also used : FSLoader(ini.trakem2.persistence.FSLoader) JarFile(java.util.jar.JarFile) File(java.io.File) Layer(ini.trakem2.display.Layer) DirectoryChooser(ij.io.DirectoryChooser)

Example 20 with Display

use of ini.trakem2.display.Display in project TrakEM2 by trakem2.

the class DisplayCanvas method keyPressed.

@Override
public void keyPressed(final KeyEvent ke) {
    final Displayable active = display.getActive();
    if (null != freehandProfile && ProjectToolbar.getToolId() == ProjectToolbar.PENCIL && ke.getKeyCode() == KeyEvent.VK_ESCAPE && null != freehandProfile) {
        freehandProfile.abort();
        ke.consume();
        return;
    }
    final int keyCode = ke.getKeyCode();
    try {
        // Enable tagging system for any alphanumeric key:
        if (!input_disabled && null != active && active instanceof Tree<?> && ProjectToolbar.isDataEditTool(ProjectToolbar.getToolId())) {
            if (tagging) {
                if (KeyEvent.VK_0 == keyCode && KeyEvent.VK_0 != last_keyCode) {
                // do nothing: keep tagging as true
                } else {
                    // last step of tagging: a char after t or after t and a number (and the char itself can be a number)
                    tagging = false;
                }
                active.keyPressed(ke);
                return;
            } else if (KeyEvent.VK_T == keyCode) {
                tagging = true;
                active.keyPressed(ke);
                return;
            }
        }
    } finally {
        last_keyCode = keyCode;
    }
    tagging = false;
    if (ke.isConsumed())
        return;
    if (!zoom_and_pan) {
        if (KeyEvent.VK_ESCAPE == keyCode) {
            cancelAnimations();
        }
        return;
    }
    final int keyChar = ke.getKeyChar();
    boolean used = false;
    switch(keyChar) {
        case '+':
        case '=':
            zoomIn();
            used = true;
            break;
        case '-':
        case '_':
            zoomOut();
            used = true;
            break;
        default:
            break;
    }
    if (used) {
        // otherwise ImageJ would use it!
        ke.consume();
        return;
    }
    if (input_disabled) {
        if (KeyEvent.VK_ESCAPE == keyCode) {
            // cancel last job if any
            if (Utils.checkYN("Really cancel job?")) {
                display.getProject().getLoader().quitJob(null);
                display.repairGUI();
            }
        }
        ke.consume();
        // only zoom is enabled, above
        return;
    }
    if (KeyEvent.VK_S == keyCode && 0 == ke.getModifiers() && display.getProject().getLoader().isAsynchronous()) {
        display.getProject().getLoader().saveTask(display.getProject(), "Save");
        ke.consume();
        return;
    } else if (KeyEvent.VK_F == keyCode && Utils.isControlDown(ke)) {
        Search.showWindow();
        ke.consume();
        return;
    }
    // if display is not read-only, check for other keys:
    switch(keyChar) {
        case '<':
        case // select next Layer up
        ',':
            // repaints as well
            display.previousLayer(ke.getModifiers());
            ke.consume();
            return;
        case '>':
        case // select next Layer down
        '.':
            display.nextLayer(ke.getModifiers());
            ke.consume();
            return;
    }
    if (null == active && null != imp.getRoi() && KeyEvent.VK_A != keyCode) {
        // control+a and a roi should select under roi
        IJ.getInstance().keyPressed(ke);
        return;
    }
    // end here if display is read-only
    if (display.isReadOnly()) {
        ke.consume();
        display.repaintAll();
        return;
    }
    if (KeyEvent.VK_ENTER == keyCode) {
        if (isTransforming()) {
            applyTransform();
            ke.consume();
            return;
        } else {
            IJ.getInstance().toFront();
            ke.consume();
            return;
        }
    }
    // check preconditions (or the keys are meaningless). Allow 'enter' to
    // bring forward the ImageJ window, and 'v' to paste a patch.
    /*if (null == active && KeyEvent.VK_ENTER != keyCode && KeyEvent.VK_V != keyCode && KeyEvent) {
			return;
		}*/
    final Layer layer = display.getLayer();
    final int mod = ke.getModifiers();
    switch(keyCode) {
        case KeyEvent.VK_COMMA:
        case // select next Layer up
        0xbc:
            display.nextLayer(ke.getModifiers());
            break;
        case KeyEvent.VK_PERIOD:
        case // select next Layer down
        0xbe:
            display.previousLayer(ke.getModifiers());
            break;
        case KeyEvent.VK_Z:
            // UNDO: shift+z or ctrl+z
            if (0 == (mod ^ Event.SHIFT_MASK) || 0 == (mod ^ Utils.getControlModifier())) {
                Bureaucrat.createAndStart(new Worker.Task("Undo") {

                    @Override
                    public void exec() {
                        if (isTransforming())
                            display.getMode().undoOneStep();
                        else
                            display.getLayerSet().undoOneStep();
                        Display.repaint(display.getLayerSet());
                    }
                }, display.getProject());
                ke.consume();
            // REDO: alt+z or ctrl+shift+z
            } else if (0 == (mod ^ Event.ALT_MASK) || 0 == (mod ^ (Event.SHIFT_MASK | Utils.getControlModifier()))) {
                Bureaucrat.createAndStart(new Worker.Task("Redo") {

                    @Override
                    public void exec() {
                        if (isTransforming())
                            display.getMode().redoOneStep();
                        else
                            display.getLayerSet().redoOneStep();
                        Display.repaint(display.getLayerSet());
                    }
                }, display.getProject());
                ke.consume();
            }
            // else, the 'z' command restores the image using ImageJ internal undo
            break;
        case KeyEvent.VK_T:
            // Enable with any tool to the left of the PENCIL
            if (null != active && !isTransforming() && ProjectToolbar.getToolId() < ProjectToolbar.PENCIL) {
                ProjectToolbar.setTool(ProjectToolbar.SELECT);
                if (0 == ke.getModifiers()) {
                    display.setMode(new AffineTransformMode(display));
                } else if (Event.SHIFT_MASK == ke.getModifiers()) {
                    for (final Displayable d : display.getSelection().getSelected()) {
                        if (d.isLinked()) {
                            Utils.showMessage("Can't enter manual non-linear transformation mode:\nat least one image is linked.");
                            return;
                        }
                    }
                    display.setMode(new NonLinearTransformMode(display));
                }
                ke.consume();
            }
            // else, let ImageJ grab the ROI into the Manager, if any
            break;
        case KeyEvent.VK_A:
            if (0 == (ke.getModifiers() ^ Utils.getControlModifier())) {
                final Roi roi = getFakeImagePlus().getRoi();
                if (null != roi)
                    display.getSelection().selectAll(roi, true);
                else
                    display.getSelection().selectAllVisible();
                Display.repaint(display.getLayer(), display.getSelection().getBox(), 0);
                ke.consume();
                // INSIDE the 'if' block, so that it can bleed to the default block which forwards to active!
                break;
            } else if (null != active) {
                active.keyPressed(ke);
                if (ke.isConsumed())
                    break;
            // TODO this is just a hack really. Should just fall back to default switch option.
            // The whole keyPressed method needs revision: should not break from it when not using the key.
            }
            break;
        case // cancel transformation
        KeyEvent.VK_ESCAPE:
            if (isTransforming())
                cancelTransform();
            else {
                // deselect
                display.select(null);
                // repaint out the brush if present
                if (ProjectToolbar.BRUSH == ProjectToolbar.getToolId()) {
                    repaint(old_brush_box, 0);
                }
            }
            ke.consume();
            break;
        case KeyEvent.VK_SPACE:
            if (0 == ke.getModifiers()) {
                if (null != active) {
                    invalidateVolatile();
                    if (Math.abs(active.getAlpha() - 0.5f) > 0.001f)
                        active.setAlpha(0.5f);
                    else
                        active.setAlpha(1.0f);
                    display.setTransparencySlider(active.getAlpha());
                    Display.repaint();
                    ke.consume();
                }
            } else {
                // ;)
                final int kem = ke.getModifiers();
                if (0 != (kem & KeyEvent.SHIFT_MASK) && 0 != (kem & KeyEvent.ALT_MASK) && 0 != (kem & KeyEvent.CTRL_MASK)) {
                    Utils.showMessage("A mathematician, like a painter or poet,\nis a maker of patterns.\nIf his patterns are more permanent than theirs,\nit is because they are made with ideas\n \nG. H. Hardy.");
                    ke.consume();
                }
            }
            break;
        case KeyEvent.VK_S:
            if (ke.isAltDown()) {
                snapping = true;
                ke.consume();
            } else if (dragging) {
                // ignore improper 's' that open ImageJ's save dialog (linux problem ... in macosx, a single dialog opens with lots of 'ssss...' in the text field)
                ke.consume();
            }
            break;
        case KeyEvent.VK_H:
            handleHide(ke);
            ke.consume();
            break;
        case KeyEvent.VK_J:
            if (!display.getSelection().isEmpty()) {
                display.adjustMinAndMaxGUI();
                ke.consume();
            }
            break;
        case KeyEvent.VK_F1:
        case KeyEvent.VK_F2:
        case KeyEvent.VK_F3:
        case KeyEvent.VK_F4:
        case KeyEvent.VK_F5:
        case KeyEvent.VK_F6:
        case KeyEvent.VK_F7:
        case KeyEvent.VK_F8:
        case KeyEvent.VK_F9:
        case KeyEvent.VK_F10:
        case KeyEvent.VK_F11:
        case KeyEvent.VK_F12:
            ProjectToolbar.keyPressed(ke);
            ke.consume();
            break;
        case KeyEvent.VK_M:
            if (0 == ke.getModifiers() && ProjectToolbar.getToolId() == ProjectToolbar.SELECT) {
                display.getSelection().measure();
                ke.consume();
            }
            break;
    }
    switch(keyChar) {
        case ':':
        case ';':
            if (null != active && active instanceof ZDisplayable) {
                if (null != display.getProject().getProjectTree().tryAddNewConnector(active, true)) {
                    ProjectToolbar.setTool(ProjectToolbar.PEN);
                }
                ke.consume();
            }
            break;
    }
    if (ke.isConsumed())
        return;
    if (null != active) {
        if (display.getMode().getClass() == DefaultMode.class) {
            active.keyPressed(ke);
        }
        if (ke.isConsumed())
            return;
    }
    // Else:
    switch(keyCode) {
        case KeyEvent.VK_G:
            if (browseToNodeLayer(ke.isShiftDown())) {
                ke.consume();
            }
            break;
        case KeyEvent.VK_I:
            if (ke.isAltDown()) {
                if (ke.isShiftDown())
                    display.importImage();
                else
                    display.importNextImage();
                ke.consume();
            }
            break;
        case // as in Inkscape
        KeyEvent.VK_PAGE_UP:
            if (null != active) {
                update_graphics = true;
                layer.getParent().addUndoMoveStep(active);
                layer.getParent().move(LayerSet.UP, active);
                layer.getParent().addUndoMoveStep(active);
                Display.repaint(layer, active, 5);
                Display.updatePanelIndex(layer, active);
                ke.consume();
            }
            break;
        case // as in Inkscape
        KeyEvent.VK_PAGE_DOWN:
            if (null != active) {
                update_graphics = true;
                layer.getParent().addUndoMoveStep(active);
                layer.getParent().move(LayerSet.DOWN, active);
                layer.getParent().addUndoMoveStep(active);
                Display.repaint(layer, active, 5);
                Display.updatePanelIndex(layer, active);
                ke.consume();
            }
            break;
        case // as in Inkscape
        KeyEvent.VK_HOME:
            if (null != active) {
                update_graphics = true;
                layer.getParent().addUndoMoveStep(active);
                layer.getParent().move(LayerSet.TOP, active);
                layer.getParent().addUndoMoveStep(active);
                Display.repaint(layer, active, 5);
                Display.updatePanelIndex(layer, active);
                ke.consume();
            }
            break;
        case // as in Inkscape
        KeyEvent.VK_END:
            if (null != active) {
                update_graphics = true;
                layer.getParent().addUndoMoveStep(active);
                layer.getParent().move(LayerSet.BOTTOM, active);
                layer.getParent().addUndoMoveStep(active);
                Display.repaint(layer, active, 5);
                Display.updatePanelIndex(layer, active);
                ke.consume();
            }
            break;
        case KeyEvent.VK_V:
            if (0 == ke.getModifiers()) {
                if (null == active || active.getClass() == Patch.class) {
                    // paste a new image
                    final ImagePlus clipboard = ImagePlus.getClipboard();
                    if (null != clipboard) {
                        final ImagePlus imp = new ImagePlus(clipboard.getTitle() + "_" + System.currentTimeMillis(), clipboard.getProcessor().crop());
                        final Object info = clipboard.getProperty("Info");
                        if (null != info)
                            imp.setProperty("Info", (String) info);
                        final double x = srcRect.x + srcRect.width / 2 - imp.getWidth() / 2;
                        final double y = srcRect.y + srcRect.height / 2 - imp.getHeight() / 2;
                        // save the image somewhere:
                        final Patch pa = display.getProject().getLoader().addNewImage(imp, x, y);
                        display.getLayer().add(pa);
                        ke.consume();
                    }
                // TODO there isn't much ImageJ integration in the pasting. Can't paste to a selected image, for example.
                } else {
                    // Each type may know how to paste data from the copy buffer into itself:
                    active.keyPressed(ke);
                    ke.consume();
                }
            }
            break;
        case KeyEvent.VK_P:
            if (0 == ke.getModifiers()) {
                display.getLayerSet().color_cues = !display.getLayerSet().color_cues;
                Display.repaint(display.getLayerSet());
                ke.consume();
            }
            break;
        case KeyEvent.VK_F:
            if (0 == (ke.getModifiers() ^ KeyEvent.SHIFT_MASK)) {
                // toggle visibility of tags
                display.getLayerSet().paint_tags = !display.getLayerSet().paint_tags;
                Display.repaint();
                ke.consume();
            } else if (0 == (ke.getModifiers() ^ KeyEvent.ALT_MASK)) {
                // toggle visibility of edge arrows
                display.getLayerSet().paint_arrows = !display.getLayerSet().paint_arrows;
                Display.repaint();
                ke.consume();
            } else if (0 == ke.getModifiers()) {
                // toggle visibility of edge confidence boxes
                display.getLayerSet().paint_edge_confidence_boxes = !display.getLayerSet().paint_edge_confidence_boxes;
                Display.repaint();
                ke.consume();
            }
            break;
        case KeyEvent.VK_DELETE:
            if (0 == ke.getModifiers()) {
                display.getSelection().deleteAll();
            }
            break;
        case KeyEvent.VK_B:
            if (0 == ke.getModifiers() && null != active && active.getClass() == Profile.class) {
                display.duplicateLinkAndSendTo(active, 0, active.getLayer().getParent().previous(layer));
                ke.consume();
            }
            break;
        case KeyEvent.VK_N:
            if (0 == ke.getModifiers() && null != active && active.getClass() == Profile.class) {
                display.duplicateLinkAndSendTo(active, 1, active.getLayer().getParent().next(layer));
                ke.consume();
            }
            break;
        case KeyEvent.VK_1:
        case KeyEvent.VK_2:
        case KeyEvent.VK_3:
        case KeyEvent.VK_4:
        case KeyEvent.VK_5:
        case KeyEvent.VK_6:
        case KeyEvent.VK_7:
        case KeyEvent.VK_8:
        case KeyEvent.VK_9:
            // run a plugin, if any
            if (null != Utils.launchTPlugIn(ke, "Display", display.getProject(), display.getActive())) {
                ke.consume();
                break;
            }
    }
    if (!(keyCode == KeyEvent.VK_UNDEFINED || keyChar == KeyEvent.CHAR_UNDEFINED) && !ke.isConsumed() && null != active && active instanceof Patch) {
        // TODO should allow forwarding for all, not just Patch
        // forward to ImageJ for a final try
        IJ.getInstance().keyPressed(ke);
        repaint(active, 5);
        ke.consume();
    }
// Utils.log2("keyCode, keyChar: " + keyCode + ", " + keyChar + " ref: " + KeyEvent.VK_UNDEFINED + ", " + KeyEvent.CHAR_UNDEFINED);
}
Also used : Roi(ij.gui.Roi) ImagePlus(ij.ImagePlus) Point(java.awt.Point) Worker(ini.trakem2.utils.Worker)

Aggregations

ArrayList (java.util.ArrayList)11 Layer (ini.trakem2.display.Layer)10 Worker (ini.trakem2.utils.Worker)10 LayerSet (ini.trakem2.display.LayerSet)9 ZDisplayable (ini.trakem2.display.ZDisplayable)9 DBObject (ini.trakem2.persistence.DBObject)9 ImagePlus (ij.ImagePlus)8 Display (ini.trakem2.display.Display)8 Displayable (ini.trakem2.display.Displayable)8 HashSet (java.util.HashSet)8 Project (ini.trakem2.Project)7 GenericDialog (ij.gui.GenericDialog)6 Roi (ij.gui.Roi)6 ProjectThing (ini.trakem2.tree.ProjectThing)6 Rectangle (java.awt.Rectangle)6 File (java.io.File)6 DirectoryChooser (ij.io.DirectoryChooser)5 Calibration (ij.measure.Calibration)5 Future (java.util.concurrent.Future)5 JPopupMenu (javax.swing.JPopupMenu)5