package kg.apc.jmeter.vizualizers;
import java.awt.event.InputEvent;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.tree.*;
import kg.apc.charting.AbstractGraphRow;
import kg.apc.jmeter.JMeterPluginsUtils;
import kg.apc.jmeter.graphs.CompositeNotifierInterface;
import kg.apc.jmeter.graphs.GraphRendererInterface;
public class JCompositeRowsSelectorPanel extends javax.swing.JPanel implements GraphRendererInterface, CompositeNotifierInterface {
private CompositeModel compositeModel;
private DefaultMutableTreeNode root1;
private DefaultMutableTreeNode root2;
private DefaultTreeModel model1;
private DefaultTreeModel model2;
private Icon folderIcon = new ImageIcon(JCompositeRowsSelectorPanel.class.getResource("folder.png"));
private Icon folderLinkIcon = new ImageIcon(JCompositeRowsSelectorPanel.class.getResource("folderLink.png"));
private Icon leafIcon = new ImageIcon(JCompositeRowsSelectorPanel.class.getResource("treeLeaf.png"));
private static String tree1RootName = "Test Plan";
private static String tree2RootName = "Composite Graph";
private CompositeGraphGui gui;
/**
* Creates new form JRowsSelectorPanel
*/
public JCompositeRowsSelectorPanel(CompositeModel compositeModel, CompositeGraphGui gui) {
this.compositeModel = compositeModel;
this.gui = gui;
initComponents();
root1 = new DefaultMutableTreeNode(tree1RootName, true);
model1 = new DefaultTreeModel(root1);
root2 = new DefaultMutableTreeNode(tree2RootName, true);
model2 = new DefaultTreeModel(root2);
jTreeGraph1.setModel(model1);
jTreeGraph2.setModel(model2);
DefaultTreeCellRenderer renderer1 = new DefaultTreeCellRenderer();
renderer1.setOpenIcon(folderIcon);
renderer1.setClosedIcon(folderIcon);
renderer1.setLeafIcon(leafIcon);
jTreeGraph1.setCellRenderer(renderer1);
DefaultTreeCellRenderer renderer2 = new DefaultTreeCellRenderer();
renderer2.setOpenIcon(folderLinkIcon);
renderer2.setClosedIcon(folderLinkIcon);
renderer2.setLeafIcon(leafIcon);
jTreeGraph2.setCellRenderer(renderer2);
}
public void updateGraph() {
gui.updateGui();
}
public Iterator<String[]> getItems() {
ConcurrentLinkedQueue<String[]> tmp = new ConcurrentLinkedQueue<String[]>();
for (int i = 0; i < root2.getChildCount(); i++) {
TreeNode nodeChart = root2.getChildAt(i);
String chart = nodeChart.toString();
for (int j = 0; j < nodeChart.getChildCount(); j++) {
String[] item = new String[2];
item[0] = chart;
item[1] = nodeChart.getChildAt(j).toString();
tmp.add(item);
}
}
return tmp.iterator();
}
private void expandAll(JTree tree, boolean expand) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
// Traverse tree from root
expandAll(tree, new TreePath(root), expand);
}
private void expandAll(JTree tree, TreePath parent, boolean expand) {
// Traverse children
TreeNode node = (TreeNode) parent.getLastPathComponent();
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements(); ) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
expandAll(tree, path, expand);
}
}
// Expansion or collapse must be done bottom-up
if (expand) {
tree.expandPath(parent);
} else {
tree.collapsePath(parent);
}
}
private boolean isNodeContained(String nodeName, DefaultMutableTreeNode root) {
Enumeration children = root.children();
while (children.hasMoreElements()) {
DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
if (nodeName.equals(child.toString())) {
return true;
}
}
return false;
}
private DefaultMutableTreeNode getNode(String nodeName, DefaultMutableTreeNode root) {
if (root != null) {
Enumeration children = root.children();
while (children.hasMoreElements()) {
DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
if (nodeName.equals(child.toString())) {
return child;
}
}
}
return null;
}
public void clearData() {
gui.updateGui();
}
private synchronized void updateTree() {
//get previous selection
TreePath selection = jTreeGraph1.getSelectionPath();
//rows will not disapear, only chart if cleared...
boolean chartsUpdated = false;
//first, check if we need to remove some visualizers
for (int i = 0; i < root1.getChildCount(); i++) {
TreeNode node = root1.getChildAt(i);
if (!compositeModel.containsVisualizer(node.toString())) {
chartsUpdated = true;
model1.removeNodeFromParent((MutableTreeNode) node);
i--;
}
}
Iterator<String> chartsIter = compositeModel.getVizualizerNamesIterator();
while (chartsIter.hasNext()) {
String chartName = chartsIter.next();
if (!isNodeContained(chartName, root1)) {
chartsUpdated = true;
DefaultMutableTreeNode node1 = new DefaultMutableTreeNode(chartName, true);
root1.add(node1);
Iterator<AbstractGraphRow> rowsIter = compositeModel.getRowsIterator(chartName);
while (rowsIter.hasNext()) {
AbstractGraphRow row = rowsIter.next();
node1.add(new DefaultMutableTreeNode(row.getLabel(), false));
}
} else {
Iterator<AbstractGraphRow> rowsIter = compositeModel.getRowsIterator(chartName);
DefaultMutableTreeNode chartNode1 = getNode(chartName, root1);
while (rowsIter.hasNext()) {
String rowName = rowsIter.next().getLabel();
if (!isNodeContained(rowName, chartNode1)) {
chartsUpdated = true;
chartNode1.add(new DefaultMutableTreeNode(rowName, false));
}
}
}
}
if (chartsUpdated) {
model1.nodeStructureChanged(root1);
expandAll(jTreeGraph1, true);
//restore selection
jTreeGraph1.setSelectionPath(selection);
}
}
/**
* This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
jPanelLogo = new javax.swing.JPanel();
jLabelLogo = new javax.swing.JLabel();
jPanel1 = new javax.swing.JPanel();
jPanelMain = new javax.swing.JPanel();
jPanelRowsTable = new javax.swing.JPanel();
jLabelGraph1 = new javax.swing.JLabel();
jLabelGraph2 = new javax.swing.JLabel();
jScrollPaneGraph1 = new javax.swing.JScrollPane();
jTreeGraph1 = new javax.swing.JTree();
jScrollPaneGraph = new javax.swing.JScrollPane();
jTreeGraph2 = new javax.swing.JTree();
jPanelButtons = new javax.swing.JPanel();
jButtonAdd = new javax.swing.JButton();
jButtonRemove = new javax.swing.JButton();
jPanelGraphPreview = new javax.swing.JPanel();
jLabelPreview = new javax.swing.JLabel();
setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
setLayout(new java.awt.BorderLayout());
jPanelLogo.setLayout(new java.awt.GridBagLayout());
jLabelLogo.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
jLabelLogo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kg/apc/jmeter/vizualizers/logoSimple.png"))); // NOI18N
jLabelLogo.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
jLabelLogo.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jLabelLogoMouseClicked(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
jPanelLogo.add(jLabelLogo, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
jPanelLogo.add(jPanel1, gridBagConstraints);
add(jPanelLogo, java.awt.BorderLayout.PAGE_END);
jPanelMain.setLayout(new java.awt.GridBagLayout());
jPanelRowsTable.setMaximumSize(new java.awt.Dimension(206, 23));
jPanelRowsTable.setPreferredSize(new java.awt.Dimension(206, 23));
jPanelRowsTable.setLayout(new java.awt.GridBagLayout());
jLabelGraph1.setText("Available Sources:");
jLabelGraph1.setMaximumSize(new java.awt.Dimension(120, 14));
jLabelGraph1.setMinimumSize(new java.awt.Dimension(120, 14));
jLabelGraph1.setPreferredSize(new java.awt.Dimension(120, 14));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(2, 4, 2, 4);
jPanelRowsTable.add(jLabelGraph1, gridBagConstraints);
jLabelGraph2.setText("Composed Graph:");
jLabelGraph2.setMaximumSize(new java.awt.Dimension(120, 14));
jLabelGraph2.setMinimumSize(new java.awt.Dimension(120, 14));
jLabelGraph2.setPreferredSize(new java.awt.Dimension(120, 14));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(2, 4, 2, 2);
jPanelRowsTable.add(jLabelGraph2, gridBagConstraints);
jScrollPaneGraph1.setMaximumSize(new java.awt.Dimension(72, 64));
jScrollPaneGraph1.setMinimumSize(new java.awt.Dimension(72, 64));
jScrollPaneGraph1.setPreferredSize(new java.awt.Dimension(72, 64));
jTreeGraph1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jTreeGraph1MouseClicked(evt);
}
});
jScrollPaneGraph1.setViewportView(jTreeGraph1);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(2, 4, 2, 4);
jPanelRowsTable.add(jScrollPaneGraph1, gridBagConstraints);
jTreeGraph2.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jTreeGraph2MouseClicked(evt);
}
});
jScrollPaneGraph.setViewportView(jTreeGraph2);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(2, 4, 2, 2);
jPanelRowsTable.add(jScrollPaneGraph, gridBagConstraints);
jPanelButtons.setFocusable(false);
jPanelButtons.setLayout(new java.awt.GridLayout(0, 1, 0, 6));
jButtonAdd.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kg/apc/jmeter/vizualizers/rightArrow.png"))); // NOI18N
jButtonAdd.setFocusable(false);
jButtonAdd.setMaximumSize(new java.awt.Dimension(30, 25));
jButtonAdd.setMinimumSize(new java.awt.Dimension(30, 25));
jButtonAdd.setPreferredSize(new java.awt.Dimension(30, 25));
jButtonAdd.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonAddActionPerformed(evt);
}
});
jPanelButtons.add(jButtonAdd);
jButtonRemove.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kg/apc/jmeter/vizualizers/leftArrow.png"))); // NOI18N
jButtonRemove.setFocusable(false);
jButtonRemove.setMaximumSize(new java.awt.Dimension(30, 25));
jButtonRemove.setMinimumSize(new java.awt.Dimension(30, 25));
jButtonRemove.setPreferredSize(new java.awt.Dimension(30, 25));
jButtonRemove.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonRemoveActionPerformed(evt);
}
});
jPanelButtons.add(jButtonRemove);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
jPanelRowsTable.add(jPanelButtons, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
jPanelMain.add(jPanelRowsTable, gridBagConstraints);
jPanelGraphPreview.setLayout(new java.awt.BorderLayout());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 4);
jPanelMain.add(jPanelGraphPreview, gridBagConstraints);
jLabelPreview.setText("Preview:");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
jPanelMain.add(jLabelPreview, gridBagConstraints);
add(jPanelMain, java.awt.BorderLayout.CENTER);
}// </editor-fold>//GEN-END:initComponents
public void addItemsToComposite(String testplan, String row) {
String[] path = new String[3];
path[0] = tree2RootName;
path[1] = testplan;
path[2] = row;
TreePath[] tp = new TreePath[1];
tp[0] = new TreePath(path);
addItemsToComposite(tp);
}
private void addItemsToComposite(TreePath[] paths) {
for (int i = 0; i < paths.length; i++) {
if (paths[i].getPath().length == 1) {
//do nothi8ng for now, root was selected
} else if (paths[i].getPath().length == 2) {
//a chart is selected, we add all nodes...
String chartName = paths[i].getPath()[1].toString();
DefaultMutableTreeNode chartNode = getNode(chartName, root1);
DefaultMutableTreeNode chartNode2;
if (!isNodeContained(chartName, root2)) {
chartNode2 = new DefaultMutableTreeNode(chartName, true);
root2.add(chartNode2);
} else {
chartNode2 = getNode(chartName, root2);
}
for (int n = 0; n < chartNode.getChildCount(); n++) {
if (!isNodeContained(chartNode.getChildAt(n).toString(), chartNode2)) {
chartNode2.add(new DefaultMutableTreeNode(chartNode.getChildAt(n).toString(), false));
model2.nodeStructureChanged(root2);
expandAll(jTreeGraph2, true);
}
}
} else if (paths[i].getPath().length == 3) {
String chartName = paths[i].getPath()[1].toString();
DefaultMutableTreeNode chartNode;
if (!isNodeContained(chartName, root2)) {
chartNode = new DefaultMutableTreeNode(chartName, true);
root2.add(chartNode);
} else {
chartNode = getNode(chartName, root2);
}
if (!isNodeContained(paths[i].getPath()[2].toString(), chartNode)) {
chartNode.add(new DefaultMutableTreeNode(paths[i].getPath()[2].toString(), false));
model2.nodeStructureChanged(root2);
expandAll(jTreeGraph2, true);
}
}
}
updateGraph();
}
private void removeItemFromComposite(TreePath[] paths) {
for (int i = 0; i < paths.length; i++) {
if (paths[i].getPath().length == 1) {
//do nothing root was selected
} else if (paths[i].getPath().length == 2) {
TreeNode node = getNode(paths[i].getPath()[1].toString(), root2);
model2.removeNodeFromParent((MutableTreeNode) node);
} else if (paths[i].getPath().length == 3) {
TreeNode chartNode = getNode(paths[i].getPath()[1].toString(), root2);
TreeNode rowNode = getNode(paths[i].getPath()[2].toString(), (DefaultMutableTreeNode) chartNode);
if (rowNode != null) {
model2.removeNodeFromParent((MutableTreeNode) rowNode);
}
if (chartNode != null) {
if (chartNode.getChildCount() == 0) {
model2.removeNodeFromParent((MutableTreeNode) chartNode);
}
}
}
}
model2.nodeStructureChanged(root2);
expandAll(jTreeGraph2, true);
updateGraph();
}
private void jButtonAddActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jButtonAddActionPerformed
{//GEN-HEADEREND:event_jButtonAddActionPerformed
TreePath[] paths = jTreeGraph1.getSelectionPaths();
if (paths != null) {
addItemsToComposite(paths);
}
}//GEN-LAST:event_jButtonAddActionPerformed
private void jButtonRemoveActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jButtonRemoveActionPerformed
{//GEN-HEADEREND:event_jButtonRemoveActionPerformed
TreePath[] paths = jTreeGraph2.getSelectionPaths();
if (paths != null) {
removeItemFromComposite(paths);
}
}//GEN-LAST:event_jButtonRemoveActionPerformed
private void jTreeGraph1MouseClicked(java.awt.event.MouseEvent evt)//GEN-FIRST:event_jTreeGraph1MouseClicked
{//GEN-HEADEREND:event_jTreeGraph1MouseClicked
if (evt.getClickCount() == 2) {
TreePath[] paths = jTreeGraph1.getSelectionPaths();
if (paths != null && paths.length == 1) {
if (paths[0].getPath().length == 3) {
addItemsToComposite(paths);
}
}
}
}//GEN-LAST:event_jTreeGraph1MouseClicked
private void jTreeGraph2MouseClicked(java.awt.event.MouseEvent evt)//GEN-FIRST:event_jTreeGraph2MouseClicked
{//GEN-HEADEREND:event_jTreeGraph2MouseClicked
if (evt.getClickCount() == 2) {
TreePath[] paths = jTreeGraph2.getSelectionPaths();
if (paths != null && paths.length == 1) {
if (paths[0].getPath().length == 3) {
removeItemFromComposite(paths);
}
}
}
}//GEN-LAST:event_jTreeGraph2MouseClicked
private void jLabelLogoMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabelLogoMouseClicked
if ((evt.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
JMeterPluginsUtils.openInBrowser(JMeterPluginsUtils.WIKI_BASE + "?utm_source=jmeter&utm_medium=logolink&utm_campaign=" + gui.getWikiPage());
}
}//GEN-LAST:event_jLabelLogoMouseClicked
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButtonAdd;
private javax.swing.JButton jButtonRemove;
private javax.swing.JLabel jLabelGraph1;
private javax.swing.JLabel jLabelGraph2;
private javax.swing.JLabel jLabelLogo;
private javax.swing.JLabel jLabelPreview;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanelButtons;
private javax.swing.JPanel jPanelGraphPreview;
private javax.swing.JPanel jPanelLogo;
private javax.swing.JPanel jPanelMain;
private javax.swing.JPanel jPanelRowsTable;
private javax.swing.JScrollPane jScrollPaneGraph;
private javax.swing.JScrollPane jScrollPaneGraph1;
private javax.swing.JTree jTreeGraph1;
private javax.swing.JTree jTreeGraph2;
// End of variables declaration//GEN-END:variables
@Override
public JPanel getGraphDisplayPanel() {
return jPanelGraphPreview;
}
@Override
public boolean isPreview() {
return true;
}
@Override
public void refresh() {
updateTree();
}
}