/* 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.comp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.cburch.logisim.circuit.CircuitState;
import com.cburch.logisim.data.AttributeSet;
import com.cburch.logisim.data.BitWidth;
import com.cburch.logisim.data.Bounds;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.util.EventSourceWeakSupport;
public abstract class ManagedComponent extends AbstractComponent {
private EventSourceWeakSupport<ComponentListener> listeners
= new EventSourceWeakSupport<ComponentListener>();
private Location loc;
private AttributeSet attrs;
private ArrayList<EndData> ends;
private List<EndData> endsView;
private Bounds bounds = null;
public ManagedComponent(Location loc, AttributeSet attrs, int num_ends) {
this.loc = loc;
this.attrs = attrs;
this.ends = new ArrayList<EndData>(num_ends);
this.endsView = Collections.unmodifiableList(ends);
}
//
// abstract AbstractComponent methods
//
@Override
public abstract ComponentFactory getFactory();
@Override
public void addComponentListener(ComponentListener l) {
listeners.add(l);
}
@Override
public void removeComponentListener(ComponentListener l) {
listeners.remove(l);
}
protected void fireEndChanged(ComponentEvent e) {
ComponentEvent copy = null;
for (ComponentListener l : listeners) {
if (copy == null) {
copy = new ComponentEvent(e.getSource(),
Collections.singletonList(e.getOldData()),
Collections.singletonList(e.getData()));
}
l.endChanged(copy);
}
}
protected void fireEndsChanged(List<EndData> oldEnds, List<EndData> newEnds) {
ComponentEvent e = null;
for (ComponentListener l : listeners) {
if (e == null) {
e = new ComponentEvent(this, oldEnds, newEnds);
}
l.endChanged(e);
}
}
protected void fireComponentInvalidated(ComponentEvent e) {
for (ComponentListener l : listeners) {
l.componentInvalidated(e);
}
}
@Override
public Location getLocation() {
return loc;
}
@Override
public AttributeSet getAttributeSet() {
return attrs;
}
@Override
public Bounds getBounds() {
if (bounds == null) {
Location loc = getLocation();
Bounds offBounds = getFactory().getOffsetBounds(getAttributeSet());
bounds = offBounds.translate(loc.getX(), loc.getY());
}
return bounds;
}
protected void recomputeBounds() {
bounds = null;
}
@Override
public List<EndData> getEnds() {
return endsView;
}
public int getEndCount() {
return ends.size();
}
@Override
public abstract void propagate(CircuitState state);
//
// methods for altering data
//
public void clearManager() {
for (EndData end : ends) {
fireEndChanged(new ComponentEvent(this, end, null));
}
ends.clear();
bounds = null;
}
public void setBounds(Bounds bounds) {
this.bounds = bounds;
}
public void setAttributeSet(AttributeSet value) {
attrs = value;
}
public void removeEnd(int index) {
ends.remove(index);
}
public void setEnd(int i, EndData data) {
if (i == ends.size()) {
ends.add(data);
fireEndChanged(new ComponentEvent(this, null, data));
} else {
EndData old = ends.get(i);
if (old == null || !old.equals(data)) {
ends.set(i, data);
fireEndChanged(new ComponentEvent(this, old, data));
}
}
}
public void setEnd(int i, Location end, BitWidth width, int type) {
setEnd(i, new EndData(end, width, type));
}
public void setEnd(int i, Location end, BitWidth width, int type, boolean exclusive) {
setEnd(i, new EndData(end, width, type, exclusive));
}
public void setEnds(EndData[] newEnds) {
List<EndData> oldEnds = ends;
int minLen = Math.min(oldEnds.size(), newEnds.length);
ArrayList<EndData> changesOld = new ArrayList<EndData>();
ArrayList<EndData> changesNew = new ArrayList<EndData>();
for (int i = 0; i < minLen; i++) {
EndData old = oldEnds.get(i);
if (newEnds[i] != null && !newEnds[i].equals(old)) {
changesOld.add(old);
changesNew.add(newEnds[i]);
oldEnds.set(i, newEnds[i]);
}
}
for (int i = oldEnds.size() - 1; i >= minLen; i--) {
changesOld.add(oldEnds.remove(i));
changesNew.add(null);
}
for (int i = minLen; i < newEnds.length; i++) {
oldEnds.add(newEnds[i]);
changesOld.add(null);
changesNew.add(newEnds[i]);
}
fireEndsChanged(changesOld, changesNew);
}
public Location getEndLocation(int i) {
return getEnd(i).getLocation();
}
//
// user interface methods
//
@Override
public void expose(ComponentDrawContext context) {
Bounds bounds = getBounds();
java.awt.Component dest = context.getDestination();
if (bounds != null) {
dest.repaint(bounds.getX() - 5, bounds.getY() - 5,
bounds.getWidth() + 10, bounds.getHeight() + 10);
}
}
@Override
public Object getFeature(Object key) {
return null;
}
}