// 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="