@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
TruthTable table = model.getTruthTable();
int inputCount = table.getInputColumnCount();
Dimension sz = getSize();
String message = null;
if (output == null) {
message = Strings.get("karnaughNoOutputError");
} else if (inputCount > MAX_VARS) {
message = Strings.get("karnaughTooManyInputsError");
}
if (message != null) {
g.setFont(BODY_FONT);
GraphicsUtil.drawCenteredText(g, message, sz.width / 2, sz.height / 2);
return;
}
int left = computeMargin(sz.width, tableWidth);
int top = computeMargin(sz.height, tableHeight);
int x = left;
int y = top;
int rowVars = ROW_VARS[inputCount];
int colVars = COL_VARS[inputCount];
int rows = 1 << rowVars;
int cols = 1 << colVars;
g.setFont(HEAD_FONT);
FontMetrics headFm = g.getFontMetrics();
String rowHeader = header(0, rowVars);
String colHeader = header(rowVars, rowVars + colVars);
int xoffs = (tableWidth + headHeight + cellWidth - headFm.stringWidth(colHeader)) / 2;
g.drawString(colHeader, x + xoffs, y + headFm.getAscent());
int headerWidth = headFm.stringWidth(rowHeader);
if (headerWidth <= headHeight) {
int headX = x + (headHeight - headerWidth) / 2;
int headY = y + (tableHeight + headHeight + cellHeight + headFm.getAscent()) / 2;
g.drawString(rowHeader, headX, headY);
} else if (g instanceof Graphics2D){
Graphics2D g2 = (Graphics2D) g.create();
int yoffs = (tableHeight + headHeight + cellHeight + headerWidth) / 2;
int headX = x + headFm.getAscent();
int headY = y + yoffs;
g2.rotate(-Math.PI / 2.0);
g2.drawString(rowHeader, -headY, headX);
g2.dispose();
}
x += headHeight;
y += headHeight;
g.setFont(BODY_FONT);
FontMetrics fm = g.getFontMetrics();
int dy = (cellHeight + fm.getAscent()) / 2;
for (int i = 0; i < cols; i++) {
String label = label(i, cols);
g.drawString(label,
x + (i + 1) * cellWidth + (cellWidth - fm.stringWidth(label)) / 2,
y + dy);
}
for (int i = 0; i < rows; i++) {
String label = label(i, rows);
g.drawString(label,
x + (cellWidth - fm.stringWidth(label)) / 2,
y + (i + 1) * cellHeight + dy);
}
int outputColumn = table.getOutputIndex(output);
x += cellWidth;
y += cellHeight;
g.setColor(ERROR_COLOR);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int row = getTableRow(i, j, rows, cols);
Entry entry = table.getOutputEntry(row, outputColumn);
if (provisionalValue != null && row == provisionalY
&& outputColumn == provisionalX) entry = provisionalValue;
if (entry.isError()) {
g.fillRect(x + j * cellWidth, y + i * cellHeight, cellWidth, cellHeight);
}
}
}
List<Implicant> implicants = model.getOutputExpressions().getMinimalImplicants(output);
if (implicants != null) {
int index = 0;
for (Implicant imp : implicants) {
g.setColor(IMP_COLORS[index % IMP_COLORS.length]);
paintImplicant(g, imp, x, y, rows, cols);
index++;
}
}
g.setColor(Color.GRAY);
if (cols > 1 || inputCount == 0) g.drawLine(x, y, left + tableWidth, y);
if (rows > 1 || inputCount == 0) g.drawLine(x, y, x, top + tableHeight);
if (outputColumn < 0) return;
g.setColor(Color.BLACK);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int row = getTableRow(i, j, rows, cols);
if (provisionalValue != null && row == provisionalY
&& outputColumn == provisionalX) {
String text = provisionalValue.getDescription();
g.setColor(Color.GREEN);
g.drawString(text,
x + j * cellWidth + (cellWidth - fm.stringWidth(text)) / 2,
y + i * cellHeight + dy);
g.setColor(Color.BLACK);
} else {
Entry entry = table.getOutputEntry(row, outputColumn);
String text = entry.getDescription();
g.drawString(text,
x + j * cellWidth + (cellWidth - fm.stringWidth(text)) / 2,
y + i * cellHeight + dy);
}