Search in sources :

Example 11 with ZDisplayable

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

the class Merger method compare.

/**
 * Take two projects and find out what is different among them,
 *  independent of id.
 */
public static final void compare(final Project p1, final Project p2) {
    Utils.log("Be warned: only Treeline, AreaTree and Connector are considered at the moment.");
    final LayerSet ls1 = p1.getRootLayerSet(), ls2 = p2.getRootLayerSet();
    final Collection<ZDisplayable> zds1 = ls1.getZDisplayables(), zds2 = ls2.getZDisplayables();
    final HashSet<Class<?>> accepted = new HashSet<Class<?>>();
    accepted.add(Treeline.class);
    accepted.add(AreaTree.class);
    accepted.add(Connector.class);
    final HashMap<Displayable, List<Change>> matched = new HashMap<Displayable, List<Change>>();
    final HashSet<ZDisplayable> empty1 = new HashSet<ZDisplayable>(), empty2 = new HashSet<ZDisplayable>();
    final HashSet<ZDisplayable> unmatched1 = new HashSet<ZDisplayable>(), unmatched2 = new HashSet<ZDisplayable>(zds2);
    // Remove instances of classes not accepted
    for (final Iterator<ZDisplayable> it = unmatched2.iterator(); it.hasNext(); ) {
        ZDisplayable zd = it.next();
        if (!accepted.contains(zd.getClass())) {
            it.remove();
            continue;
        }
        if (zd.isDeletable()) {
            it.remove();
            empty2.add(zd);
        }
    }
    zds2.removeAll(empty2);
    final AtomicInteger counter = new AtomicInteger(0);
    // or at least one or more that are similar in that they have some nodes in common.
    try {
        ini.trakem2.parallel.Process.unbound(zds1, new TaskFactory<ZDisplayable, Object>() {

            @Override
            public Object process(final ZDisplayable zd1) {
                Utils.showProgress(counter.getAndIncrement() / (float) zds1.size());
                if (!accepted.contains(zd1.getClass())) {
                    Utils.log("Ignoring: [A] " + zd1);
                    return null;
                }
                if (zd1.isDeletable()) {
                    synchronized (empty1) {
                        empty1.add(zd1);
                    }
                    return null;
                }
                final List<Change> cs = new ArrayList<Change>();
                for (final ZDisplayable zd2 : zds2) {
                    // Same class?
                    if (zd1.getClass() != zd2.getClass())
                        continue;
                    if (zd1 instanceof Tree<?> && zd2 instanceof Tree<?>) {
                        Change c = compareTrees(zd1, zd2);
                        if (c.hasSimilarNodes()) {
                            cs.add(c);
                            if (1 == cs.size()) {
                                synchronized (matched) {
                                    matched.put(zd1, cs);
                                }
                            }
                            synchronized (unmatched2) {
                                unmatched2.remove(zd2);
                            }
                        }
                        // debug
                        if (zd1.getId() == zd2.getId()) {
                            Utils.log("zd1 #" + zd1.getId() + " is similar to #" + zd2.getId() + ": " + c.hasSimilarNodes());
                        }
                    }
                }
                if (cs.isEmpty()) {
                    synchronized (unmatched1) {
                        unmatched1.add(zd1);
                    }
                }
                return null;
            }
        });
    } catch (Exception e) {
        IJError.print(e);
    }
    // reset
    Utils.showProgress(1);
    Utils.log("matched.size(): " + matched.size());
    makeGUI(p1, p2, empty1, empty2, matched, unmatched1, unmatched2);
}
Also used : ZDisplayable(ini.trakem2.display.ZDisplayable) Displayable(ini.trakem2.display.Displayable) LayerSet(ini.trakem2.display.LayerSet) HashMap(java.util.HashMap) ZDisplayable(ini.trakem2.display.ZDisplayable) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Tree(ini.trakem2.display.Tree) AreaTree(ini.trakem2.display.AreaTree) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet)

Example 12 with ZDisplayable

use of ini.trakem2.display.ZDisplayable 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 13 with ZDisplayable

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

the class Compare method findFirstXYZAxes.

/**
 * Finds the first three X,Y,Z axes as specified by the names in preset.
 */
private static int[] findFirstXYZAxes(final String[] preset, final ArrayList<ZDisplayable> pipes, final String[] pipe_names) {
    final int[] s = new int[] { -1, -1, -1 };
    int next = 0;
    for (final ZDisplayable zd : pipes) {
        pipe_names[next] = zd.getProject().getShortMeaningfulTitle(zd);
        if (-1 != s[0] && -1 != s[1] && -1 != s[2]) {
            // Already all found, just filling names
            next++;
            continue;
        }
        final String name = pipe_names[next].toLowerCase();
        if (-1 != name.indexOf(preset[0]))
            s[0] = next;
        else if (-1 != name.indexOf(preset[1]))
            s[1] = next;
        else if (-1 != name.indexOf(preset[2]))
            s[2] = next;
        next++;
    }
    return s;
}
Also used : ZDisplayable(ini.trakem2.display.ZDisplayable)

Example 14 with ZDisplayable

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

the class Compare method gatherChains.

/**
 * Gather chains for all projects considering the cp.regex, and transforms all relative to the reference Project p[0].
 *  Will ignore any for which a match exists in @param ignore.
 */
public static final Object[] gatherChains(final Project[] p, final CATAParameters cp, final String[] ignore) throws Exception {
    String regex_exclude = null;
    if (null != ignore) {
        final StringBuilder sb = new StringBuilder();
        for (final String ig : ignore) {
            sb.append("(.*").append(ig).append(".*)|");
        }
        sb.setLength(sb.length() - 1);
        regex_exclude = sb.toString();
    }
    Utils.logAll("Compare/gatherChains: using ignore string: " + regex_exclude);
    Utils.logAll("Compare/gatherChains: using regex: " + cp.regex);
    // gather all chains
    // to keep track of each project's chains
    final ArrayList[] p_chains = new ArrayList[p.length];
    final ArrayList<Chain> chains = new ArrayList<Chain>();
    for (int i = 0; i < p.length; i++) {
        // for each project:
        if (null == cp.regex) {
            p_chains[i] = createPipeChains(p[i].getRootProjectThing(), p[i].getRootLayerSet(), regex_exclude);
        } else {
            // Search (shallow) for cp.regex matches
            for (final ProjectThing pt : p[i].getRootProjectThing().findChildren(cp.regex, regex_exclude, true)) {
                final ArrayList<Chain> ac = createPipeChains(pt, p[i].getRootLayerSet(), regex_exclude);
                if (null == p_chains[i])
                    p_chains[i] = ac;
                else
                    p_chains[i].addAll(ac);
            }
            // empty
            if (null == p_chains[i])
                p_chains[i] = new ArrayList<Chain>();
        }
        chains.addAll(p_chains[i]);
        // calibrate
        final Calibration cal = p[i].getRootLayerSet().getCalibrationCopy();
        for (final Chain chain : (ArrayList<Chain>) p_chains[i]) chain.vs.calibrate(cal);
    }
    final int n_chains = chains.size();
    // register all, or relative
    if (4 == cp.transform_type) {
        // compute global average delta
        if (0 == cp.delta) {
            for (final Chain chain : chains) {
                cp.delta += (chain.vs.getAverageDelta() / n_chains);
            }
        }
        Utils.log2("Using delta: " + cp.delta);
        for (final Chain chain : chains) {
            // BEFORE making it relative
            chain.vs.resample(cp.delta, cp.with_source);
            chain.vs.relative();
        }
    } else {
        if (3 == cp.transform_type) {
            // '3' means moving least squares computed from 3D landmarks
            Utils.log2("Moving Least Squares Registration based on common fiducial points");
            // Find fiducial points, if any
            final HashMap<Project, Map<String, Tuple3d>> fiducials = new HashMap<Project, Map<String, Tuple3d>>();
            for (final Project pr : p) {
                final Set<ProjectThing> fids = pr.getRootProjectThing().findChildrenOfTypeR("fiducial_points");
                if (null == fids || 0 == fids.size()) {
                    Utils.log("No fiducial points found in project: " + pr);
                } else {
                    // the first fiducial group
                    fiducials.put(pr, Compare.extractPoints(fids.iterator().next()));
                }
            }
            if (!fiducials.isEmpty()) {
                // Register all VectorString3D relative to the first project:
                final List<VectorString3D> lvs = new ArrayList<VectorString3D>();
                final Calibration cal2 = p[0].getRootLayerSet().getCalibrationCopy();
                for (final Chain chain : chains) {
                    final Project pr = chain.pipes.get(0).getProject();
                    // first project is reference, no need to transform.
                    if (pr == p[0])
                        continue;
                    lvs.clear();
                    lvs.add(chain.vs);
                    chain.vs = transferVectorStrings(lvs, fiducials.get(pr), fiducials.get(p[0])).get(0);
                    // Set (but do not apply!) the calibration of the reference project
                    chain.vs.setCalibration(cal2);
                }
            }
        } else if (cp.transform_type < 3) {
            // '0', '1' and '2' involve a 3D affine computed from the 3 axes
            // no need //VectorString3D[][] vs_axes = new VectorString3D[p.length][];
            Vector3d[][] o = new Vector3d[p.length][];
            for (int i = 0; i < p.length; i++) {
                // 1 - find pipes to work as axes for each project
                final ArrayList<ZDisplayable> pipes = p[i].getRootLayerSet().getZDisplayables(Line3D.class, true);
                final String[] pipe_names = new String[pipes.size()];
                for (int k = 0; k < pipes.size(); k++) {
                    pipe_names[k] = p[i].getMeaningfulTitle(pipes.get(k));
                }
                final int[] s = findFirstXYZAxes(cp.preset, pipes, pipe_names);
                // if axes are -1, forget it: not found
                if (-1 == s[0] || -1 == s[1] || -1 == s[2]) {
                    Utils.log("Can't find axes for project " + p[i]);
                    o = null;
                    return null;
                }
                // obtain axes and origin
                final Object[] pack = obtainOrigin(new Line3D[] { (Line3D) pipes.get(s[0]), (Line3D) pipes.get(s[1]), (Line3D) pipes.get(s[2]) }, cp.transform_type, // will be null for the first, which will then be non-null and act as the reference for the others.
                o[0]);
                // no need //vs_axes[i] = (VectorString3D[])pack[0];
                o[i] = (Vector3d[]) pack[1];
            }
            /* // OLD WAY
				// match the scales to make the largest be 1.0
				final double scaling_factor = VectorString3D.matchOrigins(o, transform_type);
				Utils.log2("matchOrigins scaling factor: " + scaling_factor + " for transform_type " + transform_type);
				*/
            // transform all except the first (which acts as reference)
            final Transform3D M_ref = Compare.createTransform(o[0]);
            for (int i = 1; i < p.length; i++) {
                final Vector3d trans = new Vector3d(-o[i][3].x, -o[i][3].y, -o[i][3].z);
                final Transform3D M_query = Compare.createTransform(o[i]);
                // The transfer T transform: from query space to reference space.
                final Transform3D T = new Transform3D(M_ref);
                T.mulInverse(M_query);
                for (final Chain chain : (ArrayList<Chain>) p_chains[i]) {
                    // in place
                    chain.vs.transform(T);
                }
            }
        }
        // compute global average delta, after correcting calibration and transformation
        if (0 == cp.delta) {
            for (final Chain chain : chains) {
                cp.delta += (chain.vs.getAverageDelta() / n_chains);
            }
        }
        Utils.log2("Using delta: " + cp.delta);
        // After calibration and transformation, resample all to the same delta
        for (final Chain chain : chains) chain.vs.resample(cp.delta, cp.with_source);
    }
    return new Object[] { chains, p_chains };
}
Also used : HashMap(java.util.HashMap) Transform3D(org.scijava.java3d.Transform3D) ArrayList(java.util.ArrayList) Calibration(ij.measure.Calibration) Line3D(ini.trakem2.display.Line3D) Project(ini.trakem2.Project) VectorString3D(ini.trakem2.vector.VectorString3D) Vector3d(org.scijava.vecmath.Vector3d) Tuple3d(org.scijava.vecmath.Tuple3d) Map(java.util.Map) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap) ProjectThing(ini.trakem2.tree.ProjectThing)

Example 15 with ZDisplayable

use of ini.trakem2.display.ZDisplayable 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

ZDisplayable (ini.trakem2.display.ZDisplayable)13 ArrayList (java.util.ArrayList)10 HashMap (java.util.HashMap)10 HashSet (java.util.HashSet)10 Displayable (ini.trakem2.display.Displayable)9 Layer (ini.trakem2.display.Layer)7 Worker (ini.trakem2.utils.Worker)6 Map (java.util.Map)6 GenericDialog (ij.gui.GenericDialog)5 LayerSet (ini.trakem2.display.LayerSet)5 Project (ini.trakem2.Project)4 DBObject (ini.trakem2.persistence.DBObject)4 ProjectThing (ini.trakem2.tree.ProjectThing)4 Point (java.awt.Point)4 Collection (java.util.Collection)4 List (java.util.List)4 TreeMap (java.util.TreeMap)4 ImagePlus (ij.ImagePlus)3 Roi (ij.gui.Roi)3 Display (ini.trakem2.display.Display)3