// The console package (c) 1997 duane a. bailey and lyle a. mcgeoch // The class supporting the drawable area of the console window. // $Id: ConsoleCanvas.java,v 2.1 1999/07/11 02:52:16 bailey Exp $ package element; import java.awt.*; import java.awt.event.*; import java.util.*; /** * Copyright (c) 1997 McGraw-Hill * All Rights Reserved. *

* Permission to use, copy, modify, and distribute this * software and its documentation for NON-COMMERCIAL purposes * and without fee is hereby granted provided that this * copyright notice appears in all copies. Please refer to * the file "copyright.html" for further important copyright * and licensing information. *

* MCGRAW-HILL MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT. MCGRAW-HILL SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. * @version $Id: ConsoleCanvas.java,v 2.1 1999/07/11 02:52:16 bailey Exp $ * @author duane a. bailey */ class ConsoleCanvas extends Canvas implements KeyListener { final int BORDER_WIDTH = 1; final int LEFT_MARGIN = 3; // number of spaces at left of text area (includes BORDER_WIDTH) private int rows; // rows in canvas private int cols; // cols in canvas private Font theFont; // font private int charWidth; // width of characters in font private int charHeight; // height of characters in font private int charDown; // pixels skipped to bottom of first line private int charDescent; private int canvasWidth; private boolean paintDone; // has repaint request completed? private Vector lines; // the list of lines on screen private int maxWidth; ConsoleScrollbar rowScroller; ConsoleScrollbar colScroller; ConsoleKeyboard keyboard; Image osi; Graphics osg; private ConsoleCanvas() // post: constructs a 24x80 Courier based console canvas. { //this(24,80,new Font("Courier", Font.PLAIN, 12)); } ConsoleCanvas(int rows, int cols, Font theFont) // pre: rows > 0, cols > 0, theFont a valid font // post: constructs an approrpriately sized console canvas { this.rows = rows; this.cols = cols; this.theFont = theFont; this.maxWidth = 0; setFont(theFont); setBackground(Color.white); setForeground(Color.black); addKeyListener(this); FontMetrics fm = getFontMetrics(theFont); charWidth = fm.getMaxAdvance(); if (charWidth == -1) { charWidth = fm.charWidth('M'); } charWidth = fm.stringWidth("0123456789")/10; charHeight = fm.getHeight(); charDown = fm.getAscent() + fm.getLeading() + BORDER_WIDTH; charDescent = fm.getMaxDescent(); canvasWidth= charWidth*cols + LEFT_MARGIN - BORDER_WIDTH; setSize(canvasWidth + 2*BORDER_WIDTH, (rows+1)*charHeight + 2*BORDER_WIDTH); // create at least one line on the screen lines = new Vector(); lines.addElement(new ConsoleLine(cols)); } /** * @return */ public int rows() { return rows; } /** * @return */ public int cols() { return cols; } void setScrollbar(ConsoleScrollbar rowScroller, ConsoleScrollbar colScroller) // pre: rowScroller is a valid scroll bar. { this.rowScroller = rowScroller; this.colScroller = colScroller; } /** * pre: g is a valid graphics context
* post: the lines of the screen are repainted on g
* * @param g */ public void paint(Graphics g) // pre: g is a valid graphics context // post: the lines of the screen are repainted on g { if (osi == null) { Dimension d = getSize(); osi = createImage(d.width,d.height); osg = osi.getGraphics(); } int curLine = rowScroller.getValue(); int curCol = colScroller.getValue(); int lineCount = lines.size(); paintDone = true; // erase the graphics osg.clearRect(0, 0, canvasWidth + 2*BORDER_WIDTH, rows*charHeight + 2*BORDER_WIDTH); /* // redraw the frame osg.drawRect(0, 0, canvasWidth + 2*BORDER_WIDTH, rows*charHeight + BORDER_WIDTH); */ for (int i = 0; (i < rows) && (curLine < lineCount); i++) { paintLine(osg, (ConsoleLine)lines.elementAt(curLine), curCol, i); curLine++; } g.drawImage(osi, 0, 0, null); } protected void paintLine(Graphics g, ConsoleLine L, int first, int pos) // post: paints a single ConsoleLine at line 'pos' { int count = L.length-first; if (count > 0) { g.drawBytes(L.data, first, count, LEFT_MARGIN, charDown + pos*charHeight); } } protected void wipeLine(Graphics g, ConsoleLine L, int wipeFrom, int pos) { int count = L.length-wipeFrom; if (count > 0) { g.clearRect(LEFT_MARGIN + wipeFrom*charWidth, BORDER_WIDTH + pos*charHeight + charDescent, (L.length-wipeFrom)*charWidth, charHeight); } } protected void addNewBottomLine(Graphics g) // post: adds a new bottom line to the screen. { lines.addElement(new ConsoleLine(cols)); rowScroller.expandTo(lines.size()); rowScroller.scrollMaximum(); colScroller.scrollMinimum(); update(g); } /** * @param g */ public void update(Graphics g) { if (!paintDone) return; paint(g); } void append(byte b) { if (b == '\n' || b == '\r') { lines.addElement(new ConsoleLine(cols)); rowScroller.expandTo(lines.size()); } else { ConsoleLine l = (ConsoleLine)lines.lastElement(); l.append(b); colScroller.expandTo(l.length); } rowScroller.scrollMaximum(); //colScroller.scrollMinimum(); repaint(); } void write(byte b) { if (b == '\n' || b == '\r') { lines.addElement(new ConsoleLine(cols)); rowScroller.expandTo(lines.size()); } else { ConsoleLine l = (ConsoleLine)lines.lastElement(); l.append(b); colScroller.expandTo(l.length); } // colScroller.scrollMinimum(); rowScroller.scrollMaximum(); repaint(); } void setKeyboard(ConsoleKeyboard keyboard) { this.keyboard = keyboard; } /** * @param evt */ public void keyTyped(java.awt.event.KeyEvent evt) { return; } /** * @param evt */ public void keyPressed(java.awt.event.KeyEvent evt) { int keynum = evt.getKeyChar(); if ((keynum > 0) && (keynum < 128)) { keyboard.doKeyHit((byte)keynum); } } /** * @param evt */ public void keyReleased(java.awt.event.KeyEvent evt) { return; } /** * @return */ public String toString() { String s="