Package com.cburch.logisim.tools

Source Code of com.cburch.logisim.tools.EditTool$Listener

/* Copyright (c) 2010, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.logisim.tools;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;

import com.cburch.logisim.LogisimVersion;
import com.cburch.logisim.circuit.Circuit;
import com.cburch.logisim.circuit.CircuitEvent;
import com.cburch.logisim.circuit.CircuitListener;
import com.cburch.logisim.circuit.Wire;
import com.cburch.logisim.comp.Component;
import com.cburch.logisim.comp.ComponentDrawContext;
import com.cburch.logisim.comp.ComponentFactory;
import com.cburch.logisim.data.Attribute;
import com.cburch.logisim.data.AttributeSet;
import com.cburch.logisim.data.Direction;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.data.Value;
import com.cburch.logisim.gui.main.Canvas;
import com.cburch.logisim.gui.main.Selection;
import com.cburch.logisim.gui.main.SelectionActions;
import com.cburch.logisim.gui.main.Selection.Event;
import com.cburch.logisim.proj.Action;
import com.cburch.logisim.util.GraphicsUtil;
import static com.cburch.logisim.util.LocaleString.*;


public class EditTool extends Tool {
    private static final int CACHE_MAX_SIZE = 32;
    private static final Location NULL_LOCATION
        = Location.create(Integer.MIN_VALUE, Integer.MIN_VALUE);

    private class Listener implements CircuitListener, Selection.Listener {
        @Override
        public void circuitChanged(CircuitEvent event) {
            if (event.getAction() != CircuitEvent.ACTION_INVALIDATE) {
                lastX = -1;
                cache.clear();
                updateLocation(lastCanvas, lastRawX, lastRawY, lastMods);
            }
        }

        @Override
        public void selectionChanged(Event event) {
            lastX = -1;
            cache.clear();
            updateLocation(lastCanvas, lastRawX, lastRawY, lastMods);
        }
    }

    private Listener listener;
    private SelectTool select;
    private WiringTool wiring;
    private Tool current;
    private LinkedHashMap<Location,Boolean> cache;
    private Canvas lastCanvas;
    private int lastRawX;
    private int lastRawY;
    // last coordinates where wiring was computed
    private int lastX;
    private int lastY;
    // last modifiers for mouse event
    private int lastMods;
    // coordinates where to draw wiring indicator, if
    private Location wireLoc;
    // last coordinate where mouse was pressed
    private int pressX;
    // (used to determine when a short wire has been clicked)
    private int pressY;

    public EditTool(SelectTool select, WiringTool wiring) {
        this.listener = new Listener();
        this.select = select;
        this.wiring = wiring;
        this.current = select;
        this.cache = new LinkedHashMap<Location,Boolean>();
        this.lastX = -1;
        this.wireLoc = NULL_LOCATION;
        this.pressX = -1;
    }

    @Override
    public boolean equals(Object other) {
        return other instanceof EditTool;
    }

    @Override
    public int hashCode() {
        return EditTool.class.hashCode();
    }

    @Override
    public String getName() {
        return "Edit Tool";
    }

    @Override
    public String getDisplayName() {
        return getFromLocale("editTool");
    }

    @Override
    public String getDescription() {
        return getFromLocale("editToolDesc");
    }

    @Override
    public AttributeSet getAttributeSet() {
        return select.getAttributeSet();
    }

    @Override
    public void setAttributeSet(AttributeSet attrs) {
        select.setAttributeSet(attrs);
    }

    @Override
    public AttributeSet getAttributeSet(Canvas canvas) {
        return canvas.getSelection().getAttributeSet();
    }

    @Override
    public boolean isAllDefaultValues(AttributeSet attrs, LogisimVersion ver) {
        return true;
    }

    @Override
    public void paintIcon(ComponentDrawContext c, int x, int y) {
        select.paintIcon(c, x, y);
    }

    @Override
    public Set<Component> getHiddenComponents(Canvas canvas) {
        return current.getHiddenComponents(canvas);
    }

    @Override
    public void draw(Canvas canvas, ComponentDrawContext context) {
        Location loc = wireLoc;
        if (loc != NULL_LOCATION && current != wiring) {
            int x = loc.getX();
            int y = loc.getY();
            Graphics g = context.getGraphics();
            g.setColor(Value.TRUE_COLOR);
            GraphicsUtil.switchToWidth(g, 2);
            g.drawOval(x - 5, y - 5, 10, 10);
            g.setColor(Color.BLACK);
            GraphicsUtil.switchToWidth(g, 1);
        }
        current.draw(canvas, context);
    }

    @Override
    public void select(Canvas canvas) {
        current = select;
        lastCanvas = canvas;
        cache.clear();
        canvas.getCircuit().addCircuitListener(listener);
        canvas.getSelection().addListener(listener);
        select.select(canvas);
    }

    @Override
    public void deselect(Canvas canvas) {
        current = select;
        canvas.getSelection().setSuppressHandles(null);
        cache.clear();
        canvas.getCircuit().removeCircuitListener(listener);
        canvas.getSelection().removeListener(listener);
    }

    @Override
    public void mousePressed(Canvas canvas, Graphics g, MouseEvent e) {
        boolean wire = updateLocation(canvas, e);
        Location oldWireLoc = wireLoc;
        wireLoc = NULL_LOCATION;
        lastX = Integer.MIN_VALUE;
        if (wire) {
            current = wiring;
            Selection sel = canvas.getSelection();
            Circuit circ = canvas.getCircuit();
            Collection<Component> selected = sel.getAnchoredComponents();
            ArrayList<Component> suppress = null;
            for (Wire w : circ.getWires()) {
                if (selected.contains(w)) {
                    if (w.contains(oldWireLoc)) {
                        if (suppress == null) {
                            suppress = new ArrayList<Component>();
                        }

                        suppress.add(w);
                    }
                }
            }
            sel.setSuppressHandles(suppress);
        } else {
            current = select;
        }
        pressX = e.getX();
        pressY = e.getY();
        current.mousePressed(canvas, g, e);
    }

    @Override
    public void mouseDragged(Canvas canvas, Graphics g, MouseEvent e) {
        isClick(e);
        current.mouseDragged(canvas, g, e);
    }

    @Override
    public void mouseReleased(Canvas canvas, Graphics g, MouseEvent e) {
        boolean click = isClick(e) && current == wiring;
        canvas.getSelection().setSuppressHandles(null);
        current.mouseReleased(canvas, g, e);
        if (click) {
            wiring.resetClick();
            select.mousePressed(canvas, g, e);
            select.mouseReleased(canvas, g, e);
        }
        current = select;
        cache.clear();
        updateLocation(canvas, e);
    }

    @Override
    public void mouseEntered(Canvas canvas, Graphics g, MouseEvent e) {
        pressX = -1;
        current.mouseEntered(canvas, g, e);
        canvas.requestFocusInWindow();
    }

    @Override
    public void mouseExited(Canvas canvas, Graphics g, MouseEvent e) {
        pressX = -1;
        current.mouseExited(canvas, g, e);
    }

    @Override
    public void mouseMoved(Canvas canvas, Graphics g, MouseEvent e) {
        updateLocation(canvas, e);
        select.mouseMoved(canvas, g, e);
    }

    private boolean isClick(MouseEvent e) {
        int px = pressX;
        if (px < 0) {
            return false;
        } else {
            int dx = e.getX() - px;
            int dy = e.getY() - pressY;
            if (dx * dx + dy * dy <= 4) {
                return true;
            } else {
                pressX = -1;
                return false;
            }
        }
    }

    private boolean updateLocation(Canvas canvas, MouseEvent e) {
        return updateLocation(canvas, e.getX(), e.getY(), e.getModifiersEx());
    }

    private boolean updateLocation(Canvas canvas, KeyEvent e) {
        int x = lastRawX;
        if (x >= 0) {
            return updateLocation(canvas, x, lastRawY, e.getModifiersEx());
        }

        else {
            return false;
        }

    }

    private boolean updateLocation(Canvas canvas, int mx, int my, int mods) {
        int snapx = Canvas.snapXToGrid(mx);
        int snapy = Canvas.snapYToGrid(my);
        int dx = mx - snapx;
        int dy = my - snapy;
        boolean isEligible = dx * dx + dy * dy < 36;
        if ((mods & InputEvent.ALT_DOWN_MASK) != 0) {
            isEligible = true;
        }

        if (!isEligible) {
            snapx = -1;
            snapy = -1;
        }
        boolean modsSame = lastMods == mods;
        lastCanvas = canvas;
        lastRawX = mx;
        lastRawY = my;
        lastMods = mods;
        // already computed
        if (lastX == snapx && lastY == snapy && modsSame) {
            return wireLoc != NULL_LOCATION;
        } else {
            Location snap = Location.create(snapx, snapy);
            if (modsSame) {
                Object o = cache.get(snap);
                if (o != null) {
                    lastX = snapx;
                    lastY = snapy;
                    canvas.repaint();
                    boolean ret = ((Boolean) o).booleanValue();
                    wireLoc = ret ? snap : NULL_LOCATION;
                    return ret;
                }
            } else {
                cache.clear();
            }

            boolean ret = isEligible && isWiringPoint(canvas, snap, mods);
            wireLoc = ret ? snap : NULL_LOCATION;
            cache.put(snap, Boolean.valueOf(ret));
            int toRemove = cache.size() - CACHE_MAX_SIZE;
            Iterator<Location> it = cache.keySet().iterator();
            while (it.hasNext() && toRemove > 0) {
                it.next();
                it.remove();
                toRemove--;
            }

            lastX = snapx;
            lastY = snapy;
            canvas.repaint();
            return ret;
        }
    }

    private boolean isWiringPoint(Canvas canvas, Location loc, int modsEx) {
        boolean wiring = (modsEx & InputEvent.ALT_DOWN_MASK) == 0;
        boolean select = !wiring;

        if (canvas != null && canvas.getSelection() != null) {
            Collection<Component> sel = canvas.getSelection().getComponents();
            if (sel != null) {
                for (Component c : sel) {
                    if (c instanceof Wire) {
                        Wire w = (Wire) c;
                        if (w.contains(loc) && !w.endsAt(loc)) {
                            return select;
                        }

                    }
                }
            }
        }

        Circuit circ = canvas.getCircuit();
        Collection<? extends Component> at = circ.getComponents(loc);
        if (at != null && at.size() > 0) {
            return wiring;
        }


        for (Wire w : circ.getWires()) {
            if (w.contains(loc)) {
                { return wiring;
            }
}
        }
        return select;
    }

    @Override
    public void keyTyped(Canvas canvas, KeyEvent e) {
        select.keyTyped(canvas, e);
    }

    @Override
    public void keyPressed(Canvas canvas, KeyEvent e) {
        switch (e.getKeyCode()) {
        case KeyEvent.VK_BACK_SPACE:
        case KeyEvent.VK_DELETE:
            if (!canvas.getSelection().isEmpty()) {
                Action act = SelectionActions.clear(canvas.getSelection());
                canvas.getProject().doAction(act);
                e.consume();
            } else {
                wiring.keyPressed(canvas, e);
            }
            break;
        case KeyEvent.VK_INSERT:
            Action act = SelectionActions.duplicate(canvas.getSelection());
            canvas.getProject().doAction(act);
            e.consume();
            break;
        case KeyEvent.VK_UP:
            if (e.getModifiersEx() == 0) {
                attemptReface(canvas, Direction.NORTH, e);
            }

            else {
                                        select.keyPressed(canvas, e);
            }

            break;
        case KeyEvent.VK_DOWN:
            if (e.getModifiersEx() == 0) {
                attemptReface(canvas, Direction.SOUTH, e);
            }

            else {
                                        select.keyPressed(canvas, e);
            }

            break;
        case KeyEvent.VK_LEFT:
            if (e.getModifiersEx() == 0) {
                attemptReface(canvas, Direction.WEST, e);
            }

            else {
                                        select.keyPressed(canvas, e);
            }

            break;
        case KeyEvent.VK_RIGHT:
            if (e.getModifiersEx() == 0) {
                attemptReface(canvas, Direction.EAST, e);
            }

            else {
                                        select.keyPressed(canvas, e);
            }

            break;
        case KeyEvent.VK_ALT:   updateLocation(canvas, e); e.consume(); break;
        default:
            select.keyPressed(canvas, e);
        }
    }

    @Override
    public void keyReleased(Canvas canvas, KeyEvent e) {
        switch (e.getKeyCode()) {
        case KeyEvent.VK_ALT:   updateLocation(canvas, e); e.consume(); break;
        default:
            select.keyReleased(canvas, e);
        }
    }

    private void attemptReface(Canvas canvas, final Direction facing, KeyEvent e) {
        if (e.getModifiersEx() == 0) {
            final Circuit circuit = canvas.getCircuit();
            final Selection sel = canvas.getSelection();
            SetAttributeAction act = new SetAttributeAction(circuit,
                    getFromLocale("selectionRefaceAction"));
            for (Component comp : sel.getComponents()) {
                if (!(comp instanceof Wire)) {
                    Attribute<Direction> attr = getFacingAttribute(comp);
                    if (attr != null) {
                        act.set(comp, attr, facing);
                    }
                }
            }
            if (!act.isEmpty()) {
                canvas.getProject().doAction(act);
                e.consume();
            }
        }
    }

    private Attribute<Direction> getFacingAttribute(Component comp) {
        AttributeSet attrs = comp.getAttributeSet();
        Object key = ComponentFactory.FACING_ATTRIBUTE_KEY;
        Attribute<?> a = (Attribute<?>) comp.getFactory().getFeature(key, attrs);
        @SuppressWarnings("unchecked")
        Attribute<Direction> ret = (Attribute<Direction>) a;
        return ret;
    }

    @Override
    public Cursor getCursor() {
        return select.getCursor();
    }
}
TOP

Related Classes of com.cburch.logisim.tools.EditTool$Listener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.