Files
jlibwinapi/src/org/synthuse/SynthuseDlg.java
2014-04-08 22:44:07 -04:00

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);
}
}
}