/*******************************************************************************
* This file is part of logisim-evolution.
*
* logisim-evolution 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 3 of the License, or
* (at your option) any later version.
*
* logisim-evolution 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 logisim-evolution. If not, see <http://www.gnu.org/licenses/>.
*
* Original code by Carl Burch (http://www.cburch.com), 2011.
* Subsequent modifications by :
* + Haute École Spécialisée Bernoise
* http://www.bfh.ch
* + Haute École du paysage, d'ingénierie et d'architecture de Genève
* http://hepia.hesge.ch/
* + Haute École d'Ingénierie et de Gestion du Canton de Vaud
* http://www.heig-vd.ch/
* The project is currently maintained by :
* + REDS Institute - HEIG-VD
* Yverdon-les-Bains, Switzerland
* http://reds.heig-vd.ch
*******************************************************************************/
package com.cburch.logisim.circuit;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import com.cburch.logisim.comp.ComponentDrawContext;
import com.cburch.logisim.data.Direction;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.data.Value;
import com.cburch.logisim.util.GraphicsUtil;
class SplitterPainter {
static void drawLabels(ComponentDrawContext context,
SplitterAttributes attrs, Location origin) {
// compute labels
String[] ends = new String[attrs.fanout + 1];
int curEnd = -1;
int cur0 = 0;
for (int i = 0, n = attrs.bit_end.length; i <= n; i++) {
int bit = i == n ? -1 : attrs.bit_end[i];
if (bit != curEnd) {
int cur1 = i - 1;
String toAdd;
if (curEnd <= 0) {
toAdd = null;
} else if (cur0 == cur1) {
toAdd = "" + cur0;
} else {
toAdd = cur1 + "-" + cur0;
}
if (toAdd != null) {
String old = ends[curEnd];
if (old == null) {
ends[curEnd] = toAdd;
} else {
ends[curEnd] = old + "," + toAdd;
}
}
curEnd = bit;
cur0 = i;
}
}
Graphics g = context.getGraphics().create();
Font font = g.getFont();
g.setFont(font.deriveFont(7.0f));
SplitterParameters parms = attrs.getParameters();
int x = origin.getX() + parms.getEnd0X() + parms.getEndToSpineDeltaX();
int y = origin.getY() + parms.getEnd0Y() + parms.getEndToSpineDeltaY();
int dx = parms.getEndToEndDeltaX();
int dy = parms.getEndToEndDeltaY();
if (parms.getTextAngle() != 0) {
((Graphics2D) g).rotate(Math.PI / 2.0);
int t;
t = -x;
x = y;
y = t;
t = -dx;
dx = dy;
dy = t;
}
int halign = parms.getTextHorzAlign();
int valign = parms.getTextVertAlign();
x += (halign == GraphicsUtil.H_RIGHT ? -1 : 1) * (SPINE_WIDTH / 2 + 1);
y += valign == GraphicsUtil.V_TOP ? 0 : -3;
for (int i = 0, n = attrs.fanout; i < n; i++) {
String text = ends[i + 1];
if (text != null) {
GraphicsUtil.drawText(g, text, x, y, halign, valign);
}
x += dx;
y += dy;
}
g.dispose();
}
static void drawLegacy(ComponentDrawContext context,
SplitterAttributes attrs, Location origin) {
Graphics g = context.getGraphics();
CircuitState state = context.getCircuitState();
Direction facing = attrs.facing;
int fanout = attrs.fanout;
SplitterParameters parms = attrs.getParameters();
g.setColor(Color.BLACK);
int x0 = origin.getX();
int y0 = origin.getY();
int x1 = x0 + parms.getEnd0X();
int y1 = y0 + parms.getEnd0Y();
int dx = parms.getEndToEndDeltaX();
int dy = parms.getEndToEndDeltaY();
if (facing == Direction.NORTH || facing == Direction.SOUTH) {
int ySpine = (y0 + y1) / 2;
GraphicsUtil.switchToWidth(g, Wire.WIDTH);
g.drawLine(x0, y0, x0, ySpine);
int xi = x1;
int yi = y1;
for (int i = 1; i <= fanout; i++) {
if (context.getShowState()) {
g.setColor(state.getValue(Location.create(xi, yi))
.getColor());
}
int xSpine = xi + (xi == x0 ? 0 : (xi < x0 ? 10 : -10));
g.drawLine(xi, yi, xSpine, ySpine);
xi += dx;
yi += dy;
}
if (fanout > 3) {
GraphicsUtil.switchToWidth(g, SPINE_WIDTH);
g.setColor(Color.BLACK);
g.drawLine(x1 + dx, ySpine, x1 + (fanout - 2) * dx, ySpine);
} else {
g.setColor(Color.BLACK);
g.fillOval(x0 - SPINE_DOT / 2, ySpine - SPINE_DOT / 2,
SPINE_DOT, SPINE_DOT);
}
} else {
int xSpine = (x0 + x1) / 2;
GraphicsUtil.switchToWidth(g, Wire.WIDTH);
g.drawLine(x0, y0, xSpine, y0);
int xi = x1;
int yi = y1;
for (int i = 1; i <= fanout; i++) {
if (context.getShowState()) {
g.setColor(state.getValue(Location.create(xi, yi))
.getColor());
}
int ySpine = yi + (yi == y0 ? 0 : (yi < y0 ? 10 : -10));
g.drawLine(xi, yi, xSpine, ySpine);
xi += dx;
yi += dy;
}
if (fanout >= 3) {
GraphicsUtil.switchToWidth(g, SPINE_WIDTH);
g.setColor(Color.BLACK);
g.drawLine(xSpine, y1 + dy, xSpine, y1 + (fanout - 2) * dy);
} else {
g.setColor(Color.BLACK);
g.fillOval(xSpine - SPINE_DOT / 2, y0 - SPINE_DOT / 2,
SPINE_DOT, SPINE_DOT);
}
}
GraphicsUtil.switchToWidth(g, 1);
}
static void drawLines(ComponentDrawContext context,
SplitterAttributes attrs, Location origin) {
boolean showState = context.getShowState();
CircuitState state = showState ? context.getCircuitState() : null;
if (state == null)
showState = false;
SplitterParameters parms = attrs.getParameters();
int x0 = origin.getX();
int y0 = origin.getY();
int x = x0 + parms.getEnd0X();
int y = y0 + parms.getEnd0Y();
int dx = parms.getEndToEndDeltaX();
int dy = parms.getEndToEndDeltaY();
int dxEndSpine = parms.getEndToSpineDeltaX();
int dyEndSpine = parms.getEndToSpineDeltaY();
Graphics g = context.getGraphics();
Color oldColor = g.getColor();
GraphicsUtil.switchToWidth(g, Wire.WIDTH);
for (int i = 0, n = attrs.fanout; i < n; i++) {
if (showState) {
Value val = state.getValue(Location.create(x, y));
g.setColor(val.getColor());
}
g.drawLine(x, y, x + dxEndSpine, y + dyEndSpine);
x += dx;
y += dy;
}
GraphicsUtil.switchToWidth(g, SPINE_WIDTH);
g.setColor(oldColor);
int spine0x = x0 + parms.getSpine0X();
int spine0y = y0 + parms.getSpine0Y();
int spine1x = x0 + parms.getSpine1X();
int spine1y = y0 + parms.getSpine1Y();
if (spine0x == spine1x && spine0y == spine1y) { // centered
int fanout = attrs.fanout;
spine0x = x0 + parms.getEnd0X() + parms.getEndToSpineDeltaX();
spine0y = y0 + parms.getEnd0Y() + parms.getEndToSpineDeltaY();
spine1x = spine0x + (fanout - 1) * parms.getEndToEndDeltaX();
spine1y = spine0y + (fanout - 1) * parms.getEndToEndDeltaY();
if (parms.getEndToEndDeltaX() == 0) { // vertical spine
if (spine0y < spine1y) {
spine0y++;
spine1y--;
} else {
spine0y--;
spine1y++;
}
g.drawLine(x0 + parms.getSpine1X() / 4, y0, spine0x, y0);
} else {
if (spine0x < spine1x) {
spine0x++;
spine1x--;
} else {
spine0x--;
spine1x++;
}
g.drawLine(x0, y0 + parms.getSpine1Y() / 4, x0, spine0y);
}
if (fanout <= 1) { // spine is empty
int diam = SPINE_DOT;
g.fillOval(spine0x - diam / 2, spine0y - diam / 2, diam, diam);
} else {
g.drawLine(spine0x, spine0y, spine1x, spine1y);
}
} else {
int[] xSpine = { spine0x, spine1x, x0 + parms.getSpine1X() / 4 };
int[] ySpine = { spine0y, spine1y, y0 + parms.getSpine1Y() / 4 };
g.drawPolyline(xSpine, ySpine, 3);
}
}
private static final int SPINE_WIDTH = Wire.WIDTH + 2;
private static final int SPINE_DOT = Wire.WIDTH + 4;
}