/*
* Beryl - A web platform based on XML, XSLT and Java
* This file is part of the Beryl XML GUI
*
* Copyright (C) 2004 Wenzel Jakob <wazlaf@tigris.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-3107 USA
*/
package org.beryl.gui.swing;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.border.EmptyBorder;
/**
* JConsole - Very simplistic console widget supporting attributes
* @version 1.0
* @author Wenzel Jakob
*/
public class JConsole extends JPanel {
private JScrollBar scrollBar = null;
private ConsoleBuffer buffer = null;
private Image bufferImage = null;
private FontMetrics fontMetrics = null;
private boolean drawCursor = false;
private int cursorRow = 0;
private int cursorColumn = 0;
private Color cursorColor = null;
Font plainFont = null;
Font boldFont = null;
int columnWidth = -1;
int rowHeight = -1;
int descent = -1;
int offset = 0;
int width = -1;
int height = -1;
boolean dirty = false;
protected class ScrollBarListener implements AdjustmentListener {
public void adjustmentValueChanged(AdjustmentEvent event) {
offset = event.getValue();
dirty = true;
refresh();
}
};
protected class WheelListener implements MouseWheelListener {
public void mouseWheelMoved(MouseWheelEvent event) {
int notches = event.getWheelRotation();
scrollBar.setValue(scrollBar.getValue() + notches * 5);
}
};
protected class ConsoleMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
requestFocus();
}
};
/**
* Create the console widget
*/
public JConsole() {
/* Add a scrollbar */
scrollBar = new JScrollBar();
scrollBar.addAdjustmentListener(new ScrollBarListener());
addMouseWheelListener(new WheelListener());
add(scrollBar);
/* Construct the buffer */
buffer = new ConsoleBuffer(this);
/* Setup a fixed size font */
setFont(new Font("Monospaced", Font.PLAIN, 12));
/* Disable double buffering */
setDoubleBuffered(false);
/* Set background color to black */
setBackground(Color.BLACK);
/* Enable key events */
enableEvents(AWTEvent.KEY_EVENT_MASK);
/* Make the console focusable */
setFocusable(true);
/* Add a mouse listener */
addMouseListener(new ConsoleMouseListener());
/* Set a border */
setBorder(new EmptyBorder(3, 5, 5, 0));
/* Set the cursor color */
cursorColor = Color.LIGHT_GRAY;
}
/**
* Set the font
*/
public void setFont(Font font) {
plainFont = new Font(font.getFamily(), Font.PLAIN, font.getSize());
boldFont = new Font(font.getFamily(), Font.BOLD, font.getSize());
fontMetrics = getFontMetrics(plainFont);
columnWidth = fontMetrics.charWidth('A');
rowHeight = fontMetrics.getHeight();
descent = fontMetrics.getDescent();
}
/**
* Return the cursor column
*/
public int getCursorColumn() {
return cursorColumn;
}
/**
* Return the table row
*/
public int getCursorRow() {
return cursorRow;
}
/**
* Return whether to draw the cursor
*/
public boolean getDrawCursor() {
return drawCursor;
}
/**
* Define whether to draw the cursor
*/
public void setDrawCursor(boolean b) {
drawCursor = b;
}
/**
* Return the cursor color
*/
public Color getCursorColor() {
return cursorColor;
}
/**
* Set the cursor color
*/
public void setCursorColor(Color color) {
cursorColor = color;
}
/**
* Setup the layout
*/
public void doLayout() {
super.doLayout();
width = getWidth();
height = getHeight();
int scrollBarWidth = scrollBar.getPreferredSize().width;
if (width < 0 || height < 0 || scrollBarWidth < 0)
return;
bufferImage = createImage(width, height);
scrollBar.setSize(scrollBarWidth, height);
scrollBar.setLocation(width - scrollBarWidth, 0);
scrollBar.setUnitIncrement(1);
scrollBar.setBlockIncrement(height / rowHeight);
dirty = true;
updateScrollbar();
refresh();
}
/**
* Update the scroll bar values
*/
void updateScrollbar() {
Insets insets = getInsets();
int visibleRows = (height - insets.top - insets.bottom) / rowHeight;
int rowCount = buffer.getRowCount();
if (visibleRows > rowCount)
visibleRows = rowCount;
scrollBar.setMinimum(0);
scrollBar.setMaximum(rowCount);
scrollBar.setVisibleAmount(visibleRows);
if (offset + visibleRows > rowCount)
offset = rowCount - visibleRows;
scrollBar.setValue(offset);
}
/**
* Scroll to a row
*/
public void scrollToRow(int row) {
scrollBar.setValue(row);
}
/**
* Scroll to the bottom
*/
public void scrollToBottom() {
scrollBar.setValue(scrollBar.getMaximum() - scrollBar.getVisibleAmount());
}
/**
* Return the console buffer
*/
public ConsoleBuffer getBuffer() {
return buffer;
}
/**
* Set the cursor position
*/
public void setCursorPosition(int row, int column) {
if (getBuffer().getRowCount() > cursorRow)
getBuffer().getRow(cursorRow).markDirty();
getBuffer().getRow(row).markDirty();
cursorRow = row;
cursorColumn = column;
}
/**
* Always call this function after you have changed the console
* buffer. This causes a repaint of the modified rows
*/
public void refresh() {
if (bufferImage != null) {
Graphics g = bufferImage.getGraphics();
g.setColor(getBackground());
if (dirty)
g.fillRect(0, 0, width, height);
buffer.paintBuffer(g);
dirty = false;
repaint();
}
}
/**
* Transfer the buffer image to the screen
*/
protected void paintComponent(Graphics g) {
Insets insets = getInsets();
int row = cursorRow - offset;
int visibleRows = (height - insets.top - insets.bottom) / rowHeight;
boolean doDrawCursor = drawCursor && row >= 0 && row < visibleRows;
g.drawImage(bufferImage, 0, 0, width, height, 0, 0, width, height, this);
if (doDrawCursor) {
g.setXORMode(getBackground());
g.setColor(cursorColor);
g.fillRect(
insets.left + cursorColumn * columnWidth,
insets.top + row * rowHeight,
columnWidth,
rowHeight);
g.setPaintMode();
}
}
}