/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* 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-1307, USA.
*
* (C) Copyright 2001-2005, by :
* Corporate:
* EADS Astrium SAS
* EADS CRC
* Individual:
* Claude Cazenave
*
* $Id: LoggingPanel.java,v 1.11 2008/09/29 16:26:24 altournoud Exp $
*
* Changes
* -------
* 5 sept. 06 : Initial public release (CC);
*
*/
package simtools.logging.ui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.font.FontRenderContext;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import javax.swing.BoundedRangeModel;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JWindow;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import simtools.logging.SimtoolsLevel;
import simtools.logging.LogRecordLoggingEntry;
import simtools.ui.MenuResourceBundle;
import simtools.ui.UserProperties;
import simtools.util.TableFilter;
/**
* A pannel to display logging content thanks to a table with scroll bars
* @see LoggingTableModel
* @see LoggingTableRenderer
*/
public class LoggingPanel extends JPanel implements MouseListener {
/** menu resources */
protected final MenuResourceBundle menuResources;
/** properties prefix */
protected final String propertiesPrefix;
/** a table to display the stringsResources */
protected final LoggingTable table;
/** a window to display long lines */
protected JWindow descWindow;
/** a text area to display long lines */
protected JTextArea descArea;
protected BoundedRangeModel scrollBarModel;
protected Font tableFont;
/**
* Constructs this panel and connect GlobalMessageWriter to it
*/
public LoggingPanel(JFrame parent,
String propertiesPrefix,
MenuResourceBundle menuResources) {
super(new BorderLayout());
this.menuResources = menuResources;
this.propertiesPrefix=propertiesPrefix;
// Create the table
// -----------------
table = createTable();
table.addMouseListener(this);
table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
table.setColumnSelectionAllowed(true);
if (parent!=null){
createGui(parent);
}
}
public void createGui(JFrame parent){
// Put the table in a scroller
// ----------------------------
JScrollPane spp = new JScrollPane(table);
spp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollBarModel = spp.getVerticalScrollBar().getModel();
scrollBarModel.addChangeListener(new ScrollBarModelChangeListener());
// Put the scroller into the panel
// --------------------------------
add(BorderLayout.CENTER, spp);
// Create a window to popup on right click on message column
// ----------------------------------------------------------
descWindow = new JWindow(parent);
descArea = new JTextArea(4, 40);
descArea.setEditable(false);
descArea.setLineWrap(true);
JScrollPane spd = new JScrollPane(descArea,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
descWindow.getContentPane().add(BorderLayout.CENTER, spd);
descWindow.pack();
descArea.addMouseListener(this);
}
protected LoggingTable createTable(){
return new LoggingTable(menuResources);
}
protected AbstractLoggingTableModel createTableModel(){
return new LoggingTableModel(menuResources);
}
protected TableCellRenderer createTableRenderer(AbstractLoggingTableModel model){
return new LoggingTableRenderer(model);
}
/**
* Applies user properties to current context
*
* @param user
* properties
*/
public void setUserProperties(UserProperties up) {
TableColumnModel tcm = table.getColumnModel();
int nc = table.getModel().getColumnCount();
TableColumn tl[] = new TableColumn[nc];
int map[] = new int[nc];
// get number of visible columns
int ncv = up.getInt(propertiesPrefix+".logbookPanel.nbrColumn", nc);
// remove all visible columns from the table
for (int j = 0; j < nc; j++) {
map[j] = -1;
int l = table.convertColumnIndexToView(j);
if (l >= 0) {
tl[j] = tcm.getColumn(l);
table.removeColumn(tl[j]);
} else {
tl[j] = null;
}
}
// look for the visible columns index
int ncu = 0;
for (int i = 0; i < ncv; i++) {
int v = up.getInt(propertiesPrefix+".logbookPanel.columnIndex" + i, i);
if ((v < nc) && (v >= 0)) {
map[v] = i;
ncu++;
}
}
// restore the visible columns in the right order
while (ncu > 0) {
int min = nc;
int kmin = 0;
for (int k = 0; k < nc; k++) {
if ((map[k] >= 0) && (map[k] < min)) {
min = map[k];
kmin = k;
}
}
table.addColumn(tl[kmin]);
tl[kmin].setPreferredWidth(up.getInt(
propertiesPrefix+".logbookPanel.columnSize" + min, Toolkit
.getDefaultToolkit().getScreenSize().width / 10));
map[kmin] = -1;
ncu--;
}
int size = up.getInt(propertiesPrefix+".logbookPanel.size", 100);
if(size <0){
size = 100;
}
getLogbookModel().setSize(size);
}
public AbstractLoggingTableModel getLogbookModel() {
return table.tableModel;
}
/**
* Gets user properties from current context
*
* @param user
* properties
*/
public void getUserProperties(UserProperties up) {
TableColumnModel tcm = table.getColumnModel();
int ncv = tcm.getColumnCount();
up.setInt(propertiesPrefix+".logbookPanel.nbrColumn", ncv);
for (int j = 0; j < ncv; j++) {
up.setInt(propertiesPrefix+".logbookPanel.columnIndex" + j, table
.convertColumnIndexToModel(j));
up.setInt(propertiesPrefix+".logbookPanel.columnSize" + j, tcm.getColumn(j)
.getWidth());
}
up.setInt(propertiesPrefix+".logbookPanel.size", getLogbookModel().getSize());
}
//
// MouseListener interface
//
public void mouseClicked(MouseEvent e) {
if ((e.getSource() == table)
&& (e.getButton() == MouseEvent.BUTTON3)) {
// get pointed cell
int col = table.columnAtPoint(e.getPoint());
if (col < 0) {
return;
}
col = table.convertColumnIndexToModel(col);
int row = table.rowAtPoint(e.getPoint());
if (row < 0) {
return;
}
// check if content is big enough to require
// dedicated display in the descWindow
String text=(String) table.getModel().getValueAt(row, col);
int cr=text.indexOf('\n');
if(cr<0){
TableColumn tc=table.getColumnModel().getColumn(
table.columnAtPoint(e.getPoint()));
if(table.getTextWidth(text)<tc.getWidth()){
return; // one line with not enough chars
}
}
descArea.setText(text);
Point p = table.getLocationOnScreen();
int x=e.getX() + p.x;
int y=e.getY() + p.y;
Dimension screen=Toolkit.getDefaultToolkit().getScreenSize();
if((x+descWindow.getWidth())>screen.width){
x=screen.width-descWindow.getWidth();
}
if((y+descWindow.getHeight())>screen.height){
y=screen.height-descWindow.getHeight();
}
descWindow.setLocation(x,y);
descWindow.show();
return;
}
else if (e.getSource() == descArea){
descWindow.hide();
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
//
// inner classes
//
/**
* To listen to the changes in the output area vertical scroll bar model
*/
class ScrollBarModelChangeListener implements ChangeListener {
int oldMax;
public void stateChanged(ChangeEvent e) {
if (oldMax != scrollBarModel.getMaximum()) {
oldMax = scrollBarModel.getMaximum();
scrollBarModel.setValue(oldMax);
}
}
}
/**
* A JTable to display the logging content
*/
public class LoggingTable extends JTable{
protected AbstractLoggingTableModel tableModel;
protected TableCellRenderer renderer;
protected FontRenderContext fontRendererContext;
public TableCellRenderer getCellRenderer(int row, int column){
return renderer;
}
public LoggingTable(MenuResourceBundle res) {
super();
tableModel=createTableModel();
TableFilter tableFilter = new TableFilter(tableModel);
tableFilter.setTableHeader(getTableHeader());
setModel(tableFilter);
setRowSelectionAllowed(false);
setColumnSelectionAllowed(false);
Font f = getFont();
fontRendererContext = new FontRenderContext(f.getTransform(), false, false);
setRowHeight((int)f.getMaxCharBounds(fontRendererContext).getHeight());
renderer=createTableRenderer(tableModel);
addMouseListener(LoggingPanel.this);
}
public int getTextWidth(String text){
return (int)getFont().getStringBounds(text, fontRendererContext).getWidth();
}
}
/**
* For testing
* @param args
*/
public static void main(String[] args) {
JFrame f=new JFrame("Logging");
f.addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
LoggingPanel lp=new LoggingPanel(f,"test",null);
f.getContentPane().add(lp);
LoggingTableModel lm=(LoggingTableModel)lp.getLogbookModel();
lm.add(new LogRecordLoggingEntry(new LogRecord(Level.SEVERE,"DEAD")));
lm.add(new LogRecordLoggingEntry(new LogRecord(Level.WARNING,"CAUTION")));
lm.add(new LogRecordLoggingEntry(new LogRecord(SimtoolsLevel.USER_WARNING,"titi")));
lm.add(new LogRecordLoggingEntry(new LogRecord(Level.INFO,"YES")));
lm.add(new LogRecordLoggingEntry(new LogRecord(Level.CONFIG,"NO")));
lm.add(new LogRecordLoggingEntry(new LogRecord(Level.FINE,"WHY")));
lm.add(new LogRecordLoggingEntry(new LogRecord(Level.FINER,"WHO")));
lm.add(new LogRecordLoggingEntry(new LogRecord(Level.FINEST,"WHEN")));
f.pack();
f.show();
}
}