diff options
Diffstat (limited to 'java')
28 files changed, 3279 insertions, 0 deletions
diff --git a/java/EAC/BoundsException.java b/java/EAC/BoundsException.java new file mode 100644 index 00000000000..12010d570b0 --- /dev/null +++ b/java/EAC/BoundsException.java @@ -0,0 +1,13 @@ +/** + * Title: BoundsException + * Description: An exception class for when graphical objects are positioned + * partially out of their container's boundaries + */ +package EAC; + +public class BoundsException extends Exception { + + public BoundsException(String msg) { + super(msg); + } +}
\ No newline at end of file diff --git a/java/EAC/Configuration.java b/java/EAC/Configuration.java new file mode 100644 index 00000000000..426a8ba2a5e --- /dev/null +++ b/java/EAC/Configuration.java @@ -0,0 +1,220 @@ +/** + * Title: Configuration + * Description: A container of Event Analysis Configurator primitives, + * capable of executing interactions among those primitives + * one "tick" at a time. + */ +package EAC; +import java.awt.*; +import java.lang.*; + +public class Configuration extends Thread { + + // highest simulation clock value + public final long MAX_SIM_CLOCK = 1000000; + + // maximum number of primitives in a configuration + public final int MAX_PRIMITIVES = 100; + + // execution modes + public final int INITIAL = 0; + public final int RUNNING = 1; + public final int STOPPED = 2; + + // current mode + protected int mode = INITIAL; + + // simulation "clock" + protected long simulation_time; + + // one simulation time unit (msec) + public int tick; // will be set by runtime parameter + + // number of missed execution deadlines + protected int missed_deadlines; + + // simulated resource pool + protected ResourcePool rp; + + // event queue + protected Queue eventQ; + + // input and output areas + protected TextField inputArea; + protected Label reportArea; + + // collection of primitives + private Primitive primitive[]; + + // number of primitives currently stored + private int primitive_count; + + public Configuration(TextField i, Label r) { + inputArea = i; + reportArea = r; + eventQ = new Queue(); + clear(); + mode = INITIAL; + } /* constructor */ + + public void clear() { + primitive_count = 0; + simulation_time = 0; + missed_deadlines = 0; + rp = new ResourcePool(); + primitive = new Primitive[MAX_PRIMITIVES]; + eventQ.clear(); + } /* clear */ + + public void restart() { + int i; + + simulation_time = 0; + missed_deadlines = 0; + rp.release(rp.usage()); + eventQ.clear(); + for (i = 0; i < primitive_count; i++) + primitive[i].restart(); + + } /* restart */ + + public void setTick(int t) { + tick = t; + } /* setTick */ + + public void addLabel(Primitive p) { + reportArea.setText("Need a label"); + } /* addLabel */ + + public int getPrimitiveCount() { + return primitive_count; + } /* getPrimitiveCount */ + + public Primitive getPrimitive(int n) { + return primitive[n]; + } /* getPrimitive */ + + protected void setPrimitive(int n, Primitive p) { + primitive[n] = p; + } /* setPrimitive */ + + public int addPrimitive(Primitive p) throws TooManyPrimitivesException { + if (primitive_count == MAX_PRIMITIVES) + throw new TooManyPrimitivesException("ERROR: Too many primitives"); + + primitive[primitive_count++] = p; + return primitive_count; + } /* addPrimitive */ + + public boolean deletePrimitive(int i) { + if (primitive[i] == null) + return false; + else { + primitive[i] = null; + return true; + } + } /* deletePrimitive */ + + public int leftSideOverlaps(Primitive p) { + int i; + + for (i = 0; i < primitive_count; i++) { + if (primitive[i] != null) { + if ((primitive[i].contains(p.upperLeft())) || + (primitive[i].contains(p.lowerLeft())) || + (p.contains(primitive[i].lowerLeft())) || + (p.contains(primitive[i].upperLeft()))) { + return i; + } /* if */ + } /* if */ + } /* for */ + + // no overlap detected + return -1; + } /* leftSideOverlaps */ + + public int rightSideOverlaps(Primitive p) { + int i; + + for (i = 0; i < primitive_count; i++) { + if (primitive[i] != null) { + if ((primitive[i].contains(p.lowerRight())) || + (primitive[i].contains(p.upperRight())) || + (p.contains(primitive[i].upperRight())) || + (p.contains(primitive[i].lowerRight()))) { + return i; + } /* if */ + } /* if */ + } /* for */ + + // no overlap detected + return -1; + } /* rightSideOverlaps */ + + public Primitive primitiveContaining (Point p) { + int i; + + for (i = 0; i < primitive_count; i++) + if (primitive[i].contains(p)) + return primitive[i]; + + return null; + } /* primitiveContaining */ + + public void draw() { + int i; + + for (i = 0; i < primitive_count; i++) + if (primitive[i] != null) + try { + primitive[i].draw(); + } catch (BoundsException be) { + // can't happen + } + } /* draw */ + + public void eventEnqueue(Primitive p, long t) { + eventQ.enqueue(p,t); + } /* eventEnqueue */ + + public long getTime() { + return simulation_time; + } /* getTime */ + + public void run() { + Primitive nextP; + + while (true) { + simulation_time += 1; + simulation_time %= MAX_SIM_CLOCK; + try { + reportArea.setText("Simulation Time: " + + java.lang.Long.toString(simulation_time) + + " Resource Consumption: " + + java.lang.Integer.toString(rp.usage()) + + "% Missed Deadlines: " + + java.lang.Integer.toString(missed_deadlines) + + " Next Event: " + + java.lang.Long.toString(eventQ.frontTime())); + + // wake up all primitives who've set alarms for current time + while (simulation_time == eventQ.frontTime()) { + nextP = eventQ.dequeue(); + nextP.wakeup(simulation_time); + } /* while */ + } catch (EmptyQueueException eqe) { + System.out.println("Event queue empty. We're done?"); + } catch (ConnectionException ce) { + System.out.println("Connection exception in run"); + } + + try { + sleep(tick); + } + catch (InterruptedException ie) { + System.out.println("Interrupted"); + } + } /* outer while */ + } /* run */ + +}
\ No newline at end of file diff --git a/java/EAC/Configurator.java b/java/EAC/Configurator.java new file mode 100644 index 00000000000..1a9bc7a0ed8 --- /dev/null +++ b/java/EAC/Configurator.java @@ -0,0 +1,58 @@ +/** + * Title: Configurator + * Description: The application class for the Event Analysis Configurator + */ +package EAC; +import java.awt.*; +import java.awt.event.*; + +public class Configurator extends Frame { + + // Initial dimensions of the frame + public final int INITIAL_WIDTH = 800; + public final int INITIAL_HEIGHT = 600; + + protected TextField inputArea = new TextField("Input Area", 80); + protected Label reportArea = new Label(); + protected Configuration config = new Configuration(inputArea,reportArea); + protected EACPanel canvas = new EACPanel(config,inputArea,reportArea); + protected EACMenuBar menuBar = new EACMenuBar(canvas,config,inputArea,reportArea); + + Configurator(int tick) { + config.setTick(tick); + + setTitle("The Event Analysis Configurator"); + setLayout(new BorderLayout()); + reportArea.setText("Report Area"); + + // Input Area at top of frame + add(inputArea,"North"); + + // Report Area at bottom of frame + add(reportArea,"South"); + + // Canvas in the middle of frame + add(canvas,"Center"); + + // Menu Bar + setMenuBar(menuBar); + + // Move and resize + setLocation(0,0); + setSize(INITIAL_WIDTH,INITIAL_HEIGHT); + + // For exiting + addWindowListener(new Closer()); + } + + public static void main (String[] argv) { + new Configurator(java.lang.Integer.valueOf(argv[0]).intValue()).show(); + } + + class Closer extends WindowAdapter { + public void windowClosing (WindowEvent e) { + System.exit (0); + } + } + +} /* Configurator */ diff --git a/java/EAC/ConnectionException.java b/java/EAC/ConnectionException.java new file mode 100644 index 00000000000..a1f3efab7ab --- /dev/null +++ b/java/EAC/ConnectionException.java @@ -0,0 +1,14 @@ +/** + * Title: ConnectionException + * Description: An exception class for when an attempt is made to connect + * an input where one is already connected, or to add an + * output when the maximum number of outputs are already set + */ +package EAC; + +public class ConnectionException extends Exception { + + public ConnectionException(String msg) { + super(msg); + } +}
\ No newline at end of file diff --git a/java/EAC/Connector.java b/java/EAC/Connector.java new file mode 100644 index 00000000000..27c02e820bc --- /dev/null +++ b/java/EAC/Connector.java @@ -0,0 +1,197 @@ +/** + * Title: Connector + * Description: Connects two primitives in the Event Analysis Configurator + */ +package EAC; +import java.awt.*; + +public class Connector extends Primitive { + + // for drawing + protected RubberbandLine rbLine; + + // Primitives connected by connector + Primitive startP, + endP; + + // the second point of the connector + // (the anchor point is inherited from Primitive) + protected Point endpoint; + + public Connector(EACPanel p) { + super(p); + rbLine = new RubberbandLine(p); + } + + // inappropriate inherited methods: should not be used + public void setTop(Point p) {} + public Point getTop() { return null; } + + public void setEndpoint(Point p) { + endpoint = p; + } /* setEndpoint */ + + public Point getEndpoint() { + return endpoint; + } /* getEndpoint */ + + // Anchor the rubberband line AND the connector itself + public void anchor(Point p) { + rbLine.anchor(p); + anchor = p; + } /* anchor */ + + // Stretch the rubberband line + public void stretch(Point p) { + rbLine.stretch(p); + } /* stretch */ + + // End the rubberband line AND the connector itself + public void end(Point p) { + rbLine.end(p); + endpoint = p; + } /* end */ + + public void draw() throws BoundsException { + if (inBounds()) { + Graphics g = canvas.getGraphics(); + + g.drawLine(anchor.x,anchor.y,endpoint.x,endpoint.y); + drawArrowhead(g); + } else + throw new BoundsException("ERROR: Attempted to place Connector endpoint out of bounds"); + } /* draw */ + + private void drawArrowhead(Graphics g) { + final int arrowHeadWidth = 10; + Point P1 = anchor; + Point P2 = endpoint; + + // Draw Arrowhead (using java.lang.Math and floating point) + // source provided by Erik in newsgroup posting + double dx = P2.x - P1.x; + double dy = P2.y - P1.y; + final double ra = java.lang.Math.sqrt(dx*dx + dy*dy); + final double ri = (double) arrowHeadWidth; + dx /= ra; + dy /= ra; + Point p2 = new Point((int)Math.round(P2.x - dx*ri), + (int)Math.round(P2.y - dy*ri)); + int[] x = new int[3]; + int[] y = new int[3]; + double r = 0.4 * ri; + x[0] = (int)Math.round(p2.x + dy * r); + y[0] = (int)Math.round(p2.y - dx * r); + x[1] = P2.x; + y[1] = P2.y; + x[2] = (int)Math.round(p2.x - dy * r); + y[2] = (int)Math.round(p2.y + dx * r); + g.fillPolygon(x, y, x.length); + } /* drawArrowhead */ + + public boolean contains(Point p) { + return false; + } /* contains */ + + public Point upperLeft() { + return anchor; + } /* upperLeft */ + + public Point lowerRight() { + return endpoint; + } /* lowerRight */ + + public Point upperRight() { + return endpoint; + } /* upperRight */ + + public Point lowerLeft() { + return anchor; + } /* lowerLeft */ + + public boolean inBounds() { + if (canvas.contains(endpoint)) + return true; + else + return false; + } /* inBounds */ + + public void write(File f) throws java.io.IOException { + f.writeInt(f.CONNECTOR); + f.writeInt(anchor.x); + f.writeInt(anchor.y); + f.writeInt(endpoint.x); + f.writeInt(endpoint.y); + } /* write */ + + public void read(File f) throws java.io.IOException { + anchor = new Point(); + endpoint = new Point(); + + anchor.x = f.readInt(); + anchor.y = f.readInt(); + endpoint.x = f.readInt(); + endpoint.y = f.readInt(); + } /* read */ + + public int addInput(Connector c) throws ConnectionException { + throw new ConnectionException("ERROR: Connectors cannot connect each other"); + } /* addInput */ + + public int addOutput(Connector c) throws ConnectionException { + throw new ConnectionException("ERROR: Connectors cannot connect each other"); + } /* addOutput */ + + public void setInput(Primitive p) { + startP = p; + } /* setInput */ + + public void setOutput(Primitive p) { + endP = p; + } /* setOutput */ + + public Primitive getInput() { + return startP; + } /* getInput */ + + public Primitive getOutput() { + return endP; + } /* getOutput */ + + public Connector getInput(int i) throws ConnectionException { + throw new ConnectionException("Internal error: wrong getInput() called on Connector"); + } /* getInput */ + + public Connector getOutput(int i) throws ConnectionException { + throw new ConnectionException("Internal error: wrong getOutput() called on Connector"); + } /* getOutput */ + + public void removeInput(int i) throws ConnectionException { + //throw new ConnectionException("ERROR: Attempted to remove input from connector"); + startP = null; + } /* removeInput */ + + public void removeOutput(int i) throws ConnectionException { + //throw new ConnectionException("ERROR: Attempted to remove output from connector"); + endP = null; + } /* removeOutput */ + + public int getInputCount() throws ConnectionException { + //throw new ConnectionException("ERROR: Attempted to retrieve input count from connector"); + return (startP == null) ? 0 : 1; + } /* getInputCount */ + + public int getOutputCount() throws ConnectionException { + //throw new ConnectionException("ERROR: Attempted to retrieve output count from connector"); + return (endP == null) ? 0 : 1; + } /* getOutputCount */ + + public void event(Source s) throws ConnectionException { + //throw new ConnectionException("ERROR: Attempted to push event to connector"); + endP.event(s); + } /* event */ + + public void wakeup(long t) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to wake up connector"); + } /* wakeup */ +}
\ No newline at end of file diff --git a/java/EAC/EACComponent.java b/java/EAC/EACComponent.java new file mode 100644 index 00000000000..f26aca96880 --- /dev/null +++ b/java/EAC/EACComponent.java @@ -0,0 +1,460 @@ +/** + * Title: Component + * Description: A real-time component emulator, for use in the Event Analysis + * Configurator. + */ +package EAC; +import java.awt.*; + +public class EACComponent extends Primitive { + + class QueueEntry { + + Source source; + long request_time; + boolean running; + + } /* QueueEntry */ + + public class ServiceQueue { + + public QueueEntry queue[]; + + public int size; + + void enqueue(QueueEntry e) { + int i; + + for (i = 0; i < size; i++) + if (e.source == queue[i].source) { + System.out.println("Internal error: attempt to enqueue duplicate source"); + System.exit(-1); + } + + if (size >= MAX_INPUTS) { + System.out.println("Internal error: queue size at max"); + System.exit(-1); + } + + queue[size++] = e; + } /* enqueue */ + + QueueEntry dequeue() { + QueueEntry front = queue[0]; + int i; + + for (i = 0; i < size; i++) + queue[i] = queue[i+1]; + + --size; + + return front; + } /* dequeue */ + + boolean containsSource (Primitive p) { + int i; + + for (i = 0; i < size; i++) + if (queue[i].source == p) + return true; + + return false; + } /* containsSource */ + + } /* ServiceQueue */ + + // queue of running/waiting event sources + protected ServiceQueue sq; + + // Font for text + protected Font text_font = new EACFont().getFont(); + + // dimensions of the rectangle to be drawn on-screen + protected final int HEIGHT = 40; + protected final int WIDTH = 30; + + // Configuration to which the component belongs + protected Configuration config; + + // percentage of Resource Pool consumed during execution + protected int resource_consumption; + + // duration of execution + protected int duration; + + // input + protected Connector input; + + // outputs + protected Connector output[] = new Connector[MAX_OUTPUTS]; + protected int output_count = 0; + + // helps with dragging the component + protected boolean selected = false; + protected Point old_anchor; + + // Black-on-white (normal) or white-on-black (reversed)? + protected boolean reverse_color = false; + + public EACComponent(EACPanel p, Configuration c) { + super(p); + config = c; + sq = new ServiceQueue(); + sq.queue = new QueueEntry[MAX_INPUTS]; + sq.size = 0; + } /* constructor */ + + public void restart() { + sq.size = 0; + reverse_color = false; + selected = false; + } /* restart */ + + public void setTop(Point p) { + anchor = new Point(p.x - (int) (WIDTH / 2), p.y); + } /* setTop */ + + public Point getTop() { + return new Point(anchor.x + (int) (WIDTH / 2), anchor.y); + } /* getTop */ + + public void setResourceConsumption(int rc) throws NumberFormatException { + if ((rc > 0) && (rc <= 100)) + resource_consumption = rc; + else + throw new NumberFormatException(); + } /* setResourceConsumption */ + + public int getResourceConsumption() { + return resource_consumption; + } /* getResourceConsumption */ + + public void setDuration(int d) throws NumberFormatException { + if (d > 0) + duration = d; + else + throw new NumberFormatException(); + } /* setDuration */ + + public int getDuration() { + return duration; + } /* getDuration */ + + public void event(Source s) throws ConnectionException { + long time = config.getTime(); + + s.reverseColor(); + try { + s.draw(); + } catch (BoundsException be) {} + + //System.out.print(label.getText()); + //System.out.print(" event at: "); + //System.out.println(time); + + if (sq.containsSource(s)) { // missed a deadline + config.missed_deadlines++; + System.out.print(label.getText()); + System.out.print(" missed a deadline for "); + System.out.print(s.getLabel().getText()); + System.out.print(" at: "); + System.out.println(java.lang.Long.toString(time)); + } else { // there's no existing service call for this source + // prepare to add new entry to Service Queue + QueueEntry e = new QueueEntry(); + e.source = s; + e.request_time = time; + if (config.rp.reserve(resource_consumption)) { // resource reservation succeeded + reverseColor(); // indicate we're working it + try { + draw(); + } catch (BoundsException be) {} + config.eventEnqueue(this,time + duration); // set wakeup call to release resources + + // new entry will be running + e.running = true; + } else { // resource reservation failed + config.eventEnqueue(this,time + 1); // set wakeup call to try for resources again + + // new entry will be waiting + e.running = false; + } /* else */ + + sq.enqueue(e); // add new entry to Service Queue + } /* else */ + } /* event */ + + public void wakeup(long t) throws ConnectionException { + int i; + + //System.out.print(label.getText()); + //System.out.println(" wakeup at: " + java.lang.Long.toString(t)); + + while (sq.size > 0) { + if ((sq.queue[0].running) && (sq.queue[0].request_time + duration <= t)) { // time to release + config.rp.release(resource_consumption); + try { + Source s = sq.dequeue().source; // dequeue and get the source + s.normalColor(); // indicates we're done + normalColor(); + s.draw(); + draw(); + } catch (BoundsException be) {} + } else + break; + } /* while */ + + // satisfy as many waiting service calls as possible + for (i = 0; i < sq.size; i++) { + if (!sq.queue[i].running) { + if (config.rp.reserve(resource_consumption)) { // resource reservation succeeded + config.eventEnqueue(this,t + duration); // set wakeup call to release resources + sq.queue[i].request_time = t; + sq.queue[i].running = true; + sq.queue[i].source.reverseColor(); // indicates we're working it + reverseColor(); + try { + draw(); + sq.queue[i].source.draw(); + } catch (BoundsException be) {} + } else { // resource reservation failed + config.eventEnqueue(this,t + 1); // set wakeup call to try for resources again + break; // no reason to keep trying right now + } /* else */ + } /* if */ + } /* while */ + + } /* wakeup */ + + public int addInput(Connector c) throws ConnectionException { + if (input == null) { + input = c; + return 1; + } + else + throw new ConnectionException("ERROR: Input already established for this component"); + } /* setInput */ + + public int addOutput(Connector c) throws ConnectionException { + if (output_count < MAX_OUTPUTS) + output[output_count++] = c; + else + throw new ConnectionException("ERROR: Maximum outputs established for this component"); + + return output_count; + } /* addOutput */ + + public Connector getInput(int i) throws ConnectionException { + if (i != 0) + throw new ConnectionException("ERROR: Bad input index for component"); + else if (input == null) + throw new ConnectionException("ERROR: No input for this component"); + else + return input; + } /* getInput */ + + public Connector getOutput(int i) throws ConnectionException { + if ((i >= 0) && (i < output_count)) + return output[i]; + else + throw new ConnectionException("ERROR: Bad output index for component"); + } /* getOutput */ + + public void removeInput(int i) throws ConnectionException { + if (i != 0) + throw new ConnectionException("ERROR: Bad input index for component"); + else + input = null; + } /* removeInput */ + + public void removeOutput(int i) throws ConnectionException { + if ((i >= 0) && (i < output_count)) { + output[i] = output[output_count-1]; + --output_count; + } else + throw new ConnectionException("ERROR: Bad output index for component"); + } /* removeOutput */ + + public int getOutputCount() throws ConnectionException { + return output_count; + } /* getOutputCount */ + + public int getInputCount() throws ConnectionException { + return (input == null) ? 0 : 1; + } /* getInputCount */ + + public boolean contains(Point p) { + if ((p.x >= anchor.x) && + (p.x <= anchor.x + WIDTH) && + (p.y >= anchor.y) && + (p.y <= anchor.y + HEIGHT)) + return true; + else + return false; + } /* contains */ + + public Point upperLeft() { + return anchor; + } /* upperLeft */ + + public Point lowerRight() { + return new Point(anchor.x + WIDTH, anchor.y + HEIGHT); + } /* lowerRight */ + + public Point upperRight() { + return new Point(anchor.x + WIDTH, anchor.y); + } /* upperRight */ + + public Point lowerLeft() { + return new Point(anchor.x, anchor.y + HEIGHT); + } /* lowerLeft */ + + public void draw() throws BoundsException { + if (selected) + selected = false; + else if (inBounds()) { + Graphics g = canvas.getGraphics(); + char stringData[]; + Color bg, + fg; + + if (reverse_color) { + bg = Color.black; + fg = Color.white; + } else { + bg = Color.white; + fg = Color.black; + } + + g.setColor(Color.black); // rectangle is always black + g.drawRect(anchor.x,anchor.y,WIDTH,HEIGHT); + + g.setColor(bg); // interior + g.fillRect(anchor.x+1,anchor.y+1,WIDTH-1,HEIGHT-1); + + g.setColor(fg); // middle line and text + g.drawLine(anchor.x,anchor.y + (int) (HEIGHT / 2), + anchor.x + WIDTH, anchor.y + (int) (HEIGHT / 2)); + + // print resource consumption percentage + g.setFont(text_font); + g.drawString(java.lang.String.valueOf(resource_consumption), + anchor.x + 16 - (3 * java.lang.String.valueOf(resource_consumption).length()), + anchor.y + (int) (HEIGHT / 3)); + + // print duration + g.drawString(java.lang.String.valueOf(duration), + anchor.x + 16 - (3 * java.lang.String.valueOf(duration).length()), + anchor.y + (int) (HEIGHT * 3 / 4) + 3); + + } else + throw new BoundsException("ERROR: Attempted to place Component partially out of bounds"); + } /* draw */ + + public void reverseColor() { + reverse_color = true; + } /* reverseColor */ + + public void normalColor() { + reverse_color = false; + } /* normalColor */ + + public void specialDraw() { + Graphics g = canvas.getGraphics(); + + g.setXORMode(canvas.getBackground()); + g.drawRect(anchor.x,anchor.y,WIDTH,HEIGHT); + } /* specialDraw */ + + public void specialUndraw() { + Graphics g = canvas.getGraphics(); + + g.setColor(canvas.getBackground()); + g.setXORMode(canvas.getForeground()); + g.drawRect(anchor.x,anchor.y,WIDTH,HEIGHT); + } /* specialUndraw */ + + public void selectedDraw() { + // this will preclude drawing this component for one repaint() call + selected = true; + + old_anchor = anchor; + + super.selectedDraw(); + } /* selectedDraw */ + + public void reconnect() { + int i; + + // move output anchors + for (i = 0; i < output_count; i++) + output[i].setAnchor(new Point(output[i].getAnchor().x + anchor.x - old_anchor.x, + output[i].getAnchor().y + anchor.y - old_anchor.y)); + + // move input endpoint + input.setEndpoint(new Point(input.upperRight().x + anchor.x - old_anchor.x, + input.upperRight().y + anchor.y - old_anchor.y)); + + // move label anchor + label.setAnchor(new Point(label.getAnchor().x + anchor.x - old_anchor.x, + label.getAnchor().y + anchor.y - old_anchor.y)); + } /* reconnect */ + + public boolean inBounds() { + if ((canvas.contains(upperLeft())) && + (canvas.contains(lowerRight()))) + return true; + else + return false; + } /* inBounds */ + + public void write(File f) throws java.io.IOException { + char temp[]; // for writing label + int i, n; + + f.writeInt(f.COMPONENT); + f.writeInt(anchor.x); + f.writeInt(anchor.y); + f.writeInt(resource_consumption); + f.writeInt(duration); + + // Write out the associated label + n = label.getText().length(); + f.writeInt(n); // text length + temp = new char[n]; + temp = label.getText().toCharArray(); + for (i = 0; i < n; i++) + f.writeChar(temp[i]); + f.writeInt(label.getAnchor().x); // label position + f.writeInt(label.getAnchor().y); + } /* write */ + + public void read(File f) throws java.io.IOException { + char temp[]; // for reading label + int i, n; + int label_x, label_y; + + anchor = new Point(); + anchor.x = f.readInt(); + anchor.y = f.readInt(); + resource_consumption = f.readInt(); + duration = f.readInt(); + + // get label info + n = f.readInt(); // text length + label = new EACLabel(canvas,n); + temp = new char[n]; + for (i = 0; i < n; i++) + temp[i] = f.readChar(); + label.setText(java.lang.String.valueOf(temp)); + label_x = f.readInt(); + label_y = f.readInt(); + label.setAnchor(new Point(label_x,label_y)); + label.setLabelee(this); + try { + config.addPrimitive(label); + } catch (TooManyPrimitivesException tmpe) { + // have faith :-) + } + } /* read */ +}
\ No newline at end of file diff --git a/java/EAC/EACFont.java b/java/EAC/EACFont.java new file mode 100644 index 00000000000..97f4d39b6cb --- /dev/null +++ b/java/EAC/EACFont.java @@ -0,0 +1,21 @@ +/** + * Title: EACFont + * Description: The font to be used for on-screen text + */ +package EAC; +import java.awt.*; + +public class EACFont { + + // Use 9-point Courier New + public final int FONT_SIZE = 10; + protected Font eac_font = new Font("Courier New",Font.PLAIN,FONT_SIZE); + + public EACFont() { + } + + public Font getFont() { + return eac_font; + } /* getFont */ + +}
\ No newline at end of file diff --git a/java/EAC/EACLabel.java b/java/EAC/EACLabel.java new file mode 100644 index 00000000000..e841c4e4c40 --- /dev/null +++ b/java/EAC/EACLabel.java @@ -0,0 +1,187 @@ +/** + * Title: EACLabel + * Description: Text labels for Event Analysis Configurator graphical + * primitives + */ +package EAC; +import java.awt.*; + +public class EACLabel extends Primitive { + + // Font for labels + protected Font label_font = new EACFont().getFont(); + + // Font Metrics for sizing and bounds checking labels + protected FontMetrics fm = canvas.getFontMetrics(label_font); + + // Label text + protected char[] text; + + // associated Primitive + protected Primitive labelee; + + public EACLabel(EACPanel p, int n) { + super(p); + text = new char[n]; + } /* constructor */ + + public void setLabelee(Primitive p) { + labelee = p; + } /* setLabelee */ + + public Primitive getLabelee() { + return labelee; + } /* getLabelee */ + + public void setText(String s) { + text = s.toCharArray(); + } /* setText */ + + public String getText() { + return java.lang.String.valueOf(text); + } /* getText */ + + public void setTop(Point p) { + anchor = new Point(p.x - (3 * text.length), + p.y + 9); + } /* setTop */ + + public Point getTop() { + return new Point(anchor.x + (3 * text.length), + anchor.y - 9); + } /* getTop */ + + public void draw() throws BoundsException { + if (inBounds()) { + Graphics g = canvas.getGraphics(); + g.setFont(label_font); + g.drawChars(text,0,text.length,anchor.x,anchor.y); + } else + throw new BoundsException("Attempted to place Label partially out of bounds"); + } /* draw */ + + public void specialDraw() { + Graphics g = canvas.getGraphics(); + + g.setXORMode(canvas.getBackground()); + g.drawRect(upperLeft().x, upperLeft().y, + upperRight().x - upperLeft().x, // WIDTH + lowerRight().y - upperRight().y); // HEIGHT + } /* specialDraw */ + + public void specialUndraw() { + Graphics g = canvas.getGraphics(); + + g.setColor(canvas.getBackground()); + g.setXORMode(canvas.getForeground()); + g.drawRect(upperLeft().x, upperLeft().y, + upperRight().x - upperLeft().x, // WIDTH + lowerRight().y - upperRight().y); // HEIGHT + } /* specialUndraw */ + + public boolean contains(Point p) { + return ((p.x >= upperLeft().x) && + (p.x <= upperRight().x) && + (p.y <= lowerLeft().y) && + (p.y >= upperLeft().y)); + } /* contains */ + + public boolean inBounds() { + // don't know why we need this, but fm.stringWidth seems to return a + // value that's bigger than the actual width of the text + //final int xTweak = 20; + + //if (canvas.contains(anchor.x + fm.stringWidth(text.toString()) - xTweak, + // anchor.y - fm.getHeight())) + if ((canvas.contains(upperLeft())) && + (canvas.contains(upperRight())) && + (canvas.contains(lowerLeft())) && + (canvas.contains(lowerRight()))) + return true; + else + return false; + } /* inBounds */ + + public Point upperLeft() { + return new Point(anchor.x,anchor.y - 9); + } /* upperLeft */ + + public Point upperRight() { + return new Point(anchor.x + (6 * text.length),anchor.y - 9); + } /* upperRight */ + + public Point lowerLeft() { + return anchor; + } /* lowerLeft */ + + public Point lowerRight() { + return new Point(anchor.x + (6 * text.length),anchor.y); + } /* lowerRight */ + + public void write(File f) throws java.io.IOException { + int i; + + // if there's an associated primitive, that primitive + // is responsible for writing out the label info too, + // so only write out the info if there is no labelee + if (labelee == null) { + f.writeInt(f.LABEL); + f.writeInt(text.length); + f.writeInt(anchor.x); + f.writeInt(anchor.y); + for (i = 0; i < text.length; i++) + f.writeChar(text[i]); + } + } /* write */ + + public void read(File f) throws java.io.IOException { + int i; + + anchor = new Point(); + anchor.x = f.readInt(); + anchor.y = f.readInt(); + + for (i = 0; i < text.length; i++) + text[i] = f.readChar(); + } /* read */ + + public int addInput(Connector c) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to add input to label"); + } /* addInput */ + + public int addOutput(Connector c) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to add output to label"); + } /* addOutput */ + + public Connector getInput(int i) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to retrieve input from label"); + } /* getInput */ + + public Connector getOutput(int i) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to retrieve output from label"); + } /* getOutput */ + + public int getInputCount() throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to retrieve input count from label"); + } /* getInputCount */ + + public int getOutputCount() throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to retrieve output count from label"); + } /* getOutputCount */ + + public void removeInput(int i) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to remove input from label"); + } /* removeInput */ + + public void removeOutput(int i) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to remove output from label"); + } /* removeOutput */ + + public void event(Source s) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to push event to label"); + } /* event */ + + public void wakeup(long t) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to wake up label"); + } /* wakeup */ +}
\ No newline at end of file diff --git a/java/EAC/EACMenuBar.java b/java/EAC/EACMenuBar.java new file mode 100644 index 00000000000..d34a776635d --- /dev/null +++ b/java/EAC/EACMenuBar.java @@ -0,0 +1,198 @@ +/** + * Title: EACMenuBar + * Description: A subclass of MenuBar for the Event Analysis Configurator + */ +package EAC; +import java.awt.*; +import java.awt.event.*; + +public class EACMenuBar extends MenuBar { + + protected EACPanel canvas; + protected Configuration config; + protected TextField inputArea; + protected Label reportArea; + + public EACMenuBar(EACPanel p, Configuration c, TextField i, Label r) { + canvas = p; + config = c; + inputArea = i; + reportArea = r; + + // Configuration menu + Menu menu = new Menu("Configuration"); + + // Configuration menu options + MenuItem mi = new MenuItem("Clear"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (config.mode == config.RUNNING) { + config.suspend(); + config.mode = config.STOPPED; + } /* if */ + config.clear(); + canvas.repaint(); + inputArea.setText(""); + reportArea.setText("Configuration cleared"); + } /* actionPerformed */ + }); /* addActionListener */ + menu.add(mi); + + mi = new MenuItem("Load"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (config.mode == config.RUNNING) { + config.suspend(); + config.mode = config.STOPPED; + } /* if */ + config.clear(); + canvas.repaint(); + inputArea.setText(""); + reportArea.setText("Please enter a filename"); + canvas.mode = canvas.LOAD; + } /* actionPerformed */ + }); /* addActionListener */ + menu.add(mi); + + mi = new MenuItem("Save"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (config.mode == config.RUNNING) { + config.suspend(); + config.mode = config.STOPPED; + } /* if */ + canvas.repaint(); + canvas.mode = canvas.SAVE; + inputArea.setText(""); + reportArea.setText("Please enter a filename"); + } /* actionPerformed */ + }); /* addActionListener */ + menu.add(mi); + + mi = new MenuItem("Run/Restart"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (config.mode == config.INITIAL) { + config.start(); + } else if (config.mode == config.STOPPED) { + config.restart(); + canvas.repaint(); + config.resume(); + } + System.out.println(); + System.out.println("Configuration running..."); + config.mode = config.RUNNING; + } /* actionPerformed */ + }); /* addActionListener */ + menu.add(mi); + + mi = new MenuItem("Pause/Unpause"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (config.mode == config.RUNNING) { + config.suspend(); + config.mode = config.STOPPED; + } else if (config.mode == config.STOPPED) { + config.resume(); + config.mode = config.RUNNING; + } + } /* actionPerformed */ + }); /* addActionListener */ + menu.add(mi); + + add(menu); + + // New menu + menu = new Menu("New"); + + // New menu options + mi = new MenuItem("Component"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (config.mode != config.RUNNING) { + canvas.current_component = new EACComponent(canvas,config); + canvas.repaint(); + canvas.mode = canvas.COMPONENT; + } + } /* actionPerformed */ + }); /* addActionListener */ + menu.add(mi); + + mi = new MenuItem("Union"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (config.mode != config.RUNNING) { + canvas.current_shape = new Union(canvas); + canvas.repaint(); + canvas.mode = canvas.EDIT; + } + } /* actionPerformed */ + }); /* addActionListener */ + menu.add(mi); + + mi = new MenuItem("Intersection"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (config.mode != config.RUNNING) { + canvas.current_shape = new Intersection(canvas); + canvas.repaint(); + canvas.mode = canvas.EDIT; + } + } /* actionPerformed */ + }); /* addActionListener */ + menu.add(mi); + + mi = new MenuItem("Source"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (config.mode != config.RUNNING) { + canvas.current_source = new Source(canvas,config); + canvas.repaint(); + canvas.mode = canvas.SOURCE; + } + } /* actionPerformed */ + }); /* addActionListener */ + menu.add(mi); + + mi = new MenuItem("Sink"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (config.mode != config.RUNNING) { + canvas.current_shape = new Sink(canvas); + canvas.repaint(); + canvas.mode = canvas.EDIT; + } + } /* actionPerformed */ + }); /* addActionListener */ + menu.add(mi); + + mi = new MenuItem("Connector"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (config.mode != config.RUNNING) { + canvas.repaint(); + canvas.mode = canvas.CONNECTING; + } + } /* actionPerformed */ + }); /* addActionListener */ + menu.add(mi); + + mi = new MenuItem("Label"); + mi.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (config.mode != config.RUNNING) { + reportArea.setText("Enter the text for your label in the input area"); + inputArea.setText(""); + canvas.repaint(); + canvas.mode = canvas.LABEL_TYPING; + } + } /* actionPerformed */ + }); /* addActionListener */ + menu.add(mi); + + add(menu); + + } /* constructor */ + +} /* EACMenuBar */ + diff --git a/java/EAC/EACPanel.java b/java/EAC/EACPanel.java new file mode 100644 index 00000000000..333321ef545 --- /dev/null +++ b/java/EAC/EACPanel.java @@ -0,0 +1,425 @@ +/** + * Title: EACPanel + * Description: A subclass of Panel for the Event Analysis Configurator + */ +package EAC; +import java.awt.*; +import java.awt.event.*; + +public class EACPanel extends Panel { + + protected TextField inputArea; + protected Label reportArea; + + // input modes + public final int COMMAND = 0; + public final int SELECT = 1; + public final int CUT = 2; + public final int COPY = 3; + public final int PASTE = 4; + public final int EDIT = 5; + public final int CONNECTING = 6; + public final int COMPONENT = 7; + public final int LABEL_TYPING = 8; + public final int LABEL_ADDING = 9; + public final int RC_TYPING = 10; + public final int DURATION_TYPING = 11; + public final int PERIOD_TYPING = 12; + public final int SOURCE = 13; + public final int CONNECTING_END = 14; + public final int LOAD = 15; + public final int SAVE = 16; + + // current input mode + protected int mode; + + // current primitive for drawing + protected Primitive current_shape; + + // current text label + protected EACLabel current_label; + + // current component + protected EACComponent current_component; + + // current source + protected Source current_source; + + // current connector, and associated primitives (indices into config's collection) + protected Connector current_connector; + protected int connector_start_index; + protected int connector_end_index; + + // flag for associating the required label with a component or source + protected boolean component_needs_label = false; + protected boolean source_needs_label = false; + + // Component Configuration associated with this panel + protected Configuration config; + + // for dragging primitives around the panel + int moving_dx, + moving_dy; + boolean repainted; + + + // Constructor + public EACPanel(Configuration c, TextField i, Label r) { + config = c; + inputArea = i; + inputArea.addKeyListener(eac_key_adapter); + reportArea = r; + mode = COMMAND; + addMouseListener(eac_mouse_adapter); + addMouseMotionListener(eac_mm_adapter); + } /* constructor */ + + // Mouse Adapter + private class EACMouseAdapter extends MouseAdapter + implements MouseListener { + + EACPanel canvas; + + public EACMouseAdapter(EACPanel p) { + canvas = p; + } /* constructor */ + + public void mousePressed(MouseEvent e) { + switch (mode) { + case EDIT: + current_shape.setTop(new Point(e.getX(),e.getY())); + try { + if ((config.leftSideOverlaps(current_shape) == -1) && + (config.rightSideOverlaps(current_shape) == -1)) { + current_shape.draw(); + reportArea.setText(""); + config.addPrimitive(current_shape); + mode = COMMAND; + } else { + reportArea.setText("ERROR: Primitives too close together"); + } /* if */ + } catch (BoundsException be) { + reportArea.setText(be.getMessage()); + } catch (TooManyPrimitivesException tmpe) { + reportArea.setText(tmpe.getMessage()); + } /* try */ + break; + case SOURCE: + current_source.setTop(new Point(e.getX(),e.getY())); + try { + if ((config.leftSideOverlaps(current_source) == -1) && + (config.rightSideOverlaps(current_source) == -1)) { + current_source.draw(); + config.addPrimitive(current_source); + reportArea.setText("Please enter the period for this source in the input area"); + inputArea.setText(""); + mode = PERIOD_TYPING; + } else { + reportArea.setText("ERROR: Primitives too close together"); + } /* if */ + } catch (BoundsException be) { + reportArea.setText(be.getMessage()); + } catch (TooManyPrimitivesException tmpe) { + reportArea.setText(tmpe.getMessage()); + } /* try */ + break; + case COMPONENT: + current_component.setTop(new Point(e.getX(),e.getY())); + try { + if ((config.leftSideOverlaps(current_component) == -1) && + (config.rightSideOverlaps(current_component) == -1)) { + current_component.draw(); + config.addPrimitive(current_component); + reportArea.setText("Please enter the resource consumption for this component in the input area"); + inputArea.setText(""); + mode = RC_TYPING; + } else { + reportArea.setText("ERROR: Primitives too close together"); + } /* if */ + } catch (BoundsException be) { + reportArea.setText(be.getMessage()); + } catch (TooManyPrimitivesException tmpe) { + reportArea.setText(tmpe.getMessage()); + } /* try */ + break; + case CONNECTING: + current_connector = new Connector(canvas); + current_connector.anchor(new Point(e.getX(),e.getY())); + connector_start_index = config.leftSideOverlaps(current_connector); + if (connector_start_index == -1) + reportArea.setText("ERROR: Connector must begin inside a primitive"); + else + mode = CONNECTING_END; + break; + case LABEL_ADDING: + current_label.setTop(new Point(e.getX(),e.getY())); + try { + current_label.specialUndraw(); + current_label.draw(); + reportArea.setText(""); + config.addPrimitive(current_label); + mode = COMMAND; + } catch (BoundsException be) { + reportArea.setText(be.getMessage()); + } catch (TooManyPrimitivesException tmpe) { + reportArea.setText(tmpe.getMessage()); + } /* try */ + break; + default: // SELECT mode + mode = SELECT; + current_shape = config.primitiveContaining(new Point(e.getX(),e.getY())); + repaint(); + if (current_shape != null) { + repaint(); // if there was a previously selected shape, it ignored + // the last repaint() (kludge--looks better for dragging) + moving_dx = e.getX() - current_shape.getTop().x; + moving_dy = e.getY() - current_shape.getTop().y; + current_shape.selectedDraw(); + repainted = false; + } else + repaint(); // need to repaint a second time + break; + } /* switch */ + } /* mousePressed */ + + public void mouseReleased(MouseEvent e) { + switch (mode) { + case CONNECTING_END: + current_connector.end(new Point(e.getX(),e.getY())); + try { + connector_end_index = config.rightSideOverlaps(current_connector); + if (connector_end_index != -1) { + if (connector_end_index == connector_start_index) + reportArea.setText("ERROR: Connector cannot start and end at same primitive"); + else { + Primitive startP = config.getPrimitive(connector_start_index); + Primitive endP = config.getPrimitive(connector_end_index); + + // connect primitives + try { + startP.addOutput(current_connector); + current_connector.setInput(startP); + current_connector.setOutput(endP); + endP.addInput(current_connector); + + // if everything okay, draw arrow + current_connector.draw(); + reportArea.setText(""); + config.addPrimitive(current_connector); + + mode = COMMAND; + + } catch (ConnectionException ce) { + reportArea.setText(ce.getMessage()); + } + } /* else */ + } else { + reportArea.setText("ERROR: Connector must terminate inside a primitive"); + } /* if */ + } catch (BoundsException be) { + reportArea.setText(be.getMessage()); + } catch (TooManyPrimitivesException tmpe) { + reportArea.setText(tmpe.getMessage()); + } /* try */ + mode = CONNECTING; + break; + case SELECT: + if (current_shape != null) + current_shape.reconnect(); + if (repainted) // dragging occurred + repaint(); + break; + default: + //no-op + } /* switch */ + } /* mouseReleased */ + + public void mouseClicked(MouseEvent e) {} + public void mouseEntered(MouseEvent e) {} + public void mouseExited(MouseEvent e) {} + + } /* EACMouseAdapter */ + + // Mouse Motion Adapter + private class EACMouseMotionAdapter extends MouseMotionAdapter + implements MouseMotionListener { + + public void mouseDragged(MouseEvent e) { + switch (mode) { + case CONNECTING_END: + current_connector.stretch(new Point(e.getX(),e.getY())); + break; + case SELECT: + if (current_shape != null) { + Point old_top = current_shape.getTop(); + if (!repainted) { + repaint(); + repainted = true; + } /* if */ + current_shape.specialUndraw(); + current_shape.setTop(new Point(e.getX() - moving_dx,e.getY() - moving_dy)); + if (!current_shape.inBounds()) + current_shape.setTop(old_top); + current_shape.specialDraw(); + } /* if */ + default: + //no-op + } /* switch */ + } /* mouseDragged */ + + public void mouseMoved(MouseEvent e) { + switch (mode) { + case COMPONENT: + if (current_component.getAnchor() != null) + current_component.specialUndraw(); + current_component.setTop(new Point(e.getX(),e.getY())); + current_component.specialDraw(); + break; + case SOURCE: + if (current_source.getAnchor() != null) + current_source.specialUndraw(); + current_source.setTop(new Point(e.getX(),e.getY())); + current_source.specialDraw(); + break; + case EDIT: + if (current_shape.getAnchor() != null) + current_shape.specialUndraw(); + current_shape.setTop(new Point(e.getX(),e.getY())); + current_shape.specialDraw(); + break; + case LABEL_ADDING: + if (current_label.getAnchor() != null) + current_label.specialUndraw(); + current_label.setTop(new Point(e.getX(),e.getY())); + current_label.specialDraw(); + break; + default: + //no-op + } /* switch */ + } /* mouseMoved */ + + } /* EACMouseMotionAdapter */ + + // Key Adapter + private class EACKeyAdapter extends KeyAdapter implements KeyListener { + + EACPanel canvas; + + public EACKeyAdapter(EACPanel p) { + canvas = p; + } /* constructor */ + + public void keyPressed(KeyEvent e) { + Graphics g = getGraphics(); + String input; + + if ((mode == RC_TYPING) && (e.getKeyChar() == '\n')) { + input = new String(inputArea.getText()); + try { + current_component.setResourceConsumption(Integer.parseInt(input)); + current_component.draw(); + reportArea.setText("Please enter the duration for this component in the input area"); + inputArea.setText(""); + mode = DURATION_TYPING; + } catch (NumberFormatException nfe) { + reportArea.setText("Please enter an integer value between 1 and 100, inclusive"); + inputArea.setText(""); + return; + } catch (BoundsException be) { + reportArea.setText(be.getMessage()); + } /* try */ + } else if ((mode == DURATION_TYPING) && (e.getKeyChar() == '\n')) { + input = new String(inputArea.getText()); + try { + current_component.setDuration(Integer.parseInt(input)); + current_component.draw(); + reportArea.setText("Please enter a label for this component in the input area"); + inputArea.setText(""); + component_needs_label = true; + mode = LABEL_TYPING; + } catch (NumberFormatException nfe) { + reportArea.setText("Please enter an integer value"); + inputArea.setText(""); + return; + } catch (BoundsException be) { + reportArea.setText(be.getMessage()); + } /* try */ + } else if ((mode == LABEL_TYPING) && (e.getKeyChar() == '\n')) { + current_label = new EACLabel(canvas,inputArea.getText().length()); + current_label.setText(inputArea.getText()); + if (component_needs_label) { + component_needs_label = false; + current_component.setLabel(current_label); + current_label.setLabelee(current_component); + } else if (source_needs_label) { + source_needs_label = false; + current_source.setLabel(current_label); + current_label.setLabelee(current_source); + } + reportArea.setText("Click at desired label location"); + inputArea.setText(""); + mode = LABEL_ADDING; + } else if ((mode == PERIOD_TYPING) && (e.getKeyChar() == '\n')) { + input = new String(inputArea.getText()); + try { + current_source.setPeriod(Integer.parseInt(input)); + current_source.draw(); + inputArea.setText(""); + reportArea.setText("Please enter a label for this source in the input area"); + mode = LABEL_TYPING; + source_needs_label = true; + } catch (NumberFormatException nfe) { + reportArea.setText("Please enter a positive integer value"); + inputArea.setText(""); + return; + } catch (BoundsException be) { + reportArea.setText(be.getMessage()); + } /* try */ + } else if ((mode == LOAD) && (e.getKeyChar() == '\n')) { + File input_file; + input = new String(inputArea.getText()); + try { + input_file = new File(input,"r",config,canvas); + input_file.readConfiguration(); + input_file.close(); + reportArea.setText("Configuration loaded successfully"); + inputArea.setText(""); + } catch (java.io.FileNotFoundException fnfe) { + } catch (java.io.IOException ioe) { + } catch (TooManyPrimitivesException tmpe) { + reportArea.setText(tmpe.getMessage()); + } + } else if ((mode == SAVE) && (e.getKeyChar() == '\n')) { + File output_file; + input = new String(inputArea.getText()); + try { + output_file = new File(input,"rw",config,canvas); + output_file.writeConfiguration(); + output_file.close(); + reportArea.setText("Configuration saved successfully"); + inputArea.setText(""); + } catch (java.io.FileNotFoundException fnfe) { + } catch (java.io.IOException ioe) {} + } /* if */ + } /* keyPressed */ + } /* EACKeyAdapter */ + + // Mouse Adapter Instances + private EACMouseAdapter eac_mouse_adapter = new EACMouseAdapter(this); + private EACMouseMotionAdapter eac_mm_adapter = new EACMouseMotionAdapter(); + + // Key Adapter Instance + private EACKeyAdapter eac_key_adapter = new EACKeyAdapter(this); + + public void paint(Graphics g) { + g.setColor(getBackground()); + g.fillRect(0,0,getSize().width,getSize().height); + g.setColor(getForeground()); + g.drawRect(0,0,getSize().width - 1,getSize().height - 1); + config.draw(); + } /* paint */ + + public void repaint() { + paint(getGraphics()); + } /* repaint */ +}
\ No newline at end of file diff --git a/java/EAC/EACPrintStream.java b/java/EAC/EACPrintStream.java new file mode 100644 index 00000000000..9e8d82d03f0 --- /dev/null +++ b/java/EAC/EACPrintStream.java @@ -0,0 +1,16 @@ +/** + * Title: EACFileStream + * Description: A stream class for conducting file I/O in the Event Analysis Configurator. + */ +package EAC; + +import java.io.RandomAccessF; + +public class EACPrintStream { + + PrintStream ps; + + public EACPrintStream(String filename) { + ps = new PrintStream(new FileOutputStream(filename), true); + } +}
\ No newline at end of file diff --git a/java/EAC/EmptyQueueException.java b/java/EAC/EmptyQueueException.java new file mode 100644 index 00000000000..0b2af00c36f --- /dev/null +++ b/java/EAC/EmptyQueueException.java @@ -0,0 +1,13 @@ +/** + * Title: EmptyQueueException + * Description: An exception class for when an attempt is made to access + * the head of the event queue when the queue is empty + */ +package EAC; + +public class EmptyQueueException extends Exception { + + public EmptyQueueException(String msg) { + super(msg); + } +}
\ No newline at end of file diff --git a/java/EAC/File.java b/java/EAC/File.java new file mode 100644 index 00000000000..6ba151cddc0 --- /dev/null +++ b/java/EAC/File.java @@ -0,0 +1,118 @@ +/** + * Title: File + * Description: A file I/O class for the Event Analysis Configurator + */ +package EAC; + +import java.io.RandomAccessFile; + +public class File extends RandomAccessFile { + + public final int SOURCE = 1; + public final int SINK = 2; + public final int COMPONENT = 3; + public final int CONNECTOR = 4; + public final int UNION = 5; + public final int INTERSECTION = 6; + public final int LABEL = 7; + + protected Configuration config; + + protected EACPanel canvas; + + public File(String filename, String mode, Configuration c, EACPanel p) + throws java.io.FileNotFoundException { + super(filename,mode); + config = c; + canvas = p; + } /* constructor */ + + public void writeConfiguration() throws java.io.IOException { + int i; + + // write number of primitives + writeInt(config.getPrimitiveCount()); + + // write primitives + for (i = 0; i < config.getPrimitiveCount(); i++) + config.getPrimitive(i).write(this); + + } /* writeConfiguration */ + + public void readConfiguration() throws java.io.IOException, TooManyPrimitivesException { + int i, + num, + label_length, // for reading the number of chars in an EACLabel + primitiveID; + + Primitive next_primitive = new Union(canvas); // dummy initialization + + Connector next_connector; + + // read number of primitives + num = readInt(); + + for (i = 0; i < num; i++) { + primitiveID = readInt(); + switch(primitiveID) { + case SOURCE: + next_primitive = new Source(canvas,config); + next_primitive.read(this); + i++; // Add one more to the loop counter 'cause we read our own label + break; + case SINK: + next_primitive = new Sink(canvas); + next_primitive.read(this); + break; + case COMPONENT: + next_primitive = new EACComponent(canvas,config); + next_primitive.read(this); + i++; // Add one more to the loop counter 'cause we read our own label + break; + case CONNECTOR: + next_connector = new Connector(canvas); + next_primitive = next_connector; // so it can be added to the config + next_connector.read(this); + try { + int connector_start_index = config.leftSideOverlaps(next_connector); + int connector_end_index = config.rightSideOverlaps(next_connector); + + Primitive startP = config.getPrimitive(connector_start_index); + Primitive endP = config.getPrimitive(connector_end_index); + + // reinstate connection + startP.addOutput(next_connector); + next_connector.setInput(startP); + next_connector.setOutput(endP); + endP.addInput(next_connector); + + } catch (ConnectionException ce) { + // can't happen (right?) + } /* try */ + break; + case UNION: + next_primitive = new Union(canvas); + next_primitive.read(this); + break; + case INTERSECTION: + next_primitive = new Intersection(canvas); + next_primitive.read(this); + break; + case LABEL: + label_length = readInt(); + next_primitive = new EACLabel(canvas,label_length); + next_primitive.read(this); + break; + } /* switch */ + + // add to configuration + config.addPrimitive(next_primitive); + + } /* for */ + + // draw the configuration + config.draw(); + + } /* readConfiguration */ + +}
\ No newline at end of file diff --git a/java/EAC/InputMode.java b/java/EAC/InputMode.java new file mode 100644 index 00000000000..c44e4a45c4d --- /dev/null +++ b/java/EAC/InputMode.java @@ -0,0 +1,32 @@ +/** + * Title: InputMode + * Description: Maintains Configurator state for deciding how to handle input + */ +package EAC; + +public class InputMode { + + public final int COMMAND = 0; + public final int SELECT = 1; + public final int CUT = 2; + public final int COPY = 3; + public final int PASTE = 4; + public final int EDIT = 5; + public final int RESIZE = 6; + + protected int mode; + + protected Primitive current_shape; + + public InputMode() { + mode = COMMAND; + } /* constructor */ + + public int getMode() { + return mode; + } /* getMode */ + + protected void setMode(int m) { + mode = m; + } /* setMode */ +}
\ No newline at end of file diff --git a/java/EAC/Intersection.java b/java/EAC/Intersection.java new file mode 100644 index 00000000000..1e1beafb770 --- /dev/null +++ b/java/EAC/Intersection.java @@ -0,0 +1,62 @@ +/** + * Title: Intersection + * Description: A binary intersection operator class for the Event Analysis + * Configurator. Acts as a sort of filter, combining two event + * streams into one. + */ +package EAC; +import java.awt.*; + +public class Intersection extends Operator { + + // Where did the last event come from? + protected Primitive last_event_source; + + public Intersection(EACPanel p) { + super(p); + last_event_source = null; + } /* constructor */ + + public void draw() throws BoundsException { + // the intersection symbol + final char iSymbol = '^'; + + // subtle adjustments to position symbol within circle + final int xTweak = 2; + final int yTweak = -5; + + char symbol[] = new char[1]; + Graphics g = canvas.getGraphics(); + + super.draw(); + symbol[0] = iSymbol; + g.drawChars(symbol,0,1, + anchor.x + (int) (DIAMETER / 2) - xTweak, + anchor.y + (int) (DIAMETER / 2) - yTweak); + } /* draw */ + + public void event(Source s) throws ConnectionException { + //System.out.println("Intersection event"); + if (last_event_source == null) + last_event_source = s; + else if (last_event_source != s) { // we've now gotten events from two distinct sources + int i; + + last_event_source = null; + for (i = 0; i < output_count; i++) + output[i].event(s); + } // else no-op, because this event is from the same source as the last event + } /* event */ + + public void write(File f) throws java.io.IOException { + f.writeInt(f.INTERSECTION); + f.writeInt(anchor.x); + f.writeInt(anchor.y); + } /* write */ + + public void read(File f) throws java.io.IOException { + anchor = new Point(); + anchor.x = f.readInt(); + anchor.y = f.readInt(); + } /* read */ +}
\ No newline at end of file diff --git a/java/EAC/Operator.java b/java/EAC/Operator.java new file mode 100644 index 00000000000..724c9583b20 --- /dev/null +++ b/java/EAC/Operator.java @@ -0,0 +1,206 @@ +/** + * Title: Operator + * Description: An abstract binary operator class for the Event Analysis + * Configurator + */ +package EAC; +import java.awt.*; + +public abstract class Operator extends Primitive { + + // Radius of the circle + protected final int DIAMETER = 40; + + // inputs + protected Connector left_input, + right_input; + + // outputs + protected Connector output[] = new Connector[MAX_OUTPUTS]; + protected int output_count = 0; + + // helps with dragging the operator + protected boolean selected; + Point old_anchor; + + public Operator(EACPanel p) { + super(p); + } /* constructor */ + + public void setTop(Point p) { + anchor = new Point(p.x - (int) (DIAMETER / 2), p.y); + } /* setTop */ + + public Point getTop() { + return new Point(anchor.x + (int) (DIAMETER / 2), anchor.y); + } /* getTop */ + + public void draw() throws BoundsException { + Graphics g = canvas.getGraphics(); + + if (selected) + selected = false; + else if (inBounds()) + g.drawOval(anchor.x, anchor.y, DIAMETER, DIAMETER); + else + throw new BoundsException("ERROR: Attempted to place Operator partially out of bounds"); + } /* draw */ + + public void specialDraw() { + Graphics g = canvas.getGraphics(); + + g.setXORMode(canvas.getBackground()); + g.drawOval(anchor.x,anchor.y,DIAMETER,DIAMETER); + } /* specialDraw */ + + public void specialUndraw() { + Graphics g = canvas.getGraphics(); + + g.setColor(canvas.getBackground()); + g.setXORMode(canvas.getForeground()); + g.drawOval(anchor.x,anchor.y,DIAMETER,DIAMETER); + } /* specialUndraw */ + + public void selectedDraw() { + old_anchor = anchor; + selected = true; + super.selectedDraw(); + } /* selectedDraw */ + + public void reconnect() { + int i; + + // move output anchors + for (i = 0; i < output_count; i++) + output[i].setAnchor(new Point(output[i].getAnchor().x + anchor.x - old_anchor.x, + output[i].getAnchor().y + anchor.y - old_anchor.y)); + + // move input endpoints + if (left_input != null) + left_input.setEndpoint(new Point(left_input.upperRight().x + anchor.x - old_anchor.x, + left_input.upperRight().y + anchor.y - old_anchor.y)); + if (right_input != null) + right_input.setEndpoint(new Point(right_input.upperRight().x + anchor.x - old_anchor.x, + right_input.upperRight().y + anchor.y - old_anchor.y)); + + } /* reconnect */ + + public boolean contains(Point p) { + if ((p.x >= anchor.x) && + (p.x <= anchor.x + DIAMETER) && + (p.y >= anchor.y) && + (p.y <= anchor.y + DIAMETER)) + return true; + else + return false; + } /* contains */ + + public Point upperLeft() { + return anchor; + } /* upperLeft */ + + public Point lowerRight() { + return new Point(anchor.x + DIAMETER, anchor.y + DIAMETER); + } /* lowerRight */ + + public Point upperRight() { + return new Point(anchor.x + DIAMETER, anchor.y); + } /* upperRight */ + + public Point lowerLeft() { + return new Point(anchor.x, anchor.y + DIAMETER); + } /* lowerLeft */ + + public int addInput(Connector c) throws ConnectionException { + if (left_input == null) { + left_input = c; + return 0; + } else if (right_input == null) { + right_input = c; + return 1; + } else + throw new ConnectionException("ERROR: Operator already has two inputs"); + } /* addInput */ + + public int addOutput(Connector c) throws ConnectionException { + if (output_count < MAX_OUTPUTS) + output[output_count++] = c; + else + throw new ConnectionException("ERROR: Maximum outputs established for this operator"); + + return output_count; + } /* addOutput */ + + public Connector getInput(int i) throws ConnectionException { + if ((i < 0) || (i > 1)) + throw new ConnectionException("ERROR: Bad input index for operator"); + else if (i == 0) { + if (left_input == null) + throw new ConnectionException("ERROR: No left input for operator"); + else + return left_input; + } else // i == 1 + if (right_input == null) + throw new ConnectionException("ERROR: No right input for operator"); + + return right_input; + } /* getInput */ + + public Connector getOutput(int i) throws ConnectionException { + if ((i >= 0) && (i < output_count)) + return output[i]; + else + throw new ConnectionException("ERROR: Bad output index for operator"); + } /* getOutput */ + + public void removeInput(int i) throws ConnectionException { + if ((i < 0) || (i > 1)) + throw new ConnectionException("ERROR: Bad input index for operator"); + else if (i == 0) { + if (left_input == null) + throw new ConnectionException("ERROR: No left input for operator"); + else + left_input = null; + } else if (i == 1) { + if (right_input == null) + throw new ConnectionException("ERROR: No right input for operator"); + else + right_input = null; + } + } /* removeInput */ + + public void removeOutput(int i) throws ConnectionException { + if ((i < 0) || (i > output_count)) + throw new ConnectionException("ERROR: Bad output index for operator"); + else { + output[i] = output[output_count-1]; + --output_count; + } + } /* removeOutput */ + + public int getOutputCount() throws ConnectionException { + return output_count; + } /* getOutputCount */ + + public int getInputCount() throws ConnectionException { + if (left_input == null) + return 0; + else if (right_input == null) + return 1; + else + return 2; + } /* getInputCount */ + + public void wakeup(long t) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to wake up operator"); + } /* wakeup */ + + public boolean inBounds() { + if (canvas.contains(anchor.x,anchor.y) && + canvas.contains(anchor.x + DIAMETER, anchor.y + DIAMETER)) + return true; + else + return false; + } /* inBounds */ + +}
\ No newline at end of file diff --git a/java/EAC/Primitive.java b/java/EAC/Primitive.java new file mode 100644 index 00000000000..a0532a9731b --- /dev/null +++ b/java/EAC/Primitive.java @@ -0,0 +1,121 @@ +/** + * Title: Primitive + * Description: An abstract class for Event Analysis Configurator graphical + * primitives + */ +package EAC; +import java.awt.*; +import java.io.*; + +public abstract class Primitive { + + // maximum number of outputs from any primitive + public final int MAX_OUTPUTS = 8; + + // maximum number of inputs to a sink + public final int MAX_INPUTS = 8; + + // where the primitive will be drawn + protected EACPanel canvas; + + // anchor point of the graphical shape + protected Point anchor; + + // associated label + protected EACLabel label; + + public Primitive(EACPanel p) { + canvas = p; + } /* constructor */ + + public void setAnchor(Point p) { + anchor = p; + } /* setAnchor */ + + public Point getAnchor() { + return anchor; + } /* getAnchor */ + + public void setLabel(EACLabel l) { + label = l; + } /* setLabel */ + + public EACLabel getLabel() { + return label; + } /* getLabel */ + + public void restart() { + // no-op for most primitives + // overload as needed + } /* restart */ + + public void specialDraw() { + // no-op for some primitives + // overload as needed + } /* specialDraw */ + + public void specialUndraw() { + // no-op for some primitives + // overload as needed + } /* specialUndraw */ + + public void reconnect() { + // no-op for some primitives + // overload as needed + } /* reconnect */ + + public void selectedDraw() { + final int d = 4; // dimension of hotspot + Graphics g = canvas.getGraphics(); + + g.setColor(java.awt.Color.darkGray); + g.drawRect(upperLeft().x - (d/2),upperLeft().y - (d/2), d, d); + g.drawRect(lowerLeft().x - (d/2),lowerLeft().y - (d/2), d, d); + g.drawRect(upperRight().x - (d/2),upperRight().y - (d/2), d, d); + g.drawRect(lowerRight().x - (d/2),lowerRight().y - (d/2), d, d); + } /* selectedDraw */ + + // establish the top center point of the graphical shape + public abstract void setTop(Point p); + + public abstract Point getTop(); + + public abstract boolean inBounds(); + + public abstract int addInput(Connector c) throws ConnectionException; + + public abstract int addOutput(Connector c) throws ConnectionException; + + public abstract Connector getInput(int i) throws ConnectionException; + + public abstract Connector getOutput(int i) throws ConnectionException; + + public abstract void removeInput(int i) throws ConnectionException; + + public abstract void removeOutput(int i) throws ConnectionException; + + public abstract int getInputCount() throws ConnectionException; + + public abstract int getOutputCount() throws ConnectionException; + + public abstract void event(Source s) throws ConnectionException; + + public abstract void wakeup(long t) throws ConnectionException; + + public abstract void draw() throws BoundsException; + + public abstract void write(File f) throws java.io.IOException; + + public abstract void read(File f) throws java.io.IOException; + + public abstract boolean contains(Point p); + + public abstract Point upperLeft(); + + public abstract Point lowerRight(); + + public abstract Point upperRight(); + + public abstract Point lowerLeft(); + +}
\ No newline at end of file diff --git a/java/EAC/Queue.java b/java/EAC/Queue.java new file mode 100644 index 00000000000..20c4483a17a --- /dev/null +++ b/java/EAC/Queue.java @@ -0,0 +1,94 @@ +/** + * Title: Queue + * Description: The primary event queue for the Event Analysis Configurator + */ +package EAC; + +public class Queue { + + private class Node { + + public Primitive primitive; + public long time; + public Node next; + + public Node(Primitive p, long t, Node n) { + primitive = p; + time = t; + next = n; + } /* constructor */ + + } /* Node */ + + private Node head; + + private int count; + + public Queue() { + count = 0; + } /* constructor */ + + public boolean empty() { + return (count == 0); + } /* empty */ + + public void clear() { + while (!empty()) + try { + dequeue(); + } catch (EmptyQueueException eqe) { + // can't happen + } + } /* clear */ + + public void enqueue(Primitive p, long t) { + if (head == null) { + head = new Node(p,t,null); + count = 1; + } else { // non-empty + if ((head.time == t) && (head.primitive == p)) + return; // no duplicates + else if (head.time >= t) { // need new head + Node temp = new Node(p,t,head); + head = temp; + } else { // find insertion point + Node ptr = head; + + while (ptr.next != null) + if (ptr.next.time < t) + ptr = ptr.next; + else + break; + + if (ptr.next == null) + ptr.next = new Node(p,t,null); + else if ((ptr.next.time == t) && (ptr.next.primitive == p)) + return; // no duplicates + else { + Node temp = new Node(p,t,ptr.next); + ptr.next = temp; + } + } + + count++; + } /* else */ + } /* enqueue */ + + public Primitive dequeue () throws EmptyQueueException { + if (count == 0) + throw new EmptyQueueException("ERROR: dequeue called when queue empty"); + + Primitive temp = head.primitive; + head = head.next; + --count; + return temp; + } /* dequeue */ + + public long frontTime () throws EmptyQueueException { + if (count == 0) + throw new EmptyQueueException("ERROR: frontTime called when queue empty"); + + return head.time; + } /* frontTime */ + +}
\ No newline at end of file diff --git a/java/EAC/README b/java/EAC/README new file mode 100644 index 00000000000..91773ab16bd --- /dev/null +++ b/java/EAC/README @@ -0,0 +1,6 @@ +This directory contains the source code for the Event Analysis Configurator (EAC). +The EAC was built as a final project for an Advanced User Interface (CS 501) course, +taught by Dr. Kimura in the fall of 2000. + +There are also two MS-Word documents which were written as part of the project. +Hopefully these will explain what the EAC is, what it does, and how it works. diff --git a/java/EAC/ResourcePool.java b/java/EAC/ResourcePool.java new file mode 100644 index 00000000000..c2200baa2fc --- /dev/null +++ b/java/EAC/ResourcePool.java @@ -0,0 +1,46 @@ +/** + * Title: ResourcePool + * Description: An abstraction of a collection of resources that can be + * reserved and released by real-time components + */ +package EAC; + +public class ResourcePool { + + // percentage of resources reserved + protected int reserved; + + public ResourcePool() + { + reserved = 0; + } /* default constructor */ + + public ResourcePool(int r) { + reserved = r; + } /* constructor */ + + public int usage() { + return reserved; + } /* usage */ + + public boolean reserve(int r) { + if (reserved + r > 100) + return false; + else { + //System.out.println("Reservation ok: " + java.lang.Integer.toString(r)); + reserved += r; + return true; + } /* else */ + } /* reserve */ + + public boolean release(int r) { + if (reserved - r < 0) + return false; + else { + //System.out.println("Release ok: " + java.lang.Integer.toString(r)); + reserved -= r; + return true; + } /* else */ + } /* release */ + +}
\ No newline at end of file diff --git a/java/EAC/Rubberband.java b/java/EAC/Rubberband.java new file mode 100644 index 00000000000..b5fcf7e60a0 --- /dev/null +++ b/java/EAC/Rubberband.java @@ -0,0 +1,103 @@ +/** + * A abstract base class for rubberbands.<p> + * + * Rubberbands do their rubberbanding inside of a Component, + * which must be specified at construction time.<p> + * + * Subclasses are responsible for implementing + * <em>void drawLast(Graphics g)</em> and + * <em>void drawNext(Graphics g)</em>. + * + * drawLast() draws the appropriate geometric shape at the last + * rubberband location, while drawNext() draws the appropriate + * geometric shape at the next rubberband location. All of the + * underlying support for rubberbanding is taken care of here, + * including handling XOR mode setting; extensions of Rubberband + * need not concern themselves with anything but drawing the + * last and next geometric shapes.<p> + * + * @version 1.00, 12/27/95 + * @author David Geary + */ +package EAC; +import java.awt.*; + +abstract public class Rubberband { + protected Point anchor = new Point(0,0); + protected Point stretched = new Point(0,0); + protected Point last = new Point(0,0); + protected Point end = new Point(0,0); + + private Component component; + private boolean firstStretch = true; + + abstract public void drawLast(Graphics g); + abstract public void drawNext(Graphics g); + + public Rubberband(Component component) { + this.component = component; + } + + public Point getAnchor () { return anchor; } + public Point getStretched() { return stretched; } + public Point getLast () { return last; } + public Point getEnd () { return end; } + public void setAnchor(Point p) { anchor = p; } + public void setEnd(Point p) { end = p; } + + public void anchor(Point p) { + firstStretch = true; + anchor.x = p.x; + anchor.y = p.y; + + stretched.x = last.x = anchor.x; + stretched.y = last.y = anchor.y; + } + + public void stretch(Point p) { + last.x = stretched.x; + last.y = stretched.y; + stretched.x = p.x; + stretched.y = p.y; + + Graphics g = component.getGraphics(); + if (g != null) { + g.setXORMode(component.getBackground()); + + if (firstStretch == true) + firstStretch = false; + else + drawLast(g); + + drawNext(g); + } + } + + public void end(Point p) { + last.x = end.x = p.x; + last.y = end.y = p.y; + + Graphics g = component.getGraphics(); + if(g != null) { + g.setXORMode(component.getBackground()); + drawLast(g); + } + } + + public Rectangle bounds() { + return new Rectangle(stretched.x < anchor.x ? + stretched.x : anchor.x, + stretched.y < anchor.y ? + stretched.y : anchor.y, + Math.abs(stretched.x - anchor.x), + Math.abs(stretched.y - anchor.y)); + } + + public Rectangle lastBounds() { + return new Rectangle( + last.x < anchor.x ? last.x : anchor.x, + last.y < anchor.y ? last.y : anchor.y, + Math.abs(last.x - anchor.x), + Math.abs(last.y - anchor.y)); + } +} diff --git a/java/EAC/RubberbandLine.java b/java/EAC/RubberbandLine.java new file mode 100644 index 00000000000..8a4ebfd2230 --- /dev/null +++ b/java/EAC/RubberbandLine.java @@ -0,0 +1,28 @@ +/** + * Title: RubberbandLine + * Description: A line subclass of Rubberband + */ +package EAC; +import java.awt.*; + +public class RubberbandLine extends Rubberband { + + public RubberbandLine(EACPanel p) { + super(p); + } /* RubberbandLine constructor */ + + public void drawNext(Graphics g) { + g.drawLine(getAnchor().x, + getAnchor().y, + getStretched().x, + getStretched().y); + } /* drawNext */ + + public void drawLast(Graphics g) { + g.drawLine(getAnchor().x, + getAnchor().y, + getLast().x, + getLast().y); + } /* drawLast */ + +} /* RubberbandLine */ diff --git a/java/EAC/Sink.java b/java/EAC/Sink.java new file mode 100644 index 00000000000..f4f8d02d0fe --- /dev/null +++ b/java/EAC/Sink.java @@ -0,0 +1,231 @@ +/** + * Title: Sink + * Description: An event sink for the Event Analysis Configurator + */ +package EAC; +import java.awt.*; + +public class Sink extends Primitive { + + // triangle dimensions + protected final int WIDTH = 20; + protected final int HEIGHT = 35; + + // lower left and lower right corner points + // inherited anchor attribute holds the top point + protected Point p2, + p3; + + // inputs + protected Connector input[] = new Connector[MAX_INPUTS]; + protected int input_count; + + // for help with dragging this Sink + Point old_anchor; + + public Sink(EACPanel p) { + super(p); + } /* constructor */ + + public void draw() throws BoundsException { + int x[] = new int[3], + y[] = new int[3]; + + if (inBounds()) { + Graphics g = canvas.getGraphics(); + + g.drawLine(anchor.x,anchor.y,p2.x,p2.y); + g.drawLine(p2.x,p2.y,p3.x,p3.y); + g.drawLine(p3.x,p3.y,anchor.x,anchor.y); + + /* Make it black */ + x[0] = anchor.x; + x[1] = p2.x; + x[2] = p3.x; + + y[0] = anchor.y; + y[1] = p2.y; + y[2] = p3.y; + + g.fillPolygon(x,y,3); + } else + throw new BoundsException("ERROR: Attempted to place Sink partially out of bounds"); + } /* draw */ + + public void selectedDraw() { + old_anchor = anchor; + super.selectedDraw(); + } /* selectedDraw */ + + public void specialDraw() { + int x[] = new int[3], + y[] = new int[3]; + + Graphics g = canvas.getGraphics(); + + g.setXORMode(canvas.getBackground()); + g.drawLine(anchor.x,anchor.y,p2.x,p2.y); + g.drawLine(p2.x,p2.y,p3.x,p3.y); + g.drawLine(p3.x,p3.y,anchor.x,anchor.y); + + /* Make it black */ + x[0] = anchor.x; + x[1] = p2.x; + x[2] = p3.x; + + y[0] = anchor.y; + y[1] = p2.y; + y[2] = p3.y; + + g.fillPolygon(x,y,3); + } /* specialDraw */ + + public void specialUndraw() { + int x[] = new int[3], + y[] = new int[3]; + + Graphics g = canvas.getGraphics(); + + g.setColor(canvas.getBackground()); + g.setXORMode(canvas.getForeground()); + g.drawLine(anchor.x,anchor.y,p2.x,p2.y); + g.drawLine(p2.x,p2.y,p3.x,p3.y); + g.drawLine(p3.x,p3.y,anchor.x,anchor.y); + + /* Make it black */ + x[0] = anchor.x; + x[1] = p2.x; + x[2] = p3.x; + + y[0] = anchor.y; + y[1] = p2.y; + y[2] = p3.y; + + g.fillPolygon(x,y,3); + } /* specialUndraw */ + + public void reconnect() { + int i; + + for (i = 0; i < input_count; i++) + input[i].setEndpoint(new Point(input[i].upperRight().x + anchor.x - old_anchor.x, + input[i].upperRight().y + anchor.y - old_anchor.y)); + } /* reconnect */ + + public boolean contains(Point p) { + if ((p.x >= p2.x) && + (p.x <= p3.x) && + (p.y >= anchor.y) && + (p.y <= anchor.y + HEIGHT)) + return true; + else + return false; + } /* contains */ + + public Point upperLeft() { + return new Point(p2.x,anchor.y); + } /* upperLeft */ + + public Point lowerRight() { + return p3; + } /* lowerRight */ + + public Point upperRight() { + return new Point(p3.x,anchor.y); + } /* upperRight */ + + public Point lowerLeft() { + return p2; + } /* lowerLeft */ + + public void setTop(Point p) { + anchor = p; + p2 = bottomLeft(); + p3 = bottomRight(); + } /* setTop */ + + public Point getTop() { + return anchor; + } /* getTop */ + + public boolean inBounds() { + if (canvas.contains(bottomLeft()) && + canvas.contains(bottomRight())) + return true; + else + return false; + } /* inBounds */ + + private Point bottomLeft() { + return new Point(anchor.x - WIDTH, anchor.y + HEIGHT); + } /* bottomLeft */ + + private Point bottomRight() { + return new Point(anchor.x + WIDTH, anchor.y + HEIGHT); + } /* bottomRight */ + + public void write(File f) throws java.io.IOException { + f.writeInt(f.SINK); + f.writeInt(anchor.x); + f.writeInt(anchor.y); + } /* write */ + + public void read(File f) throws java.io.IOException { + anchor = new Point(); + anchor.x = f.readInt(); + anchor.y = f.readInt(); + p2 = bottomLeft(); + p3 = bottomRight(); + } /* read */ + + public int addInput(Connector c) throws ConnectionException { + if (input_count == MAX_INPUTS) + throw new ConnectionException("ERROR: Maximum inputs established for sink"); + else + input[input_count++] = c; + + return input_count; + } /* addInput */ + + public int addOutput(Connector c) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to add output to sink"); + } /* addOutput */ + + public Connector getInput(int i) throws ConnectionException { + if ((i < 0) || (i >= input_count)) + throw new ConnectionException("ERROR: Bad input index for sink"); + else + return input[i]; + } /* getInput */ + + public Connector getOutput(int i) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to retrieve output from source"); + } /* getOutput */ + + public void removeOutput(int i) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to remove output from source"); + } /* removeOutput */ + + public void removeInput(int i) throws ConnectionException { + if ((i >= 0) && (i < input_count)) { + input[i] = input[input_count-1]; + --input_count; + } else + throw new ConnectionException("ERROR: Bad input index for sink"); + } /* removeInput */ + + public int getInputCount() throws ConnectionException { + return input_count; + } /* getInputCount */ + + public int getOutputCount() throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to retrieve output count from sink"); + } /* getOutputCount */ + + public void event(Source s) { + } /* event */ + + public void wakeup(long t) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to wake up sink"); + } /* wakeup */ +}
\ No newline at end of file diff --git a/java/EAC/Source.java b/java/EAC/Source.java new file mode 100644 index 00000000000..d8b50ee224f --- /dev/null +++ b/java/EAC/Source.java @@ -0,0 +1,341 @@ +/** + * Title: Source + * Description: An event source for the Event Analysis Configurator + */ +package EAC; +import java.awt.*; + +public class Source extends Primitive { + + // Font for text + protected Font text_font = new EACFont().getFont(); + + // triangle dimensions + protected final int WIDTH = 20; + protected final int HEIGHT = 35; + + // lower left and lower right corner points + // inherited anchor attribute holds the top point + protected Point p2, + p3; + + // period at which events will be generated + protected int period; + + // where the Source was anchored prior to a move + protected Point old_anchor; + + // where events will be pushed + protected Connector output[] = new Connector[MAX_OUTPUTS]; + protected int output_count; + + // Is this Source currently selected for dragging? + protected boolean selected = false; + + // Black-on-white (normal) or white-on-black (reversed)? + protected boolean reverse_color = false; + + // configuration to which the Source belongs + Configuration config; + + public Source(EACPanel p, Configuration c) { + super(p); + config = c; + output_count = 0; + period = 0; + } /* constructor */ + + private void drawTriangle(Graphics g) { + g.drawLine(anchor.x,anchor.y,p2.x,p2.y); + g.drawLine(p2.x,p2.y,p3.x,p3.y); + g.drawLine(p3.x,p3.y,anchor.x,anchor.y); + } /* drawTriangle */ + + public void draw() throws BoundsException { + int x[] = new int[3], + y[] = new int[3]; + + if (selected) + selected = false; + else if (inBounds()) { + Graphics g = canvas.getGraphics(); + Color bg, + fg; + + x[0] = anchor.x; + x[1] = p2.x; + x[2] = p3.x; + + y[0] = anchor.y; + y[1] = p2.y; + y[2] = p3.y; + + if (reverse_color) { + bg = Color.black; + fg = Color.white; + } else { + bg = Color.white; + fg = Color.black; + } + + g.setColor(bg); // for interior + g.fillPolygon(x,y,3); + + g.setColor(Color.black); // triangle itself is always black + drawTriangle(g); + + g.setColor(fg); // for text + + // print period + if (period > 0) { + g.setFont(text_font); + g.drawString(java.lang.String.valueOf(period), + anchor.x - (3 * java.lang.String.valueOf(period).length()), + anchor.y + 28); + } + } else + throw new BoundsException("ERROR: Attempted to place source partially out of bounds"); + } /* draw */ + + public void selectedDraw() { + Graphics g = canvas.getGraphics(); + int x[] = new int[3], + y[] = new int[3]; + + old_anchor = anchor; + x[0] = anchor.x; + x[1] = p2.x; + x[2] = p3.x; + + y[0] = anchor.y; + y[1] = p2.y; + y[2] = p3.y; + + //drawTriangle(); + g.setColor(canvas.getBackground()); + g.fillPolygon(x,y,3); + + // this will preclude drawing this Source for one repaint() call + selected = true; + + super.selectedDraw(); + } /* selectedDraw */ + + public void specialDraw() { + Graphics g = canvas.getGraphics(); + + g.setXORMode(canvas.getBackground()); + drawTriangle(g); + } /* specialDraw */ + + public void specialUndraw() { + Graphics g = canvas.getGraphics(); + + g.setColor(canvas.getBackground()); + g.setXORMode(canvas.getForeground()); + drawTriangle(g); + } /* specialUndraw */ + + public void reverseColor() { + reverse_color = true; + } /* reverseColor */ + + public void normalColor() { + reverse_color = false; + } /* normalColor */ + + public void reconnect() { + int i; + + for (i = 0; i < output_count; i++) + output[i].setAnchor(new Point(output[i].getAnchor().x + anchor.x - old_anchor.x, + output[i].getAnchor().y + anchor.y - old_anchor.y)); + + // move label anchor + label.setAnchor(new Point(label.getAnchor().x + anchor.x - old_anchor.x, + label.getAnchor().y + anchor.y - old_anchor.y)); + } /* reconnect */ + + public boolean contains(Point p) { + if ((p.x >= p2.x) && + (p.x <= p3.x) && + (p.y >= anchor.y) && + (p.y <= anchor.y + HEIGHT)) + return true; + else + return false; + } /* contains */ + + public Point upperLeft() { + return new Point(p2.x,anchor.y); + } /* upperLeft */ + + public Point lowerRight() { + return p3; + } /* lowerRight */ + + public Point upperRight() { + return new Point(p3.x,anchor.y); + } /* upperRight */ + + public Point lowerLeft() { + return p2; + } /* lowerLeft */ + + public void setTop(Point p) { + anchor = p; + p2 = bottomLeft(); + p3 = bottomRight(); + } /* setTop */ + + public Point getTop() { + return anchor; + } /* getTop */ + + public void setPeriod(int p) throws NumberFormatException { + if (p > 0) { + period = p; + config.eventEnqueue(this,period); // Enqueue first wakeup time + } + else + throw new NumberFormatException(); + } /* setPeriod */ + + public int getPeriod() { + return period; + } /* getPeriod */ + + public void restart() { + config.eventEnqueue(this,period); + reverse_color = false; + selected = false; + } /* restart */ + + public int addOutput(Connector c) throws ConnectionException { + if (output_count == MAX_OUTPUTS) + throw new ConnectionException("ERROR: Maximum outputs established for source"); + else + output[output_count++] = c; + + return output_count; + } /* addOutput */ + + public int addInput(Connector c) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to add input to source"); + } /* addInput */ + + public Connector getOutput(int i) throws ConnectionException { + if ((i < 0) || (i >= output_count)) + throw new ConnectionException("ERROR: Bad output index for source"); + else + return output[i]; + } /* getOutput */ + + public Connector getInput(int i) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to retrieve input from source"); + } /* getInput */ + + public void removeInput(int i) throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to remove input from source"); + } /* removeInput */ + + public void removeOutput(int i) throws ConnectionException { + if ((i >= 0) && (i < output_count)) { + output[i] = output[output_count-1]; + --output_count; + } else + throw new ConnectionException("ERROR: Bad output index for source"); + } /* removeOutput */ + + public int getOutputCount() throws ConnectionException { + return output_count; + } /* getOutputCount */ + + public int getInputCount() throws ConnectionException { + throw new ConnectionException("ERROR: Attempted to retrieve input count from source"); + } /* getInputCount */ + + public void event(Source s) throws ConnectionException { + throw new ConnectionException("Internal error: event() called on source"); + } /* event */ + + public void wakeup(long t) throws ConnectionException { + int i; + + //System.out.println("Source wakeup at: " + java.lang.Long.toString(t)); + config.eventEnqueue(this,t + period); // enqueue next wakeup time + + // send an event to all outputs + for (i = 0; i < output_count; i++) + output[i].event(this); + } /* wakeup */ + + public boolean inBounds() { + if (canvas.contains(bottomLeft()) && + canvas.contains(bottomRight()) && + canvas.contains(anchor)) + return true; + else + return false; + } /* inBounds */ + + private Point bottomLeft() { + return new Point(anchor.x - WIDTH, anchor.y + HEIGHT); + } /* bottomLeft */ + + private Point bottomRight() { + return new Point(anchor.x + WIDTH, anchor.y + HEIGHT); + } /* bottomRight */ + + public void write(File f) throws java.io.IOException { + char temp[]; // for reading label + int i, n; + + f.writeInt(f.SOURCE); + f.writeInt(anchor.x); + f.writeInt(anchor.y); + f.writeInt(period); + + // Write out the associated label + n = label.getText().length(); + f.writeInt(n); // text length + temp = new char[n]; + temp = label.getText().toCharArray(); + + for (i = 0; i < n; i++) + f.writeChar(temp[i]); + f.writeInt(label.getAnchor().x); // label position + f.writeInt(label.getAnchor().y); + } /* write */ + + public void read(File f) throws java.io.IOException { + char temp[]; // for reading label + int i, n; + int label_x, label_y; + + anchor = new Point(); + anchor.x = f.readInt(); + anchor.y = f.readInt(); + period = f.readInt(); + config.eventEnqueue(this,period); // Enqueue first event + p2 = bottomLeft(); + p3 = bottomRight(); + + // get label info + n = f.readInt(); // text length + label = new EACLabel(canvas,n); + temp = new char[n]; + for (i = 0; i < n; i++) + temp[i] = f.readChar(); + label.setText(java.lang.String.valueOf(temp)); + label_x = f.readInt(); + label_y = f.readInt(); + label.setAnchor(new Point(label_x,label_y)); + label.setLabelee(this); + try { + config.addPrimitive(label); + } catch (TooManyPrimitivesException tmpe) { + // have faith :-) + } + } /* read */ +}
\ No newline at end of file diff --git a/java/EAC/System Manual.doc b/java/EAC/System Manual.doc Binary files differnew file mode 100644 index 00000000000..89d76eba720 --- /dev/null +++ b/java/EAC/System Manual.doc diff --git a/java/EAC/TooManyPrimitivesException.java b/java/EAC/TooManyPrimitivesException.java new file mode 100644 index 00000000000..d9cb8efa733 --- /dev/null +++ b/java/EAC/TooManyPrimitivesException.java @@ -0,0 +1,13 @@ +/** + * Title: TooManyPrimitivesException + * Description: An exception class for when an attempt is made to add a + * primitives when the maximum number have already been added + */ +package EAC; + +public class TooManyPrimitivesException extends Exception { + + public TooManyPrimitivesException(String msg) { + super(msg); + } +}
\ No newline at end of file diff --git a/java/EAC/Union.java b/java/EAC/Union.java new file mode 100644 index 00000000000..107390dc560 --- /dev/null +++ b/java/EAC/Union.java @@ -0,0 +1,56 @@ +/** + * Title: Union + * Description: A binary union operator class for the Event Analysis + * Configurator. Acts as a sort of multiplexor, combining two + * event streams into one. + */ +package EAC; +import java.awt.*; + +public class Union extends Operator { + + public Union(EACPanel p) { + super(p); + } /* constructor */ + + public void draw() throws BoundsException { + // the union symbol + final char uSymbol = 'U'; + + // subtle adjustments to position symbol within circle + final int xTweak = 4; + final int yTweak = -4; + + char symbol[] = new char[1]; + + Graphics g = canvas.getGraphics(); + + super.draw(); + symbol[0] = (char) uSymbol; + g.drawChars(symbol,0,1, + anchor.x + (int) (DIAMETER / 2) - xTweak, + anchor.y + (int) (DIAMETER / 2) - yTweak); + } /* draw */ + + public void event(Source s) throws ConnectionException { + int i; + + //System.out.println("Union event"); + + // send an event to all outputs + for (i = 0; i < output_count; i++) + output[i].event(s); + } /* event */ + + public void write(File f) throws java.io.IOException { + f.writeInt(f.UNION); + f.writeInt(anchor.x); + f.writeInt(anchor.y); + } /* write */ + + public void read(File f) throws java.io.IOException { + anchor = new Point(); + anchor.x = f.readInt(); + anchor.y = f.readInt(); + } /* read */ +}
\ No newline at end of file diff --git a/java/EAC/User Manual.doc b/java/EAC/User Manual.doc Binary files differnew file mode 100644 index 00000000000..5f17fc98f37 --- /dev/null +++ b/java/EAC/User Manual.doc |