/*
* EuroCarbDB, a framework for carbohydrate bioinformatics
*
* Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
* A copy of this license accompanies this distribution in the file LICENSE.txt.
*
* 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.
*
* Last commit: $Rev: 1930 $ by $Author: david@nixbioinf.org $ on $Date:: 2010-07-29 #$
*/
/**
@author Alessio Ceroni (a.ceroni@imperial.ac.uk)
*/
package org.eurocarbdb.application.glycoworkbench.plugin.reporting;
import org.eurocarbdb.application.glycoworkbench.plugin.*;
import org.eurocarbdb.application.glycoworkbench.*;
import org.eurocarbdb.application.glycanbuilder.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.awt.print.*;
import java.awt.image.*;
public class ProfilesComparisonReportTableFrame extends JFrame implements ActionListener, TableModel, ListSelectionListener {
// singletons
private GlycoWorkbench theApplication;
private ActionManager theActionManager;
protected ProfilesComparisonReportDocument theDocument;
protected ProfilesComparisonReportOptions theOptions;
// components
private JMenuBar theMenuBar;
private JToolBar theToolBar;
private GlycanTable theTable;
private TableSorter theTableSorter;
private Vector<TableModelListener> tm_listeners = new Vector<TableModelListener>();
public ProfilesComparisonReportTableFrame(GlycoWorkbench application, ProfilesComparisonReportDocument doc, ProfilesComparisonReportOptions opt) {
// set singletons
theApplication = application;
theActionManager = new ActionManager();
theDocument = doc;
theOptions = opt;
// initialize the action set
createActions();
// set layout
getContentPane().setLayout(new BorderLayout());
// set the MenuBar
theMenuBar = createMenuBar();
setJMenuBar(theMenuBar);
// set the toolbars
UIManager.getDefaults().put("ToolTip.hideAccelerator",Boolean.TRUE);
theToolBar = createToolBar();
getContentPane().add(theToolBar,BorderLayout.NORTH);
// create table
theTable = new GlycanTable();
theTable.setGlycanRenderer(theApplication.getWorkspace().getGlycanRenderer());
theTable.setShowRedend(false);
theTable.setGlycanScale(0.333);
theTable.setShowVerticalLines(true);
theTable.getSelectionModel().addListSelectionListener(this);
theTable.setPopupMenu(createPopupMenu());
theTableSorter = new TableSorter(this);
theTableSorter.setTableHeader(theTable.getTableHeader());
theTable.setModel(theTableSorter);
for( int i=0; i<theDocument.getNoColumns(); i++ )
theTable.getColumn(theDocument.getNames().get(i)).setCellRenderer(new HeatMapCellRenderer(25));
fireTableChanged();
getContentPane().add(theTable.getScrollPane(),BorderLayout.CENTER);
// finish setting up
setSize(900,700);
setLocationRelativeTo(theApplication);
updateActions();
}
private void createActions() {
//file
for(Map.Entry<String,String> e : SVGUtils.getExportFormats().entrySet() )
theActionManager.add("export=" + e.getKey(),FileUtils.defaultThemeManager.getImageIcon(""),"Export to " + e.getValue() + "...",-1, "",this);
theActionManager.add("print",FileUtils.defaultThemeManager.getImageIcon("print"),"Print...",KeyEvent.VK_P, "ctrl P",this);
theActionManager.add("close",FileUtils.defaultThemeManager.getImageIcon("close"),"Close",KeyEvent.VK_C, "ctrl Q",this);
// edit
theActionManager.add("cut",FileUtils.defaultThemeManager.getImageIcon("cut"),"Cut",KeyEvent.VK_T, "ctrl X",this);
theActionManager.add("copy",FileUtils.defaultThemeManager.getImageIcon("copy"),"Copy",KeyEvent.VK_C, "ctrl C",this);
theActionManager.add("delete",FileUtils.defaultThemeManager.getImageIcon("delete"),"Delete",KeyEvent.VK_DELETE, "",this);
theActionManager.add("screenshot",FileUtils.defaultThemeManager.getImageIcon("screenshot"),"Screenshot",KeyEvent.VK_PRINTSCREEN, "PRINTSCREEN",this);
theActionManager.add("filterselection",FileUtils.defaultThemeManager.getImageIcon(""),"Show only selected fragments",-1, "",this);
theActionManager.add("showallrows",FileUtils.defaultThemeManager.getImageIcon(""),"Show all fragments",-1, "",this);
}
private void updateActions() {
boolean has_selection = theTable.getSelectedRows().length>0;
theActionManager.get("cut").setEnabled(has_selection);
theActionManager.get("copy").setEnabled(has_selection);
theActionManager.get("delete").setEnabled(has_selection);
theActionManager.get("filterselection").setEnabled(has_selection);
theActionManager.get("showallrows").setEnabled(!theTableSorter.isAllRowsVisible());
}
private JMenu createExportDrawingMenu() {
JMenu export_menu = new JMenu("Export to graphical formats");
export_menu.setIcon(FileUtils.defaultThemeManager.getImageIcon("export"));
for(Map.Entry<String,String> e : SVGUtils.getExportFormats().entrySet() )
export_menu.add(theActionManager.get("export="+e.getKey()));
return export_menu;
}
private JMenu createFileMenu() {
JMenu file_menu = new JMenu("File");
file_menu.add(createExportDrawingMenu());
file_menu.addSeparator();
file_menu.add(theActionManager.get("print"));
file_menu.addSeparator();
file_menu.add(theActionManager.get("close"));
return file_menu;
}
private JMenu createEditMenu() {
JMenu edit_menu = new JMenu("Edit");
edit_menu.setMnemonic(KeyEvent.VK_E);
edit_menu.add(theActionManager.get("copy"));
edit_menu.add(theActionManager.get("delete"));
edit_menu.add(theActionManager.get("screenshot"));
edit_menu.addSeparator();
return edit_menu;
}
private JMenuBar createMenuBar() {
JMenuBar menubar = new JMenuBar();
menubar.add(createFileMenu());
menubar.add(createEditMenu());
return menubar;
}
private JToolBar createToolBar() {
JToolBar toolbar = new JToolBar();
toolbar.setFloatable(false);
toolbar.add(theActionManager.get("print"));
toolbar.addSeparator();
toolbar.add(theActionManager.get("cut"));
toolbar.add(theActionManager.get("copy"));
toolbar.add(theActionManager.get("delete"));
toolbar.add(theActionManager.get("screenshot"));
return toolbar;
}
private JPopupMenu createPopupMenu() {
JPopupMenu menu = new JPopupMenu();
menu.add(theActionManager.get("cut"));
menu.add(theActionManager.get("copy"));
menu.add(theActionManager.get("delete"));
menu.addSeparator();
menu.add(theActionManager.get("filterselection"));
menu.add(theActionManager.get("showallrows"));
return menu;
}
// table model
public void addTableModelListener(TableModelListener l) {
if( l!=null )
tm_listeners.add(l);
}
public void removeTableModelListener(TableModelListener l) {
tm_listeners.remove(l);
}
public Class<?> getColumnClass(int columnIndex) {
if( columnIndex==0 )
return Glycan.class;
if( columnIndex==1 )
return Double.class;
return Double.class;
}
public String getColumnName(int columnIndex) {
if( columnIndex==0 )
return "Structure";
if( columnIndex==1 )
return "m/z";
return theDocument.getNames().get(columnIndex-2);
}
public int getColumnCount() {
return 2 + theDocument.getNoColumns();
}
public int getRowCount() {
return theDocument.getNoRows();
}
public Object getValueAt(int rowIndex, int columnIndex) {
ProfilesComparisonReportDocument.Row row = theDocument.getRows().get(rowIndex);
if( columnIndex==0 )
return row.structure;
if( columnIndex==1 )
return row.mz_ratio;
return row.getColumn(columnIndex-2);
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
}
// actions
public void cut() {
copy();
delete();
}
public void delete() {
}
public void copy() {
int[] sel_ind = theTable.getSelectedRows();
if( sel_ind.length>0 ) {
Vector<Glycan> structures = new Vector<Glycan>();
for( int i=0; i<sel_ind.length; i++ ) {
int r = theTableSorter.modelIndex(sel_ind[i]);
structures.add(theDocument.getRows().get(r).structure);
}
ClipUtils.setContents(new GlycanSelection(theTable.getSelectedData(),theApplication.getWorkspace().getGlycanRenderer(),structures));
}
}
public void getScreenshot() {
ClipUtils.setContents(SVGUtils.getImage(theTable));
}
public void onPrint() {
theTable.print(theApplication.getWorkspace().getPrinterJob(),null);
}
public void onExportTo(String format) {
// imposto la dialog per il salvataggio del file
JFileChooser fileChooser = new JFileChooser();
fileChooser.addChoosableFileFilter(new ExtensionFileFilter(format));
// visualizzo la dialog
int returnVal = fileChooser.showSaveDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
// aggiunge l'estension
String filename = fileChooser.getSelectedFile().getAbsolutePath();
filename = FileUtils.enforceExtension(filename,format);
// chiede conferma prima di sovrascrivere il file
File file = new File(filename);
if (file.exists()) {
int retValue = JOptionPane.showOptionDialog(this, "File exists. Overwrite file: " + filename + "?",
"Salva documento", JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, null, null, null);
if( retValue!=JOptionPane.YES_OPTION )
return;
}
// esporta il documento su file
try {
SVGUtils.export(filename,theTable,format);
}
catch(Exception e) {
LogUtils.report(e);
}
}
}
public void filterSelection() {
int[] sel_inds = theTable.getSelectedRows();
if( sel_inds!=null & sel_inds.length>0 )
theTableSorter.setVisibleRows(theTableSorter.modelIndexes(sel_inds));
}
public void showAllRows() {
theTableSorter.resetVisibleRows();
}
private void updateView() {
fireTableChanged();
}
// events
public void actionPerformed(ActionEvent e) {
String action = GlycanAction.getAction(e);
String param = GlycanAction.getParam(e);
if( action.equals("export") )
onExportTo(param);
else if( action.equals("print") )
onPrint();
else if( action.equals("close") )
this.setVisible(false);
else if( action.equals("cut") )
cut();
else if( action.equals("copy") )
copy();
else if( action.equals("delete") )
delete();
else if( action.equals("screenshot") )
getScreenshot();
else if( action.equals("filterselection") )
filterSelection();
else if( action.equals("showallrows") )
showAllRows();
}
public void valueChanged(ListSelectionEvent e) {
updateActions();
}
public void fireTableStructureChanged() {
for(Iterator<TableModelListener> i=tm_listeners.iterator(); i.hasNext(); )
i.next().tableChanged(new TableModelEvent(this,TableModelEvent.HEADER_ROW));
}
public void fireTableChanged() {
for(Iterator<TableModelListener> i=tm_listeners.iterator(); i.hasNext(); ) {
i.next().tableChanged(new TableModelEvent(this));
}
}
public void fireRowChanged(int row) {
for(Iterator<TableModelListener> i=tm_listeners.iterator(); i.hasNext(); ) {
i.next().tableChanged(new TableModelEvent(this,row));
}
}
public void fireRowsChanged(int from, int to) {
for(Iterator<TableModelListener> i=tm_listeners.iterator(); i.hasNext(); ) {
i.next().tableChanged(new TableModelEvent(this,from,to));
}
}
public void fireRowsChanged(int[] ind) {
for( int l=0; l<ind.length; l++ ) {
for(Iterator<TableModelListener> i=tm_listeners.iterator(); i.hasNext(); ) {
i.next().tableChanged(new TableModelEvent(this,ind[l]));
}
}
}
public void fireRowsChanged(Collection<Integer> indexes) {
for(Integer ind : indexes ) {
for(Iterator<TableModelListener> i=tm_listeners.iterator(); i.hasNext(); ) {
i.next().tableChanged(new TableModelEvent(this,ind));
}
}
}
public void fireRowDeleted(int ind) {
for(Iterator<TableModelListener> i=tm_listeners.iterator(); i.hasNext(); ) {
i.next().tableChanged(new TableModelEvent(this,ind,ind,TableModelEvent.ALL_COLUMNS,TableModelEvent.DELETE));
}
}
public void fireRowsDeleted(int[] ind) {
for( int l=0; l<ind.length; l++ ) {
for(Iterator<TableModelListener> i=tm_listeners.iterator(); i.hasNext(); ) {
i.next().tableChanged(new TableModelEvent(this,ind[l],ind[l],TableModelEvent.ALL_COLUMNS,TableModelEvent.DELETE));
}
}
}
public void fireRowsDeleted(Collection<Integer> indexes) {
for(Integer ind : indexes ) {
for(Iterator<TableModelListener> i=tm_listeners.iterator(); i.hasNext(); ) {
i.next().tableChanged(new TableModelEvent(this,ind,ind,TableModelEvent.ALL_COLUMNS,TableModelEvent.DELETE));
}
}
}
}
class HeatMapCellRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 0L;
private boolean fill_cell;
private int spot_radius;
public HeatMapCellRenderer() {
fill_cell = true;
spot_radius = 0;
}
public HeatMapCellRenderer(int sr) {
fill_cell = false;
spot_radius = sr;
}
public void setValue(Object value) {
Color color = getColor((Double)value);
if( fill_cell )
setBackground(color);
else
setIcon(createSpot(color,getRadius((Double)value,spot_radius)));
}
public ImageIcon createSpot(Color color, int radius) {
// Create an image that supports transparent pixels
BufferedImage img = GraphicUtils.createCompatibleImage(2*spot_radius,2*spot_radius,false);
// create a graphic context
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setBackground(new Color(255,255,255,0));
// paint the spot
g2d.setColor(color);
g2d.fill(new Ellipse2D.Double(spot_radius-radius,spot_radius-radius,2*radius,2*radius));
return new ImageIcon(img);
}
private static Color getColor(double value) {
if( value<=-1.)
return Color.red;
if( value>=1. )
return Color.green;
if( value<0. )
return new Color(-(float)value,0.f,0.f);
if( value>0. )
return new Color(0.f,(float)value,0.f);
return Color.black;
}
private static int getRadius(double value, int spot_radius) {
if( value>=1.)
return spot_radius;
if( value<=-1. )
return spot_radius;
if( value>0. )
return (int)(value*(double)spot_radius);
if( value<0. )
return (int)(-value*(double)spot_radius);
return 0;
}
}