package com.performizeit.mjprof.plugins.output;
import com.performizeit.mjprof.model.Profile;
import com.performizeit.mjprof.model.ProfileVisitor;
import com.performizeit.mjprof.model.SFNode;
import com.performizeit.mjprof.parser.ThreadDump;
import com.performizeit.mjprof.parser.ThreadInfo;
import com.performizeit.mjprof.parser.ThreadInfoProps;
import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.util.HashMap;
/**
* Created by life on 27/10/14.
*/
public class ThreadDumpGuiViewer extends JPanel implements TreeSelectionListener {
ThreadDump toDisplay;
private JTree tree;
//Optionally play with line styles. Possible values are
//"Angled" (the default), "Horizontal", and "None".
private static boolean playWithLineStyle = false;
private static String lineStyle = "Horizontal";
//Optionally set the look and feel.
private static boolean useSystemLookAndFeel = false;
public ThreadDumpGuiViewer(ThreadDump toDisplay) {
super(new GridLayout(1, 0));
this.toDisplay = toDisplay;
//Create the nodes.
DefaultMutableTreeNode top =
new DefaultMutableTreeNode("Thread Dump");
createNodes(top);
//Create a tree that allows one selection at a time.
tree = new JTree(top);
tree.getSelectionModel().setSelectionMode
(TreeSelectionModel.SINGLE_TREE_SELECTION);
//Listen for when the selection changes.
tree.addTreeSelectionListener(this);
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}
if (playWithLineStyle) {
System.out.println("line style = " + lineStyle);
tree.putClientProperty("JTree.lineStyle", lineStyle);
}
//Create the scroll pane and add the tree to it.
JScrollPane treeView = new JScrollPane(tree);
Dimension minimumSize = new Dimension(1000, 800);
this.setMinimumSize(minimumSize);
this.setSize(minimumSize);
treeView.setMaximumSize(minimumSize);
treeView.setSize(minimumSize);
//Add the split pane to this panel.
add(treeView);
}
/**
* Required by TreeSelectionListener interface.
*/
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)
tree.getLastSelectedPathComponent();
if (node == null) return;
Object nodeInfo = node.getUserObject();
}
private void createNodes(DefaultMutableTreeNode top) {
for (ThreadInfo ti : toDisplay.getStacks()) {
DefaultMutableTreeNode tgui = createThreadProfile(ti);
top.add(tgui);
}
}
class Vis implements ProfileVisitor {
HashMap<Integer, DefaultMutableTreeNode> parents = new HashMap<>();
public Vis(DefaultMutableTreeNode thread) {
parents.put(0, thread);
}
@Override
public void visit(SFNode stackframe, int level) {
if (level == 0) return;
DefaultMutableTreeNode parent = parents.get(level - 1);
DefaultMutableTreeNode me = new DefaultMutableTreeNode("[" + stackframe.getCount() + "] " + stackframe.getStackFrame());
parent.add(me);
parents.put(level, me);
}
}
private DefaultMutableTreeNode createThreadProfile(ThreadInfo ti) {
Profile p = (Profile) ti.getVal(ThreadInfoProps.STACK);
DefaultMutableTreeNode thread = new DefaultMutableTreeNode(p.getCount() + " " + ti.getVal(ThreadInfoProps.NAME) + " " + ti.getVal(ThreadInfoProps.STATE));
p.visit(new Vis(thread));
return thread;
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event dispatch thread.
*/
public static void createAndShowGUI(ThreadDump td, String title) {
if (useSystemLookAndFeel) {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
System.err.println("Couldn't use system look and feel.");
}
}
//Create and set up the window.
JFrame frame = new JFrame(title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add content to the window.
frame.add(new ThreadDumpGuiViewer(td));
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(() -> createAndShowGUI(null, "mjprof test"));
}
}