Package com.cburch.logisim.gui.log

Source Code of com.cburch.logisim.gui.log.TablePanel$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.gui.log;

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.JScrollBar;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.cburch.logisim.data.Value;
import com.cburch.logisim.util.GraphicsUtil;

class TablePanel extends LogPanel {
  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 ModelListener {
    public void selectionChanged(ModelEvent event) {
      computeRowCount();
    }

    public void entryAdded(ModelEvent event, Value[] values) {
      int oldCount = rowCount;
      computeRowCount();
      if (oldCount == rowCount) {
        int value = vsb.getValue();
        if (value > vsb.getMinimum()
            && value < vsb.getMaximum() - vsb.getVisibleAmount()) {
          vsb.setValue(vsb.getValue() - vsb.getUnitIncrement(-1));
        } else {
          repaint();
        }
      }
    }
   
    public void filePropertyChanged(ModelEvent event) { }
   
    private void computeRowCount() {
      Model model = getModel();
      Selection sel = model.getSelection();
      int rows = 0;
      for (int i = sel.size() - 1; i >= 0; i--) {
        int x = model.getValueLog(sel.get(i)).size();
        if (x > rows) rows = x;
      }
      if (rowCount != rows) {
        rowCount = rows;
        computePreferredSize();
      }
    }
  }
 
  private class VerticalScrollBar extends JScrollBar
      implements ChangeListener {
    private int oldMaximum = -1;
    private int oldExtent = -1;

    public VerticalScrollBar() {
      getModel().addChangeListener(this);
    }
   
    @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 stateChanged(ChangeEvent event) {
      int newMaximum = getMaximum();
      int newExtent = getVisibleAmount();
      if (oldMaximum != newMaximum || oldExtent != newExtent) {
        if (getValue() + oldExtent >= oldMaximum) {
          setValue(newMaximum - newExtent);
        }
        oldMaximum = newMaximum;
        oldExtent = newExtent;
      }
    }
  }
 
  private MyListener myListener = new MyListener();
  private int cellWidth = 25; // reasonable start values
  private int cellHeight = 15;
  private int rowCount = 0;
  private int tableWidth;
  private int tableHeight;
  private VerticalScrollBar vsb;
 
  public TablePanel(LogFrame frame) {
    super(frame);
    vsb = new VerticalScrollBar();
    modelChanged(null, getModel());
  }
 
  @Override
  public String getTitle() {
    return Strings.get("tableTab");
  }
 
  @Override
  public String getHelpText() {
    return Strings.get("tableHelp");
  }
 
  @Override
  public void localeChanged() {
    computePreferredSize();
    repaint();
  }
 
  @Override
  public void modelChanged(Model oldModel, Model newModel) {
    if (oldModel != null) oldModel.removeModelListener(myListener);
    if (newModel != null) newModel.addModelListener(myListener);
  }
 
  public int getColumn(MouseEvent event) {
    int x = event.getX() - (getWidth() - tableWidth) / 2;
    if (x < 0) return -1;
    Selection sel = getModel().getSelection();
    int ret = (x + COLUMN_SEP / 2) / (cellWidth + COLUMN_SEP);
    return ret >= 0 && ret < sel.size() ? ret : -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;
    return ret >= 0 && ret < rowCount ? ret : -1;
  }
 
  @Override
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
   
    Dimension sz = getSize();
    int top = Math.max(0, (sz.height - tableHeight) / 2);
    int left = Math.max(0, (sz.width - tableWidth) / 2);
    Model model = getModel();
    if (model == null) return;
    Selection sel = model.getSelection();
    int columns = sel.size();
    if (columns == 0) {
      g.setFont(BODY_FONT);
      GraphicsUtil.drawCenteredText(g, Strings.get("tableEmptyMessage"), sz.width / 2, sz.height / 2);
      return;
    }
   
    g.setColor(Color.GRAY);
    int lineY = top + cellHeight + HEADER_SEP / 2;
    g.drawLine(left, lineY, left + tableWidth, lineY);
   
    g.setColor(Color.BLACK);
    g.setFont(HEAD_FONT);
    FontMetrics headerMetric = g.getFontMetrics();
    int x = left;
    int y = top + headerMetric.getAscent() + 1;
    for (int i = 0; i < columns; i++) {
      x = paintHeader(sel.get(i).toShortString(), x, y, g, headerMetric);
    }
   
    g.setFont(BODY_FONT);
    FontMetrics bodyMetric = g.getFontMetrics();
    Rectangle clip = g.getClipBounds();
    int firstRow = Math.max(0, (clip.y - y) / cellHeight - 1);
    int lastRow = Math.min(rowCount, 2 + (clip.y + clip.height - y) / cellHeight);
    int y0 = top + cellHeight + HEADER_SEP;
    x = left;
    for (int col = 0; col < columns; col++) {
      SelectionItem item = sel.get(col);
      ValueLog log = model.getValueLog(item);
      int radix = item.getRadix();
      int offs = rowCount - log.size();
      y = y0 + Math.max(offs, firstRow) * cellHeight;
      for (int row = Math.max(offs, firstRow); row < lastRow; row++) {
        Value val = log.get(row - offs);
        String label = val.toDisplayString(radix);
        int width = bodyMetric.stringWidth(label);
        g.drawString(label, x + (cellWidth - width) / 2,
            y + bodyMetric.getAscent());
        y += cellHeight;
      }
      x += cellWidth + COLUMN_SEP;
    }
  }

  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() {
    Model model = getModel();
    Selection sel = model.getSelection();
    int columns = sel.size();
    if (columns == 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;
      for (int i = 0; i < columns; i++) {
        String header = sel.get(i).toShortString();
        cellWidth = Math.max(cellWidth, fm.stringWidth(header));
      }
    }
   
    tableWidth = (cellWidth + COLUMN_SEP) * columns - COLUMN_SEP;
    tableHeight = cellHeight * (1 + rowCount) + HEADER_SEP;
    setPreferredSize(new Dimension(tableWidth, tableHeight));
    revalidate();
    repaint();
  }

  JScrollBar getVerticalScrollBar() {
    return vsb;
  }
}
TOP

Related Classes of com.cburch.logisim.gui.log.TablePanel$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.