/* * Copyright 2014, Synthuse.org * Released under the Apache Version 2.0 License. * * last modified by ejakubowski */ package org.synthuse; import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Point; import java.awt.Toolkit; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; import javax.swing.DefaultComboBoxModel; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JToolBar; import javax.swing.JSplitPane; import javax.swing.JRadioButton; import javax.swing.WindowConstants; import java.awt.Component; import javax.swing.Box; import javax.swing.ButtonGroup; import javax.swing.JButton; import java.awt.Dimension; import javax.swing.JComboBox; import javax.swing.JScrollPane; /* import com.jgoodies.forms.layout.FormLayout; import com.jgoodies.forms.layout.ColumnSpec; import com.jgoodies.forms.layout.RowSpec; import com.jgoodies.forms.factories.FormFactory; */ import com.sun.jna.platform.win32.WinDef.HWND; import javax.swing.JLabel; import javax.swing.SwingConstants; import java.awt.FlowLayout; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.List; import javax.swing.JTextPane; import org.synthuse.Api.User32; import org.synthuse.DragTarget.dragEvents; //public class SynthuseDlg extends JDialog { public class SynthuseDlg extends JFrame { /** * */ public static String VERSION_STR = "1.1.2"; public static String RES_STR_MAIN_ICON = "/org/synthuse/img/gnome-robots.png"; public static String RES_STR_REFRESH_IMG = "/org/synthuse/img/rapidsvn.png"; public static String RES_STR_TESTIDE_IMG = "/org/synthuse/img/applications-education.png"; public static String RES_STR_HELP_IMG = "/org/synthuse/img/help-3.png"; public static String RES_STR_TARGET_IMG = "/org/synthuse/img/bullseye-logo-th18x18.png"; public static String RES_STR_FIND_IMG = "/org/synthuse/img/edit-find-3.png"; public static String RES_STR_SETACTION_IMG = "/org/synthuse/img/document-new-5.png"; public static String RES_STR_CANCEL_IMG = "/org/synthuse/img/document-close-2.png"; public static List actionListQueue = new ArrayList(); private static final long serialVersionUID = 1L; private XpathManager.Events xpathEvents = null; private JPanel contentPane; private JLabel lblStatus; private JButton btnRefresh; private JTextPane textPane; private JButton btnSetAction; private JButton btnCancel; private JButton btnFind; public static Config config = new Config(Config.DEFAULT_PROP_FILENAME); private String dialogResult = ""; private String lastDragHwnd = ""; private String lastRuntimeId =""; private JComboBox cmbXpath; private JButton btnTestIde; private TestIdeFrame testIde = null; private int targetX; private int targetY; private UiaBridge uiabridge = new UiaBridge(); /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { SynthuseDlg frame = new SynthuseDlg(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the frame. */ public SynthuseDlg() { setIconImage(Toolkit.getDefaultToolkit().getImage(SynthuseDlg.class.getResource(RES_STR_MAIN_ICON))); //setModal(true); setTitle("Synthuse"); setBounds(100, 100, 827, 420); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPane.setLayout(new BorderLayout(0, 0)); setContentPane(contentPane); JToolBar toolBar = new JToolBar(); contentPane.add(toolBar, BorderLayout.NORTH); JRadioButton rdbtnWindows = new JRadioButton("Windows Enumerated Xml"); rdbtnWindows.setSelected(true); toolBar.add(rdbtnWindows); Component horizontalStrut = Box.createHorizontalStrut(20); toolBar.add(horizontalStrut); JRadioButton rdbtnUrl = new JRadioButton("Url: "); rdbtnUrl.setEnabled(false); toolBar.add(rdbtnUrl); // Group the radio buttons. ButtonGroup group = new ButtonGroup(); group.add(rdbtnWindows); group.add(rdbtnUrl); JComboBox cmbUrl = new JComboBox(); cmbUrl.setEnabled(false); cmbUrl.setEditable(true); toolBar.add(cmbUrl); Component horizontalStrut_1 = Box.createHorizontalStrut(20); toolBar.add(horizontalStrut_1); btnRefresh = new JButton(" Refresh "); btnRefresh.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { //WindowsEnumeratedXml wex = new WindowsEnumeratedXml(textPane, lblStatus); //wex.run(); WindowsEnumeratedXml.getXmlThreaded(textPane, lblStatus); } }); btnRefresh.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_REFRESH_IMG))); toolBar.add(btnRefresh); Component horizontalStrut_3 = Box.createHorizontalStrut(20); toolBar.add(horizontalStrut_3); btnTestIde = new JButton("Test IDE"); btnTestIde.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { if (testIde == null) { testIde = new TestIdeFrame(); if (SynthuseDlg.actionListQueue.size() > 0) { // if stuff is already in the queue add it to the test ide for (String action : SynthuseDlg.actionListQueue) { testIde.txtTest.append(action + "\n"); } } } testIde.setVisible(true); } }); btnTestIde.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_TESTIDE_IMG))); toolBar.add(btnTestIde); Component horizontalStrut_2 = Box.createHorizontalStrut(20); toolBar.add(horizontalStrut_2); JButton helpBtn = new JButton("Help"); helpBtn.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_HELP_IMG))); helpBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { String about = ""; about += "Synthuse Version " + VERSION_STR + " create by Edward Jakubowski ejakubowski7@gmail.com\n\n"; about += "System information: \n"; about += " Java version - " + System.getProperty("java.version") + "\n"; about += " Java home - " + System.getProperty("java.home") + "\n"; about += " OS Name - " + System.getProperty("os.name") + "\n"; about += " OS Arch - " + System.getProperty("os.arch") + "\n"; String jclasspath = System.getProperty("java.class.path"); jclasspath = jclasspath.replaceAll(";", ";\n "); if (!System.getProperty("os.name").startsWith("Windows")) jclasspath = jclasspath.replaceAll(":", ":\n "); about += " Java class path - " + jclasspath + "\n\n"; JOptionPane.showMessageDialog(null, about , "About", JOptionPane.QUESTION_MESSAGE); } }); toolBar.add(helpBtn); JSplitPane splitPane = new JSplitPane(); splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT); contentPane.add(splitPane, BorderLayout.CENTER); JPanel panel = new JPanel(); panel.setMinimumSize(new Dimension(20, 35)); splitPane.setLeftComponent(panel); /* panel.setLayout(new FormLayout(new ColumnSpec[] { FormFactory.RELATED_GAP_COLSPEC, ColumnSpec.decode("left:max(11dlu;default)"), FormFactory.RELATED_GAP_COLSPEC, ColumnSpec.decode("left:default"), FormFactory.RELATED_GAP_COLSPEC, FormFactory.DEFAULT_COLSPEC, FormFactory.RELATED_GAP_COLSPEC, FormFactory.DEFAULT_COLSPEC, FormFactory.RELATED_GAP_COLSPEC, FormFactory.DEFAULT_COLSPEC,}, new RowSpec[] { FormFactory.RELATED_GAP_ROWSPEC, RowSpec.decode("default:grow"),})); */ panel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 0.5; c.gridwidth = 1; c.gridx = 0; c.gridy = 0; c.insets = new Insets(3,3,3,3); // add padding around objects DragTarget lblTarget = new DragTarget(); lblTarget.setHorizontalAlignment(SwingConstants.CENTER); lblTarget.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_TARGET_IMG))); panel.add(lblTarget, c); btnFind = new JButton("Find"); btnFind.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { String xpathItem = cmbXpath.getSelectedItem().toString(); int matches = XpathManager.nextXpathMatch(xpathItem, textPane, lblStatus, false); if (matches < 0) //check for an error return; //don't save bad xpath to combobox if (config.xpathList == null) config.xpathList = ""; if (!config.xpathList.contains(xpathItem + "\u00ba")){ config.xpathList += xpathItem + "\u00ba"; refreshDatabinding(); cmbXpath.setSelectedItem(xpathItem); } } }); cmbXpath = new JComboBox(); cmbXpath.setPreferredSize(new Dimension(440, 20));//fix the width of the combobox cmbXpath.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");//fix the width of the combobox cmbXpath.setEditable(true); cmbXpath.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ENTER) { btnFind.doClick(); } } }); c.gridwidth = 3; c.gridx = 1; panel.add(cmbXpath, c); btnFind.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_FIND_IMG))); c.gridwidth = 1; c.gridx = 4; panel.add(btnFind, c); btnSetAction = new JButton("Set Action"); btnSetAction.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { CommandPopupMenu menu = new CommandPopupMenu(); final String xpathItem = cmbXpath.getSelectedItem().toString(); menu.events = new CommandPopupMenu.menuEvents() { @Override public void menuItemClicked(String command, int paramCount, boolean useXpath, ActionEvent e) { String actionStr = CommandPopupMenu.buildSkeletonCommand(command, paramCount, xpathItem, useXpath); SynthuseDlg.actionListQueue.add(actionStr); lblStatus.setText("Setting Action: " + actionStr); if (testIde != null) testIde.txtTest.append(actionStr + "\n"); } }; Component c = (Component) e.getSource(); menu.show(c, -1, c.getHeight()); } }); btnSetAction.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_SETACTION_IMG))); c.gridwidth = 1; c.gridx = 5; panel.add(btnSetAction, c); btnCancel = new JButton("Cancel"); btnCancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { dialogResult = ""; SynthuseDlg.this.disposeWindow(); } }); btnCancel.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_CANCEL_IMG))); c.gridwidth = 1; c.gridx = 6; panel.add(btnCancel, c); JScrollPane scrollPane = new JScrollPane(); splitPane.setRightComponent(scrollPane); textPane = new JTextPane(); textPane.setEditable(false); textPane.setEditorKitForContentType("text/xml", new XmlEditorKit()); textPane.setContentType("text/xml"); scrollPane.setViewportView(textPane); JPanel panel_1 = new JPanel(); FlowLayout flowLayout = (FlowLayout) panel_1.getLayout(); flowLayout.setAlignment(FlowLayout.LEFT); panel_1.setMinimumSize(new Dimension(20, 20)); contentPane.add(panel_1, BorderLayout.SOUTH); lblStatus = new JLabel("Status:"); lblStatus.setHorizontalAlignment(SwingConstants.LEFT); lblStatus.setVerticalAlignment(SwingConstants.TOP); panel_1.add(lblStatus); xpathEvents = new XpathManager.Events() { @Override public void statusChanged(String status) { lblStatus.setText(status); } @Override public void executionCompleted(Object input, String results) { //buildXpathStatementThreaded finished, with results being the xpath statement if (input instanceof HWND) { // in case thread takes long time to process lastDragHwnd = Api.GetHandleAsString((HWND)input); } XpathManager.nextXpathMatch(results, textPane, lblStatus, true); cmbXpath.setSelectedItem(results); } }; lblTarget.events = new dragEvents() { public void dragStarted(JComponent c) { //might be nice to minimize this window, if we weren't displaying realtime information about each window } public void dragMouseMoved(int x, int y) { targetX = x; targetY = y; targetDragged(); } public void dropped(JComponent c) { lastDragHwnd = ""; //sometimes with multithreaded the order becomes incorrect, so we may want to refresh this on dropped. targetDragged(); } }; this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent arg0) { KeyboardHook.stopGlobalKeyboardHook(); //stop keyboard hook config.save(); SynthuseDlg.this.dispose(); // force app to close } }); KeyboardHook.addKeyEvent(KeyEvent.VK_3, true, true, false);// refresh xml when CTRL+SHIFT+3 is pressed //add global hook and event KeyboardHook.StartGlobalKeyboardHookThreaded(new KeyboardHook.KeyboardEvents() { @Override public void keyPressed(KeyboardHook.TargetKeyPress target) { //System.out.println("target key pressed " + target.targetKeyCode); if (target.targetKeyCode == KeyEvent.VK_3){ btnRefresh.doClick(); } } }); btnRefresh.doClick(); refreshDatabinding(); } /* @Override public void setVisible(final boolean visible) { // make sure that frame is marked as not disposed if it is asked to be visible if (visible) { //setDisposed(false); } // let's handle visibility... if (!visible || !isVisible()) { // have to check this condition simply because super.setVisible(true) invokes toFront if frame was already visible super.setVisible(visible); } // ...and bring frame to the front.. in a strange and weird way if (visible) { int state = super.getExtendedState(); state &= ~JFrame.ICONIFIED; super.setExtendedState(state); super.setAlwaysOnTop(true); super.toFront(); super.requestFocus(); super.setAlwaysOnTop(false); } } */ public String showDialog() { //this.setModal(true); Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); this.setLocation(dim.width/2-this.getSize().width/2, dim.height/2-this.getSize().height/2); this.setVisible(true); return dialogResult; } public void refreshDatabinding() { if (config.xpathList != null) cmbXpath.setModel(new DefaultComboBoxModel(config.xpathList.split("\u00ba"))); if (config.xpathHightlight != null) XmlEditorKit.TAG_HIGHLIGHTED = config.xpathHightlight; } public void targetDragged() { HWND hwnd = Api.GetWindowFromPoint(new Point(targetX,targetY)); String handleStr = Api.GetHandleAsString(hwnd); String classStr = WindowsEnumeratedXml.escapeXmlAttributeValue(Api.GetWindowClassName(hwnd)); String parentStr = Api.GetHandleAsString(User32.instance.GetParent(hwnd)); String enumProperties = uiabridge.getWindowInfo(targetX, targetY, WindowInfo.UIA_PROPERTY_LIST); String runtimeId = WindowInfo.getRuntimeIdFromProperties(enumProperties); lblStatus.setText("rid:" + runtimeId + " class: " + classStr + " hWnd: " + handleStr + " parent: " + parentStr + " X,Y: " + targetX + ", " + targetY); if (!lastDragHwnd.equals(handleStr) || !lastRuntimeId.equals(runtimeId)) { if (!lastDragHwnd.isEmpty()) { Api.refreshWindow(Api.GetHandleFromString(lastDragHwnd)); } lastDragHwnd = handleStr; lastRuntimeId = runtimeId; //lastDragHwnd = (hwnd + ""); Api.highlightWindow(hwnd); XpathManager.buildXpathStatementThreaded(hwnd, enumProperties, textPane, xpathEvents); } } public void disposeWindow() { WindowEvent closingEvent = new WindowEvent(this, WindowEvent.WINDOW_CLOSING); Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(closingEvent); } }