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 4210783..6b50d52 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 TextArea txt = themeControl(new TextArea("", 0, 0, TextArea.SCROLLBARS_NONE), 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"); @@ -29,6 +35,11 @@ private Application() { public void windowClosing(WindowEvent we) { System.exit(0); } + + @Override + public void windowDeactivated(WindowEvent e) { + keyListener.onFrameDeactivated(); + } }); } @@ -39,7 +50,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 +61,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 +75,17 @@ private void setIcon() { } } + private void onBtn_Click() { + if(keyListener.getModifierKeyState().isKeyDown()) { + 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); @@ -86,10 +103,34 @@ 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(); } } + + 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) -> { + 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 e778a69..1cbe097 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; @@ -11,11 +9,11 @@ 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, Button btn) { + void init(TextArea 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,26 @@ 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; + txt.setText(history.get(historyIndex)); + } + } + + public void goForward() + { + if (historyIndex > 0) { + historyIndex--; + ignoreTextChange = true; + 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..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 ) { @@ -61,8 +69,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 +80,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 4ed2591..401ab84 100644 --- a/src/main/java/org/iuscsg/autotyper/hotkey/HotKeyListener.java +++ b/src/main/java/org/iuscsg/autotyper/hotkey/HotKeyListener.java @@ -5,15 +5,26 @@ public class HotKeyListener implements KeyListener { - private boolean backDown = false; - private boolean forwardDown = false; - private OnHistoryChangeListener onForwardListener; - private OnHistoryChangeListener onBackListener; + 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 HotKeyListener(OnHistoryChangeListener onForwardListener, OnHistoryChangeListener onBackListener) { - this.onForwardListener = onForwardListener; - this.onBackListener = onBackListener; + public KeyState getModifierKeyState() { + return this.onModifierKeyState; } @Override @@ -22,28 +33,26 @@ public void keyTyped(KeyEvent e) { /* NOT NEEDED */} @Override public void keyPressed(KeyEvent e) { - switch(e.getKeyCode()) { - case KeyEvent.VK_UP: backDown = true; break; - case KeyEvent.VK_DOWN: forwardDown = true; break; - } - executeListenersIfHotKeysPressed(); + 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: backDown = false; break; - case KeyEvent.VK_DOWN: forwardDown = false; break; - } + selectAllKeyState.handleKeyReleased(e); + onModifierKeyState.handleKeyReleased(e); + onBackKeyState.handleKeyReleased(e); + onForwardKeyState.handleKeyReleased(e); } - - private void executeListenersIfHotKeysPressed() { - if (backDown) { - onBackListener.onChange(); - } else if(forwardDown) { - onForwardListener.onChange(); - } + public void onFrameDeactivated() { + selectAllKeyState.handleFrameDeactivation(); + onModifierKeyState.handleFrameDeactivation(); + onBackKeyState.handleFrameDeactivation(); + onForwardKeyState.handleFrameDeactivation(); } + } 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; + } +} 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); +}