442 lines
14 KiB
Java
442 lines
14 KiB
Java
/*
|
|
* 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.0.9";
|
|
|
|
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<String> actionListQueue = new ArrayList<String>();
|
|
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<String> cmbXpath;
|
|
private JButton btnTestIde;
|
|
|
|
private TestIdeFrame testIde = null;
|
|
private int targetX;
|
|
private int targetY;
|
|
private WpfBridge wpf = new WpfBridge();
|
|
|
|
/**
|
|
* 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<String> cmbUrl = new JComboBox<String>();
|
|
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) {
|
|
//lblStatus.setText("Loading Windows Enumerated Xml...");
|
|
//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) {
|
|
JOptionPane.showMessageDialog(null, "Version " + VERSION_STR + " create by Edward Jakubowski ejakubowski7@gmail.com", "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<String>();
|
|
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.dispose();
|
|
}
|
|
});
|
|
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) {
|
|
|
|
config.save();
|
|
SynthuseDlg.this.dispose(); // force app to close
|
|
}
|
|
});
|
|
|
|
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<String>(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 runtimeId = wpf.getRuntimeIdFromPoint(targetX, targetY);
|
|
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, runtimeId, textPane, xpathEvents);
|
|
}
|
|
}
|
|
}
|