package com.github.lindenb.jvarkit.util.swing;
import htsjdk.samtools.util.CloserUtil;
import htsjdk.samtools.util.IOUtil;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.Toolkit;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableCellRenderer;
/**
* Panel used to display the content of an exception
* @author pierre
*
*/
@SuppressWarnings("serial")
public class ThrowablePane extends JPanel
{
/**
* Constructor with a throwable
* @param throwable
*/
public ThrowablePane(Throwable throwable,String message)
{
super(new BorderLayout());
if(message==null) message=throwable.getLocalizedMessage();
if(message==null) message=throwable.getMessage();
Dimension screen= Toolkit.getDefaultToolkit().getScreenSize();
setPreferredSize(new Dimension(screen.width/2,screen.height/2));
setBorder(BorderFactory.createLineBorder(Color.RED,2));
List<StackTraceElement> rows = new ArrayList<>();
for(final StackTraceElement ste: throwable.getStackTrace())
{
rows.add(ste);
}
final AbstractGenericTable<StackTraceElement> tableModel = new AbstractGenericTable<StackTraceElement>(rows)
{
public int getColumnCount() {
return 4;
}
@Override
public String getColumnName(int columnIndex) {
switch(columnIndex)
{
case 0: return "Class";
case 1: return "Method";
case 2: return "File";
case 3: return "Line";
}
return null;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
switch(columnIndex)
{
case 0: return String.class;
case 1: return String.class;
case 2: return String.class;
case 3: return Integer.class;
}
return null;
}
@Override
public Object getValueOf(final StackTraceElement e, int columnIndex) {
if(e==null || columnIndex<0) return null;
switch(columnIndex)
{
case 0: return e.getClassName();
case 1: return e.getMethodName();
case 2: return e.getFileName();
case 3: return e.getLineNumber();
}
return null;
}
};
JTabbedPane tabbedPane=new JTabbedPane(JTabbedPane.SCROLL_TAB_LAYOUT);
this.add(tabbedPane,BorderLayout.CENTER);
JTextField tf= new JTextField(throwable.getClass()+" : "+message);
tf.setToolTipText(tf.getText());
tf.setEditable(false);
tf.setCaretPosition(0);
tf.setForeground(Color.RED);
tf.setFont(new Font("Dialog",Font.PLAIN,24));
tabbedPane.addTab("Message", tf);
JPanel pane= new JPanel(new GridLayout(0,1));
tabbedPane.addTab("Trace", pane);
StringWriter statckTrace= new StringWriter();
throwable.printStackTrace(new PrintWriter(statckTrace));
JTextArea msg= new JTextArea(throwable.getClass().getName()+
"\n"+
statckTrace.toString());
msg.setEditable(false);
msg.setBackground(Color.WHITE);
msg.setLineWrap(true);
JScrollPane scroll=new JScrollPane(msg);
scroll.setBorder(BorderFactory.createTitledBorder("An exception of type "+
throwable.getClass().getName() +
" has occured"));
scroll.setPreferredSize(new Dimension(200,200));
pane.add(scroll);
JTable table = new JTable(tableModel);
DefaultTableCellRenderer render= new DefaultTableCellRenderer()
{
private static final long serialVersionUID = 1L;
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
Component c= super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
row, column);
Object pack= table.getModel().getValueAt(row, 0);
if(!isSelected &&
pack!=null &&
!pack.toString().contains("com.github.lindenb") )
{
setBackground(Color.GREEN);
}
else if(isSelected)
{
setBackground(Color.RED);
}
else
{
setBackground(Color.WHITE);
}
return c;
}
};
render.setOpaque(true);
for(int i=0;i< table.getColumnModel().getColumnCount();++i)
{
table.getColumnModel().getColumn(i).setCellRenderer(render);
}
table.setBackground(Color.WHITE);
scroll=new JScrollPane(table);
scroll.setBorder(BorderFactory.createTitledBorder("Stack Trace"));
pane.add(scroll);
/** try to display the file */
for(StackTraceElement ste: rows)
{
String classname = ste.getClassName();
if(classname==null) continue;
classname.replace('.', '/');
classname="/"+classname+".java";
InputStream in = null;
try {
in= getClass().getResourceAsStream(classname);
if(in==null) continue;
String javaFile = IOUtil.readFully(in);
JTextArea area= new JTextArea(javaFile.toString());
JPanel srcPane= new JPanel(new BorderLayout());
srcPane.setBorder(BorderFactory.createTitledBorder("Source"));
srcPane.add(new JScrollPane(area));
tabbedPane.addTab("Source", srcPane);
}
catch (Throwable e)
{
break;
}
finally
{
CloserUtil.close(in);
}
break;
}
setBackground(Color.RED);
pane.setOpaque(true);
pane.setBackground(Color.RED);
}
/** display an alert via OptionPane.showMessageDialog */
static public void show(Component owner, String message,Throwable t)
{
try {
JOptionPane.showMessageDialog(owner,new ThrowablePane(t,message),"Error",JOptionPane.ERROR_MESSAGE,null);
}
catch (HeadlessException e)
{
t.printStackTrace(System.err);
}
}
/** display an alert via OptionPane.showMessageDialog */
static public void show(Component owner, Throwable t)
{
show(owner,null,t);
}
}