Synthuse version 1.0.5
base version by ejakubowski
8
.classpath
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||||
|
<classpathentry kind="lib" path="lib/jna-3.4.0.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/platform-3.4.0.jar"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
||||||
17
.project
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>Synthuse</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
11
.settings/org.eclipse.jdt.core.prefs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.6
|
||||||
BIN
lib/jna-3.4.0.jar
Normal file
BIN
lib/platform-3.4.0.jar
Normal file
30
readme.txt
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
Synthuse
|
||||||
|
|
||||||
|
Version 1.0.5 released on 1-30-2014
|
||||||
|
By Edward Jakubowski ejakubowski7@gmail.com
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Synthuse is a portable java base software testing framework for desktop windows
|
||||||
|
applications. This framework has a built-in object spy and automation Test IDE.
|
||||||
|
What makes this different from other frameworks is that it shares similar command
|
||||||
|
syntax as Selenium. It also utilizes Xpath statements to locate target windows/objects
|
||||||
|
The familar syntaxes makes it easier to train automation tester in this frameworks.
|
||||||
|
|
||||||
|
|
||||||
|
Configurations:
|
||||||
|
All configurable settings are stored in the following file: synthuse.properties
|
||||||
|
Changes to this file will not take affect until you restart the application.
|
||||||
|
Example synthuse.properties file below:
|
||||||
|
urlList=
|
||||||
|
xpathList=//win[@class\='Notepad']\u00BA
|
||||||
|
xpathHightlight=.*process\="([^"]*)".*
|
||||||
|
|
||||||
|
|
||||||
|
Software Requirements:
|
||||||
|
- Java 1.6 or greater
|
||||||
|
|
||||||
|
|
||||||
|
Release Notes:
|
||||||
|
1-30-2014 version 1.0.5
|
||||||
|
- Base version
|
||||||
|
|
||||||
399
src/org/synthuse/Api.java
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
|
||||||
|
import com.sun.jna.Native;
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.HDC;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.HPEN;
|
||||||
|
import com.sun.jna.platform.win32.WinNT.HANDLE;
|
||||||
|
import com.sun.jna.platform.win32.WinUser;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.HWND;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.LPARAM;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.LRESULT;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.RECT;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.WPARAM;
|
||||||
|
import com.sun.jna.platform.win32.WinNT.LARGE_INTEGER;
|
||||||
|
import com.sun.jna.platform.win32.WinUser.WNDENUMPROC;
|
||||||
|
import com.sun.jna.ptr.PointerByReference;
|
||||||
|
import com.sun.jna.win32.W32APIOptions;
|
||||||
|
|
||||||
|
public class Api {
|
||||||
|
|
||||||
|
public static int WM_SETTEXT = 0x000c;
|
||||||
|
public static int WM_GETTEXT = 0x000D;
|
||||||
|
public static int WM_GETTEXTLENGTH = 0x000E;
|
||||||
|
public static int WM_MOUSEMOVE = 0x200;
|
||||||
|
public static int WM_LBUTTONDOWN = 0x0201;
|
||||||
|
public static int WM_LBUTTONUP = 0x0202;
|
||||||
|
public static int WM_LBUTTONDBLCLK = 0x203;
|
||||||
|
public static int WM_RBUTTONDOWN = 0x0204;
|
||||||
|
public static int WM_RBUTTONUP = 0x0205;
|
||||||
|
public static int WM_RBUTTONDBLCLK = 0x206;
|
||||||
|
public static int WM_MBUTTONDOWN = 0x207;
|
||||||
|
public static int WM_MBUTTONUP = 0x208;
|
||||||
|
public static int WM_MBUTTONDBLCLK = 0x209;
|
||||||
|
public static int WM_MOUSEWHEEL = 0x20A;
|
||||||
|
public static int WM_MOUSEHWHEEL = 0x20E;
|
||||||
|
public static int WM_MOUSEHOVER = 0x2A1;
|
||||||
|
public static int WM_NCMOUSELEAVE = 0x2A2;
|
||||||
|
public static int WM_MOUSELEAVE = 0x2A3;
|
||||||
|
|
||||||
|
public static int WM_CLOSE = 0x10;
|
||||||
|
public static int WM_DESTROY = 0x0002;
|
||||||
|
public static int WM_NCDESTROY = 0x0082;
|
||||||
|
public static int WM_QUIT = 0x12;
|
||||||
|
|
||||||
|
public static int WM_SETFOCUS = 0x0007;
|
||||||
|
public static int WM_NEXTDLGCTL = 0x0028;
|
||||||
|
public static int WM_ENABLE = 0x000A;
|
||||||
|
public static int WM_KEYFIRST = 0x100;
|
||||||
|
public static int WM_KEYDOWN = 0x100;
|
||||||
|
public static int WM_KEYUP = 0x101;
|
||||||
|
public static int WM_CHAR = 0x102;
|
||||||
|
public static int WM_DEADCHAR = 0x103;
|
||||||
|
public static int WM_SYSKEYDOWN = 0x104;
|
||||||
|
public static int WM_SYSKEYUP = 0x105;
|
||||||
|
public static int WM_SYSCHAR = 0x106;
|
||||||
|
|
||||||
|
public static int WM_CUT = 0x300;
|
||||||
|
public static int WM_COPY = 0x301;
|
||||||
|
public static int WM_PASTE = 0x302;
|
||||||
|
public static int WM_CLEAR = 0x303;
|
||||||
|
public static int WM_UNDO = 0x304;
|
||||||
|
|
||||||
|
|
||||||
|
public static int PROCESS_QUERY_INFORMATION = 0x0400;
|
||||||
|
public static int PROCESS_VM_READ = 0x0010;
|
||||||
|
|
||||||
|
public static int PS_SOLID = 0x0;
|
||||||
|
public static int HOLLOW_BRUSH = 0x5;
|
||||||
|
|
||||||
|
public static int WM_PAINT = 0x0F;
|
||||||
|
public static int WM_SETREDRAW = 0x0B;
|
||||||
|
public static int WM_ERASEBKGND = 0x14;
|
||||||
|
|
||||||
|
public static int RDW_FRAME = 0x0400;
|
||||||
|
public static int RDW_INVALIDATE = 0x0001;
|
||||||
|
public static int RDW_UPDATENOW = 0x0100;
|
||||||
|
public static int RDW_ALLCHILDREN = 0x0080;
|
||||||
|
|
||||||
|
public static int VK_SHIFT = 16;
|
||||||
|
public static int VK_LSHIFT = 0xA0;
|
||||||
|
public static int VK_RSHIFT = 0xA1;
|
||||||
|
public static int VK_CONTROL = 17;
|
||||||
|
public static int VK_LCONTROL = 0xA2;
|
||||||
|
public static int VK_RCONTROL = 0xA3;
|
||||||
|
public static int VK_MENU = 18;
|
||||||
|
public static int VK_LMENU = 0xA4;
|
||||||
|
public static int VK_RMENU = 0xA5;
|
||||||
|
|
||||||
|
public static int CWP_ALL = 0x0000; // Does not skip any child windows
|
||||||
|
|
||||||
|
public User32 user32;
|
||||||
|
public Psapi psapi;
|
||||||
|
public Kernel32 kernel32;
|
||||||
|
|
||||||
|
public static final int POINT_Y(long i)
|
||||||
|
{
|
||||||
|
return (int) (i >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int POINT_X(long i)
|
||||||
|
{
|
||||||
|
return (int) (i & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface User32 extends W32APIOptions {
|
||||||
|
User32 instance = (User32) Native.loadLibrary("user32", User32.class, DEFAULT_OPTIONS);
|
||||||
|
|
||||||
|
boolean ShowWindow(HWND hWnd, int nCmdShow);
|
||||||
|
boolean SetForegroundWindow(HWND hWnd);
|
||||||
|
void SwitchToThisWindow(HWND hWnd, boolean fAltTab);
|
||||||
|
HWND SetFocus(HWND hWnd);
|
||||||
|
|
||||||
|
HWND FindWindow(String winClass, String title);
|
||||||
|
LRESULT SendMessage(HWND hWnd, int Msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT SendMessageA(HWND editHwnd, int wmGettext, long l, byte[] lParamStr);
|
||||||
|
boolean DestroyWindow(HWND hWnd);
|
||||||
|
|
||||||
|
boolean EnumWindows (WNDENUMPROC wndenumproc, int lParam);
|
||||||
|
boolean EnumChildWindows(HWND hWnd, WNDENUMPROC lpEnumFunc, Pointer data);
|
||||||
|
HWND GetParent(HWND hWnd);
|
||||||
|
boolean IsWindowVisible(HWND hWnd);
|
||||||
|
|
||||||
|
int GetWindowRect(HWND hWnd, RECT r);
|
||||||
|
HDC GetWindowDC(HWND hWnd);
|
||||||
|
int ReleaseDC(HWND hWnd, HDC hDC);
|
||||||
|
boolean InvalidateRect(HWND hWnd, long lpRect, boolean bErase);
|
||||||
|
boolean UpdateWindow(HWND hWnd);
|
||||||
|
boolean RedrawWindow(HWND hWnd, long lprcUpdate, long hrgnUpdate, int flags);
|
||||||
|
|
||||||
|
void GetWindowTextA(HWND hWnd, byte[] buffer, int buflen);
|
||||||
|
int GetTopWindow(HWND hWnd);
|
||||||
|
int GetWindow(HWND hWnd, int flag);
|
||||||
|
final int GW_HWNDNEXT = 2;
|
||||||
|
int GetClassName(HWND hWnd, char[] buffer2, int i);
|
||||||
|
int GetWindowModuleFileName(HWND hWnd, char[] buffer2, int i);
|
||||||
|
int GetWindowThreadProcessId(HWND hWnd, PointerByReference pref);
|
||||||
|
|
||||||
|
boolean GetCursorPos(long[] lpPoint); //use macros POINT_X() and POINT_Y() on long lpPoint[0]
|
||||||
|
|
||||||
|
HWND WindowFromPoint(long point);
|
||||||
|
HWND ChildWindowFromPointEx(HWND hwndParent, long point, int uFlags);
|
||||||
|
boolean ClientToScreen(HWND hWnd, long[] lpPoint);//use macros POINT_X() and POINT_Y() on long lpPoint[0]
|
||||||
|
boolean ScreenToClient(HWND hWnd, long[] lpPoint);//use macros POINT_X() and POINT_Y() on long lpPoint[0]
|
||||||
|
//HWND WindowFromPoint(int xPoint, int yPoint);
|
||||||
|
//HWND WindowFromPoint(POINT point);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Gdi32 extends W32APIOptions {
|
||||||
|
Gdi32 instance = (Gdi32) Native.loadLibrary("gdi32", Gdi32.class, DEFAULT_OPTIONS);
|
||||||
|
HANDLE SelectObject(HDC hdc, HANDLE hgdiobj);
|
||||||
|
HANDLE GetStockObject(int fnObject);
|
||||||
|
boolean Rectangle(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
|
||||||
|
HPEN CreatePen(int fnPenStyle, int nWidth, int crColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Psapi extends W32APIOptions {
|
||||||
|
Psapi instance = (Psapi) Native.loadLibrary("psapi", Psapi.class, DEFAULT_OPTIONS);
|
||||||
|
int GetModuleBaseNameW(Pointer hProcess, Pointer hmodule, char[] lpBaseName, int size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Kernel32 extends W32APIOptions {
|
||||||
|
Kernel32 instance = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class, DEFAULT_OPTIONS);
|
||||||
|
boolean GetDiskFreeSpaceEx(String lpDirectoryName, LARGE_INTEGER.ByReference lpFreeBytesAvailable, LARGE_INTEGER.ByReference lpTotalNumberOfBytes, LARGE_INTEGER.ByReference lpTotalNumberOfFreeBytes);
|
||||||
|
int GetLastError();
|
||||||
|
Pointer OpenProcess(int dwDesiredAccess, boolean bInheritHandle, Pointer pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Api() {
|
||||||
|
user32 = User32.instance;
|
||||||
|
psapi = Psapi.instance;
|
||||||
|
kernel32 = Kernel32.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String GetHandleAsString(HWND hWnd) {
|
||||||
|
if (hWnd == null)
|
||||||
|
return "0";
|
||||||
|
//String longHexStr = hWnd.toString().substring("native@".length());
|
||||||
|
String longHexStr = hWnd.getPointer().toString().substring("native@".length());
|
||||||
|
Long l = Long.decode(longHexStr);
|
||||||
|
return l.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HWND GetHandleFromString(String hWnd) {
|
||||||
|
if (hWnd == null)
|
||||||
|
return null;
|
||||||
|
if (hWnd.isEmpty())
|
||||||
|
return null;
|
||||||
|
String cleanNumericHandle = hWnd.replaceAll("[^\\d.]", "");
|
||||||
|
try {
|
||||||
|
return (new HWND(new Pointer(Long.parseLong(cleanNumericHandle))));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String GetWindowClassName(HWND hWnd) {
|
||||||
|
char[] buffer = new char[1026];
|
||||||
|
User32.instance.GetClassName(hWnd, buffer, 1026);
|
||||||
|
return Native.toString(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String GetWindowText(HWND hWnd) {
|
||||||
|
String text = "";
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
User32.instance.GetWindowTextA(hWnd, buffer, buffer.length);
|
||||||
|
text = Native.toString(buffer);
|
||||||
|
if (text.isEmpty())
|
||||||
|
text = new Api().sendWmGetText(hWnd);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HWND GetWindowFromPoint(Point p) {
|
||||||
|
|
||||||
|
long[] getPos = new long [1];
|
||||||
|
User32.instance.GetCursorPos(getPos);
|
||||||
|
HWND hwnd = User32.instance.WindowFromPoint(getPos[0]);
|
||||||
|
HWND childHwnd = GetHiddenChildWindowFromPoint(hwnd, getPos[0]);
|
||||||
|
hwnd = childHwnd;
|
||||||
|
//System.out.println(getPos[0] + "," + getPos[1] + " int: " + x + ", " + y);
|
||||||
|
//System.out.println("child: " + GetHandleAsString(childHwnd) + " " + POINT_X(getPos[0]) +", " + POINT_Y(getPos[0]));
|
||||||
|
return hwnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HWND GetHiddenChildWindowFromPoint(HWND inHwnd, long point)
|
||||||
|
{
|
||||||
|
//int x = POINT_X(point);int y = POINT_Y(point);
|
||||||
|
|
||||||
|
long[] getPos = new long [1];
|
||||||
|
getPos[0] = point;
|
||||||
|
//if (!User32.instance.ClientToScreen(inHwnd, getPos)) return lHWND;
|
||||||
|
//x = POINT_X(getPos[0]);y = POINT_Y(getPos[0]);
|
||||||
|
//System.out.println("ClientToScreen " + GetHandleAsString(inHwnd) + ", " + x + ", " + y);
|
||||||
|
|
||||||
|
if (!User32.instance.ScreenToClient(inHwnd, getPos)) return inHwnd; // if point is not correct use original hwnd.
|
||||||
|
//x = POINT_X(getPos[0]);y = POINT_Y(getPos[0]);
|
||||||
|
//System.out.println("ScreenToClient " + GetHandleAsString(inHwnd) + ", " + x + ", " + y);
|
||||||
|
|
||||||
|
HWND childHwnd = User32.instance.ChildWindowFromPointEx(inHwnd, getPos[0], CWP_ALL);
|
||||||
|
//System.out.println("ChildWindowFromPointEx2 " + GetHandleAsString(inHwnd) + ", " + x + ", " + y + " = " + GetHandleAsString(childHwnd));
|
||||||
|
|
||||||
|
if (childHwnd == null) // if childHwnd is not correct use original hwnd.
|
||||||
|
return inHwnd;
|
||||||
|
|
||||||
|
return childHwnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HWND findWindowByTitle(String title) {
|
||||||
|
HWND handle = user32.FindWindow(null, title);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean activateWindow(HWND handle) {
|
||||||
|
boolean result = user32.SetForegroundWindow(handle);
|
||||||
|
user32.SetFocus(handle);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetDialogFocus(HWND hdlg, HWND hwndControl) {
|
||||||
|
WPARAM wp = new WPARAM(hwndControl.getPointer().getLong(0));
|
||||||
|
LPARAM lp = new LPARAM(1);
|
||||||
|
user32.SendMessage(hdlg, WM_NEXTDLGCTL, wp, lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean showWindow(HWND handle) {
|
||||||
|
return user32.ShowWindow(handle, WinUser.SW_SHOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hideWindow(HWND handle) {
|
||||||
|
return user32.ShowWindow(handle, WinUser.SW_HIDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean minimizeWindow(HWND handle) {
|
||||||
|
return user32.ShowWindow(handle, WinUser.SW_MINIMIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean maximizeWindow(HWND handle) {
|
||||||
|
return user32.ShowWindow(handle, WinUser.SW_MAXIMIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean restoreWindow(HWND handle) {
|
||||||
|
return user32.ShowWindow(handle, WinUser.SW_RESTORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean closeWindow(HWND handle) {
|
||||||
|
//return user32.DestroyWindow(handle);
|
||||||
|
user32.SendMessage(handle, WM_CLOSE , null, null);
|
||||||
|
//user32.SendMessage(handle, WM_NCDESTROY , null, null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void switchToThisWindow(HWND handle, boolean fAltTab) {
|
||||||
|
user32.SwitchToThisWindow(handle, fAltTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String sendWmGetText(HWND handle) {
|
||||||
|
int bufSize = 8192;
|
||||||
|
byte[] lParamStr = new byte[bufSize];
|
||||||
|
user32.SendMessageA(handle, WM_GETTEXT, bufSize, lParamStr);
|
||||||
|
return (Native.toString(lParamStr));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendWmSetText(HWND handle, String text) {
|
||||||
|
user32.SendMessageA(handle, WM_SETTEXT, 0, Native.toByteArray(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendClick(HWND handle) {
|
||||||
|
user32.SendMessageA(handle, WM_LBUTTONDOWN, 0, null);
|
||||||
|
user32.SendMessageA(handle, WM_LBUTTONUP, 0, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendDoubleClick(HWND handle) {
|
||||||
|
user32.SendMessageA(handle, WM_LBUTTONDBLCLK, 0, null);
|
||||||
|
//user32.SendMessageA(handle, WM_LBUTTONUP, 0, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendRightClick(HWND handle) {
|
||||||
|
user32.SendMessageA(handle, WM_RBUTTONDOWN, 0, null);
|
||||||
|
user32.SendMessageA(handle, WM_RBUTTONUP, 0, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendKeyDown(HWND handle, int keyCode) {
|
||||||
|
user32.SendMessageA(handle, WM_KEYDOWN, keyCode, null);
|
||||||
|
//user32.SendMessageA(handle, WM_KEYUP, keyCode, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendKeyUp(HWND handle, int keyCode) {
|
||||||
|
//user32.SendMessageA(handle, WM_KEYDOWN, keyCode, null);
|
||||||
|
user32.SendMessageA(handle, WM_KEYUP, keyCode, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDiskUsedPercentage() {
|
||||||
|
return getDiskUsedPercentage(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDiskUsedPercentage(String target) {
|
||||||
|
LARGE_INTEGER.ByReference lpFreeBytesAvailable = new LARGE_INTEGER.ByReference();
|
||||||
|
LARGE_INTEGER.ByReference lpTotalNumberOfBytes = new LARGE_INTEGER.ByReference();
|
||||||
|
LARGE_INTEGER.ByReference lpTotalNumberOfFreeBytes = new LARGE_INTEGER.ByReference();
|
||||||
|
Kernel32.instance.GetDiskFreeSpaceEx(target, lpFreeBytesAvailable, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes);
|
||||||
|
double freeBytes = lpTotalNumberOfFreeBytes.getValue();
|
||||||
|
double totalBytes = lpTotalNumberOfBytes.getValue();
|
||||||
|
//System.out.println("freespace " + humanReadableByteCount(freeBytes) + "/ totalspace " + humanReadableByteCount(totalBytes));
|
||||||
|
return (int)(((totalBytes-freeBytes)/totalBytes) * 100.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String humanReadableByteCount(double bytes) {
|
||||||
|
boolean si = true;
|
||||||
|
int unit = si ? 1000 : 1024;
|
||||||
|
if (bytes < unit) return bytes + " B";
|
||||||
|
int exp = (int) (Math.log(bytes) / Math.log(unit));
|
||||||
|
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");
|
||||||
|
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates highlight around selected window
|
||||||
|
public static void highlightWindow(HWND hwnd){
|
||||||
|
//COLORREF i.e. 0x00804070 Red = 0x70 green = 0x40 blue = 0x80
|
||||||
|
//g_hRectanglePen = CreatePen (PS_SOLID, 3, RGB(256, 0, 0));
|
||||||
|
HPEN rectPen = Gdi32.instance.CreatePen(PS_SOLID, 3, 0x00000099); //RGB(255, 0, 0)
|
||||||
|
RECT rect = new RECT();
|
||||||
|
User32.instance.GetWindowRect(hwnd, rect);
|
||||||
|
HDC dc = User32.instance.GetWindowDC(hwnd);
|
||||||
|
if (dc != null) {
|
||||||
|
// Select our created pen into the DC and backup the previous pen.
|
||||||
|
HANDLE prevPen = Gdi32.instance.SelectObject(dc, rectPen);
|
||||||
|
|
||||||
|
// Select a transparent brush into the DC and backup the previous brush.
|
||||||
|
HANDLE prevBrush = Gdi32.instance.SelectObject(dc, Gdi32.instance.GetStockObject(HOLLOW_BRUSH));
|
||||||
|
|
||||||
|
// Draw a rectangle in the DC covering the entire window area of the found window.
|
||||||
|
Gdi32.instance.Rectangle (dc, 0, 0, rect.right - rect.left, rect.bottom - rect.top);
|
||||||
|
|
||||||
|
// Reinsert the previous pen and brush into the found window's DC.
|
||||||
|
Gdi32.instance.SelectObject(dc, prevPen);
|
||||||
|
Gdi32.instance.SelectObject(dc, prevBrush);
|
||||||
|
|
||||||
|
// Finally release the DC.
|
||||||
|
User32.instance.ReleaseDC(hwnd, dc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void refreshWindow(HWND hwnd) {
|
||||||
|
User32.instance.InvalidateRect(hwnd, 0, true);
|
||||||
|
User32.instance.UpdateWindow(hwnd);
|
||||||
|
User32.instance.RedrawWindow(hwnd, 0, 0, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
194
src/org/synthuse/CommandPopupMenu.java
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class CommandPopupMenu extends JPopupMenu {
|
||||||
|
|
||||||
|
public static interface menuEvents {
|
||||||
|
void menuItemClicked(String command, int paramCount, boolean useXpath, ActionEvent e);
|
||||||
|
}
|
||||||
|
public menuEvents events = new menuEvents() {
|
||||||
|
public void menuItemClicked(String command, int paramCount, boolean useXpath, ActionEvent e) {
|
||||||
|
JOptionPane.showMessageDialog(null, command);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public CommandPopupMenu() {
|
||||||
|
|
||||||
|
JMenu mnKeyboard = new JMenu("Keyboard");
|
||||||
|
add(mnKeyboard);
|
||||||
|
|
||||||
|
CommandMenuItem mntmSendkeys = new CommandMenuItem("sendKeys", 2, false);
|
||||||
|
mnKeyboard.add(mntmSendkeys);
|
||||||
|
|
||||||
|
CommandMenuItem mntmKeydown = new CommandMenuItem("keyDown", 2, false);
|
||||||
|
mnKeyboard.add(mntmKeydown);
|
||||||
|
|
||||||
|
CommandMenuItem mntmKeyup = new CommandMenuItem("keyUp", 2, false);
|
||||||
|
mnKeyboard.add(mntmKeyup);
|
||||||
|
|
||||||
|
CommandMenuItem mntmKeycopy = new CommandMenuItem("keyCopy", 1);
|
||||||
|
mnKeyboard.add(mntmKeycopy);
|
||||||
|
|
||||||
|
CommandMenuItem mntmKeypaste = new CommandMenuItem("keyPaste", 1);
|
||||||
|
mnKeyboard.add(mntmKeypaste);
|
||||||
|
|
||||||
|
CommandMenuItem mntmKeyEsc = new CommandMenuItem("keyEscape", 1);
|
||||||
|
mnKeyboard.add(mntmKeyEsc);
|
||||||
|
|
||||||
|
CommandMenuItem mntmKeyFunc = new CommandMenuItem("keyFunctionX", 2, false);
|
||||||
|
mnKeyboard.add(mntmKeyFunc);
|
||||||
|
|
||||||
|
JMenu mnMouse = new JMenu("Mouse");
|
||||||
|
add(mnMouse);
|
||||||
|
|
||||||
|
CommandMenuItem mntmClick = new CommandMenuItem("click", 1, false);
|
||||||
|
mnMouse.add(mntmClick);
|
||||||
|
|
||||||
|
CommandMenuItem mntmDoubleclick = new CommandMenuItem("doubleClick", 1, false);
|
||||||
|
mnMouse.add(mntmDoubleclick);
|
||||||
|
|
||||||
|
CommandMenuItem mntmRightclick = new CommandMenuItem("rightClick", 1, false);
|
||||||
|
mnMouse.add(mntmRightclick);
|
||||||
|
|
||||||
|
CommandMenuItem mntmwinClick = new CommandMenuItem("winClick", 2);
|
||||||
|
mnMouse.add(mntmwinClick);
|
||||||
|
|
||||||
|
CommandMenuItem mntmwinDoubleClick = new CommandMenuItem("winDoubleClick", 2);
|
||||||
|
mnMouse.add(mntmwinDoubleClick);
|
||||||
|
|
||||||
|
CommandMenuItem mntmwinRightClick = new CommandMenuItem("winRightClick", 2);
|
||||||
|
mnMouse.add(mntmwinRightClick);
|
||||||
|
|
||||||
|
CommandMenuItem mntmDraganddrop = new CommandMenuItem("dragAndDrop", 3);
|
||||||
|
mnMouse.add(mntmDraganddrop);
|
||||||
|
|
||||||
|
CommandMenuItem mntmMousedown = new CommandMenuItem("mouseDown", 1, false);
|
||||||
|
mnMouse.add(mntmMousedown);
|
||||||
|
|
||||||
|
CommandMenuItem mntmMouseup = new CommandMenuItem("mouseUp", 1, false);
|
||||||
|
mnMouse.add(mntmMouseup);
|
||||||
|
|
||||||
|
CommandMenuItem mntmMousedownright = new CommandMenuItem("mouseDownRight", 1, false);
|
||||||
|
mnMouse.add(mntmMousedownright);
|
||||||
|
|
||||||
|
CommandMenuItem mntmMouseupright = new CommandMenuItem("mouseUpRight", 1, false);
|
||||||
|
mnMouse.add(mntmMouseupright);
|
||||||
|
|
||||||
|
CommandMenuItem mntmMousemove = new CommandMenuItem("mouseMove", 3, false);
|
||||||
|
mnMouse.add(mntmMousemove);
|
||||||
|
|
||||||
|
JMenu mnWinMessages = new JMenu("Win Messages");
|
||||||
|
add(mnWinMessages);
|
||||||
|
|
||||||
|
CommandMenuItem mntmWindowfocus = new CommandMenuItem("windowFocus", 2);
|
||||||
|
mnWinMessages.add(mntmWindowfocus);
|
||||||
|
|
||||||
|
CommandMenuItem mntmWindowSwitchToThis = new CommandMenuItem("windowSwitchToThis", 2);
|
||||||
|
mnWinMessages.add(mntmWindowSwitchToThis);
|
||||||
|
|
||||||
|
CommandMenuItem mntmSetcursorposition = new CommandMenuItem("setCursorPosition", 3);
|
||||||
|
mnWinMessages.add(mntmSetcursorposition);
|
||||||
|
|
||||||
|
CommandMenuItem mntmWindowminimize = new CommandMenuItem("windowMinimize", 2);
|
||||||
|
mnWinMessages.add(mntmWindowminimize);
|
||||||
|
|
||||||
|
CommandMenuItem mntmWindowmaximize = new CommandMenuItem("windowMaximize", 2);
|
||||||
|
mnWinMessages.add(mntmWindowmaximize);
|
||||||
|
|
||||||
|
CommandMenuItem mntmWindowrestore = new CommandMenuItem("windowRestore", 2);
|
||||||
|
mnWinMessages.add(mntmWindowrestore);
|
||||||
|
|
||||||
|
CommandMenuItem mntmWindowhide = new CommandMenuItem("windowHide", 2);
|
||||||
|
mnWinMessages.add(mntmWindowhide);
|
||||||
|
|
||||||
|
CommandMenuItem mntmWindowshow = new CommandMenuItem("windowShow", 2);
|
||||||
|
mnWinMessages.add(mntmWindowshow);
|
||||||
|
|
||||||
|
CommandMenuItem mntmWindowclose = new CommandMenuItem("windowClose", 2);
|
||||||
|
mnWinMessages.add(mntmWindowclose);
|
||||||
|
|
||||||
|
CommandMenuItem mntmSetwindowtext = new CommandMenuItem("setWindowText", 3);
|
||||||
|
mnWinMessages.add(mntmSetwindowtext);
|
||||||
|
|
||||||
|
CommandMenuItem mntmGetwindowtext = new CommandMenuItem("getWindowText", 2);
|
||||||
|
mnWinMessages.add(mntmGetwindowtext);
|
||||||
|
|
||||||
|
CommandMenuItem mntmGetwindowclass = new CommandMenuItem("getWindowClass", 2);
|
||||||
|
mnWinMessages.add(mntmGetwindowclass);
|
||||||
|
|
||||||
|
CommandMenuItem mntmPause = new CommandMenuItem("pause", 2, false);
|
||||||
|
add(mntmPause);
|
||||||
|
|
||||||
|
CommandMenuItem mntmWaitfortitle = new CommandMenuItem("waitForTitle", 2, false);
|
||||||
|
add(mntmWaitfortitle);
|
||||||
|
|
||||||
|
CommandMenuItem mntmWaitfortext = new CommandMenuItem("waitForText", 2, false);
|
||||||
|
add(mntmWaitfortext);
|
||||||
|
|
||||||
|
CommandMenuItem mntmWaitforclass = new CommandMenuItem("waitForClass", 2, false);
|
||||||
|
add(mntmWaitforclass);
|
||||||
|
|
||||||
|
CommandMenuItem mntmWaitforvisible = new CommandMenuItem("waitForVisible", 2);
|
||||||
|
add(mntmWaitforvisible);
|
||||||
|
|
||||||
|
CommandMenuItem mntmSettimeout = new CommandMenuItem("setTimeout", 2, false);
|
||||||
|
add(mntmSettimeout);
|
||||||
|
|
||||||
|
CommandMenuItem mntmSetspeed = new CommandMenuItem("setSpeed", 2, false);
|
||||||
|
add(mntmSetspeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CommandMenuItem extends JMenuItem {
|
||||||
|
public String commandText = "";
|
||||||
|
public int paramCount = 2;
|
||||||
|
public boolean useXpath = true;
|
||||||
|
|
||||||
|
public CommandMenuItem(String arg0, int paramCount) {
|
||||||
|
super(arg0);
|
||||||
|
init(arg0, paramCount, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandMenuItem(String arg0, int paramCount, boolean useXpath) {
|
||||||
|
super(arg0);
|
||||||
|
init(arg0, paramCount, useXpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(String arg0, int paramCount, boolean useXpath) {
|
||||||
|
this.commandText = arg0;
|
||||||
|
this.paramCount = paramCount;
|
||||||
|
this.useXpath = useXpath;
|
||||||
|
this.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
events.menuItemClicked(commandText, CommandMenuItem.this.paramCount, CommandMenuItem.this.useXpath, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String buildSkeletonCommand(String command, int paramCount, String xpathStr, boolean useXpath) {
|
||||||
|
String xpathItem = xpathStr;
|
||||||
|
if (!useXpath)
|
||||||
|
xpathItem = "";
|
||||||
|
String actionStr = "| do | " + command + " | ";
|
||||||
|
if (paramCount > 1)
|
||||||
|
actionStr += "on | " + xpathItem + " | ";
|
||||||
|
if (paramCount > 2)
|
||||||
|
actionStr += "with | |";
|
||||||
|
return actionStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
611
src/org/synthuse/CommandProcessor.java
Normal file
@@ -0,0 +1,611 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
|
import com.sun.jna.platform.win32.WinDef.HWND;
|
||||||
|
|
||||||
|
public class CommandProcessor implements Runnable{
|
||||||
|
|
||||||
|
private static String WIN_XML = "";
|
||||||
|
public static long LAST_UPDATED_XML = 0;
|
||||||
|
public static long SPEED = 1000; // ms
|
||||||
|
public static double XML_UPDATE_THRESHOLD = 5.0; // seconds
|
||||||
|
public static long WAIT_TIMEOUT_THRESHOLD = 30000; //ms
|
||||||
|
public static AtomicBoolean STOP_PROCESSOR = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
public String lastError = "";
|
||||||
|
public String scriptStr = "";
|
||||||
|
private Api api = new Api();
|
||||||
|
|
||||||
|
private int executeErrorCount = 0;
|
||||||
|
private String currentCommandText = "";
|
||||||
|
|
||||||
|
public static interface Events {
|
||||||
|
void statusChanged(String status);
|
||||||
|
void executionCompleted();
|
||||||
|
}
|
||||||
|
public Events events = new Events() {
|
||||||
|
public void statusChanged(String status){
|
||||||
|
System.out.println(status);
|
||||||
|
}
|
||||||
|
public void executionCompleted(){
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public CommandProcessor () {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandProcessor (String scriptStr, Events customEvents) { //multithreading support
|
||||||
|
this.scriptStr = scriptStr;
|
||||||
|
this.events = customEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() { //multithreading support
|
||||||
|
executeAllScriptCommands(scriptStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void executeThreaded(String scriptStr, Events customEvents) { //multithreading support
|
||||||
|
Thread t = new Thread(new CommandProcessor(scriptStr, customEvents));
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void executeAllScriptCommands(String scriptStr) {
|
||||||
|
events.statusChanged("Executing Test Script...");
|
||||||
|
//CommandProcessor cmdProcessor = new CommandProcessor();
|
||||||
|
int errors = 0;
|
||||||
|
long startTime = System.nanoTime();
|
||||||
|
String[] lines = scriptStr.split("\n");
|
||||||
|
for (String line : lines) {
|
||||||
|
|
||||||
|
if (!line.trim().startsWith("|"))
|
||||||
|
continue; //skip if it doesn't start with bar
|
||||||
|
String[] parsed = line.split("\\|");
|
||||||
|
//System.out.println("line: " + line);
|
||||||
|
//System.out.println("parsed len = " + parsed.length);
|
||||||
|
//System.out.println("parsed 2 = " + parsed[2]);
|
||||||
|
//System.out.println("parsed 4 = " + parsed[4]);
|
||||||
|
events.statusChanged("Executing line: " + line);
|
||||||
|
if (parsed.length == 4 || parsed.length == 3)
|
||||||
|
execute(parsed[2].trim(), new String[] {});
|
||||||
|
if (parsed.length == 6)
|
||||||
|
execute(parsed[2].trim(), new String[] {parsed[4].trim()});
|
||||||
|
if (parsed.length == 7)
|
||||||
|
execute(parsed[2].trim(), new String[] {parsed[4].trim(), parsed[6].trim()});
|
||||||
|
|
||||||
|
if (executeErrorCount > 0) //check if any errors occurred
|
||||||
|
++errors;
|
||||||
|
|
||||||
|
if (STOP_PROCESSOR.get())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
double seconds = ((double)(System.nanoTime() - startTime) / 1000000000);
|
||||||
|
String forcedStr = "Completed";
|
||||||
|
if (STOP_PROCESSOR.get())
|
||||||
|
forcedStr = "Stopped";
|
||||||
|
events.statusChanged("Script Execution " + forcedStr + " with " + errors + " error(s) in " + new DecimalFormat("#.###").format(seconds) + " seconds");
|
||||||
|
events.executionCompleted();
|
||||||
|
if (errors > 0)
|
||||||
|
JOptionPane.showMessageDialog(null, lastError);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object execute(String command, String[] args) {
|
||||||
|
executeErrorCount = 0;
|
||||||
|
currentCommandText = command;
|
||||||
|
String joinedArgs = "";
|
||||||
|
for (String arg : args)
|
||||||
|
joinedArgs += arg + " | ";
|
||||||
|
if (joinedArgs.endsWith("| "))
|
||||||
|
joinedArgs = joinedArgs.substring(0, joinedArgs.length()-2);
|
||||||
|
StatusWindow sw = new StatusWindow(command + " " + joinedArgs, -1);
|
||||||
|
|
||||||
|
Object result = executeCommandSwitch(command, args);
|
||||||
|
if (SPEED > 0)
|
||||||
|
try { Thread.sleep(SPEED); } catch (Exception e) {e.printStackTrace();}
|
||||||
|
sw.dispose();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object executeCommandSwitch(String command, String[] args) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
//Key commands
|
||||||
|
if (command.equals("sendKeys"))
|
||||||
|
return cmdSendKeys(args);
|
||||||
|
if (command.equals("keyDown"))
|
||||||
|
return cmdKeyDown(args);
|
||||||
|
if (command.equals("keyUp"))
|
||||||
|
return cmdKeyUp(args);
|
||||||
|
if (command.equals("keyCopy"))
|
||||||
|
return cmdKeyCopy(args);
|
||||||
|
if (command.equals("keyPaste"))
|
||||||
|
return cmdKeyPaste(args);
|
||||||
|
if (command.equals("keyEscape"))
|
||||||
|
return cmdKeyEscape(args);
|
||||||
|
if (command.equals("keyFunctionX"))
|
||||||
|
return cmdKeyFunc(args);
|
||||||
|
|
||||||
|
|
||||||
|
//Mouse commands
|
||||||
|
if (command.equals("click"))
|
||||||
|
return cmdClick(args);
|
||||||
|
if (command.equals("doubleClick"))
|
||||||
|
return cmdDoubleClick(args);
|
||||||
|
if (command.equals("rightClick"))
|
||||||
|
return cmdRightClick(args);
|
||||||
|
if (command.equals("winClick"))
|
||||||
|
return cmdWinClick(args);
|
||||||
|
if (command.equals("winDoubleClick"))
|
||||||
|
return cmdWinDoubleClick(args);
|
||||||
|
if (command.equals("winRightClick"))
|
||||||
|
return cmdWinRightClick(args);
|
||||||
|
if (command.equals("dragAndDrop"))
|
||||||
|
return cmdRightClick(args);
|
||||||
|
if (command.equals("mouseDown"))
|
||||||
|
return cmdMouseDown(args);
|
||||||
|
if (command.equals("mouseUp"))
|
||||||
|
return cmdMouseUp(args);
|
||||||
|
if (command.equals("mouseDownRight"))
|
||||||
|
return cmdMouseDownRight(args);
|
||||||
|
if (command.equals("mouseUpRight"))
|
||||||
|
return cmdMouseUpRight(args);
|
||||||
|
if (command.equals("mouseMove"))
|
||||||
|
return cmdMouseMove(args);
|
||||||
|
|
||||||
|
//Windows Api Commands
|
||||||
|
if (command.equals("windowFocus"))
|
||||||
|
return cmdWindowFocus(args);
|
||||||
|
if (command.equals("windowMinimize"))
|
||||||
|
return cmdWindowMinimize(args);
|
||||||
|
if (command.equals("windowMaximize"))
|
||||||
|
return cmdWindowMaximize(args);
|
||||||
|
if (command.equals("windowRestore"))
|
||||||
|
return cmdWindowRestore(args);
|
||||||
|
if (command.equals("windowShow"))
|
||||||
|
return cmdWindowShow(args);
|
||||||
|
if (command.equals("windowHide"))
|
||||||
|
return cmdWindowHide(args);
|
||||||
|
if (command.equals("windowSwitchToThis"))
|
||||||
|
return cmdWindowSwitchToThis(args);
|
||||||
|
if (command.equals("windowClose"))
|
||||||
|
return cmdWindowClose(args);
|
||||||
|
if (command.equals("setWindowText"))
|
||||||
|
return cmdSetText(args);
|
||||||
|
if (command.equals("getWindowText"))
|
||||||
|
return cmdGetText(args);
|
||||||
|
|
||||||
|
// Misc Commands
|
||||||
|
if (command.equals("delay") || command.equals("pause")) {
|
||||||
|
Thread.sleep(Long.parseLong(args[0]));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.equals("setSpeed"))
|
||||||
|
return cmdSetSpeed(args);
|
||||||
|
if (command.equals("setTimeout"))
|
||||||
|
return cmdSetTimeout(args);
|
||||||
|
if (command.equals("waitForTitle"))
|
||||||
|
return cmdWaitForTitle(args);
|
||||||
|
if (command.equals("waitForText"))
|
||||||
|
return cmdWaitForText(args);
|
||||||
|
if (command.equals("waitForClass"))
|
||||||
|
return cmdWaitForClass(args);
|
||||||
|
if (command.equals("waitForVisible"))
|
||||||
|
return cmdWaitForVisible(args);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
appendError(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
appendError("Error: Command '" + command + "' not found.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendError(Exception e) {
|
||||||
|
++executeErrorCount;
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
e.printStackTrace(new PrintWriter(sw));
|
||||||
|
lastError += new Timestamp((new Date()).getTime()) + " - " + sw.toString() + "\n";
|
||||||
|
try {
|
||||||
|
sw.close();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendError(String msg) {
|
||||||
|
++executeErrorCount;
|
||||||
|
lastError += new Timestamp((new Date()).getTime()) + " - " + msg + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkArgumentLength(String[] args, int expectedLength) {
|
||||||
|
if (args.length < expectedLength) {
|
||||||
|
appendError("Error: expected at least " + expectedLength + " arguments (" + currentCommandText + "[" + args.length + "])");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean whenFalseAppendError(boolean cmdResult) {
|
||||||
|
if (!cmdResult)
|
||||||
|
appendError("Error: command '" + currentCommandText + "' failed");
|
||||||
|
return cmdResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HWND findHandleWithXpath(String xpath) {
|
||||||
|
return findHandleWithXpath(xpath, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HWND findHandleWithXpath(String xpath, boolean ignoreFailedFind) {
|
||||||
|
HWND result = null;
|
||||||
|
double secondsFromLastUpdate = ((double)(System.nanoTime() - LAST_UPDATED_XML) / 1000000000);
|
||||||
|
if (secondsFromLastUpdate > XML_UPDATE_THRESHOLD) { //default 5 second threshold
|
||||||
|
WIN_XML = WindowsEnumeratedXml.getXml();
|
||||||
|
LAST_UPDATED_XML = System.nanoTime();
|
||||||
|
}
|
||||||
|
WindowsEnumeratedXml.evaluateXpathGetValues(WIN_XML, xpath);
|
||||||
|
String resultStr = "";
|
||||||
|
List<String> resultList = WindowsEnumeratedXml.evaluateXpathGetValues(WIN_XML, xpath);
|
||||||
|
for(String item: resultList) {
|
||||||
|
if (item.contains("hwnd=")) {
|
||||||
|
List<String> hwndList = WindowsEnumeratedXml.evaluateXpathGetValues(item, "//@hwnd");
|
||||||
|
resultStr = hwndList.get(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
resultStr = item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result = Api.GetHandleFromString(resultStr);
|
||||||
|
if (result == null && !ignoreFailedFind)
|
||||||
|
appendError("Error: Failed to find window handle matching: " + xpath);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdSendKeys(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
return whenFalseAppendError(RobotMacro.sendKeys(args[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdKeyDown(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
if (args[0].length() < 1){
|
||||||
|
appendError("Error: command '" + currentCommandText + "' failed, expected first argument length > 0");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char keyChar = args[0].charAt(0);
|
||||||
|
return RobotMacro.keyDown(keyChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdKeyUp(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
if (args[0].length() < 1){
|
||||||
|
appendError("Error: command '" + currentCommandText + "' failed, expected first argument length > 0");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char keyChar = args[0].charAt(0);
|
||||||
|
return RobotMacro.keyUp(keyChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdKeyCopy(String[] args) {
|
||||||
|
RobotMacro.copyKey();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdKeyPaste(String[] args) {
|
||||||
|
RobotMacro.pasteKey();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdKeyEscape(String[] args) {
|
||||||
|
RobotMacro.escapeKey();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdKeyFunc(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
if (args[0].length() < 1){
|
||||||
|
appendError("Error: command '" + currentCommandText + "' failed, expected first argument length > 0");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int fNum = Integer.parseInt(args[0]);
|
||||||
|
RobotMacro.functionKey(fNum);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdClick(String[] args) {
|
||||||
|
RobotMacro.leftClickMouse();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdDoubleClick(String[] args) {
|
||||||
|
RobotMacro.doubleClickMouse();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdRightClick(String[] args) {
|
||||||
|
RobotMacro.rightClickMouse();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdMouseDown(String[] args) {
|
||||||
|
RobotMacro.leftMouseDown();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdMouseUp(String[] args) {
|
||||||
|
RobotMacro.leftMouseUp();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdMouseDownRight(String[] args) {
|
||||||
|
RobotMacro.rightMouseDown();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdMouseUpRight(String[] args) {
|
||||||
|
RobotMacro.rightMouseUp();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdMouseMove(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 2))
|
||||||
|
return false;
|
||||||
|
int x = Integer.parseInt(args[0]);
|
||||||
|
int y = Integer.parseInt(args[1]);
|
||||||
|
RobotMacro.mouseMove(x, y);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWinClick(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return false;
|
||||||
|
api.sendClick(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWinDoubleClick(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return false;
|
||||||
|
api.sendDoubleClick(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWinRightClick(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return false;
|
||||||
|
api.sendRightClick(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWindowFocus(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return false;
|
||||||
|
api.activateWindow(handle);
|
||||||
|
//api.showWindow(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWindowMinimize(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return false;
|
||||||
|
api.minimizeWindow(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWindowMaximize(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return false;
|
||||||
|
api.maximizeWindow(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWindowRestore(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return false;
|
||||||
|
api.restoreWindow(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWindowHide(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return false;
|
||||||
|
api.hideWindow(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWindowShow(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return false;
|
||||||
|
api.showWindow(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWindowSwitchToThis(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return false;
|
||||||
|
api.switchToThisWindow(handle, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean cmdWindowClose(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return false;
|
||||||
|
api.closeWindow(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdSetText(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 2))
|
||||||
|
return false;
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return false;
|
||||||
|
api.sendWmSetText(handle, args[1]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String cmdGetText(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return "";
|
||||||
|
HWND handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle == null)
|
||||||
|
return "";
|
||||||
|
return api.sendWmGetText(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdSetSpeed(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
long speed = Long.parseLong(args[0]);
|
||||||
|
SPEED = speed;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdSetTimeout(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
long timeout = Long.parseLong(args[0]);
|
||||||
|
WAIT_TIMEOUT_THRESHOLD = timeout;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWaitForTitle(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
long totalAttempts = (long) (WAIT_TIMEOUT_THRESHOLD / (XML_UPDATE_THRESHOLD * 1000));
|
||||||
|
long attemptCount = 0;
|
||||||
|
String xpath = "/EnumeratedWindows/win[@TEXT='" + WindowsEnumeratedXml.escapeXmlAttributeValue(args[0].toUpperCase()) + "']";
|
||||||
|
HWND handle = findHandleWithXpath(xpath, true);
|
||||||
|
if (handle != null)// first test without a timeout
|
||||||
|
return true;
|
||||||
|
while (attemptCount < totalAttempts) {
|
||||||
|
handle = findHandleWithXpath(xpath, true);
|
||||||
|
if (handle != null)
|
||||||
|
break;
|
||||||
|
try {Thread.sleep((long)(XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();}
|
||||||
|
++attemptCount;
|
||||||
|
if (STOP_PROCESSOR.get())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return handle != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWaitForText(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
long totalAttempts = (long) (WAIT_TIMEOUT_THRESHOLD / (XML_UPDATE_THRESHOLD * 1000));
|
||||||
|
long attemptCount = 0;
|
||||||
|
String xpath = "//[@TEXT='" + WindowsEnumeratedXml.escapeXmlAttributeValue(args[0].toUpperCase()) + "']";
|
||||||
|
HWND handle = findHandleWithXpath(xpath, true);
|
||||||
|
if (handle != null)// first test without a timeout
|
||||||
|
return true;
|
||||||
|
while (attemptCount < totalAttempts) {
|
||||||
|
handle = findHandleWithXpath(xpath, true);
|
||||||
|
if (handle != null)
|
||||||
|
break;
|
||||||
|
try {Thread.sleep((long)(XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();}
|
||||||
|
++attemptCount;
|
||||||
|
if (STOP_PROCESSOR.get())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return handle != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWaitForClass(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
long totalAttempts = (long) (WAIT_TIMEOUT_THRESHOLD / (XML_UPDATE_THRESHOLD * 1000));
|
||||||
|
long attemptCount = 0;
|
||||||
|
String xpath = "//win[@CLASS='" + WindowsEnumeratedXml.escapeXmlAttributeValue(args[0].toUpperCase()) + "']";
|
||||||
|
HWND handle = findHandleWithXpath(xpath, true);
|
||||||
|
if (handle != null)// first test without a timeout
|
||||||
|
return true;
|
||||||
|
while (attemptCount < totalAttempts) {
|
||||||
|
handle = findHandleWithXpath(xpath, true);
|
||||||
|
if (handle != null)
|
||||||
|
break;
|
||||||
|
try {Thread.sleep((long)(XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();}
|
||||||
|
++attemptCount;
|
||||||
|
if (STOP_PROCESSOR.get())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return handle != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cmdWaitForVisible(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
long totalAttempts = (long) (WAIT_TIMEOUT_THRESHOLD / (XML_UPDATE_THRESHOLD * 1000));
|
||||||
|
long attemptCount = 0;
|
||||||
|
HWND handle = findHandleWithXpath(args[0], true);
|
||||||
|
if (handle != null)// first test without a timeout
|
||||||
|
return true;
|
||||||
|
while (attemptCount < totalAttempts) {
|
||||||
|
handle = findHandleWithXpath(args[0], true);
|
||||||
|
if (handle != null)
|
||||||
|
break;
|
||||||
|
try {Thread.sleep((long)(XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();}
|
||||||
|
++attemptCount;
|
||||||
|
if (STOP_PROCESSOR.get())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return handle != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
27
src/org/synthuse/Config.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
public class Config extends PropertiesSerializer {
|
||||||
|
|
||||||
|
public static String DEFAULT_PROP_FILENAME = "synthuse.properties";
|
||||||
|
|
||||||
|
public String urlList = "";
|
||||||
|
public String xpathList = "";
|
||||||
|
public String xpathHightlight = ".*process=\"([^\"]*)\".*";
|
||||||
|
|
||||||
|
public Config() //needed for cloning
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Config(String propertyFilename)
|
||||||
|
{
|
||||||
|
super(propertyFilename);
|
||||||
|
load(propertyFilename);
|
||||||
|
}
|
||||||
|
}
|
||||||
167
src/org/synthuse/DragTarget.java
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import java.awt.Cursor;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.datatransfer.DataFlavor;
|
||||||
|
import java.awt.datatransfer.Transferable;
|
||||||
|
import java.awt.dnd.DragSource;
|
||||||
|
import java.awt.dnd.DragSourceAdapter;
|
||||||
|
import java.awt.dnd.DragSourceDragEvent;
|
||||||
|
import java.awt.dnd.DragSourceMotionListener;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
import javax.activation.ActivationDataFlavor;
|
||||||
|
import javax.activation.DataHandler;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.TransferHandler;
|
||||||
|
|
||||||
|
|
||||||
|
public class DragTarget extends JLabel {
|
||||||
|
|
||||||
|
public static String CUSTOM_ICON_RESOURCE = "/org/synthuse/img/bullseye-logo-th32x32.png";
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public static interface dragEvents {
|
||||||
|
void dragStarted(JComponent c);
|
||||||
|
void dragMouseMoved(int x, int y);
|
||||||
|
void dropped(JComponent c);
|
||||||
|
}
|
||||||
|
public dragEvents events = new dragEvents() {
|
||||||
|
public void dragStarted(JComponent c) {
|
||||||
|
|
||||||
|
}
|
||||||
|
public void dragMouseMoved(int x, int y) {
|
||||||
|
|
||||||
|
}
|
||||||
|
public void dropped(JComponent c) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public DragTarget() {
|
||||||
|
|
||||||
|
this.setTransferHandler(new CustomTransferHandler());
|
||||||
|
|
||||||
|
this.addMouseListener(new MouseAdapter(){
|
||||||
|
public void mousePressed(MouseEvent e)
|
||||||
|
{
|
||||||
|
JComponent comp = (JComponent)e.getSource();
|
||||||
|
TransferHandler handler = comp.getTransferHandler();
|
||||||
|
//c.setOpaque(true);
|
||||||
|
handler.exportAsDrag(comp, e, TransferHandler.MOVE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
class CustomTransferHandler extends TransferHandler {
|
||||||
|
//private final JWindow window = new JWindow();
|
||||||
|
private final DataFlavor localObjectFlavor;
|
||||||
|
private final JLabel label = new JLabel();
|
||||||
|
//public Cursor blankCursor = null;
|
||||||
|
public Cursor customCursor = null;
|
||||||
|
|
||||||
|
public CustomTransferHandler () {
|
||||||
|
//System.out.println("CustomTransferHandler");
|
||||||
|
localObjectFlavor = new ActivationDataFlavor(DragTarget.class, DataFlavor.javaJVMLocalObjectMimeType, "JLabel");
|
||||||
|
//label = DragTarget.this;
|
||||||
|
//window.add(label);
|
||||||
|
//window.setAlwaysOnTop(true);
|
||||||
|
//window.setBackground(new Color(0,true));
|
||||||
|
// Create a new blank cursor.
|
||||||
|
//BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
|
||||||
|
//blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(cursorImg, new Point(0, 0), "blank cursor");
|
||||||
|
try {
|
||||||
|
BufferedImage image = ImageIO.read(SynthuseDlg.class.getResourceAsStream(CUSTOM_ICON_RESOURCE));
|
||||||
|
customCursor = Toolkit.getDefaultToolkit().createCustomCursor(image, new Point(15, 16), "custom cursor");
|
||||||
|
} catch (Exception e1) {
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DragSource.getDefaultDragSource().addDragSourceMotionListener(new DragSourceMotionListener() {
|
||||||
|
@Override
|
||||||
|
public void dragMouseMoved(DragSourceDragEvent e) {
|
||||||
|
events.dragMouseMoved(e.getLocation().x, e.getLocation().y);
|
||||||
|
//Point pt = e.getLocation();
|
||||||
|
//pt.translate(-9, -9); // offset
|
||||||
|
//window.setLocation(pt);
|
||||||
|
//e.getDragSourceContext().setCursor(customCursor);//DragSource.DefaultLinkDrop
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
DragSource.getDefaultDragSource().addDragSourceListener(new DragSourceAdapter() {
|
||||||
|
@Override
|
||||||
|
public void dragEnter(DragSourceDragEvent e) {
|
||||||
|
e.getDragSourceContext().setCursor(customCursor);//DragSource.DefaultLinkDrop
|
||||||
|
//System.out.println("dragEnter");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Transferable createTransferable(JComponent c) {
|
||||||
|
//System.out.println("createTransferable");
|
||||||
|
//JLabel l = (JLabel)c;
|
||||||
|
//String text = l.getText();
|
||||||
|
final DataHandler dh = new DataHandler(c, localObjectFlavor.getMimeType());
|
||||||
|
return dh;
|
||||||
|
//return new StringSelection("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canImport(TransferSupport support) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean importData(TransferSupport support) {
|
||||||
|
System.out.println("importData");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSourceActions(JComponent c) {
|
||||||
|
//System.out.println("getSourceActions");
|
||||||
|
events.dragStarted(c);
|
||||||
|
JLabel p = (JLabel)c;
|
||||||
|
label.setIcon(p.getIcon());
|
||||||
|
//label.setText(p.draggingLabel.getText());
|
||||||
|
//window.pack();
|
||||||
|
//Point pt = p.getLocation();
|
||||||
|
//SwingUtilities.convertPointToScreen(pt, p);
|
||||||
|
//window.setLocation(pt);
|
||||||
|
//window.setVisible(true);
|
||||||
|
return MOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void exportDone(JComponent c, Transferable data, int action) {
|
||||||
|
//System.out.println("exportDone");
|
||||||
|
events.dropped(c);
|
||||||
|
JLabel src = (JLabel)c;
|
||||||
|
if(action == TransferHandler.MOVE) {
|
||||||
|
src.remove(src);
|
||||||
|
src.revalidate();
|
||||||
|
src.repaint();
|
||||||
|
}
|
||||||
|
src = null;
|
||||||
|
//window.setVisible(false);
|
||||||
|
//window.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
198
src/org/synthuse/PropertiesSerializer.java
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
// example class for PropertiesSerializer
|
||||||
|
public class Configuration extends PropertiesSerializer{
|
||||||
|
|
||||||
|
public static final String DEFAULT_PROP_FILENAME = "./ctf.properties";
|
||||||
|
|
||||||
|
// General Settings
|
||||||
|
public String tests_dir = "./tests";
|
||||||
|
public String logs_dir = "./logs";
|
||||||
|
public int statusTimer = 2000;
|
||||||
|
|
||||||
|
public Configuration() //needed for cloning
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Configuration(String propertyFilename)
|
||||||
|
{
|
||||||
|
super(propertyFilename);
|
||||||
|
load(propertyFilename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class PropertiesSerializer {
|
||||||
|
|
||||||
|
protected Properties prop = new Properties();
|
||||||
|
protected String propertyFilename = null;
|
||||||
|
|
||||||
|
public PropertiesSerializer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PropertiesSerializer(String propertyFilename)
|
||||||
|
{
|
||||||
|
this.propertyFilename = propertyFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(String propertyFilename)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
prop.load(new FileInputStream(propertyFilename));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
Field[] fields = this.getClass().getFields();
|
||||||
|
for (int i = 0 ; i < fields.length; i++)
|
||||||
|
{
|
||||||
|
//fields[i].get(this);
|
||||||
|
String pName = fields[i].getName();
|
||||||
|
String pType = "String";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pType = fields[i].get(this).getClass().getSimpleName();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
//e.printStackTrace();
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (pType.equalsIgnoreCase("integer"))
|
||||||
|
fields[i].set(this, Integer.parseInt(prop.get(pName) + ""));
|
||||||
|
if (pType.equalsIgnoreCase("boolean"))
|
||||||
|
fields[i].set(this, Boolean.parseBoolean(prop.get(pName) + ""));
|
||||||
|
else
|
||||||
|
fields[i].set(this, prop.get(pName));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
//e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save()
|
||||||
|
{
|
||||||
|
Field[] fields = this.getClass().getFields();
|
||||||
|
for (int i = 0 ; i < fields.length; i++)
|
||||||
|
{
|
||||||
|
//fields[i].get(this);
|
||||||
|
try {
|
||||||
|
String pName = fields[i].getName();
|
||||||
|
//String pType = fields[i].get(this).getClass().getSimpleName();
|
||||||
|
if (fields[i].get(this) == null)
|
||||||
|
prop.setProperty(pName, "");
|
||||||
|
else
|
||||||
|
prop.setProperty(pName, fields[i].get(this) + "");
|
||||||
|
} catch (Exception e) {
|
||||||
|
//e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileOutputStream fos = new FileOutputStream(propertyFilename);
|
||||||
|
prop.store(fos, "");
|
||||||
|
fos.flush();
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object clone()
|
||||||
|
{
|
||||||
|
Object newObject = null;
|
||||||
|
try {
|
||||||
|
newObject = (Object)this.getClass().newInstance();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
Field[] fields = this.getClass().getFields();
|
||||||
|
for (int i = 0 ; i < fields.length; i++)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
//fields[i].get(this);
|
||||||
|
//String pName = fields[i].getName();
|
||||||
|
fields[i].set(newObject, fields[i].get(this));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
//e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasChanged()
|
||||||
|
{
|
||||||
|
boolean changes = false;
|
||||||
|
Field[] fields = this.getClass().getFields();
|
||||||
|
for (int i = 0 ; i < fields.length; i++)
|
||||||
|
{
|
||||||
|
//fields[i].get(this);
|
||||||
|
try {
|
||||||
|
String pName = fields[i].getName();
|
||||||
|
//String pType = fields[i].get(this).getClass().getSimpleName();
|
||||||
|
if (prop.getProperty(pName).compareTo(fields[i].get(this)+"") != 0)
|
||||||
|
changes = true;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
//e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPropertyFilename()
|
||||||
|
{
|
||||||
|
return this.propertyFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPropertyFilename(String filename)
|
||||||
|
{
|
||||||
|
this.propertyFilename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readValue(String propertyName)
|
||||||
|
{
|
||||||
|
String val = "";
|
||||||
|
val = prop.getProperty(propertyName);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeValue(String propertyName, String propertValue)
|
||||||
|
{
|
||||||
|
prop.setProperty(propertyName, propertValue);
|
||||||
|
try {
|
||||||
|
prop.store(new FileOutputStream(propertyFilename), null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
371
src/org/synthuse/RobotMacro.java
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
|
||||||
|
public class RobotMacro {
|
||||||
|
|
||||||
|
public static Exception lastException = null;
|
||||||
|
|
||||||
|
public static boolean executeCommand(String cmd) {
|
||||||
|
Runtime runtime = Runtime.getRuntime();
|
||||||
|
try {
|
||||||
|
runtime.exec(cmd);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void delay(int time) {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
robot.delay(time);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void moveMouse(int x, int y) {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
robot.mouseMove(x, y);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void leftClickMouse() {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
robot.mousePress(InputEvent.BUTTON1_MASK);
|
||||||
|
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void doubleClickMouse() {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
robot.mousePress(InputEvent.BUTTON1_MASK);
|
||||||
|
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||||
|
robot.delay(100);
|
||||||
|
robot.mousePress(InputEvent.BUTTON1_MASK);
|
||||||
|
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void rightClickMouse() {
|
||||||
|
try {
|
||||||
|
System.out.println("rightClickMouse");
|
||||||
|
Robot robot = new Robot();
|
||||||
|
//robot.mouseMove(200, 200);
|
||||||
|
//robot.delay(1000);
|
||||||
|
robot.mousePress(InputEvent.BUTTON3_MASK);
|
||||||
|
robot.mouseRelease(InputEvent.BUTTON3_MASK);
|
||||||
|
//System.out.println("rightClickMouse good");
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void leftMouseDown() {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
robot.mousePress(InputEvent.BUTTON1_MASK);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void leftMouseUp() {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void rightMouseDown() {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
robot.mousePress(InputEvent.BUTTON3_MASK);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void rightMouseUp() {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
robot.mouseRelease(InputEvent.BUTTON3_MASK);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void mouseMove(int x, int y) {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
robot.mouseMove(x, y);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void copyKey() {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
robot.keyPress(KeyEvent.VK_CONTROL);
|
||||||
|
robot.keyPress(KeyEvent.VK_C);
|
||||||
|
robot.keyRelease(KeyEvent.VK_C);
|
||||||
|
robot.keyRelease(KeyEvent.VK_CONTROL);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void pasteKey() {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
robot.keyPress(KeyEvent.VK_CONTROL);
|
||||||
|
robot.keyPress(KeyEvent.VK_V);
|
||||||
|
robot.keyRelease(KeyEvent.VK_V);
|
||||||
|
robot.keyRelease(KeyEvent.VK_CONTROL);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void escapeKey() {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
robot.keyPress(KeyEvent.VK_ESCAPE);
|
||||||
|
robot.keyRelease(KeyEvent.VK_ESCAPE);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void functionKey(int functionNum) {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
int keyCode = 0;
|
||||||
|
switch (functionNum) {
|
||||||
|
case 1: keyCode = KeyEvent.VK_F1; break;
|
||||||
|
case 2: keyCode = KeyEvent.VK_F2; break;
|
||||||
|
case 3: keyCode = KeyEvent.VK_F3; break;
|
||||||
|
case 4: keyCode = KeyEvent.VK_F4; break;
|
||||||
|
case 5: keyCode = KeyEvent.VK_F5; break;
|
||||||
|
case 6: keyCode = KeyEvent.VK_F6; break;
|
||||||
|
case 7: keyCode = KeyEvent.VK_F7; break;
|
||||||
|
case 8: keyCode = KeyEvent.VK_F8; break;
|
||||||
|
case 9: keyCode = KeyEvent.VK_F9; break;
|
||||||
|
case 10: keyCode = KeyEvent.VK_F10; break;
|
||||||
|
case 11: keyCode = KeyEvent.VK_F11; break;
|
||||||
|
case 12: keyCode = KeyEvent.VK_F12; break;
|
||||||
|
}
|
||||||
|
robot.keyPress(keyCode);
|
||||||
|
robot.keyRelease(keyCode);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void tildeKey() {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
pressKeyCodes(robot, new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_QUOTE});
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean sendKeys(String keyCommands) {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
for (int i = 0; i < keyCommands.length(); i++) {
|
||||||
|
char key = keyCommands.charAt(i);
|
||||||
|
int[] keyCode = getKeyCode(key);
|
||||||
|
pressKeyCodes(robot, keyCode);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean pressKey(char key) {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
int[] keyCode = getKeyCode(key);
|
||||||
|
pressKeyCodes(robot, keyCode);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean keyDown(char key) {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
int[] keyCodes = getKeyCode(key);
|
||||||
|
for (int i = 0; i < keyCodes.length; i++) {
|
||||||
|
robot.keyPress(keyCodes[i]);
|
||||||
|
//System.out.println("pressed: " + keyCodes[i]);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean keyUp(char key) {
|
||||||
|
try {
|
||||||
|
Robot robot = new Robot();
|
||||||
|
int[] keyCodes = getKeyCode(key);
|
||||||
|
for (int i = keyCodes.length - 1; i >= 0; i--) {
|
||||||
|
robot.keyRelease(keyCodes[i]);
|
||||||
|
//System.out.println("released: " + keyCodes[i]);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastException = e;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void pressKeyCodes(Robot robot, int[] keyCodes) {
|
||||||
|
for (int i = 0; i < keyCodes.length; i++) {
|
||||||
|
robot.keyPress(keyCodes[i]);
|
||||||
|
//System.out.println("pressed: " + keyCodes[i]);
|
||||||
|
}
|
||||||
|
//robot.delay(50);
|
||||||
|
for (int i = keyCodes.length - 1; i >= 0; i--) {
|
||||||
|
robot.keyRelease(keyCodes[i]);
|
||||||
|
//System.out.println("released: " + keyCodes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] getKeyCode(char key) {
|
||||||
|
switch (key) {
|
||||||
|
case 'a': return(new int[]{KeyEvent.VK_A});
|
||||||
|
case 'b': return(new int[]{KeyEvent.VK_B});
|
||||||
|
case 'c': return(new int[]{KeyEvent.VK_C});
|
||||||
|
case 'd': return(new int[]{KeyEvent.VK_D});
|
||||||
|
case 'e': return(new int[]{KeyEvent.VK_E});
|
||||||
|
case 'f': return(new int[]{KeyEvent.VK_F});
|
||||||
|
case 'g': return(new int[]{KeyEvent.VK_G});
|
||||||
|
case 'h': return(new int[]{KeyEvent.VK_H});
|
||||||
|
case 'i': return(new int[]{KeyEvent.VK_I});
|
||||||
|
case 'j': return(new int[]{KeyEvent.VK_J});
|
||||||
|
case 'k': return(new int[]{KeyEvent.VK_K});
|
||||||
|
case 'l': return(new int[]{KeyEvent.VK_L});
|
||||||
|
case 'm': return(new int[]{KeyEvent.VK_M});
|
||||||
|
case 'n': return(new int[]{KeyEvent.VK_N});
|
||||||
|
case 'o': return(new int[]{KeyEvent.VK_O});
|
||||||
|
case 'p': return(new int[]{KeyEvent.VK_P});
|
||||||
|
case 'q': return(new int[]{KeyEvent.VK_Q});
|
||||||
|
case 'r': return(new int[]{KeyEvent.VK_R});
|
||||||
|
case 's': return(new int[]{KeyEvent.VK_S});
|
||||||
|
case 't': return(new int[]{KeyEvent.VK_T});
|
||||||
|
case 'u': return(new int[]{KeyEvent.VK_U});
|
||||||
|
case 'v': return(new int[]{KeyEvent.VK_V});
|
||||||
|
case 'w': return(new int[]{KeyEvent.VK_W});
|
||||||
|
case 'x': return(new int[]{KeyEvent.VK_X});
|
||||||
|
case 'y': return(new int[]{KeyEvent.VK_Y});
|
||||||
|
case 'z': return(new int[]{KeyEvent.VK_Z});
|
||||||
|
case 'A': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_A});
|
||||||
|
case 'B': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_B});
|
||||||
|
case 'C': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_C});
|
||||||
|
case 'D': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_D});
|
||||||
|
case 'E': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_E});
|
||||||
|
case 'F': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_F});
|
||||||
|
case 'G': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_G});
|
||||||
|
case 'H': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_H});
|
||||||
|
case 'I': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_I});
|
||||||
|
case 'J': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_J});
|
||||||
|
case 'K': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_K});
|
||||||
|
case 'L': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_L});
|
||||||
|
case 'M': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_M});
|
||||||
|
case 'N': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_N});
|
||||||
|
case 'O': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_O});
|
||||||
|
case 'P': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_P});
|
||||||
|
case 'Q': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_Q});
|
||||||
|
case 'R': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_R});
|
||||||
|
case 'S': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_S});
|
||||||
|
case 'T': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_T});
|
||||||
|
case 'U': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_U});
|
||||||
|
case 'V': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_V});
|
||||||
|
case 'W': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_W});
|
||||||
|
case 'X': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_X});
|
||||||
|
case 'Y': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_Y});
|
||||||
|
case 'Z': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_Z});
|
||||||
|
case '`': return(new int[]{KeyEvent.VK_BACK_QUOTE});
|
||||||
|
case '0': return(new int[]{KeyEvent.VK_0});
|
||||||
|
case '1': return(new int[]{KeyEvent.VK_1});
|
||||||
|
case '2': return(new int[]{KeyEvent.VK_2});
|
||||||
|
case '3': return(new int[]{KeyEvent.VK_3});
|
||||||
|
case '4': return(new int[]{KeyEvent.VK_4});
|
||||||
|
case '5': return(new int[]{KeyEvent.VK_5});
|
||||||
|
case '6': return(new int[]{KeyEvent.VK_6});
|
||||||
|
case '7': return(new int[]{KeyEvent.VK_7});
|
||||||
|
case '8': return(new int[]{KeyEvent.VK_8});
|
||||||
|
case '9': return(new int[]{KeyEvent.VK_9});
|
||||||
|
case '-': return(new int[]{KeyEvent.VK_MINUS});
|
||||||
|
case '=': return(new int[]{KeyEvent.VK_EQUALS});
|
||||||
|
case '~': return(new int[]{KeyEvent.VK_ENTER});//return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_QUOTE});
|
||||||
|
case '!': return(new int[]{KeyEvent.VK_EXCLAMATION_MARK});
|
||||||
|
case '@': return(new int[]{KeyEvent.VK_AT});
|
||||||
|
case '#': return(new int[]{KeyEvent.VK_NUMBER_SIGN});
|
||||||
|
case '$': return(new int[]{KeyEvent.VK_DOLLAR});
|
||||||
|
case '%': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_5});
|
||||||
|
case '^': return(new int[]{KeyEvent.VK_CIRCUMFLEX});
|
||||||
|
case '&': return(new int[]{KeyEvent.VK_AMPERSAND});
|
||||||
|
case '*': return(new int[]{KeyEvent.VK_ASTERISK});
|
||||||
|
case '(': return(new int[]{KeyEvent.VK_LEFT_PARENTHESIS});
|
||||||
|
case ')': return(new int[]{KeyEvent.VK_RIGHT_PARENTHESIS});
|
||||||
|
case '_': return(new int[]{KeyEvent.VK_UNDERSCORE});
|
||||||
|
case '+': return(new int[]{KeyEvent.VK_PLUS});
|
||||||
|
case '\t': return(new int[]{KeyEvent.VK_TAB});
|
||||||
|
case '\n': return(new int[]{KeyEvent.VK_ENTER});
|
||||||
|
case '[': return(new int[]{KeyEvent.VK_OPEN_BRACKET});
|
||||||
|
case ']': return(new int[]{KeyEvent.VK_CLOSE_BRACKET});
|
||||||
|
case '\\': return(new int[]{KeyEvent.VK_BACK_SLASH});
|
||||||
|
case '{': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_OPEN_BRACKET});
|
||||||
|
case '}': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_CLOSE_BRACKET});
|
||||||
|
case '|': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_SLASH});
|
||||||
|
case ';': return(new int[]{KeyEvent.VK_SEMICOLON});
|
||||||
|
case ':': return(new int[]{KeyEvent.VK_COLON});
|
||||||
|
case '\'': return(new int[]{KeyEvent.VK_QUOTE});
|
||||||
|
case '"': return(new int[]{KeyEvent.VK_QUOTEDBL});
|
||||||
|
case ',': return(new int[]{KeyEvent.VK_COMMA});
|
||||||
|
case '<': return(new int[]{KeyEvent.VK_LESS});
|
||||||
|
case '.': return(new int[]{KeyEvent.VK_PERIOD});
|
||||||
|
case '>': return(new int[]{KeyEvent.VK_GREATER});
|
||||||
|
case '/': return(new int[]{KeyEvent.VK_SLASH});
|
||||||
|
case '?': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_SLASH}); // needs Shift
|
||||||
|
case ' ': return(new int[]{KeyEvent.VK_SPACE});
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Cannot find Key Code for character " + key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
72
src/org/synthuse/StatusWindow.java
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.FlowLayout;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JWindow;
|
||||||
|
|
||||||
|
|
||||||
|
public class StatusWindow extends JWindow {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
public static int FONT_SIZE = 14;
|
||||||
|
public static int FONT_BOLD = Font.BOLD; //Font.PLAIN
|
||||||
|
public static int Y_BOTTOM_OFFSET = -100;
|
||||||
|
public static Color BACKGROUND_COLOR = Color.yellow;
|
||||||
|
public static Color FOREGROUND_COLOR = Color.black;
|
||||||
|
//private int displayTime = -1;
|
||||||
|
//private String displayText = "";
|
||||||
|
public StatusWindow(String lblText, int displayTime) {
|
||||||
|
super();
|
||||||
|
//this.displayTime = displayTime;
|
||||||
|
//this.displayText = lblText;
|
||||||
|
//this.setLayout(new FlowLayout());
|
||||||
|
JLabel lbl = new JLabel(lblText);
|
||||||
|
lbl.setFont(new Font(lbl.getName(), FONT_BOLD, FONT_SIZE));
|
||||||
|
lbl.setOpaque(true); //background isn't painted without this
|
||||||
|
lbl.setBackground(BACKGROUND_COLOR);
|
||||||
|
lbl.setForeground(FOREGROUND_COLOR);
|
||||||
|
this.getContentPane().setLayout(new FlowLayout());
|
||||||
|
this.getContentPane().add(lbl);
|
||||||
|
this.pack();
|
||||||
|
this.setVisible(true);
|
||||||
|
//
|
||||||
|
if (displayTime > 0) {
|
||||||
|
Timer timer = new Timer(true);
|
||||||
|
timer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
StatusWindow.this.dispose();
|
||||||
|
}
|
||||||
|
}, displayTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisible(final boolean visible) {
|
||||||
|
super.setVisible(visible);
|
||||||
|
// ...and bring window to the front.. in a strange and weird way
|
||||||
|
if (visible) {
|
||||||
|
super.setAlwaysOnTop(true);
|
||||||
|
super.toFront();
|
||||||
|
super.requestFocus();
|
||||||
|
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
|
||||||
|
//this.setLocation(dim.width/2-this.getSize().width/2, dim.height/2-this.getSize().height/2);
|
||||||
|
this.setLocation(dim.width/2-this.getSize().width/2, dim.height + Y_BOTTOM_OFFSET );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
438
src/org/synthuse/SynthuseDlg.java
Normal file
@@ -0,0 +1,438 @@
|
|||||||
|
/*
|
||||||
|
* 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.5";
|
||||||
|
|
||||||
|
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 JComboBox<String> cmbXpath;
|
||||||
|
private JButton btnTestIde;
|
||||||
|
|
||||||
|
private TestIdeFrame testIde = null;
|
||||||
|
private int targetX;
|
||||||
|
private int targetY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.getXmlThreaded(textPane, lblStatus);
|
||||||
|
//appendToPane(WindowsEnumeratedXml.getXml());
|
||||||
|
//lblStatus.setText("Windows Enumerated Xml loaded");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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 + "<EFBFBD>")){
|
||||||
|
config.xpathList += xpathItem + "<EFBFBD>";
|
||||||
|
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("<EFBFBD>")));
|
||||||
|
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));
|
||||||
|
|
||||||
|
lblStatus.setText("class: " + classStr + " hWnd: " + handleStr + " parent: " + parentStr + " X,Y: " + targetX + ", " + targetY);
|
||||||
|
if (!lastDragHwnd.equals(handleStr)) {
|
||||||
|
if (!lastDragHwnd.isEmpty()) {
|
||||||
|
Api.refreshWindow(Api.GetHandleFromString(lastDragHwnd));
|
||||||
|
}
|
||||||
|
lastDragHwnd = handleStr;
|
||||||
|
//lastDragHwnd = (hwnd + "");
|
||||||
|
Api.highlightWindow(hwnd);
|
||||||
|
XpathManager.buildXpathStatementThreaded(hwnd, textPane, xpathEvents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
132
src/org/synthuse/TestIdeFrame.java
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
import javax.swing.JToolBar;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.JTextArea;
|
||||||
|
import javax.swing.WindowConstants;
|
||||||
|
|
||||||
|
import java.awt.datatransfer.Clipboard;
|
||||||
|
import java.awt.datatransfer.StringSelection;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
|
||||||
|
public class TestIdeFrame extends JFrame {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private JPanel contentPane;
|
||||||
|
public JTextArea txtTest;
|
||||||
|
private JButton btnRun;
|
||||||
|
private JButton btnClear;
|
||||||
|
private JButton btnCopy;
|
||||||
|
private JLabel lblStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the frame.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public TestIdeFrame() {
|
||||||
|
setTitle("Test IDE - Synthuse");
|
||||||
|
setIconImage(Toolkit.getDefaultToolkit().getImage(TestIdeFrame.class.getResource("/org/qedsys/synthuse/applications-education.png")));
|
||||||
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
setBounds(100, 100, 700, 367);
|
||||||
|
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);
|
||||||
|
|
||||||
|
btnRun = new JButton("Run");
|
||||||
|
btnRun.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent arg0) {
|
||||||
|
if (btnRun.getText().equals("Run")) {
|
||||||
|
btnRun.setText("Stop");
|
||||||
|
btnRun.setIcon(new ImageIcon(SynthuseDlg.class.getResource("/org/qedsys/synthuse/dialog-close.png")));
|
||||||
|
CommandProcessor.STOP_PROCESSOR.set(false);
|
||||||
|
CommandProcessor.executeThreaded(txtTest.getText(), new CommandProcessor.Events() {
|
||||||
|
@Override
|
||||||
|
public void statusChanged(String status) {
|
||||||
|
lblStatus.setText(status);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void executionCompleted() {
|
||||||
|
btnRun.setText("Run");
|
||||||
|
btnRun.setIcon(new ImageIcon(SynthuseDlg.class.getResource("/org/qedsys/synthuse/arrow-right-3.png")));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CommandProcessor.STOP_PROCESSOR.set(true);
|
||||||
|
//btnRun.setText("Run");
|
||||||
|
//btnRun.setIcon(new ImageIcon(SynthuseDlg.class.getResource("/org/qedsys/synthuse/arrow-right-3.png")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
btnRun.setIcon(new ImageIcon(SynthuseDlg.class.getResource("/org/qedsys/synthuse/arrow-right-3.png")));
|
||||||
|
toolBar.add(btnRun);
|
||||||
|
|
||||||
|
btnClear = new JButton("Clear");
|
||||||
|
btnClear.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent arg0) {
|
||||||
|
txtTest.setText("");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
btnClear.setIcon(new ImageIcon(SynthuseDlg.class.getResource("/org/qedsys/synthuse/user-trash-2.png")));
|
||||||
|
toolBar.add(btnClear);
|
||||||
|
|
||||||
|
btnCopy = new JButton("Copy Script");
|
||||||
|
btnCopy.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent arg0) {
|
||||||
|
StringSelection stringSelection = new StringSelection(txtTest.getText());
|
||||||
|
Clipboard clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||||
|
clpbrd.setContents(stringSelection, null);
|
||||||
|
//StatusWindow sw = new StatusWindow("this is a test BLAH really long string goes here to test status of stuff yaya!!!!123123 123 123", 4000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
btnCopy.setIcon(new ImageIcon(SynthuseDlg.class.getResource("/org/qedsys/synthuse/edit-copy-7.png")));
|
||||||
|
toolBar.add(btnCopy);
|
||||||
|
|
||||||
|
JScrollPane scrollPane = new JScrollPane();
|
||||||
|
contentPane.add(scrollPane, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
txtTest = new JTextArea();
|
||||||
|
txtTest.setText("Click the Run button above to test the script below...\r\n\r\n");
|
||||||
|
scrollPane.setViewportView(txtTest);
|
||||||
|
|
||||||
|
lblStatus = new JLabel(" ");
|
||||||
|
contentPane.add(lblStatus, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
|
this.addWindowListener(new WindowAdapter() {
|
||||||
|
@Override
|
||||||
|
public void windowClosing(WindowEvent e) {
|
||||||
|
//TestIdeFrame.this.setVisible(false);
|
||||||
|
TestIdeFrame.this.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
71
src/org/synthuse/WindowInfo.java
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import org.synthuse.Api.*;
|
||||||
|
|
||||||
|
import com.sun.jna.Native;
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.HWND;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.RECT;
|
||||||
|
import com.sun.jna.ptr.PointerByReference;
|
||||||
|
|
||||||
|
public class WindowInfo {
|
||||||
|
|
||||||
|
public HWND hwnd;
|
||||||
|
public String hwndStr = "";
|
||||||
|
public HWND parent = null;
|
||||||
|
public String parentStr = "";
|
||||||
|
public RECT rect;
|
||||||
|
public String text;
|
||||||
|
public String className = "";
|
||||||
|
public boolean isChild = false;
|
||||||
|
public String processName = "";
|
||||||
|
public long pid = 0;
|
||||||
|
public Object xmlObj = null;
|
||||||
|
|
||||||
|
public WindowInfo(HWND hWnd, boolean isChild) {
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
User32.instance.GetWindowTextA(hWnd, buffer, buffer.length);
|
||||||
|
text = Native.toString(buffer);
|
||||||
|
if (text.isEmpty())
|
||||||
|
text = new Api().sendWmGetText(hWnd);
|
||||||
|
|
||||||
|
char[] buffer2 = new char[1026];
|
||||||
|
User32.instance.GetClassName(hWnd, buffer2, 1026);
|
||||||
|
className = Native.toString(buffer2);
|
||||||
|
|
||||||
|
rect = new RECT();
|
||||||
|
User32.instance.GetWindowRect(hWnd, rect);
|
||||||
|
|
||||||
|
this.isChild = isChild;
|
||||||
|
if (isChild) {
|
||||||
|
parent = User32.instance.GetParent(hWnd);
|
||||||
|
parentStr = Api.GetHandleAsString(parent);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//User32.instance.GetWindowModuleFileName(hWnd, path, 512);
|
||||||
|
PointerByReference pointer = new PointerByReference();
|
||||||
|
User32.instance.GetWindowThreadProcessId(hWnd, pointer);
|
||||||
|
Pointer p = pointer.getPointer();
|
||||||
|
pid = p.getLong(0);
|
||||||
|
Pointer process = Kernel32.instance.OpenProcess(Api.PROCESS_QUERY_INFORMATION | Api.PROCESS_VM_READ, false, pointer.getValue());
|
||||||
|
Psapi.instance.GetModuleBaseNameW(process, null, buffer2, 512);
|
||||||
|
processName = Native.toString(buffer2);
|
||||||
|
//processName = Native.toString(path);
|
||||||
|
}
|
||||||
|
this.hwnd = hWnd;
|
||||||
|
hwndStr = Api.GetHandleAsString(hWnd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return String.format("(%d,%d)-(%d,%d) : \"%s\" [%s] {%s}", rect.left,rect.top,rect.right,rect.bottom,text,className,hwnd.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
253
src/org/synthuse/WindowsEnumeratedXml.java
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JTextPane;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.transform.OutputKeys;
|
||||||
|
import javax.xml.transform.Transformer;
|
||||||
|
import javax.xml.transform.TransformerFactory;
|
||||||
|
import javax.xml.transform.dom.DOMSource;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import javax.xml.xpath.XPath;
|
||||||
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
import javax.xml.xpath.XPathExpression;
|
||||||
|
import javax.xml.xpath.XPathFactory;
|
||||||
|
|
||||||
|
import org.w3c.dom.Attr;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
import com.sun.jna.platform.win32.WinUser;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.HWND;
|
||||||
|
|
||||||
|
public class WindowsEnumeratedXml implements Runnable{
|
||||||
|
public static Exception lastException = null;
|
||||||
|
|
||||||
|
public JTextPane outputPane = null;
|
||||||
|
public JLabel lblStatus = null;
|
||||||
|
public WindowsEnumeratedXml() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public WindowsEnumeratedXml(JTextPane outputPane, JLabel lblStatus) {
|
||||||
|
this.outputPane = outputPane;
|
||||||
|
this.lblStatus = lblStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
lblStatus.setText("Loading Windows Enumerated Xml...");
|
||||||
|
long startTime = System.nanoTime();
|
||||||
|
outputPane.setText(getXml());
|
||||||
|
outputPane.setCaretPosition(0);
|
||||||
|
double seconds = ((double)(System.nanoTime() - startTime) / 1000000000);
|
||||||
|
lblStatus.setText("Windows Enumerated Xml loaded in " + new DecimalFormat("#.###").format(seconds) + " seconds");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void getXmlThreaded(JTextPane outputPane, JLabel lblStatus) {
|
||||||
|
Thread t = new Thread(new WindowsEnumeratedXml(outputPane, lblStatus));
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getXml() {
|
||||||
|
final Map<String, WindowInfo> infoList = new LinkedHashMap<String, WindowInfo>();
|
||||||
|
final Map<String, String> processList = new LinkedHashMap<String, String>();
|
||||||
|
|
||||||
|
class ChildWindowCallback implements WinUser.WNDENUMPROC {
|
||||||
|
@Override
|
||||||
|
public boolean callback(HWND hWnd, Pointer lParam) {
|
||||||
|
infoList.put(Api.GetHandleAsString(hWnd), new WindowInfo(hWnd, true));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ParentWindowCallback implements WinUser.WNDENUMPROC {
|
||||||
|
@Override
|
||||||
|
public boolean callback(HWND hWnd, Pointer lParam) {
|
||||||
|
infoList.put(Api.GetHandleAsString(hWnd), new WindowInfo(hWnd, false));
|
||||||
|
Api.User32.instance.EnumChildWindows(hWnd, new ChildWindowCallback(), new Pointer(0));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Api.User32.instance.EnumWindows(new ParentWindowCallback(), 0);
|
||||||
|
|
||||||
|
// convert window info list to xml dom
|
||||||
|
try {
|
||||||
|
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||||
|
|
||||||
|
// root elements
|
||||||
|
Document doc = docBuilder.newDocument();
|
||||||
|
Element rootElement = doc.createElement("EnumeratedWindows");
|
||||||
|
doc.appendChild(rootElement);
|
||||||
|
|
||||||
|
long parentCount = 0;
|
||||||
|
long childCount = 0;
|
||||||
|
for (String handle : infoList.keySet()) {
|
||||||
|
WindowInfo w = infoList.get(handle);
|
||||||
|
//System.out.println(w);
|
||||||
|
// create new win xml element
|
||||||
|
Element win = doc.createElement("win");
|
||||||
|
win.setAttribute("hwnd", w.hwndStr);
|
||||||
|
win.setAttribute("text", w.text);
|
||||||
|
win.setAttribute("TEXT", w.text.toUpperCase());
|
||||||
|
win.setAttribute("class", w.className);
|
||||||
|
win.setAttribute("CLASS", w.className.toUpperCase());
|
||||||
|
if (!w.isChild) {
|
||||||
|
parentCount++;
|
||||||
|
if (w.processName != null && !w.processName.isEmpty()) {
|
||||||
|
if (!processList.containsKey(w.pid+""))
|
||||||
|
processList.put(w.pid+"", w.hwndStr);
|
||||||
|
win.setAttribute("process", w.processName);
|
||||||
|
win.setAttribute("PROCESS", w.processName.toUpperCase());
|
||||||
|
win.setAttribute("pid", w.pid+"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
//win.setAttribute("parent", w.parent + ""); // not really needed since child node is append to parent node
|
||||||
|
|
||||||
|
if (w.isChild && infoList.containsKey(w.parentStr)) {
|
||||||
|
childCount++;
|
||||||
|
WindowInfo parentWi = infoList.get(w.parentStr);
|
||||||
|
if (parentWi.xmlObj != null)
|
||||||
|
((Element)parentWi.xmlObj).appendChild(win);
|
||||||
|
else
|
||||||
|
rootElement.appendChild(win);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rootElement.appendChild(win);
|
||||||
|
w.xmlObj = win;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate totals on various windows.
|
||||||
|
Element totals = doc.createElement("totals");
|
||||||
|
totals.setAttribute("parentCount", parentCount+"");
|
||||||
|
totals.setAttribute("childCount", childCount+"");
|
||||||
|
totals.setAttribute("windowCount", infoList.size()+"");
|
||||||
|
totals.setAttribute("processCount", processList.size()+"");
|
||||||
|
totals.setAttribute("updatedLast", new Timestamp((new Date()).getTime()) + "");
|
||||||
|
rootElement.appendChild(totals);
|
||||||
|
String output = nodeToString(rootElement);
|
||||||
|
//System.out.println("count - " + infoList.size() + "\r\n");
|
||||||
|
return output;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String escapeXmlAttributeValue(String unescapedStr) {
|
||||||
|
String result = "";
|
||||||
|
try {
|
||||||
|
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||||
|
// root elements
|
||||||
|
Document doc = docBuilder.newDocument();
|
||||||
|
Element rootElement = doc.createElement("temp");
|
||||||
|
doc.appendChild(rootElement);
|
||||||
|
Attr attribute = doc.createAttribute("attrib");
|
||||||
|
attribute.setNodeValue(unescapedStr);
|
||||||
|
rootElement.setAttributeNode(attribute);
|
||||||
|
result = nodeToString(rootElement);
|
||||||
|
result = result.replaceAll("[^\"]*\"([^\"]*)\"[^\"]*", "$1"); // keep the string within quotes.
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
//lastException = e;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String nodeToString(Node node) {
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
try {
|
||||||
|
Transformer t = TransformerFactory.newInstance().newTransformer();
|
||||||
|
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||||
|
t.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||||
|
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
|
||||||
|
t.transform(new DOMSource(node), new StreamResult(sw));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
return sw.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String queryWindowInfoXml(String xpathExpr) {
|
||||||
|
String nl = System.getProperty("line.separator");
|
||||||
|
String result = "<result>" + nl;
|
||||||
|
String xml = getXml();
|
||||||
|
List<String> resultList = evaluateXpathGetValues(xml, xpathExpr);
|
||||||
|
for(String item: resultList) {
|
||||||
|
result += " " + item;
|
||||||
|
}
|
||||||
|
result += "</result>" + nl;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HWND queryHandleWindowInfoXml(String xpathExpr) {
|
||||||
|
String xml = getXml();
|
||||||
|
String result = "";
|
||||||
|
List<String> resultList = evaluateXpathGetValues(xml, xpathExpr);
|
||||||
|
for(String item: resultList) {
|
||||||
|
if (item.contains("hwnd")) {
|
||||||
|
List<String> hwndList = evaluateXpathGetValues(item, "//@hwnd");
|
||||||
|
result = hwndList.get(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Api.GetHandleFromString(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static List<String> evaluateXpathGetValues(String xml, String xpathExpr) {
|
||||||
|
List<String> resultLst = new ArrayList<String>();
|
||||||
|
try {
|
||||||
|
InputSource inSource = new InputSource(new StringReader(xml));
|
||||||
|
XPathFactory factory = XPathFactory.newInstance();
|
||||||
|
XPath xpath = factory.newXPath();
|
||||||
|
XPathExpression expr = xpath.compile(xpathExpr);
|
||||||
|
|
||||||
|
Object result = expr.evaluate(inSource, XPathConstants.NODESET);
|
||||||
|
NodeList nodes = (NodeList) result;
|
||||||
|
for (int i = 0; i < nodes.getLength(); i++) {
|
||||||
|
String val = nodes.item(i).getNodeValue();
|
||||||
|
if (val == null) // if we can't get a string value try to transform the xml node to a string
|
||||||
|
val = nodeToString(nodes.item(i));
|
||||||
|
else
|
||||||
|
val += System.getProperty("line.separator");
|
||||||
|
resultLst.add(val);
|
||||||
|
//System.out.println("match " + i + ": " + val);
|
||||||
|
}
|
||||||
|
} catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
|
return resultLst;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
209
src/org/synthuse/XmlEditorKit.java
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.*;
|
||||||
|
import javax.swing.text.*;
|
||||||
|
|
||||||
|
/* Example:
|
||||||
|
|
||||||
|
// Set editor kit
|
||||||
|
jtextpane.setEditorKitForContentType("text/xml", new XmlEditorKit());
|
||||||
|
jtextpane.setContentType("text/xml");
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class XmlEditorKit extends StyledEditorKit {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 2969169649596107757L;
|
||||||
|
private ViewFactory xmlViewFactory;
|
||||||
|
|
||||||
|
private static HashMap<Pattern, Color> patternColors;
|
||||||
|
private static String TAG_PATTERN = "(</?[a-z]*)\\s?>?";
|
||||||
|
private static String TAG_END_PATTERN = "(/>)";
|
||||||
|
private static String TAG_ATTRIBUTE_PATTERN = "\\s([a-zA-Z0-9]*)\\s*?\\=\\s*?\\\"";
|
||||||
|
private static String TAG_ATTRIBUTE_VALUE = "[a-zA-Z0-9]*\\=(\"[^\"]*\")";
|
||||||
|
private static String TAG_COMMENT = "(<!--.*-->)";
|
||||||
|
private static String TAG_CDATA_START = "(\\<!\\[CDATA\\[).*";
|
||||||
|
private static String TAG_CDATA_END = ".*(]]>)";
|
||||||
|
|
||||||
|
//public static String TAG_HIGHLIGHTED = ".*hwnd=\"([^\"]*)\".*";
|
||||||
|
public static String TAG_HIGHLIGHTED = "";
|
||||||
|
public static Color TAG_HIGHLIGHTED_COLOR = new Color(170, 255, 48);
|
||||||
|
|
||||||
|
public static int HIGHLIGHTED_START = 0;
|
||||||
|
public static int HIGHLIGHTED_END = 0;
|
||||||
|
public static Color HIGHLIGHTED_COLOR = new Color(240, 255, 112);
|
||||||
|
|
||||||
|
static {
|
||||||
|
// NOTE: the order is important!
|
||||||
|
patternColors = new HashMap<Pattern, Color>();
|
||||||
|
patternColors.put(Pattern.compile(TAG_CDATA_START), new Color(128, 128, 128));
|
||||||
|
patternColors.put(Pattern.compile(TAG_CDATA_END), new Color(128, 128, 128));
|
||||||
|
patternColors.put(Pattern.compile(TAG_PATTERN), new Color(63, 127, 127));
|
||||||
|
patternColors.put(Pattern.compile(TAG_ATTRIBUTE_PATTERN), new Color(127, 0, 127));
|
||||||
|
patternColors.put(Pattern.compile(TAG_END_PATTERN), new Color(63, 127, 127));
|
||||||
|
patternColors.put(Pattern.compile(TAG_ATTRIBUTE_VALUE), new Color(42, 0, 255));
|
||||||
|
patternColors.put(Pattern.compile(TAG_COMMENT), new Color(63, 95, 191));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class XmlView extends PlainView {
|
||||||
|
|
||||||
|
|
||||||
|
public XmlView(Element element) {
|
||||||
|
|
||||||
|
super(element);
|
||||||
|
|
||||||
|
// Set tabsize to 4 (instead of the default 8)
|
||||||
|
getDocument().putProperty(PlainDocument.tabSizeAttribute, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int drawUnselectedText(Graphics graphics, int x, int y, int p0, int p1) throws BadLocationException {
|
||||||
|
try {
|
||||||
|
|
||||||
|
Document doc = getDocument();
|
||||||
|
String text = doc.getText(p0, p1 - p0);
|
||||||
|
|
||||||
|
Segment segment = getLineBuffer();
|
||||||
|
int initialXpos = x;
|
||||||
|
|
||||||
|
SortedMap<Integer, Integer> startMap = new TreeMap<Integer, Integer>();
|
||||||
|
SortedMap<Integer, Color> colorMap = new TreeMap<Integer, Color>();
|
||||||
|
|
||||||
|
// Match all regexes on this snippet, store positions
|
||||||
|
for (Map.Entry<Pattern, Color> entry : patternColors.entrySet()) {
|
||||||
|
|
||||||
|
Matcher matcher = entry.getKey().matcher(text);
|
||||||
|
|
||||||
|
while (matcher.find()) {
|
||||||
|
startMap.put(matcher.start(1), matcher.end(1));
|
||||||
|
colorMap.put(matcher.start(1), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check the map for overlapping parts
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
//add tag highlighted background colors
|
||||||
|
if (!TAG_HIGHLIGHTED.isEmpty()) {
|
||||||
|
Matcher highlightMatcher = Pattern.compile(TAG_HIGHLIGHTED).matcher(text);
|
||||||
|
while(highlightMatcher.find()) {
|
||||||
|
int start = highlightMatcher.start(1);
|
||||||
|
int end = highlightMatcher.end(1);
|
||||||
|
if (i < start) {
|
||||||
|
graphics.setColor(Color.black);
|
||||||
|
doc.getText(p0 + i, start - i, segment);
|
||||||
|
x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
|
||||||
|
}
|
||||||
|
graphics.setColor(TAG_HIGHLIGHTED_COLOR);
|
||||||
|
i = end;
|
||||||
|
doc.getText(p0 + start, i - start, segment);
|
||||||
|
int width = Utilities.getTabbedTextWidth(segment, graphics.getFontMetrics(), x, this, p0 + start);
|
||||||
|
//graphics.drawLine(x, y, width, y);graphics.getFontMetrics()
|
||||||
|
graphics.fillRect(x, y - graphics.getFontMetrics().getHeight() + 2, width, graphics.getFontMetrics().getHeight());
|
||||||
|
graphics.setColor(Color.black);
|
||||||
|
doc.getText(p0 + start, i - start, segment);
|
||||||
|
x = Utilities.drawTabbedText(segment, x, y, graphics, this, start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x = initialXpos;
|
||||||
|
i=0;
|
||||||
|
//add highlighted background colors based on position
|
||||||
|
//String textx = doc.getText(p0, p1 - p0);
|
||||||
|
if ((HIGHLIGHTED_START < p1 && HIGHLIGHTED_START >= p0) || (HIGHLIGHTED_END <= p1 && HIGHLIGHTED_END > p0) || ( HIGHLIGHTED_START < p1 && HIGHLIGHTED_END > p0)) {
|
||||||
|
//select whole line
|
||||||
|
int start = 0;
|
||||||
|
int end = text.length();
|
||||||
|
// test to see if only partial line is needed.
|
||||||
|
if (HIGHLIGHTED_START > p0)
|
||||||
|
start = HIGHLIGHTED_START - p0;
|
||||||
|
if (HIGHLIGHTED_END < p1)
|
||||||
|
end -= p1 - HIGHLIGHTED_END;
|
||||||
|
if (i < start) { // fill in normal color if start highlight isn't at the beginning
|
||||||
|
graphics.setColor(Color.black);
|
||||||
|
doc.getText(p0 + i, start - i, segment);
|
||||||
|
x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
|
||||||
|
}
|
||||||
|
graphics.setColor(HIGHLIGHTED_COLOR);// fill in the highlight color
|
||||||
|
i = end;
|
||||||
|
if (i - start > 0) {
|
||||||
|
doc.getText(p0 + start, i - start, segment);
|
||||||
|
int width = Utilities.getTabbedTextWidth(segment, graphics.getFontMetrics(), x, this, p0 + start);
|
||||||
|
//graphics.drawLine(x, y, width, y);graphics.getFontMetrics()
|
||||||
|
graphics.fillRect(x, y - graphics.getFontMetrics().getHeight() + 2, width, graphics.getFontMetrics().getHeight());
|
||||||
|
graphics.setColor(Color.black);
|
||||||
|
doc.getText(p0 + start, i - start, segment);
|
||||||
|
x = Utilities.drawTabbedText(segment, x, y, graphics, this, start);
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// System.out.println("invalid highlighting " + (i - start) + " is <= 0 (" + p0 + "-" + p1 + "=" + (p1 - p0) +") " + start + ", " + end + " len=" + text.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
x = initialXpos;
|
||||||
|
i=0;
|
||||||
|
// Color the parts of xml foreground font
|
||||||
|
for (Map.Entry<Integer, Integer> entry : startMap.entrySet()) {
|
||||||
|
int start = entry.getKey();
|
||||||
|
int end = entry.getValue();
|
||||||
|
|
||||||
|
if (i < start) {
|
||||||
|
graphics.setColor(Color.black);
|
||||||
|
doc.getText(p0 + i, start - i, segment);
|
||||||
|
x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
graphics.setColor(colorMap.get(start));
|
||||||
|
i = end;
|
||||||
|
doc.getText(p0 + start, i - start, segment);
|
||||||
|
x = Utilities.drawTabbedText(segment, x, y, graphics, this, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Paint possible remaining text black
|
||||||
|
if (i < text.length()) {
|
||||||
|
graphics.setColor(Color.black);
|
||||||
|
doc.getText(p0 + i, text.length() - i, segment);
|
||||||
|
x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class XmlViewFactory extends Object implements ViewFactory {
|
||||||
|
/**
|
||||||
|
* @see javax.swing.text.ViewFactory#create(javax.swing.text.Element)
|
||||||
|
*/
|
||||||
|
public View create(Element element) {
|
||||||
|
|
||||||
|
return new XmlView(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlEditorKit() {
|
||||||
|
xmlViewFactory = new XmlViewFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ViewFactory getViewFactory() {
|
||||||
|
return xmlViewFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getContentType() {
|
||||||
|
return "text/xml";
|
||||||
|
}
|
||||||
|
}
|
||||||
203
src/org/synthuse/XpathManager.java
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import java.awt.EventQueue;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.JTextPane;
|
||||||
|
|
||||||
|
import org.synthuse.Api.User32;
|
||||||
|
|
||||||
|
import com.sun.jna.platform.win32.WinDef.HWND;
|
||||||
|
|
||||||
|
public class XpathManager implements Runnable{
|
||||||
|
|
||||||
|
private HWND hwnd = null;
|
||||||
|
private JTextPane windowsXmlTextPane = null;
|
||||||
|
|
||||||
|
public static interface Events {
|
||||||
|
void statusChanged(String status);
|
||||||
|
void executionCompleted(Object input, String results);
|
||||||
|
}
|
||||||
|
public Events events = new Events() {
|
||||||
|
public void statusChanged(String status){
|
||||||
|
System.out.println(status);
|
||||||
|
}
|
||||||
|
public void executionCompleted(Object input, String results){
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public XpathManager(HWND hwnd, JTextPane windowsXmlTextPane, Events events) {
|
||||||
|
this.events = events;
|
||||||
|
this.hwnd = hwnd;
|
||||||
|
this.windowsXmlTextPane = windowsXmlTextPane;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String results = buildXpathStatement();
|
||||||
|
events.executionCompleted(hwnd, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void buildXpathStatementThreaded(HWND hwnd, JTextPane windowsXmlTextPane, Events events) {
|
||||||
|
Thread t = new Thread(new XpathManager(hwnd, windowsXmlTextPane, events));
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String buildXpathStatement() {
|
||||||
|
String builtXpath = "";
|
||||||
|
try {
|
||||||
|
String classStr = WindowsEnumeratedXml.escapeXmlAttributeValue(Api.GetWindowClassName(hwnd));
|
||||||
|
String handleStr = Api.GetHandleAsString(hwnd);
|
||||||
|
String txtOrig = Api.GetWindowText(hwnd);
|
||||||
|
String txtStr = WindowsEnumeratedXml.escapeXmlAttributeValue(txtOrig);
|
||||||
|
String xml = this.windowsXmlTextPane.getText();
|
||||||
|
builtXpath = "//win[@class='" + classStr + "']";
|
||||||
|
List<String> resultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
|
||||||
|
//int matches = nextXpathMatch(builtXpath, textPane, true);
|
||||||
|
if (resultList.size() > 1) { // if there are multiple results with the simple xpath then include parent class and text with the xpath statement.
|
||||||
|
HWND parent = User32.instance.GetParent(hwnd);
|
||||||
|
String parentClassStr = WindowsEnumeratedXml.escapeXmlAttributeValue(Api.GetWindowClassName(parent));
|
||||||
|
String parentTxtOrig = Api.GetWindowText(parent);
|
||||||
|
String parentTxtStr = WindowsEnumeratedXml.escapeXmlAttributeValue(parentTxtOrig);
|
||||||
|
if (!parentTxtStr.isEmpty()) {
|
||||||
|
if (parentTxtOrig.length() > 20) {// if the parent text is too long only test the first 20 characters
|
||||||
|
parentTxtStr = WindowsEnumeratedXml.escapeXmlAttributeValue(parentTxtOrig.substring(0, 20));
|
||||||
|
parentTxtStr = " and starts-with(@text,'" + parentTxtStr + "')";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
parentTxtStr = " and @text='" + parentTxtStr + "'";
|
||||||
|
}
|
||||||
|
if (!parentClassStr.isEmpty())
|
||||||
|
builtXpath = "//win[@class='" + parentClassStr + "'" + parentTxtStr + "]/win[@class='" + classStr + "']";
|
||||||
|
resultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
|
||||||
|
if (resultList.size() > 1) { // if there are still multiple results add position to the xpath
|
||||||
|
int position = 1;
|
||||||
|
for (String result : resultList) {
|
||||||
|
if (result.contains(handleStr)) {
|
||||||
|
builtXpath += "[" + position + "]";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resultList.size() == 0) { //some reason a window might have a parent window that is not associated with it's child (orphans!!)
|
||||||
|
if (!txtStr.isEmpty()) {
|
||||||
|
if (parentTxtOrig.length() > 30) {// if the text is too long only test the first 20 characters
|
||||||
|
txtStr = WindowsEnumeratedXml.escapeXmlAttributeValue(txtStr.substring(0, 30));
|
||||||
|
txtStr = " and starts-with(@text,'" + txtStr + "')";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
txtStr = " and @text='" + txtStr + "'";
|
||||||
|
}
|
||||||
|
builtXpath = "//win[@class='" + classStr + "'" + txtStr + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return builtXpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int nextXpathMatch(String xpathExpr, JTextPane targetText, JLabel lblStatus, boolean alwaysFromTop) {
|
||||||
|
int results = 0;
|
||||||
|
try {
|
||||||
|
if (xpathExpr.length() == 0)
|
||||||
|
return results;
|
||||||
|
|
||||||
|
if (targetText instanceof JTextPane) {
|
||||||
|
final JTextPane target = (JTextPane)targetText;
|
||||||
|
target.requestFocus();
|
||||||
|
int cPos = target.getCaretPosition();
|
||||||
|
if (alwaysFromTop)
|
||||||
|
cPos = 0;
|
||||||
|
int len = target.getStyledDocument().getLength();
|
||||||
|
String xml = target.getText(0, len);
|
||||||
|
WindowsEnumeratedXml.lastException = null;
|
||||||
|
List<String> resultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, xpathExpr);
|
||||||
|
if (resultList.size() == 0 && WindowsEnumeratedXml.lastException != null) {
|
||||||
|
String errMsg = WindowsEnumeratedXml.lastException.getCause().getMessage();
|
||||||
|
JOptionPane.showMessageDialog(null, "Exception: " + errMsg, "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
results = resultList.size();
|
||||||
|
String txt = "";
|
||||||
|
String targetStr = target.getText(cPos, (len - cPos));
|
||||||
|
int matches = 0;
|
||||||
|
int mPos = 0;
|
||||||
|
target.select(cPos, cPos); //clear selection
|
||||||
|
for (int i = 0; i < resultList.size(); i++) {
|
||||||
|
txt = resultList.get(i).trim();
|
||||||
|
if (txt.length() == 0)
|
||||||
|
continue;
|
||||||
|
//if (txt.endsWith("\r\n"))
|
||||||
|
// txt = txt.substring(0, txt.length() - 2).trim();
|
||||||
|
txt = txt.replaceAll("\r\n", "\n").trim();
|
||||||
|
while ((mPos = targetStr.indexOf(txt)) != -1) {
|
||||||
|
if (matches == 0){
|
||||||
|
if (!alwaysFromTop)
|
||||||
|
flashMatchingWindow(txt);
|
||||||
|
//target.setCaretPosition(cPos + mPos);
|
||||||
|
//target.select(cPos + mPos, cPos + mPos + txt.length());
|
||||||
|
XmlEditorKit.HIGHLIGHTED_START = cPos + mPos;
|
||||||
|
XmlEditorKit.HIGHLIGHTED_END = cPos + mPos + txt.length();
|
||||||
|
//System.out.println("HIGHLIGHTED_START = " + (cPos + mPos));
|
||||||
|
//System.out.println("HIGHLIGHTED_END = " + (cPos + mPos + txt.length()));
|
||||||
|
final int cpos = cPos + mPos +2;
|
||||||
|
EventQueue.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
target.updateUI();
|
||||||
|
target.setCaretPosition(cpos);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
targetStr = targetStr.substring(mPos + txt.length());
|
||||||
|
++matches;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lblStatus.setText(results + " matches");
|
||||||
|
if (cPos > 0 && matches == 0 && !alwaysFromTop) { //ask if user wants to search from top
|
||||||
|
int result = JOptionPane.showConfirmDialog(null, "No more matches found. Do you want to search from the top of the document?", "Find", JOptionPane.YES_NO_OPTION);
|
||||||
|
if (result == JOptionPane.YES_OPTION) {
|
||||||
|
target.setCaretPosition(0);
|
||||||
|
nextXpathMatch(xpathExpr, targetText, lblStatus, alwaysFromTop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
XmlEditorKit.HIGHLIGHTED_START = 0;
|
||||||
|
XmlEditorKit.HIGHLIGHTED_END = 0;
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void flashMatchingWindow(String txtXml) {
|
||||||
|
if (txtXml.contains("hwnd")) {
|
||||||
|
List<String> hwndList = WindowsEnumeratedXml.evaluateXpathGetValues(txtXml, "//@hwnd");
|
||||||
|
if (hwndList.size() > 0) {
|
||||||
|
String hwndStr = hwndList.get(0);
|
||||||
|
HWND tHwnd = Api.GetHandleFromString(hwndStr);
|
||||||
|
Api.highlightWindow(tHwnd);
|
||||||
|
try { Thread.sleep(100); } catch (Exception e) {e.printStackTrace();}
|
||||||
|
Api.refreshWindow(tHwnd);
|
||||||
|
try { Thread.sleep(100); } catch (Exception e) {e.printStackTrace();}
|
||||||
|
Api.highlightWindow(tHwnd);
|
||||||
|
try { Thread.sleep(100); } catch (Exception e) {e.printStackTrace();}
|
||||||
|
Api.refreshWindow(tHwnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
BIN
src/org/synthuse/img/applications-education.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/org/synthuse/img/arrow-right-3.png
Normal file
|
After Width: | Height: | Size: 951 B |
BIN
src/org/synthuse/img/bullseye-logo-th18x18.png
Normal file
|
After Width: | Height: | Size: 610 B |
BIN
src/org/synthuse/img/bullseye-logo-th32x32.png
Normal file
|
After Width: | Height: | Size: 333 B |
BIN
src/org/synthuse/img/dialog-close.png
Normal file
|
After Width: | Height: | Size: 991 B |
BIN
src/org/synthuse/img/document-close-2.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/org/synthuse/img/document-new-5.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/org/synthuse/img/edit-copy-7.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/org/synthuse/img/edit-find-3.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/org/synthuse/img/gnome-robots.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/org/synthuse/img/help-3.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/org/synthuse/img/rapidsvn.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/org/synthuse/img/run-rebuild-2.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/org/synthuse/img/user-trash-2.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
6
synthuse.properties
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#
|
||||||
|
#Sun Feb 16 21:34:31 EST 2014
|
||||||
|
DEFAULT_PROP_FILENAME=
|
||||||
|
urlList=
|
||||||
|
xpathList=
|
||||||
|
xpathHightlight=.*process\="([^"]*)".*
|
||||||