/* Copyright 2008, 2009, 2010 by the Oxford University Computing Laboratory
This file is part of HermiT.
HermiT 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 3 of the License, or
(at your option) any later version.
HermiT 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 HermiT. If not, see <http://www.gnu.org/licenses/>.
*/
package org.semanticweb.HermiT.debugger;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.EventListenerList;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import org.semanticweb.HermiT.Prefixes;
@SuppressWarnings("serial")
public class DerivationViewer extends JFrame {
protected final Prefixes m_prefixes;
protected final DerivationTreeTreeModel m_derivationTreeTreeModel;
protected final JTree m_derivationTree;
public DerivationViewer(Prefixes prefixes,DerivationHistory.Fact root) {
super("Derivation tree for "+root.toString(prefixes));
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
m_prefixes=prefixes;
m_derivationTreeTreeModel=new DerivationTreeTreeModel(root);
m_derivationTree=new JTree(m_derivationTreeTreeModel);
m_derivationTree.setLargeModel(true);
m_derivationTree.setShowsRootHandles(true);
m_derivationTree.setCellRenderer(new DerivationTreeCellRenderer());
JScrollPane scrollPane=new JScrollPane(m_derivationTree);
scrollPane.setPreferredSize(new Dimension(600,400));
JButton button=new JButton("Refresh");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
refresh();
}
});
JPanel panel=new JPanel(new BorderLayout());
panel.add(scrollPane,BorderLayout.CENTER);
panel.add(button,BorderLayout.SOUTH);
setContentPane(panel);
getRootPane().setDefaultButton(button);
pack();
setLocation(150,150);
setVisible(true);
}
public void refresh() {
m_derivationTreeTreeModel.refresh();
}
protected static class DerivationTreeTreeModel implements TreeModel,Serializable {
private static final long serialVersionUID=9210217812084186766L;
protected final EventListenerList m_eventListeners;
protected final DerivationHistory.Fact m_root;
public DerivationTreeTreeModel(DerivationHistory.Fact root) {
m_eventListeners=new EventListenerList();
m_root=root;
}
public void addTreeModelListener(TreeModelListener listener) {
m_eventListeners.add(TreeModelListener.class,listener);
}
public void removeTreeModelListener(TreeModelListener listener) {
m_eventListeners.remove(TreeModelListener.class,listener);
}
public Object getChild(Object parent,int index) {
DerivationHistory.Fact parentFact=(DerivationHistory.Fact)parent;
DerivationHistory.Derivation derivation=parentFact.getDerivation();
return derivation.getPremise(index);
}
public int getChildCount(Object parent) {
DerivationHistory.Fact parentFact=(DerivationHistory.Fact)parent;
DerivationHistory.Derivation derivation=parentFact.getDerivation();
return derivation.getNumberOfPremises();
}
public int getIndexOfChild(Object parent,Object child) {
DerivationHistory.Fact parentFact=(DerivationHistory.Fact)parent;
DerivationHistory.Derivation derivation=parentFact.getDerivation();
for (int index=0;index<derivation.getNumberOfPremises();index++)
if (child.equals(derivation.getPremise(index)))
return index;
return -1;
}
public Object getRoot() {
return m_root;
}
public boolean isLeaf(Object node) {
DerivationHistory.Fact nodeFact=(DerivationHistory.Fact)node;
DerivationHistory.Derivation derivation=nodeFact.getDerivation();
return derivation.getNumberOfPremises()==0;
}
public void valueForPathChanged(TreePath path,Object newValue) {
}
public void refresh() {
Object[] listeners=m_eventListeners.getListenerList();
TreeModelEvent e=new TreeModelEvent(this,new Object[] { getRoot() });
for (Object listener : listeners)
if (listener instanceof TreeModelListener)
((TreeModelListener)listener).treeStructureChanged(e);
}
}
protected static class TextIcon implements Icon,Serializable {
private static final long serialVersionUID=2955881594360729470L;
protected static final int WIDTH=16;
protected static final int HEIGHT=16;
protected final Color m_background;
protected final Color m_foreground;
protected final String m_text;
protected final Font m_font;
public TextIcon(Color background,Color foreground,String text,Font font) {
m_background=background;
m_foreground=foreground;
m_text=text;
m_font=font;
}
public int getIconHeight() {
return WIDTH;
}
public int getIconWidth() {
return HEIGHT;
}
public void paintIcon(Component c,Graphics g,int x,int y) {
Color oldColor=g.getColor();
g.setColor(m_background);
g.fillOval(x+2,y+2,x+WIDTH-2,y+HEIGHT-2);
g.setColor(m_foreground);
Font oldFont=g.getFont();
g.setFont(m_font);
FontMetrics fontMetrics=g.getFontMetrics();
int textX=x+(WIDTH-fontMetrics.stringWidth(m_text))/2+2;
int textY=y+(HEIGHT+fontMetrics.getAscent()-fontMetrics.getDescent())/2;
g.drawString(m_text,textX,textY);
g.setFont(oldFont);
g.setColor(oldColor);
}
}
protected static final Font s_font=new Font("Serif",Font.BOLD,11);
protected static final Icon DLCLAUSE_APPLICATION_ICON=new TextIcon(Color.YELLOW,Color.BLACK,"R",s_font);
protected static final Icon DISJUNCT_APPLICATION_ICON=new TextIcon(Color.CYAN,Color.BLACK,"D",s_font);
protected static final Icon MERGING_ICON=new TextIcon(Color.BLUE,Color.WHITE,"M",s_font);
protected static final Icon GRAPH_CHECKING_ICON=new TextIcon(Color.DARK_GRAY,Color.WHITE,"G",s_font);
protected static final Icon CLASH_DETECTION_ICON=new TextIcon(Color.BLACK,Color.WHITE,"C",s_font);
protected static final Icon EXISTENTIAL_EXPANSION_ICON=new TextIcon(Color.RED,Color.WHITE,"E",s_font);
protected static final Icon BASE_FACT_ICON=new TextIcon(Color.MAGENTA,Color.WHITE,"B",s_font);
protected class DerivationTreeCellRenderer extends DefaultTreeCellRenderer {
public Component getTreeCellRendererComponent(JTree tree,Object value,boolean selected,boolean expanded,boolean leaf,int row,boolean hasFocus) {
DerivationHistory.Fact fact=(DerivationHistory.Fact)value;
DerivationHistory.Derivation derivation=fact.getDerivation();
StringBuffer text=new StringBuffer();
text.append(fact.toString(m_prefixes));
text.append(derivation.toString(m_prefixes));
super.getTreeCellRendererComponent(tree,text.toString(),selected,expanded,leaf,row,hasFocus);
if (derivation instanceof DerivationHistory.DLClauseApplication)
setIcon(DLCLAUSE_APPLICATION_ICON);
else if (derivation instanceof DerivationHistory.DisjunctApplication)
setIcon(DISJUNCT_APPLICATION_ICON);
else if (derivation instanceof DerivationHistory.Merging)
setIcon(MERGING_ICON);
else if (derivation instanceof DerivationHistory.GraphChecking)
setIcon(GRAPH_CHECKING_ICON);
else if (derivation instanceof DerivationHistory.ClashDetection)
setIcon(CLASH_DETECTION_ICON);
else if (derivation instanceof DerivationHistory.ExistentialExpansion)
setIcon(EXISTENTIAL_EXPANSION_ICON);
else if (derivation instanceof DerivationHistory.BaseFact)
setIcon(BASE_FACT_ICON);
else
setIcon(null);
return this;
}
}
}