Package com.cburch.logisim.tools.move

Source Code of com.cburch.logisim.tools.move.MoveGesture

/* 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.move;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.cburch.logisim.circuit.Circuit;
import com.cburch.logisim.circuit.Wire;
import com.cburch.logisim.comp.Component;
import com.cburch.logisim.comp.EndData;
import com.cburch.logisim.data.Direction;
import com.cburch.logisim.data.Location;

public class MoveGesture {
    private MoveRequestListener listener;
    private Circuit circuit;
    private HashSet<Component> selected;

    private transient Set<ConnectionData> connections;
    private transient AvoidanceMap initAvoid;
    private HashMap<MoveRequest,MoveResult> cachedResults;

    public MoveGesture(MoveRequestListener listener, Circuit circuit,
            Collection<Component> selected) {
        this.listener = listener;
        this.circuit = circuit;
        this.selected = new HashSet<Component>(selected);
        this.connections = null;
        this.initAvoid = null;
        this.cachedResults = new HashMap<MoveRequest,MoveResult>();
    }

    HashSet<Component> getSelected() {
        return selected;
    }

    AvoidanceMap getFixedAvoidanceMap() {
        AvoidanceMap ret = initAvoid;
        if (ret == null) {
            HashSet<Component> comps = new HashSet<Component>(circuit.getNonWires());
            comps.addAll(circuit.getWires());
            comps.removeAll(selected);
            ret = AvoidanceMap.create(comps, 0, 0);
            initAvoid = ret;
        }
        return ret;
    }

    Set<ConnectionData> getConnections() {
        Set<ConnectionData> ret = connections;
        if (ret == null) {
            ret = computeConnections(circuit, selected);
            connections = ret;
        }
        return ret;
    }

    public MoveResult findResult(int dx, int dy) {
        MoveRequest request = new MoveRequest(this, dx, dy);
        synchronized (cachedResults) {
            return cachedResults.get(request);
        }
    }

    public boolean enqueueRequest(int dx, int dy) {
        MoveRequest request = new MoveRequest(this, dx, dy);
        synchronized (cachedResults) {
            Object result = cachedResults.get(request);
            if (result == null) {
                ConnectorThread.enqueueRequest(request, false);
                return true;
            } else {
                return false;
            }
        }
    }

    public MoveResult forceRequest(int dx, int dy) {
        MoveRequest request = new MoveRequest(this, dx, dy);
        ConnectorThread.enqueueRequest(request, true);
        synchronized (cachedResults) {
            Object result = cachedResults.get(request);
            while (result == null) {
                try {
                    cachedResults.wait();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return null;
                }
                result = cachedResults.get(request);
            }
            return (MoveResult) result;
        }
    }

    void notifyResult(MoveRequest request, MoveResult result) {
        synchronized (cachedResults) {
            cachedResults.put(request, result);
            cachedResults.notifyAll();
        }
        if (listener != null) {
            listener.requestSatisfied(this, request.getDeltaX(), request.getDeltaY());
        }
    }

    private static Set<ConnectionData> computeConnections(Circuit circuit,
            Set<Component> selected) {
        if (selected == null || selected.isEmpty()) {
            return Collections.emptySet();
        }


        // first identify locations that might be connected
        Set<Location> locs = new HashSet<Location>();
        for (Component comp : selected) {
            for (EndData end : comp.getEnds()) {
                locs.add(end.getLocation());
            }
        }

        // now see which of them require connection
        Set<ConnectionData> conns = new HashSet<ConnectionData>();
        for (Location loc : locs) {
            boolean found = false;
            for (Component comp : circuit.getComponents(loc)) {
                if (!selected.contains(comp)) {
                    found = true;
                    break;
                }
            }
            if (found) {
                List<Wire> wirePath;
                Location wirePathStart;
                Wire lastOnPath = findWire(circuit, loc, selected, null);
                if (lastOnPath == null) {
                    wirePath = Collections.emptyList();
                    wirePathStart = loc;
                } else {
                    wirePath = new ArrayList<Wire>();
                    Location cur = loc;
                    for (Wire w = lastOnPath; w != null;
                            w = findWire(circuit, cur, selected, w)) {
                        wirePath.add(w);
                        cur = w.getOtherEnd(cur);
                    }
                    Collections.reverse(wirePath);
                    wirePathStart = cur;
                }

                Direction dir = null;
                if (lastOnPath != null) {
                    Location other = lastOnPath.getOtherEnd(loc);
                    int dx = loc.getX() - other.getX();
                    int dy = loc.getY() - other.getY();
                    if (Math.abs(dx) > Math.abs(dy)) {
                        dir = dx > 0 ? Direction.EAST : Direction.WEST;
                    } else {
                        dir = dy > 0 ? Direction.SOUTH : Direction.NORTH;
                    }
                }
                conns.add(new ConnectionData(loc, dir, wirePath, wirePathStart));
            }
        }
        return conns;
    }

    private static Wire findWire(Circuit circ, Location loc,
            Set<Component> ignore, Wire ignoreW) {
        Wire ret = null;
        for (Component comp : circ.getComponents(loc)) {
            if (!ignore.contains(comp) && comp != ignoreW) {
                if (ret == null && comp instanceof Wire) {
                    ret = (Wire) comp;
                } else {
                    return null;
                }
            }
        }
        return ret;
    }

}
TOP

Related Classes of com.cburch.logisim.tools.move.MoveGesture

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.