/******************************************************************************* * ALMA - Atacama Large Millimeter Array * Copyright (c) COSYLAB - Control System Laboratory, 2011 * (in the framework of the ALMA collaboration). * All rights reserved. * * This library 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 library 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 library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *******************************************************************************/ /* * Created on Dec 18, 2004 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package com.cosylab.logging.client; import java.awt.Component; import java.awt.FontMetrics; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Vector; import javax.swing.JComponent; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellRenderer; import com.cosylab.logging.engine.log.ILogEntry; import com.cosylab.logging.engine.log.LogTypeHelper; import com.cosylab.logging.engine.log.LogField; import alma.acs.logging.table.LogTooltipHelper; import alma.acs.logging.table.renderer.EntryTypeRenderer; import alma.acs.util.IsoDateFormat; /** * The table used to represent data in the right panel of the * main window * * @author acaproni * */ public class DetailedLogTable extends JTable { /** * The string shown when the dialog is not displaying a log */ private static final String NOT_AVAILABLE=""; public class MultilineRenderer extends JTextArea implements TableCellRenderer { public MultilineRenderer() { super (100,20); setWrapStyleWord(true); setLineWrap(true); } public Component getTableCellRendererComponent( // JTable table, Object obj, boolean isSelected, boolean hasFocus, int row, int column) { setText(obj.toString()); int newSize = normalRowHeight*formatText(obj.toString()); if (DetailedLogTable.this.getRowHeight(row)!=newSize) { DetailedLogTable.this.setRowHeight(row, newSize); } FontMetrics fm = this.getFontMetrics(getFont()); return this; } /** * Calculate the number of lines to display the string in the * renderer. * <P> * Setting the preferred size worked with jdk 1.3 but * now does not and I did not find anything on the net so I have * to find a solution by myself. * <P> * The calculation is not 100% perfect but seems to work pretty well. * In future we should think of changing this strategy with something * better.. * * @param str The string to display into the renderer * @return The number of lines (probably) needed to display the * string into the text area. */ private int formatText(String str) { if (str==null || str.length()==0) { return 1; } FontMetrics fm = this.getFontMetrics(getFont()); int pixels = fm.stringWidth(str); if (pixels<getSize().width) { return 1; } return pixels/getPreferredSize().width+1; } } /** * The model for this table. * * @author acaproni * */ public class DetailedTableModel extends AbstractTableModel { /** * An object of <code>LogTypeHelper</code> is needed in order to have * <code>EntryTypeRenderer</code> working properly. */ public LogTypeHelper logType=null; @Override public int getColumnCount() { return 2; } @Override public int getRowCount() { return rowsNum; } @Override public Object getValueAt(int row, int col) { if (col==1 && row==LogField.ENTRYTYPE.ordinal()) { return logType; } return nameValue[row][col]; } } /** * The table model */ private DetailedTableModel dataModel = new DetailedTableModel(); /** * The rows in the table */ private int rowsNum; /** * The height of a row with only one line of text */ private int normalRowHeight; /** * The pairs <name,value> i.e. all the values displayed in the table. * <P> * The first column contains the title of each cell in HTML format; * the second column contains the value displayed in the right column of the * table in plain text. * The renderes will take such a string and format to be properly displayed, * with the exception of the log type that is stored into the * <code>DetailedTableModel</code> as a <code>LogTypeHelper</code>. */ private String[][] nameValue; /** * The multiline renderer for the log message */ private MultilineRenderer logMessageRenderer = new MultilineRenderer(); private EntryTypeRenderer entryTypeRenderer = new EntryTypeRenderer(true); /** * Build a table using the data in the log entry * * @param log The logEntry with the data to display */ public DetailedLogTable() { super(); setModel(dataModel); setRowSelectionAllowed(false); setColumnSelectionAllowed(false); setCellSelectionEnabled(false); setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); getColumnModel().getColumn(0).setHeaderValue("LogField"); getColumnModel().getColumn(1).setHeaderValue("Value"); getColumnModel().getColumn(0).setMinWidth(110); getColumnModel().getColumn(0).setMaxWidth(250); getColumnModel().getColumn(1).setMinWidth(250); setEmptyContent(); normalRowHeight=getRowHeight(); } /** * Fill the table with an empty content (no log selected) * */ private void setEmptyContent() { rowsNum = LogField.values().length; nameValue = new String[rowsNum][2]; for (int i=0; i<LogField.values().length; i++) { nameValue[i][0]= "<HTML><B>"+LogField.values()[i].getName()+"</B>"; nameValue[i][1]=NOT_AVAILABLE; } dataModel.fireTableDataChanged(); } /** * Fill the table with the fields of the given log. * * @param log The log whose content is shown in the table */ public void setupContent(ILogEntry log) { if (log==null) { setEmptyContent(); return; } // The number of rows in the table is given by the number of fields // of each LogEntry plus the number of the "data" elements for the selected log Vector<ILogEntry.AdditionalData> additionalData = log.getAdditionalData(); rowsNum = LogField.values().length; if (additionalData!=null) { rowsNum+=additionalData.size(); } if (rowsNum > 0) { nameValue = new String[rowsNum][2]; for (int i=0; i<LogField.values().length; i++) { LogField field = LogField.values()[i]; nameValue[i][0]= "<HTML><B>"+field.getName()+"</B>"; Object obj = log.getField(field); if (obj!=null) { if (field==LogField.ENTRYTYPE) { nameValue[i][1]=obj.toString(); dataModel.logType=(LogTypeHelper)obj; } else if (field==LogField.TIMESTAMP) { SimpleDateFormat df = new IsoDateFormat(); Date dt = new Date((Long)obj); StringBuffer dateSB = new StringBuffer(); java.text.FieldPosition pos = new java.text.FieldPosition(0); df.format(dt,dateSB,pos); nameValue[i][1]=dateSB.toString(); } else { nameValue[i][1]= obj.toString(); } } else { nameValue[i][1]=""; } } for (int i=LogField.values().length; i < rowsNum; i++) { nameValue[i][0] = "<HTML><B>Additional</B> <I>"+additionalData.get(i-LogField.values().length).name+"</I>"; String temp = (String)additionalData.get(i-LogField.values().length).value; nameValue[i][1] = temp; } dataModel.fireTableDataChanged(); } } /** * Sets a tool tip on all the cells. It pops up when the value is not fully displayed while * the mouse scrolls over it. * * @see javax.swing.JTable#prepareRenderer(TableCellRenderer, int, int) */ public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) { Component c = super.prepareRenderer(renderer, rowIndex, vColIndex); if (vColIndex==1) { LogTooltipHelper.setToolTip((JComponent)c,nameValue[rowIndex][vColIndex].toString(),96); } return c; } /* (non-Javadoc) * @see javax.swing.JTable#getCellRenderer(int, int) */ @Override public TableCellRenderer getCellRenderer(int row, int column) { if (column==0) { return super.getCellRenderer(row, column); } else { if (row!=LogField.ENTRYTYPE.ordinal()) { return logMessageRenderer; } else { return entryTypeRenderer; } } } }