/* Copyright (c) 2006, 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.gui.main;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.HashSet;
import com.cburch.logisim.circuit.CircuitEvent;
import com.cburch.logisim.circuit.CircuitListener;
import com.cburch.logisim.circuit.ComponentAction;
import com.cburch.logisim.circuit.Wire;
import com.cburch.logisim.comp.Component;
import com.cburch.logisim.comp.ComponentDrawContext;
import com.cburch.logisim.data.AttributeSet;
import com.cburch.logisim.data.Bounds;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.proj.Project;
import com.cburch.logisim.proj.ProjectEvent;
import com.cburch.logisim.proj.ProjectListener;
import com.cburch.logisim.tools.CustomHandles;
public class Selection extends SelectionBase {
public static class Event {
Object source;
Event(Object source) { this.source = source; }
public Object getSource() { return source; }
}
public static interface Listener {
public void selectionChanged(Selection.Event event);
}
private class MyListener implements ProjectListener, CircuitListener {
private HashSet justRemoved = new HashSet();
public void projectChanged(ProjectEvent event) {
if(event.getAction() == ProjectEvent.ACTION_COMPLETED) {
Object actRaw = event.getData();
if(actRaw instanceof ComponentAction) {
ComponentAction act = (ComponentAction) actRaw;
HashSet ws = justRemoved;
justRemoved = new HashSet();
ws.addAll(getAnchoredComponents());
addOverlapsAdds(ws, act.getRemovals(), act.getAdditions());
addOverlapsAdds(ws, act.getIncidentalRemovals(), act.getIncidentalAdditions());
addOverlapsAdds(ws, act.getIncidentalRemovals(), act.getAdditions());
}
} else if(event.getAction() != ProjectEvent.ACTION_SELECTION) {
justRemoved.clear();
}
}
private void addOverlapsAdds(Collection ws, Collection removals,
Collection additions) {
for(Iterator it = removals.iterator(); it.hasNext(); ) {
Object wRaw = it.next();
if(wRaw instanceof Wire && ws.contains(wRaw)) {
addAllOverlaps((Wire) wRaw, additions);
}
}
}
private void addAllOverlaps(Wire w0, Collection from) {
for(Iterator it = from.iterator(); it.hasNext(); ) {
Object w1Raw = it.next();
if(w1Raw instanceof Wire) {
Wire w1 = (Wire) w1Raw;
if(w0.overlaps(w1)) {
add(w1);
}
}
}
}
public void circuitChanged(CircuitEvent event) {
if(event.getAction() == CircuitEvent.ACTION_REMOVE) {
Component comp = (Component) event.getData();
if(comp instanceof Wire && selected.contains(comp)) {
justRemoved.add(comp);
}
remove(comp);
} else if(event.getAction() == CircuitEvent.ACTION_CLEAR) {
clear(false);
}
}
}
private MyListener myListener;
private boolean isVisible = true;
public Selection(Project proj) {
super(proj);
myListener = new MyListener();
proj.addProjectListener(myListener);
proj.addCircuitListener(myListener);
}
//
// query methods
//
public boolean isEmpty() {
return selected.isEmpty() && lifted.isEmpty();
}
public boolean equals(Object other) {
if(!(other instanceof Selection)) return false;
Selection otherSelection = (Selection) other;
return this.selected.equals(otherSelection.selected)
&& this.lifted.equals(otherSelection.lifted);
}
public Collection getComponents() {
return unionSet;
}
public Collection getAnchoredComponents() {
return selected;
}
public Collection getFloatingComponents() {
return lifted;
}
public Collection getHiddenComponents() {
return isVisible ? Collections.EMPTY_SET : unionSet;
}
public Collection getComponentsContaining(Location query) {
HashSet ret = new HashSet();
for(Iterator it = unionSet.iterator(); it.hasNext(); ) {
Component comp = (Component) it.next();
if(comp.contains(query)) ret.add(comp);
}
return ret;
}
public Collection getComponentsContaining(Location query, Graphics g) {
HashSet ret = new HashSet();
for(Iterator it = unionSet.iterator(); it.hasNext(); ) {
Component comp = (Component) it.next();
if(comp.contains(query, g)) ret.add(comp);
}
return ret;
}
public Collection getComponentsWithin(Bounds bds) {
HashSet ret = new HashSet();
for(Iterator it = unionSet.iterator(); it.hasNext(); ) {
Component comp = (Component) it.next();
if(bds.contains(comp.getBounds())) ret.add(comp);
}
return ret;
}
public Collection getComponentsWithin(Bounds bds, Graphics g) {
HashSet ret = new HashSet();
for(Iterator it = unionSet.iterator(); it.hasNext(); ) {
Component comp = (Component) it.next();
if(bds.contains(comp.getBounds(g))) ret.add(comp);
}
return ret;
}
public boolean contains(Component comp) {
return unionSet.contains(comp);
}
//
// graphics methods
//
public void setVisible(boolean value) {
isVisible = value;
}
public void draw(ComponentDrawContext context) {
if(isVisible) {
Graphics g = context.getGraphics();
for(Iterator it = lifted.iterator(); it.hasNext(); ) {
Component c = (Component) it.next();
Location loc = c.getLocation();
Graphics g_new = g.create();
context.setGraphics(g_new);
c.getFactory().drawGhost(context, Color.GRAY,
loc.getX(), loc.getY(), c.getAttributeSet());
g_new.dispose();
}
for(Iterator it = unionSet.iterator(); it.hasNext(); ) {
Component comp = (Component) it.next();
if(!suppressHandles.contains(comp)) {
Graphics g_new = g.create();
context.setGraphics(g_new);
CustomHandles handler
= (CustomHandles) comp.getFeature(CustomHandles.class);
if(handler == null) {
context.drawHandles(comp);
} else {
handler.drawHandles(context);
}
g_new.dispose();
}
}
context.setGraphics(g);
}
}
public void drawGhostsShifted(ComponentDrawContext context,
int dx, int dy) {
if(shouldSnap()) {
dx = Canvas.snapXToGrid(dx);
dy = Canvas.snapYToGrid(dy);
}
Graphics g = context.getGraphics();
for(Iterator it = unionSet.iterator(); it.hasNext(); ) {
Component comp = (Component) it.next();
AttributeSet attrs = comp.getAttributeSet();
Location loc = comp.getLocation();
int x = loc.getX() + dx;
int y = loc.getY() + dy;
context.setGraphics(g.create());
comp.getFactory().drawGhost(context, Color.gray, x, y, attrs);
context.getGraphics().dispose();
}
context.setGraphics(g);
}
public void print() {
System.err.println(" isVisible: " + isVisible); //OK
super.print();
}
}
|