Package com.cburch.logisim.analyze.gui

Source Code of com.cburch.logisim.analyze.gui.TableTab$MyListener

/* Copyright (c) 2010, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.logisim.analyze.gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;
import javax.swing.JScrollBar;

import com.cburch.logisim.analyze.model.Entry;
import com.cburch.logisim.analyze.model.TruthTable;
import com.cburch.logisim.analyze.model.TruthTableEvent;
import com.cburch.logisim.analyze.model.TruthTableListener;
import com.cburch.logisim.util.GraphicsUtil;

class TableTab extends JPanel implements TruthTablePanel, TabInterface {
  private static final Font HEAD_FONT = new Font("Serif", Font.BOLD, 14);
  private static final Font BODY_FONT = new Font("Serif", Font.PLAIN, 14);
  private static final int COLUMN_SEP = 8;
  private static final int HEADER_SEP = 4;
 
  private class MyListener implements TruthTableListener {
    public void cellsChanged(TruthTableEvent event) {
      repaint();
    }

    public void structureChanged(TruthTableEvent event) {
      computePreferredSize();
    }
  }
 
  private MyListener myListener = new MyListener();
  private TruthTable table;
  private int cellWidth = 25; // reasonable start values
  private int cellHeight = 15;
  private int tableWidth;
  private int tableHeight;
  private int provisionalX;
  private int provisionalY;
  private Entry provisionalValue = null;
  private TableTabCaret caret;
  private TableTabClip clip;
 
  public TableTab(TruthTable table) {
    this.table = table;
    table.addTruthTableListener(myListener);
    setToolTipText(" ");
    caret = new TableTabCaret(this);
    clip = new TableTabClip(this);
  }

  public TruthTable getTruthTable() {
    return table;
  }
 
  TableTabCaret getCaret() {
    return caret;
  }
 
  void localeChanged() {
    computePreferredSize();
    repaint();
  }
 
  public int getColumn(MouseEvent event) {
    int x = event.getX() - (getWidth() - tableWidth) / 2;
    if (x < 0) return -1;
    int inputs = table.getInputColumnCount();
    int cols = inputs + table.getOutputColumnCount();
    int ret = (x + COLUMN_SEP / 2) / (cellWidth + COLUMN_SEP);
    if (inputs == 0) ret--;
    return ret >= 0 ? ret < cols ? ret : cols : -1;
  }
 
  int getColumnCount() {
    int inputs = table.getInputColumnCount();
    int outputs = table.getOutputColumnCount();
    return inputs + outputs;
  }
 
  public int getOutputColumn(MouseEvent event) {
    int inputs = table.getInputColumnCount();
    if (inputs == 0) inputs = 1;
    int ret = getColumn(event);
    return ret >= inputs ? ret - inputs : -1;
  }
 
  public int getRow(MouseEvent event) {
    int y = event.getY() - (getHeight() - tableHeight) / 2;
    if (y < cellHeight + HEADER_SEP) return -1;
    int ret = (y - cellHeight - HEADER_SEP) / cellHeight;
    int rows = table.getRowCount();
    return ret >= 0 ? ret < rows ? ret : rows : -1;
  }
 
  public void setEntryProvisional(int y, int x, Entry value) {
    provisionalY = y;
    provisionalX = x;
    provisionalValue = value;
   
    int top = (getHeight() - tableHeight) / 2 + cellHeight + HEADER_SEP
      + y * cellHeight;
    repaint(0, top, getWidth(), cellHeight);
  }
 
  @Override
  public String getToolTipText(MouseEvent event) {
    int row = getRow(event);
    int col = getOutputColumn(event);
    Entry entry = table.getOutputEntry(row, col);
    return entry.getErrorMessage();
  }
 
  @Override
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
   
    caret.paintBackground(g);
   
    Dimension sz = getSize();
    int top = Math.max(0, (sz.height - tableHeight) / 2);
    int left = Math.max(0, (sz.width - tableWidth) / 2);
    int inputs = table.getInputColumnCount();
    int outputs = table.getOutputColumnCount();
    if (inputs == 0 && outputs == 0) {
      g.setFont(BODY_FONT);
      GraphicsUtil.drawCenteredText(g, Strings.get("tableEmptyMessage"), sz.width / 2, sz.height / 2);
      return;
    }
   
    g.setColor(Color.GRAY);
    int lineX = left + (cellWidth + COLUMN_SEP) * inputs
      - COLUMN_SEP / 2;
    if (inputs == 0) lineX = left + cellWidth + COLUMN_SEP / 2;
    int lineY = top + cellHeight + HEADER_SEP / 2;
    g.drawLine(left, lineY, left + tableWidth, lineY);
    g.drawLine(lineX, top, lineX, top + tableHeight);
   
    g.setColor(Color.BLACK);
    g.setFont(HEAD_FONT);
    FontMetrics headerMetric = g.getFontMetrics();
    int x = left;
    int y = top + headerMetric.getAscent() + 1;
    if (inputs == 0) {
      x = paintHeader(Strings.get("tableNullHeader"), x, y, g, headerMetric);
    } else {
      for (int i = 0; i < inputs; i++) {
        x = paintHeader(table.getInputHeader(i), x, y, g, headerMetric);
      }
    }
    if (outputs == 0) {
      x = paintHeader(Strings.get("tableNullHeader"), x, y, g, headerMetric);
    } else {
      for (int i = 0; i < outputs; i++) {
        x = paintHeader(table.getOutputHeader(i), x, y, g, headerMetric);
      }
    }
   
    g.setFont(BODY_FONT);
    FontMetrics bodyMetric = g.getFontMetrics();
    y = top + cellHeight + HEADER_SEP;
    Rectangle clip = g.getClipBounds();
    int firstRow = Math.max(0, (clip.y - y) / cellHeight);
    int lastRow = Math.min(table.getRowCount(), 2 + (clip.y + clip.height - y) / cellHeight);
    y += firstRow * cellHeight;
    if (inputs == 0) left += cellWidth + COLUMN_SEP;
    boolean provisional = false;
    for (int i = firstRow; i < lastRow; i++) {
      x = left;
      for (int j = 0; j < inputs + outputs; j++) {
        Entry entry = j < inputs ? table.getInputEntry(i, j)
            : table.getOutputEntry(i, j - inputs);
        if (provisionalValue != null && i == provisionalY
            && j - inputs == provisionalX) {
          provisional = true;
          entry = provisionalValue;
        }
        if (entry.isError()) {
          g.setColor(ERROR_COLOR);
          g.fillRect(x, y, cellWidth, cellHeight);
          g.setColor(Color.BLACK);
        }
        String label = entry.getDescription();
        int width = bodyMetric.stringWidth(label);
        if (provisional) {
          provisional = false;
          g.setColor(Color.GREEN);
          g.drawString(label, x + (cellWidth - width) / 2,
              y + bodyMetric.getAscent());
          g.setColor(Color.BLACK);
        } else {
          g.drawString(label, x + (cellWidth - width) / 2,
              y + bodyMetric.getAscent());
        }
        x += cellWidth + COLUMN_SEP;
      }
      y += cellHeight;
    }
   
    caret.paintForeground(g);
  }
 
  int getCellWidth() { return cellWidth; }
  int getCellHeight() { return cellHeight; }
 
  int getX(int col) {
    Dimension sz = getSize();
    int left = Math.max(0, (sz.width - tableWidth) / 2);
    int inputs = table.getInputColumnCount();
    if (inputs == 0) left += cellWidth + COLUMN_SEP;
    return left + col * (cellWidth + COLUMN_SEP);
  }
 
  int getY(int row) {
    Dimension sz = getSize();
    int top = Math.max(0, (sz.height - tableHeight) / 2);
    return top + cellHeight + HEADER_SEP + row * cellHeight;
  }

  private int paintHeader(String header, int x, int y,
      Graphics g, FontMetrics fm) {
    int width = fm.stringWidth(header);
    g.drawString(header, x + (cellWidth - width) / 2, y);
    return x + cellWidth + COLUMN_SEP;
  }
 
  private void computePreferredSize() {
    int inputs = table.getInputColumnCount();
    int outputs = table.getOutputColumnCount();
    if (inputs == 0 && outputs == 0) {
      setPreferredSize(new Dimension(0, 0));
      return;
    }
   
    Graphics g = getGraphics();
    if (g == null) {
      cellHeight = 16;
      cellWidth = 24;
    } else {
      FontMetrics fm = g.getFontMetrics(HEAD_FONT);
      cellHeight = fm.getHeight();
      cellWidth = 24;
      if (inputs == 0 || outputs == 0) {
        cellWidth = Math.max(cellWidth, fm.stringWidth(Strings.get("tableNullHeader")));
      }
      for (int i = 0; i < inputs + outputs; i++) {
        String header = i < inputs ? table.getInputHeader(i)
            : table.getOutputHeader(i - inputs);
        cellWidth = Math.max(cellWidth, fm.stringWidth(header));
      }
    }
   
    if (inputs == 0) inputs = 1;
    if (outputs == 0) outputs = 1;
    tableWidth = (cellWidth + COLUMN_SEP) * (inputs + outputs) - COLUMN_SEP;
    tableHeight = cellHeight * (1 + table.getRowCount()) + HEADER_SEP;
    setPreferredSize(new Dimension(tableWidth, tableHeight));
    revalidate();
    repaint();
  }

  JScrollBar getVerticalScrollBar() {
    return new JScrollBar() {
      @Override
      public int getUnitIncrement(int direction) {
        int curY = getValue();
        if (direction > 0) {
          return curY > 0 ? cellHeight : cellHeight + HEADER_SEP;
        } else {
          return curY > cellHeight + HEADER_SEP ? cellHeight
              : cellHeight + HEADER_SEP;
        }
      }
   
      @Override
      public int getBlockIncrement(int direction) {
        int curY = getValue();
        int curHeight = getVisibleAmount();
        int numCells = curHeight / cellHeight - 1;
        if (numCells <= 0) numCells = 1;
        if (direction > 0) {
          return curY > 0
            ? numCells * cellHeight
            : numCells * cellHeight + HEADER_SEP;
        } else {
          return curY > cellHeight + HEADER_SEP
            ? numCells * cellHeight
            : numCells * cellHeight + HEADER_SEP;
        }
      }
    };
  }

  public void copy() {
    requestFocus();
    clip.copy();
  }

  public void paste() {
    requestFocus();
    clip.paste();
  }

  public void delete() {
    requestFocus();
    int r0 = caret.getCursorRow();
    int r1 = caret.getMarkRow();
    int c0 = caret.getCursorCol();
    int c1 = caret.getMarkCol();
    if (r0 < 0 || r1 < 0) return;
    if (r1 < r0) { int t = r0; r0 = r1; r1 = t; }
    if (c1 < c0) { int t = c0; c0 = c1; c1 = t; }
    int inputs = table.getInputColumnCount();
    for (int c = c0; c <= c1; c++) {
      if (c >= inputs) {
        for (int r = r0; r <= r1; r++) {
          table.setOutputEntry(r, c - inputs, Entry.DONT_CARE);
        }
      }
    }
  }

  public void selectAll() {
    caret.selectAll();
  }
}
TOP

Related Classes of com.cburch.logisim.analyze.gui.TableTab$MyListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.