/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2007-2009 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at LICENSE.html or
* http://www.sun.com/cddl.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this License Header
* Notice in each file.
*
* If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s): Alexandre (Shura) Iline. (shurymury@gmail.com)
*
* The Original Software is the Jemmy library.
* The Initial Developer of the Original Software is Alexandre Iline.
* All Rights Reserved.
*
*/
/*
* HierarchyView.java
*
* Created on Nov 24, 2009, 11:06:58 PM
*/
package org.jemmy.browser;
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.event.ListDataListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import org.jemmy.control.Wrap;
import org.jemmy.control.Wrapper;
import org.jemmy.lookup.ControlHierarchy;
import org.jemmy.lookup.ControlList;
/**
*
* @author shura
*/
public class HierarchyView extends javax.swing.JFrame {
public static void startApp(final String[] argv) {
new Thread(new Runnable() {
public void run() {
if (argv.length > 0) {
try {
Class appClass = Class.forName(argv[0]);
appClass.getMethod("main", new Class[]{(new String[0]).getClass()}).invoke(null, (Object) Arrays.copyOfRange(argv, 1, argv.length));
} catch (IllegalAccessException ex) {
Logger.getLogger(HierarchyView.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
Logger.getLogger(HierarchyView.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(HierarchyView.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchMethodException ex) {
Logger.getLogger(HierarchyView.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(HierarchyView.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(HierarchyView.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}).start();
}
DefaultTreeModel model;
PropertiesPanel propPanel;
InterfacesPanel intPanel;
BrowserDescriptor descr;
Wrap<?> root;
ArrayList<Class> subHs;
ComboBoxModel comboModel = new MyComboModel();
ReflectionPanel reflectionPanel;
private int sleepValue;
SearchDialog sd = new SearchDialog(this);
ImageLabel imageLabel;
public HierarchyView(BrowserDescriptor descr) throws AWTException {
this(descr, null);
}
private HierarchyView(BrowserDescriptor descr, Wrap<?> root) throws AWTException {
this.descr = descr;
this.root = root;
subHs = new ArrayList<Class>();
setTitle(descr.getTitle());
rebuildModel();
initComponents();
imageLabel = new ImageLabel();
imageScroll.setViewportView(imageLabel);
underPropPanel.setLayout(new BorderLayout());
propPanel = new PropertiesPanel();
underPropPanel.add(propPanel);
underIntPanel.setLayout(new BorderLayout());
intPanel = new InterfacesPanel();
underIntPanel.add(intPanel);
underReflectionPanel.setLayout(new BorderLayout());
reflectionPanel = new ReflectionPanel();
underReflectionPanel.add(reflectionPanel, BorderLayout.CENTER);
controlTree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent arg0) {
try {
MyTreeNode selected = (MyTreeNode) arg0.getPath().getLastPathComponent();
propPanel.setWrap(selected.getWrap());
intPanel.setWrap(selected.getWrap());
reflectionPanel.setControl(selected.getWrap().getControl().getClass());
positionImage(selected.getWrap());
} catch (IllegalAccessException ex) {
Logger.getLogger(HierarchyView.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
Logger.getLogger(HierarchyView.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(HierarchyView.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
refreshingLbl.setVisible(false);
controlTab.setMnemonicAt(0, KeyEvent.VK_1);
controlTab.setMnemonicAt(1, KeyEvent.VK_2);
controlTab.setMnemonicAt(2, KeyEvent.VK_3);
controlTab.setMnemonicAt(3, KeyEvent.VK_4);
robot = new Robot();
}
private void positionImage(Wrap<?> wrap) {
org.jemmy.Rectangle bounds = wrap.getScreenBounds();
imageLabel.setBounds(bounds);
Point center = new Point((int)(bounds.getX() + bounds.getWidth() / 2),
(int)(bounds.getY() + bounds.getHeight() / 2));
center.x -= imageScroll.getViewport().getWidth() / 2;
center.y -= imageScroll.getViewport().getHeight() / 2;
imageScroll.getHorizontalScrollBar().setValue(center.x);
imageScroll.getVerticalScrollBar().setValue(center.y);
}
public ComboBoxModel getComboModel() {
return comboModel;
}
DefaultMutableTreeNode rootNode;
private void rebuildModel() {
rootNode = new DefaultMutableTreeNode("");
model = new DefaultTreeModel(rootNode);
fillAll(descr, rootNode, null);
}
private void fillAll(HierarchyDescriptor subDescr, DefaultMutableTreeNode parent, Wrap wrap) {
ControlList hierarchy = subDescr.getHierarchy();
Wrapper wrapper = subDescr.getWrapper();
List controls = null;
if (wrap == null) {
controls = hierarchy.getControls();
} else {
if (hierarchy instanceof ControlHierarchy) {
controls = ((ControlHierarchy) hierarchy).getChildren(wrap.getControl());
}
}
MyTreeNode node;
if (controls != null) {
for (Object c : controls) {
node = new MyTreeNode(c, wrapper.wrap(Object.class, c));
parent.add(node);
fillAll(subDescr, node, node.getWrap());
}
}
if (wrap != null) {
HierarchyDescriptor hd = subDescr.getSubHierarchyDescriptor(wrap);
if (hd != null) {
fillAll(hd, parent, null);
}
}
}
public DefaultTreeModel getTreeModel() {
return model;
}
/** 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() {
jSplitPane1 = new javax.swing.JSplitPane();
jPanel1 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
controlTree = new javax.swing.JTree();
refreshBtt = new javax.swing.JButton();
jLabel1 = new javax.swing.JLabel();
sleep = new javax.swing.JTextField();
jLabel2 = new javax.swing.JLabel();
refreshingLbl = new javax.swing.JLabel();
jButton1 = new javax.swing.JButton();
controlTab = new javax.swing.JTabbedPane();
underPropPanel = new javax.swing.JPanel();
underReflectionPanel = new javax.swing.JPanel();
underIntPanel = new javax.swing.JPanel();
jPanel2 = new javax.swing.JPanel();
imageScroll = new javax.swing.JScrollPane();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
formKeyReleased(evt);
}
});
jSplitPane1.setDividerLocation(400);
controlTree.setModel(getTreeModel());
controlTree.setRootVisible(false);
controlTree.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
controlTreeKeyReleased(evt);
}
});
jScrollPane1.setViewportView(controlTree);
refreshBtt.setMnemonic('r');
refreshBtt.setText("Refresh");
refreshBtt.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
refreshBttActionPerformed(evt);
}
});
jLabel1.setText("In");
sleep.setText("0");
sleep.setAlignmentX(1.0F);
sleep.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
sleepActionPerformed(evt);
}
});
jLabel2.setText("seconds");
refreshingLbl.setText("Refreshing");
jButton1.setMnemonic('s');
jButton1.setText("Search");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jButton1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 80, Short.MAX_VALUE)
.addComponent(refreshingLbl)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(sleep, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(refreshBtt)
.addContainerGap())
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 425, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(refreshBtt)
.addComponent(jLabel2)
.addComponent(sleep, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel1)
.addComponent(refreshingLbl)
.addComponent(jButton1))
.addContainerGap())
);
jSplitPane1.setLeftComponent(jPanel1);
javax.swing.GroupLayout underPropPanelLayout = new javax.swing.GroupLayout(underPropPanel);
underPropPanel.setLayout(underPropPanelLayout);
underPropPanelLayout.setHorizontalGroup(
underPropPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 433, Short.MAX_VALUE)
);
underPropPanelLayout.setVerticalGroup(
underPropPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 429, Short.MAX_VALUE)
);
controlTab.addTab("1. Properties", underPropPanel);
javax.swing.GroupLayout underReflectionPanelLayout = new javax.swing.GroupLayout(underReflectionPanel);
underReflectionPanel.setLayout(underReflectionPanelLayout);
underReflectionPanelLayout.setHorizontalGroup(
underReflectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 433, Short.MAX_VALUE)
);
underReflectionPanelLayout.setVerticalGroup(
underReflectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 429, Short.MAX_VALUE)
);
controlTab.addTab("2. Reflection", underReflectionPanel);
javax.swing.GroupLayout underIntPanelLayout = new javax.swing.GroupLayout(underIntPanel);
underIntPanel.setLayout(underIntPanelLayout);
underIntPanelLayout.setHorizontalGroup(
underIntPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 433, Short.MAX_VALUE)
);
underIntPanelLayout.setVerticalGroup(
underIntPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 429, Short.MAX_VALUE)
);
controlTab.addTab("3. Interfaces", underIntPanel);
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(imageScroll, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 433, Short.MAX_VALUE)
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(imageScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 429, Short.MAX_VALUE)
);
controlTab.addTab("4. Image", jPanel2);
jSplitPane1.setRightComponent(controlTab);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 851, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 469, Short.MAX_VALUE)
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void refreshBttActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshBttActionPerformed
sleep.setEditable(false);
refreshBtt.setVisible(false);
refreshingLbl.setVisible(true);
new Thread(new Runnable() {
public void run() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
sleepValue = Integer.parseInt(sleep.getText());
}
});
int restSleep = sleepValue;
while (restSleep > 0) {
final String newText = Integer.toString(restSleep);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
sleep.setText(newText);
}
});
Thread.sleep(1000);
restSleep--;
}
rebuildModel();
} catch (InvocationTargetException ex) {
Logger.getLogger(HierarchyView.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException e) {
Logger.getLogger(HierarchyView.class.getName()).log(Level.SEVERE, null, e);
} finally {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
refreshingLbl.setVisible(false);
refreshBtt.setVisible(true);
sleep.setEditable(true);
sleep.setText(Integer.toString(sleepValue));
controlTree.setModel(model);
controlTree.revalidate();
controlTree.requestFocus();
takeShot();
}
});
}
}
}).start();
}//GEN-LAST:event_refreshBttActionPerformed
private Robot robot;
private BufferedImage shot = null;
private Rectangle fullScreen = new Rectangle(new Point(0, 0), Toolkit.getDefaultToolkit().getScreenSize());;
private void takeShot() {
shot = robot.createScreenCapture(fullScreen);
imageLabel.setIcon(new ImageIcon(shot));
}
private void sleepActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sleepActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_sleepActionPerformed
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
sd.setLocation(getLocation().x, getLocation().y + getHeight() - sd.getHeight());
sd.setVisible(true);
if (sd.isConfirmed()) {
MyTreeNode res = search(rootNode, sd.getClassNameFilter(), sd.getPropertyFilter());
if (res != null) {
controlTree.setSelectionPath(new TreePath(res.getPath()));
controlTree.requestFocus();
} else {
String msg = "Class name: \"" + sd.getClassNameFilter() + "\""+
((sd.getPropertyFilter() != null) ? (", property: \"" + sd.getPropertyFilter() + "\"") : "");
JOptionPane.showMessageDialog(null, msg, "None found", JOptionPane.ERROR_MESSAGE);
}
}
}//GEN-LAST:event_jButton1ActionPerformed
private void formKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_formKeyReleased
}//GEN-LAST:event_formKeyReleased
private void controlTreeKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_controlTreeKeyReleased
}//GEN-LAST:event_controlTreeKeyReleased
private MyTreeNode search(DefaultMutableTreeNode node, String className, String property) {
if (node instanceof MyTreeNode && ((MyTreeNode) node).getWrap().getControl().getClass().getName().indexOf(className) > 1) {
MyTreeNode mtnode = (MyTreeNode) node;
if (property != null) {
HashMap<String, Object> props = mtnode.getWrap().getProperties();
for (String prop : props.keySet()) {
if (props.get(prop) != null) {
if (props.get(prop).toString() != null) {
if (props.get(prop).toString().contains(property)) {
return mtnode;
}
}
}
}
} else {
return mtnode;
}
}
MyTreeNode res;
for (int i = 0; i < node.getChildCount(); i++) {
res = search((DefaultMutableTreeNode) node.getChildAt(i), className, property);
if (res != null) {
return res;
}
}
return null;
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JTabbedPane controlTab;
private javax.swing.JTree controlTree;
private javax.swing.JScrollPane imageScroll;
private javax.swing.JButton jButton1;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JSplitPane jSplitPane1;
private javax.swing.JButton refreshBtt;
private javax.swing.JLabel refreshingLbl;
private javax.swing.JTextField sleep;
private javax.swing.JPanel underIntPanel;
private javax.swing.JPanel underPropPanel;
private javax.swing.JPanel underReflectionPanel;
// End of variables declaration//GEN-END:variables
// End of variables declaration
private class MyTreeNode extends DefaultMutableTreeNode {
Wrap wrap = null;
Object control;
public MyTreeNode(Object control, Wrap wrap) {
super(control);
this.control = control;
this.wrap = wrap;
}
public Wrap<?> getWrap() {
return wrap;
}
@Override
public String toString() {
return control.getClass().getName();
}
}
private class MyComboModel implements ComboBoxModel {
Class<?> selected;
public void setSelectedItem(Object arg0) {
System.out.println(arg0 + " selected");
selected = (Class<?>) arg0;
}
public Object getSelectedItem() {
System.out.println("selected = " + selected);
return selected;
}
public int getSize() {
return subHs.size();
}
public Object getElementAt(int arg0) {
return subHs.get(arg0);
}
public void addListDataListener(ListDataListener arg0) {
}
public void removeListDataListener(ListDataListener arg0) {
}
}
}