/* Copyright (C) Paul Falstad and Iain Sharp This file is part of CircuitJS1. CircuitJS1 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. CircuitJS1 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with CircuitJS1. If not, see <http://www.gnu.org/licenses/>. */ package com.lushprojects.circuitjs1.client; //import java.awt.*; //import java.util.StringTokenizer; import com.google.gwt.canvas.dom.client.TextMetrics; abstract class ChipElm extends CircuitElm { int csize, cspc, cspc2; int bits; final int FLAG_SMALL = 1; final int FLAG_FLIP_X = 1024; final int FLAG_FLIP_Y = 2048; public ChipElm(int xx, int yy) { super(xx, yy); if (needsBits()) bits = (this instanceof DecadeElm) ? 10 : 4; noDiagonal = true; setupPins(); setSize(sim.smallGridCheckItem.getState() ? 1 : 2); } public ChipElm(int xa, int ya, int xb, int yb, int f, StringTokenizer st) { super(xa, ya, xb, yb, f); if (needsBits()) bits = new Integer(st.nextToken()).intValue(); noDiagonal = true; setupPins(); setSize((f & FLAG_SMALL) != 0 ? 1 : 2); int i; for (i = 0; i != getPostCount(); i++) { if (pins == null) volts[i] = new Double(st.nextToken()).doubleValue(); else if (pins[i].state) { volts[i] = new Double(st.nextToken()).doubleValue(); pins[i].value = volts[i] > 2.5; } } } boolean needsBits() { return false; } void setSize(int s) { csize = s; cspc = 8*s; cspc2 = cspc*2; flags &= ~FLAG_SMALL; flags |= (s == 1) ? FLAG_SMALL : 0; } abstract void setupPins(); void draw(Graphics g) { drawChip(g); } void drawChip(Graphics g) { int i; Font oldfont = g.getFont(); Font f = new Font("SansSerif", 0, 10*csize); g.setFont(f); // FontMetrics fm = g.getFontMetrics(); for (i = 0; i != getPostCount(); i++) { Pin p = pins[i]; setVoltageColor(g, volts[i]); Point a = p.post; Point b = p.stub; drawThickLine(g, a, b); p.curcount = updateDotCount(p.current, p.curcount); drawDots(g, b, a, p.curcount); if (p.bubble) { g.setColor(sim.printableCheckItem.getState() ? Color.white : Color.black); drawThickCircle(g, p.bubbleX, p.bubbleY, 1); g.setColor(lightGrayColor); drawThickCircle(g, p.bubbleX, p.bubbleY, 3); } g.setColor(whiteColor); // int sw = fm.stringWidth(p.text); int sw=(int)g.context.measureText(p.text).getWidth(); int asc=(int)g.currentFontSize; g.drawString(p.text, p.textloc.x-sw/2, p.textloc.y+asc/2); if (p.lineOver) { int ya = p.textloc.y-asc/2; g.drawLine(p.textloc.x-sw/2, ya, p.textloc.x+sw/2, ya); } } g.setColor(needsHighlight() ? selectColor : lightGrayColor); drawThickPolygon(g, rectPointsX, rectPointsY, 4); if (clockPointsX != null) g.drawPolyline(clockPointsX, clockPointsY, 3); drawPosts(g); g.setFont(oldfont); } int rectPointsX[], rectPointsY[]; int clockPointsX[], clockPointsY[]; Pin pins[]; int sizeX, sizeY; boolean lastClock; void drag(int xx, int yy) { yy = sim.snapGrid(yy); if (xx < x) { xx = x; yy = y; } else { y = y2 = yy; x2 = sim.snapGrid(xx); } setPoints(); } void setPoints() { clockPointsX = null; if (x2-x > sizeX*cspc2 && this == sim.dragElm) setSize(2); int hs = cspc; int x0 = x+cspc2; int y0 = y; int xr = x0-cspc; int yr = y0-cspc; int xs = sizeX*cspc2; int ys = sizeY*cspc2; rectPointsX = new int[] { xr, xr+xs, xr+xs, xr }; rectPointsY = new int[] { yr, yr, yr+ys, yr+ys }; setBbox(xr, yr, rectPointsX[2], rectPointsY[2]); int i; for (i = 0; i != getPostCount(); i++) { Pin p = pins[i]; switch (p.side) { case SIDE_N: p.setPoint(x0, y0, 1, 0, 0, -1, 0, 0); break; case SIDE_S: p.setPoint(x0, y0, 1, 0, 0, 1, 0, ys-cspc2);break; case SIDE_W: p.setPoint(x0, y0, 0, 1, -1, 0, 0, 0); break; case SIDE_E: p.setPoint(x0, y0, 0, 1, 1, 0, xs-cspc2, 0);break; } } } Point getPost(int n) { return pins[n].post; } abstract int getVoltageSourceCount(); // output count void setVoltageSource(int j, int vs) { int i; for (i = 0; i != getPostCount(); i++) { Pin p = pins[i]; if (p.output && j-- == 0) { p.voltSource = vs; return; } } System.out.println("setVoltageSource failed for " + this); } void stamp() { int i; for (i = 0; i != getPostCount(); i++) { Pin p = pins[i]; if (p.output) sim.stampVoltageSource(0, nodes[i], p.voltSource); } } void execute() {} void doStep() { int i; for (i = 0; i != getPostCount(); i++) { Pin p = pins[i]; if (!p.output) p.value = volts[i] > 2.5; } execute(); for (i = 0; i != getPostCount(); i++) { Pin p = pins[i]; if (p.output) sim.updateVoltageSource(0, nodes[i], p.voltSource, p.value ? 5 : 0); } } void reset() { int i; for (i = 0; i != getPostCount(); i++) { pins[i].value = false; pins[i].curcount = 0; volts[i] = 0; } lastClock = false; } String dump() { String s = super.dump(); if (needsBits()) s += " " + bits; int i; for (i = 0; i != getPostCount(); i++) { if (pins[i].state) s += " " + volts[i]; } return s; } void getInfo(String arr[]) { arr[0] = getChipName(); int i, a = 1; for (i = 0; i != getPostCount(); i++) { Pin p = pins[i]; if (arr[a] != null) arr[a] += "; "; else arr[a] = ""; String t = p.text; if (p.lineOver) t += '\''; if (p.clock) t = "Clk"; arr[a] += t + " = " + getVoltageText(volts[i]); if (i % 2 == 1) a++; } } void setCurrent(int x, double c) { int i; for (i = 0; i != getPostCount(); i++) if (pins[i].output && pins[i].voltSource == x) pins[i].current = c; } String getChipName() { return "chip"; } boolean getConnection(int n1, int n2) { return false; } boolean hasGroundConnection(int n1) { return pins[n1].output; } double getCurrentIntoPoint(int xa, int ya) { int i; for (i = 0; i != getPostCount(); i++) if (pins[i].post.x == xa && pins[i].post.y == ya) return pins[i].current; return 0; } public EditInfo getEditInfo(int n) { if (n == 0) { EditInfo ei = new EditInfo("", 0, -1, -1); ei.checkbox = new Checkbox("Flip X", (flags & FLAG_FLIP_X) != 0); return ei; } if (n == 1) { EditInfo ei = new EditInfo("", 0, -1, -1); ei.checkbox = new Checkbox("Flip Y", (flags & FLAG_FLIP_Y) != 0); return ei; } return null; } public void setEditValue(int n, EditInfo ei) { if (n == 0) { if (ei.checkbox.getState()) flags |= FLAG_FLIP_X; else flags &= ~FLAG_FLIP_X; setPoints(); } if (n == 1) { if (ei.checkbox.getState()) flags |= FLAG_FLIP_Y; else flags &= ~FLAG_FLIP_Y; setPoints(); } } final int SIDE_N = 0; final int SIDE_S = 1; final int SIDE_W = 2; final int SIDE_E = 3; class Pin { Pin(int p, int s, String t) { pos = p; side = s; text = t; } Point post, stub; Point textloc; int pos, side, voltSource, bubbleX, bubbleY; String text; boolean lineOver, bubble, clock, output, value, state; double curcount, current; void setPoint(int px, int py, int dx, int dy, int dax, int day, int sx, int sy) { if ((flags & FLAG_FLIP_X) != 0) { dx = -dx; dax = -dax; px += cspc2*(sizeX-1); sx = -sx; } if ((flags & FLAG_FLIP_Y) != 0) { dy = -dy; day = -day; py += cspc2*(sizeY-1); sy = -sy; } int xa = px+cspc2*dx*pos+sx; int ya = py+cspc2*dy*pos+sy; post = new Point(xa+dax*cspc2, ya+day*cspc2); stub = new Point(xa+dax*cspc , ya+day*cspc ); textloc = new Point(xa , ya ); if (bubble) { bubbleX = xa+dax*10*csize; bubbleY = ya+day*10*csize; } if (clock) { clockPointsX = new int[3]; clockPointsY = new int[3]; clockPointsX[0] = xa+dax*cspc-dx*cspc/2; clockPointsY[0] = ya+day*cspc-dy*cspc/2; clockPointsX[1] = xa; clockPointsY[1] = ya; clockPointsX[2] = xa+dax*cspc+dx*cspc/2; clockPointsY[2] = ya+day*cspc+dy*cspc/2; } } } }