From 23010edc728b8ae5fbaf02f10ce9946fe30230fb Mon Sep 17 00:00:00 2001 From: Jason Gallavin Date: Sun, 27 Jan 2019 16:28:59 -0500 Subject: [PATCH 1/3] Rework application to support the clipboard with the ctrl key --- .../org/iuscsg/autotyper/Application.java | 55 +++++++++++++++---- .../org/iuscsg/autotyper/HistoryManager.java | 47 ++++++++-------- .../autotyper/hotkey/HotKeyListener.java | 54 ++++++++++++------ .../hotkey/OnHistoryChangeListener.java | 6 -- .../iuscsg/autotyper/hotkey/OnKeyChange.java | 6 ++ 5 files changed, 112 insertions(+), 56 deletions(-) delete mode 100644 src/main/java/org/iuscsg/autotyper/hotkey/OnHistoryChangeListener.java create mode 100644 src/main/java/org/iuscsg/autotyper/hotkey/OnKeyChange.java diff --git a/src/main/java/org/iuscsg/autotyper/Application.java b/src/main/java/org/iuscsg/autotyper/Application.java index 4210783..550d1ec 100644 --- a/src/main/java/org/iuscsg/autotyper/Application.java +++ b/src/main/java/org/iuscsg/autotyper/Application.java @@ -1,7 +1,11 @@ package org.iuscsg.autotyper; +import org.iuscsg.autotyper.hotkey.HotKeyListener; + import javax.imageio.ImageIO; import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; @@ -10,15 +14,17 @@ // changing the package or the name of this class will require updating the isRunningInJar method in this class. public class Application extends Frame { - private TextField txt = makeTextField(); + private TextField txt = themeControl(new TextField(), 12); private HistoryManager historyManager = new HistoryManager(); - + private Button btn = makeButton(); + private HotKeyListener keyListener = makeHotKeyListener(); private Application() { if(shouldRedirectLogging()) // logging for if anyone runs into issues. turnOnLogging(); setIcon(); - Button btn = makeButton(); - historyManager.init(txt, btn); + historyManager.init(txt); + btn.addKeyListener(keyListener); + txt.addKeyListener(keyListener); add(txt); add(btn); setTitle("Auto Typer"); @@ -39,7 +45,7 @@ public static void main(String[] args) { private Button makeButton() { Button btn = new Button(); btn.setLabel("Type it!"); - btn.addActionListener(e ->typeWithDelay(txt.getText())); + btn.addActionListener(e -> onBtn_Click()); return themeControl(btn, 18); } @@ -50,11 +56,6 @@ private T themeControl(T component, int fontSize) { return component; } - private TextField makeTextField() { - TextField txt = new TextField(); - return themeControl(txt, 12); - } - private void setIcon() { try { InputStream letter = this.getClass().getClassLoader().getResourceAsStream("resources/letter.png"); @@ -69,6 +70,17 @@ private void setIcon() { } } + private void onBtn_Click() { + if(keyListener.IsModifierKeDown()) { + String clipboard = getClipboard(); + if(clipboard != null && clipboard.length() > 0) { + typeWithDelay(clipboard); + return; + } + } + typeWithDelay(txt.getText()); + } + private void typeWithDelay(String text) { (new Thread(new Typer(text))).start(); historyManager.addToHistory(text); @@ -92,4 +104,27 @@ private void turnOnLogging() { e.printStackTrace(); } } + + private String getClipboard() { + try { + return (String) Toolkit.getDefaultToolkit() + .getSystemClipboard().getData(DataFlavor.stringFlavor); + } catch (UnsupportedFlavorException | IOException e) { + e.printStackTrace(); + } + return null; + } + + private HotKeyListener makeHotKeyListener() { + return new HotKeyListener( + (boolean down) -> { if(down) historyManager.goForward(); }, + (boolean down) -> { if(down) historyManager.goBack(); }, + (boolean down) -> { + System.out.println("modifier: " + down); + if(down) + btn.setLabel("Type from clipboard!"); + else + btn.setLabel("Type It!"); + }); + } } diff --git a/src/main/java/org/iuscsg/autotyper/HistoryManager.java b/src/main/java/org/iuscsg/autotyper/HistoryManager.java index e778a69..1996c07 100644 --- a/src/main/java/org/iuscsg/autotyper/HistoryManager.java +++ b/src/main/java/org/iuscsg/autotyper/HistoryManager.java @@ -1,7 +1,5 @@ package org.iuscsg.autotyper; -import org.iuscsg.autotyper.hotkey.HotKeyListener; - import java.awt.*; import java.util.ArrayList; import java.util.Collections; @@ -13,9 +11,9 @@ class HistoryManager private int historyIndex = 0; private TextField txt; - void init(TextField txt, Button btn) { + void init(TextField txt) { this.txt = txt; - HotKeyListener hotkeyListener = initHotKeyListener(); + txt.addTextListener(e -> { if(ignoreTextChange) { ignoreTextChange = false; @@ -23,10 +21,6 @@ void init(TextField txt, Button btn) { } historyIndex = -1; }); - - txt.addKeyListener(hotkeyListener); - btn.addKeyListener(hotkeyListener); - } void addToHistory(String text) { @@ -36,23 +30,28 @@ void addToHistory(String text) { historyIndex = 0; } - private HotKeyListener initHotKeyListener() { - return new HotKeyListener(() -> { - if(historyIndex > 0){ - historyIndex--; - ignoreTextChange = true; - txt.setText(history.get(historyIndex)); - } - }, () -> { - if(history.size() > historyIndex + 1) { - if(historyIndex == -1) { - history.add(0, txt.getText()); - historyIndex++; - } + public void goBack() { + if(history.size() > historyIndex + 1) { + if(historyIndex == -1) { + history.add(0, txt.getText()); historyIndex++; - ignoreTextChange = true; - txt.setText(history.get(historyIndex)); } - }); + historyIndex++; + ignoreTextChange = true; + System.out.println("Set Text"); + txt.setText(history.get(historyIndex)); + } + } + + public void goForward() + { + if (historyIndex > 0) { + historyIndex--; + ignoreTextChange = true; + System.out.println("Set Text"); + txt.setText(history.get(historyIndex)); + } } + + } diff --git a/src/main/java/org/iuscsg/autotyper/hotkey/HotKeyListener.java b/src/main/java/org/iuscsg/autotyper/hotkey/HotKeyListener.java index 4ed2591..f2b31b5 100644 --- a/src/main/java/org/iuscsg/autotyper/hotkey/HotKeyListener.java +++ b/src/main/java/org/iuscsg/autotyper/hotkey/HotKeyListener.java @@ -5,15 +5,21 @@ public class HotKeyListener implements KeyListener { - private boolean backDown = false; - private boolean forwardDown = false; + private boolean backKeyDown = false; + private boolean forwardKeyDown = false; + private boolean modifierKeyDown = false; + private OnKeyChange onForwardListener; + private OnKeyChange onBackListener; + private OnKeyChange onModifierListener; - private OnHistoryChangeListener onForwardListener; - private OnHistoryChangeListener onBackListener; - - public HotKeyListener(OnHistoryChangeListener onForwardListener, OnHistoryChangeListener onBackListener) { + public HotKeyListener(OnKeyChange onForwardListener, OnKeyChange onBackListener, OnKeyChange onModifierListener) { this.onForwardListener = onForwardListener; this.onBackListener = onBackListener; + this.onModifierListener = onModifierListener; + } + + public boolean IsModifierKeDown() { + return this.modifierKeyDown; } @Override @@ -23,27 +29,43 @@ public void keyTyped(KeyEvent e) { /* NOT NEEDED */} public void keyPressed(KeyEvent e) { switch(e.getKeyCode()) { - case KeyEvent.VK_UP: backDown = true; break; - case KeyEvent.VK_DOWN: forwardDown = true; break; + case KeyEvent.VK_UP: backKeyDown = true; break; + case KeyEvent.VK_DOWN: forwardKeyDown = true; break; + case KeyEvent.VK_CONTROL: modifierKeyDown = true; break; } - executeListenersIfHotKeysPressed(); + executeListenersOnDown(); } @Override public void keyReleased(KeyEvent e) { switch(e.getKeyCode()) { - case KeyEvent.VK_UP: backDown = false; break; - case KeyEvent.VK_DOWN: forwardDown = false; break; + case KeyEvent.VK_UP: backKeyDown = false; break; + case KeyEvent.VK_DOWN: forwardKeyDown = false; break; + case KeyEvent.VK_CONTROL: modifierKeyDown = false; break; } + executeListenersOnUp(); } - private void executeListenersIfHotKeysPressed() { - if (backDown) { - onBackListener.onChange(); - } else if(forwardDown) { - onForwardListener.onChange(); + private void executeListenersOnDown() { + if (backKeyDown) { + onBackListener.onChange(true); + } else if(forwardKeyDown) { + onForwardListener.onChange(true); + } + else if(modifierKeyDown){ + onModifierListener.onChange(true); } } + + + private void executeListenersOnUp() { + if (!backKeyDown) + onBackListener.onChange(false); + if(!forwardKeyDown) + onForwardListener.onChange(false); + if(!modifierKeyDown) + onModifierListener.onChange(false); + } } diff --git a/src/main/java/org/iuscsg/autotyper/hotkey/OnHistoryChangeListener.java b/src/main/java/org/iuscsg/autotyper/hotkey/OnHistoryChangeListener.java deleted file mode 100644 index c35f4de..0000000 --- a/src/main/java/org/iuscsg/autotyper/hotkey/OnHistoryChangeListener.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.iuscsg.autotyper.hotkey; - -public interface OnHistoryChangeListener -{ - void onChange(); -} diff --git a/src/main/java/org/iuscsg/autotyper/hotkey/OnKeyChange.java b/src/main/java/org/iuscsg/autotyper/hotkey/OnKeyChange.java new file mode 100644 index 0000000..5e3c11a --- /dev/null +++ b/src/main/java/org/iuscsg/autotyper/hotkey/OnKeyChange.java @@ -0,0 +1,6 @@ +package org.iuscsg.autotyper.hotkey; + +public interface OnKeyChange +{ + void onChange(boolean keyDown); +} From a97c5845a9ec462cc7d0641cc3daaa7b0fb5598a Mon Sep 17 00:00:00 2001 From: Jason Gallavin Date: Sun, 27 Jan 2019 23:55:40 -0500 Subject: [PATCH 2/3] Add Multiline TextBox. Add support for CTRL + A for linux. --- pom.xml | 2 +- .../org/iuscsg/autotyper/Application.java | 28 ++++--- .../org/iuscsg/autotyper/HistoryManager.java | 6 +- src/main/java/org/iuscsg/autotyper/Typer.java | 4 +- .../autotyper/hotkey/HotKeyListener.java | 73 ++++++++----------- .../org/iuscsg/autotyper/hotkey/KeyState.java | 34 +++++++++ 6 files changed, 86 insertions(+), 61 deletions(-) create mode 100644 src/main/java/org/iuscsg/autotyper/hotkey/KeyState.java diff --git a/pom.xml b/pom.xml index 011349c..db748a5 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.iuscsg.autotyper auto-typer - 1.2-SNAPSHOT + 1.3-SNAPSHOT auto-typer https://github.com/ius-csg/AutoTyper diff --git a/src/main/java/org/iuscsg/autotyper/Application.java b/src/main/java/org/iuscsg/autotyper/Application.java index 550d1ec..6b50d52 100644 --- a/src/main/java/org/iuscsg/autotyper/Application.java +++ b/src/main/java/org/iuscsg/autotyper/Application.java @@ -14,7 +14,7 @@ // changing the package or the name of this class will require updating the isRunningInJar method in this class. public class Application extends Frame { - private TextField txt = themeControl(new TextField(), 12); + private TextArea txt = themeControl(new TextArea("", 0, 0, TextArea.SCROLLBARS_NONE), 12); private HistoryManager historyManager = new HistoryManager(); private Button btn = makeButton(); private HotKeyListener keyListener = makeHotKeyListener(); @@ -35,6 +35,11 @@ private Application() { public void windowClosing(WindowEvent we) { System.exit(0); } + + @Override + public void windowDeactivated(WindowEvent e) { + keyListener.onFrameDeactivated(); + } }); } @@ -71,7 +76,7 @@ private void setIcon() { } private void onBtn_Click() { - if(keyListener.IsModifierKeDown()) { + if(keyListener.getModifierKeyState().isKeyDown()) { String clipboard = getClipboard(); if(clipboard != null && clipboard.length() > 0) { typeWithDelay(clipboard); @@ -98,7 +103,7 @@ private boolean isRunningInJar() { private void turnOnLogging() { try { - PrintStream out = new PrintStream(new FileOutputStream("AutoTyper.log")); + PrintStream out = new PrintStream(new FileOutputStream("AutoTyper.log", true)); System.setOut(out); } catch (FileNotFoundException e) { e.printStackTrace(); @@ -107,8 +112,7 @@ private void turnOnLogging() { private String getClipboard() { try { - return (String) Toolkit.getDefaultToolkit() - .getSystemClipboard().getData(DataFlavor.stringFlavor); + return (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor); } catch (UnsupportedFlavorException | IOException e) { e.printStackTrace(); } @@ -120,11 +124,13 @@ private HotKeyListener makeHotKeyListener() { (boolean down) -> { if(down) historyManager.goForward(); }, (boolean down) -> { if(down) historyManager.goBack(); }, (boolean down) -> { - System.out.println("modifier: " + down); - if(down) - btn.setLabel("Type from clipboard!"); - else - btn.setLabel("Type It!"); - }); + if(down) btn.setLabel("Type from clipboard!"); + else btn.setLabel("Type It!"); + }, + (down) -> { if(txt.hasFocus()) { + txt.selectAll(); + } } + ); } + } diff --git a/src/main/java/org/iuscsg/autotyper/HistoryManager.java b/src/main/java/org/iuscsg/autotyper/HistoryManager.java index 1996c07..1cbe097 100644 --- a/src/main/java/org/iuscsg/autotyper/HistoryManager.java +++ b/src/main/java/org/iuscsg/autotyper/HistoryManager.java @@ -9,9 +9,9 @@ class HistoryManager private ArrayList history = new ArrayList<>(Collections.singletonList("")); private boolean ignoreTextChange = false; private int historyIndex = 0; - private TextField txt; + private TextArea txt; - void init(TextField txt) { + void init(TextArea txt) { this.txt = txt; txt.addTextListener(e -> { @@ -38,7 +38,6 @@ public void goBack() { } historyIndex++; ignoreTextChange = true; - System.out.println("Set Text"); txt.setText(history.get(historyIndex)); } } @@ -48,7 +47,6 @@ public void goForward() if (historyIndex > 0) { historyIndex--; ignoreTextChange = true; - System.out.println("Set Text"); txt.setText(history.get(historyIndex)); } } diff --git a/src/main/java/org/iuscsg/autotyper/Typer.java b/src/main/java/org/iuscsg/autotyper/Typer.java index 5dbf88a..db4f2de 100644 --- a/src/main/java/org/iuscsg/autotyper/Typer.java +++ b/src/main/java/org/iuscsg/autotyper/Typer.java @@ -61,8 +61,7 @@ else if(isAlphaNumeric(key)) private void typeKeyWithShift(String key, int keycode) { try { robot.keyPress(KeyEvent.VK_SHIFT); - robot.keyPress(keycode); - robot.keyRelease(keycode); + typeKeyWithKeyCode(key, keycode); robot.keyRelease(KeyEvent.VK_SHIFT); } catch (IllegalArgumentException e) { System.out.println("Invalid key: " + key + " with Shift key and keycode: " + keycode); @@ -73,6 +72,7 @@ private void typeKeyWithKeyCode(String key, int keycode) { try { robot.keyPress(keycode); robot.keyRelease(keycode); + robot.delay(8); } catch (IllegalArgumentException e) { System.out.println("Invalid key: " + key + " with keycode: " + keycode); } diff --git a/src/main/java/org/iuscsg/autotyper/hotkey/HotKeyListener.java b/src/main/java/org/iuscsg/autotyper/hotkey/HotKeyListener.java index f2b31b5..401ab84 100644 --- a/src/main/java/org/iuscsg/autotyper/hotkey/HotKeyListener.java +++ b/src/main/java/org/iuscsg/autotyper/hotkey/HotKeyListener.java @@ -5,21 +5,26 @@ public class HotKeyListener implements KeyListener { - private boolean backKeyDown = false; - private boolean forwardKeyDown = false; - private boolean modifierKeyDown = false; - private OnKeyChange onForwardListener; - private OnKeyChange onBackListener; - private OnKeyChange onModifierListener; - public HotKeyListener(OnKeyChange onForwardListener, OnKeyChange onBackListener, OnKeyChange onModifierListener) { - this.onForwardListener = onForwardListener; - this.onBackListener = onBackListener; - this.onModifierListener = onModifierListener; + private KeyState selectAllKeyState; + private KeyState onModifierKeyState; + private KeyState onBackKeyState; + private KeyState onForwardKeyState; + + public HotKeyListener(OnKeyChange onForwardListener, + OnKeyChange onBackListener, + OnKeyChange onModifierListener, + OnKeyChange onSelectAllListener) { + this.selectAllKeyState = new KeyState(down -> { + if(this.onModifierKeyState.isKeyDown() && down) onSelectAllListener.onChange(true); + }, KeyEvent.VK_A); + this.onModifierKeyState = new KeyState(onModifierListener, KeyEvent.VK_CONTROL); + this.onBackKeyState = new KeyState(onBackListener, KeyEvent.VK_UP); + this.onForwardKeyState = new KeyState(onForwardListener, KeyEvent.VK_DOWN); } - public boolean IsModifierKeDown() { - return this.modifierKeyDown; + public KeyState getModifierKeyState() { + return this.onModifierKeyState; } @Override @@ -28,44 +33,26 @@ public void keyTyped(KeyEvent e) { /* NOT NEEDED */} @Override public void keyPressed(KeyEvent e) { - switch(e.getKeyCode()) { - case KeyEvent.VK_UP: backKeyDown = true; break; - case KeyEvent.VK_DOWN: forwardKeyDown = true; break; - case KeyEvent.VK_CONTROL: modifierKeyDown = true; break; - } - executeListenersOnDown(); + selectAllKeyState.handleKeyPressed(e); + onModifierKeyState.handleKeyPressed(e); + onBackKeyState.handleKeyPressed(e); + onForwardKeyState.handleKeyPressed(e); } @Override public void keyReleased(KeyEvent e) { - switch(e.getKeyCode()) { - case KeyEvent.VK_UP: backKeyDown = false; break; - case KeyEvent.VK_DOWN: forwardKeyDown = false; break; - case KeyEvent.VK_CONTROL: modifierKeyDown = false; break; - } - executeListenersOnUp(); + selectAllKeyState.handleKeyReleased(e); + onModifierKeyState.handleKeyReleased(e); + onBackKeyState.handleKeyReleased(e); + onForwardKeyState.handleKeyReleased(e); } - - private void executeListenersOnDown() { - if (backKeyDown) { - onBackListener.onChange(true); - } else if(forwardKeyDown) { - onForwardListener.onChange(true); - } - else if(modifierKeyDown){ - onModifierListener.onChange(true); - } + public void onFrameDeactivated() { + selectAllKeyState.handleFrameDeactivation(); + onModifierKeyState.handleFrameDeactivation(); + onBackKeyState.handleFrameDeactivation(); + onForwardKeyState.handleFrameDeactivation(); } - - private void executeListenersOnUp() { - if (!backKeyDown) - onBackListener.onChange(false); - if(!forwardKeyDown) - onForwardListener.onChange(false); - if(!modifierKeyDown) - onModifierListener.onChange(false); - } } diff --git a/src/main/java/org/iuscsg/autotyper/hotkey/KeyState.java b/src/main/java/org/iuscsg/autotyper/hotkey/KeyState.java new file mode 100644 index 0000000..2b8bf36 --- /dev/null +++ b/src/main/java/org/iuscsg/autotyper/hotkey/KeyState.java @@ -0,0 +1,34 @@ +package org.iuscsg.autotyper.hotkey; + +import java.awt.event.KeyEvent; + +public class KeyState +{ + private boolean keyDown = false; + private OnKeyChange onKeyChangeListener; + private int keycode; + + public KeyState(OnKeyChange onKeyChangeListener, int keycode) { + this.onKeyChangeListener = onKeyChangeListener; + this.keycode = keycode; + } + + public void handleKeyPressed(KeyEvent e) { + if(e.getKeyCode() == keycode && !keyDown) { + keyDown = true; + onKeyChangeListener.onChange(true); + } + } + public void handleKeyReleased(KeyEvent e) { + if(e.getKeyCode() == keycode && keyDown) { + keyDown = false; + onKeyChangeListener.onChange(false); + } + } + public boolean isKeyDown() { + return this.keyDown; + } + public void handleFrameDeactivation() { + keyDown = false; + } +} From 6afea7ed3d234652f2b83f436234634fd0dde3e5 Mon Sep 17 00:00:00 2001 From: Jason Gallavin Date: Mon, 28 Jan 2019 00:02:47 -0500 Subject: [PATCH 3/3] Add Enter key to the list of possible characters for the typer. --- src/main/java/org/iuscsg/autotyper/Typer.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/iuscsg/autotyper/Typer.java b/src/main/java/org/iuscsg/autotyper/Typer.java index db4f2de..5a955fb 100644 --- a/src/main/java/org/iuscsg/autotyper/Typer.java +++ b/src/main/java/org/iuscsg/autotyper/Typer.java @@ -3,6 +3,7 @@ import java.awt.AWTException; import java.awt.Robot; import java.awt.event.KeyEvent; +import java.security.Key; import java.util.HashMap; import java.util.Map; @@ -51,6 +52,13 @@ else if(isAlpha(key) && key.toUpperCase().equals(key)) typeKeyWithShift(key, getKeyCode(key)); else if(isAlphaNumeric(key)) typeKeyWithKeyCode(key, getKeyCode(key)); + else if(key.equals("\n")) + typeKeyWithKeyCode(key, KeyEvent.VK_ENTER); + else if(key.equals("\r")) { + // ignore this character + } + else + System.out.println("Unknown Key: " + key); } catch (IllegalAccessException e) { e.printStackTrace(); } catch(NoSuchFieldException e ) {