From 00aae813ded58a7c52de6deaed609bc2a41e3f77 Mon Sep 17 00:00:00 2001 From: eviltester <3K1aDZQQgLtvBXuI> Date: Sun, 15 Oct 2017 13:10:27 +0100 Subject: [PATCH] amended Robot on counterstring to be cancellable and tidy up the threading, removed an unused dependency and added an "are you sure" quit dialog that also quits the counterstring thread --- README.md | 9 + pom.xml | 5 +- .../cannedtext/CannedTextItemTreeFinder.java | 4 +- .../html/comments/HTMLCommentReporter.java | 4 +- .../javafortesters/javafx/Config.java | 4 +- .../javafx/CounterStringStage.java | 232 ++++++++++-------- .../javafortesters/javafx/County.java | 41 ++++ .../javafortesters/javafx/MainGui.java | 37 ++- .../javafx/StringGeneratorStage.java | 10 +- .../javafx/UrlLauncherGridStage.java | 3 - .../launcher/LauncherUrlLoader.java | 3 - .../launcher/LauncherUrlSet.java | 3 - .../CounterstringCreationTest.java | 3 - .../launcher/UrlLauncherTest.java | 4 +- 14 files changed, 227 insertions(+), 135 deletions(-) create mode 100644 src/main/java/uk/co/compendiumdev/javafortesters/javafx/County.java diff --git a/README.md b/README.md index 1e1f5ad..32bf6a2 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,15 @@ Compendium_Developments = https://www.compendiumdev.co.uk ## Release Notes +### 20171015 15th October 2017 + +- Amended Robot counterstring generator to not have a hanging thread that keeps going + - used service for JavaFx +- click on 'Robot' button during counterstring generation while typing cancels the generation and typing +- added handlers to prompt for application exit +- added handlers to stop counterstring service when window hidden or application closes +- Added - Y/N Exit App dialog + ### 20161112 - started using this in videos for youtube, so other people saw it diff --git a/pom.xml b/pom.xml index c3b342b..d46d7cb 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,8 @@ uk.co.compendiumdev testtoolhub - 1.1-SNAPSHOT + + 1.1 @@ -15,11 +16,13 @@ junit 4.11 + org.apache.httpcomponents diff --git a/src/main/java/uk/co/compendiumdev/javafortesters/cannedtext/CannedTextItemTreeFinder.java b/src/main/java/uk/co/compendiumdev/javafortesters/cannedtext/CannedTextItemTreeFinder.java index fdd0302..c21512b 100644 --- a/src/main/java/uk/co/compendiumdev/javafortesters/cannedtext/CannedTextItemTreeFinder.java +++ b/src/main/java/uk/co/compendiumdev/javafortesters/cannedtext/CannedTextItemTreeFinder.java @@ -2,9 +2,7 @@ import uk.co.compendiumdev.javafortesters.tree.TreeBranch; -/** - * Created by Alan on 27/02/2015. - */ + public class CannedTextItemTreeFinder { private final TreeBranch root; diff --git a/src/main/java/uk/co/compendiumdev/javafortesters/html/comments/HTMLCommentReporter.java b/src/main/java/uk/co/compendiumdev/javafortesters/html/comments/HTMLCommentReporter.java index c19d112..e42e3f9 100644 --- a/src/main/java/uk/co/compendiumdev/javafortesters/html/comments/HTMLCommentReporter.java +++ b/src/main/java/uk/co/compendiumdev/javafortesters/html/comments/HTMLCommentReporter.java @@ -5,9 +5,7 @@ import java.io.IOException; -/** - * Created by Alan on 24/03/2015. - */ + public class HTMLCommentReporter { HTMLCommentFinder comments; diff --git a/src/main/java/uk/co/compendiumdev/javafortesters/javafx/Config.java b/src/main/java/uk/co/compendiumdev/javafortesters/javafx/Config.java index a0a43d6..bdfe257 100644 --- a/src/main/java/uk/co/compendiumdev/javafortesters/javafx/Config.java +++ b/src/main/java/uk/co/compendiumdev/javafortesters/javafx/Config.java @@ -1,8 +1,6 @@ package uk.co.compendiumdev.javafortesters.javafx; -/** - * Created by Alan on 21/01/2015. - */ + public class Config { public static int getDefaultWindowWidth(){ diff --git a/src/main/java/uk/co/compendiumdev/javafortesters/javafx/CounterStringStage.java b/src/main/java/uk/co/compendiumdev/javafortesters/javafx/CounterStringStage.java index 1182f0a..d8ef883 100644 --- a/src/main/java/uk/co/compendiumdev/javafortesters/javafx/CounterStringStage.java +++ b/src/main/java/uk/co/compendiumdev/javafortesters/javafx/CounterStringStage.java @@ -1,36 +1,32 @@ package uk.co.compendiumdev.javafortesters.javafx; -import uk.co.compendiumdev.javafortesters.counterstrings.CounterString; -import uk.co.compendiumdev.javafortesters.counterstrings.CounterStringCreationError; -import uk.co.compendiumdev.javafortesters.counterstrings.CounterStringRangeListIterator; -import uk.co.compendiumdev.javafortesters.counterstrings.CounterStringRangeStruct; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; +import javafx.concurrent.Service; import javafx.concurrent.Task; import javafx.event.ActionEvent; +import javafx.event.Event; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.*; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.control.TextArea; -import javafx.scene.control.TextField; import javafx.scene.input.Clipboard; import javafx.scene.input.ClipboardContent; import javafx.scene.layout.*; import javafx.stage.Stage; +import javafx.stage.WindowEvent; +import uk.co.compendiumdev.javafortesters.counterstrings.CounterString; +import uk.co.compendiumdev.javafortesters.counterstrings.CounterStringCreationError; -import java.awt.*; import java.awt.event.KeyEvent; import java.io.PrintWriter; import java.io.StringWriter; -import java.util.List; public class CounterStringStage extends Stage { private static CounterStringStage counterStringSingletonStage=null; + private static Service task; public static void singletonActivate(){ @@ -41,38 +37,7 @@ public static void singletonActivate(){ counterStringSingletonStage.requestFocus(); } - private class County{ - - private List range; - private CounterStringRangeListIterator ranger; - private CounterString counterstring; - private String spacer; - private Robot robot; - - public void createCounterStringRangesFor(int counterStringLength, String spacer) { - this.counterstring = new CounterString(); - this.spacer = counterstring.getSingleCharSpacer(spacer); - this.range = counterstring.createCounterStringRangesFor(counterStringLength, spacer); - this.ranger = new CounterStringRangeListIterator(range); - try { - this.robot = new Robot(); - } catch (AWTException e) { - e.printStackTrace(); - } - } - - public boolean hasAnotherValueInRangeList() { - return this.ranger.hasAnotherValueInRangeList(); - } - - public String getNextCounterStringEntry() { - return counterstring.getCounterStringRepresentationOfNumber(ranger.getNextCounterStringValue(), this.spacer); - } - public Robot getRobot(){ - return this.robot; - } - } public CounterStringStage(boolean hidden) { @@ -141,103 +106,154 @@ public CounterStringStage(boolean hidden) { if(!hidden) this.show(); + + + // when close stage, stop the counterstring generation + this.addEventHandler(WindowEvent.WINDOW_CLOSE_REQUEST, new EventHandler() { + @Override + public void handle(Event event) { + if(task!=null) { + if (task.isRunning()) { + task.cancel(); + robotType.setText("Robot"); + robotType.setTooltip(new Tooltip("Have robot type counterstring into field")); + } + } + } + }); + + // when focus changes stop the counterstring generation +// this.focusedProperty().addListener(new ChangeListener() { +// @Override +// public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { +// if(task!=null) { +// if (task.isRunning()) { +// task.cancel(); +// robotType.setText("Robot"); +// robotType.setTooltip(new Tooltip("Have robot type counterstring into field")); +// } +// } +// } +// }); + + County county = new County(); //robot typing into field- never stop thread - once robot is used a thread ticks over in the background // ready to be re-used - Task task = new Task() { + task = new Service() { @Override - public Void call() throws Exception { - int x=5; - while(true) { - if(robotType.getText().startsWith("Robot")){ - x=5; - } - final int finalX = x--; + protected Task createTask() { + return new Task(){ + @Override + public Void call() throws Exception { + int x=5; - Platform.runLater(new Runnable() { - @Override - public void run() { + while(!isCancelled()) { + if(robotType.getText().startsWith("Robot")){ + x=5; + } + final int finalX = x--; + Platform.runLater(new Runnable() { + @Override + public void run() { - // This needs to be a state machine - // Robot means stop don't do anything - // Start means start counting down - // In [ means continue counting - // GO means calculate the counterstring - // ... means iterate through and send the keys - if (robotType.getText().startsWith("Start") || robotType.getText().startsWith("In [")) { - robotType.setText("In [" + finalX + "] secs"); - } - if (finalX <= 0) { - robotType.setText("GO"); - // calculate counterstring and iterator here - robotType.setText("..."); - } - if(robotType.getText().startsWith("...")){ - if(county.hasAnotherValueInRangeList()){ - String outputString = county.getNextCounterStringEntry(); - robotType.setText("..."+outputString); - //System.out.println(outputString); - for(char c : outputString.toCharArray()) { - //System.out.println(""+c); - // this hack means that with robot we should really default to * - if(c=='*'){ - county.getRobot().keyPress(KeyEvent.VK_SHIFT); - county.getRobot().keyPress(KeyEvent.VK_8); - county.getRobot().keyRelease(KeyEvent.VK_8); - county.getRobot().keyRelease(KeyEvent.VK_SHIFT); - }else { - county.getRobot().keyPress(KeyEvent.getExtendedKeyCodeForChar(c)); - county.getRobot().keyRelease(KeyEvent.getExtendedKeyCodeForChar(c)); + // This needs to be a state machine + // Robot means stop don't do anything + // Start means start counting down + // In [ means continue counting + // GO means calculate the counterstring + // ... means iterate through and send the keys + if (robotType.getText().startsWith("Start") || robotType.getText().startsWith("In [")) { + robotType.setText("In [" + finalX + "] secs"); + } + if (finalX <= 0) { + robotType.setText("GO"); + // calculate counterstring and iterator here + + robotType.setText("..."); + } + if(robotType.getText().startsWith("...")){ + if(county.hasAnotherValueInRangeList()){ + String outputString = county.getNextCounterStringEntry(); + robotType.setText("..."+outputString); + //System.out.println(outputString); + for(char c : outputString.toCharArray()) { + //System.out.println(""+c); + // this hack means that with robot we should really default to * + if(c=='*'){ + county.getRobot().keyPress(KeyEvent.VK_SHIFT); + county.getRobot().keyPress(KeyEvent.VK_8); + county.getRobot().keyRelease(KeyEvent.VK_8); + county.getRobot().keyRelease(KeyEvent.VK_SHIFT); + }else { + county.getRobot().keyPress(KeyEvent.getExtendedKeyCodeForChar(c)); + county.getRobot().keyRelease(KeyEvent.getExtendedKeyCodeForChar(c)); + } + if(isCancelled()){ + break; + } + } + }else{ + // we are finished + robotType.setText("Robot"); + robotType.setTooltip(new Tooltip("Have robot type counterstring into field")); + cancel(); + return; } } - }else{ - // we are finished - robotType.setText("Robot"); } + }); + + if(robotType.getText().startsWith("Robot")||robotType.getText().startsWith("In [")) { + Thread.sleep(1000); + }else{ + Thread.sleep(10); + x=5; } + System.out.println("Thread " + x); } - }); - - if(robotType.getText().startsWith("Robot")||robotType.getText().startsWith("In [")) { - Thread.sleep(1000); - }else{ - Thread.sleep(10); - x=5; + return null; } - System.out.println("Thread " + x); - } + }; } }; - Thread th = new Thread(task); - th.setDaemon(true); - - - robotType.setOnAction( new EventHandler() { + @Override public void handle(ActionEvent e) { + System.out.println("clicked robot"); try { - if(!th.isAlive()) { - th.start(); + if(task.isRunning()){ + robotType.setText("Cancelling"); + task.cancel(); + robotType.setText("Robot"); + robotType.setTooltip(new Tooltip("Have robot type counterstring into field")); + return; } + if(robotType.getText().startsWith("Robot")){ - county.createCounterStringRangesFor(Integer.parseInt(counterLength.getText()), counterstringSpacer.getText()); - robotType.setText("Start"); + if(!task.isRunning()){ + task.reset(); + county.createCounterStringRangesFor(Integer.parseInt(counterLength.getText()), counterstringSpacer.getText()); + robotType.setText("Start"); + robotType.setTooltip(new Tooltip("Click Button again to cancel Robot Typing")); + task.start(); + } }else{ robotType.setText("Robot"); @@ -335,6 +351,7 @@ public void handle(ActionEvent e) { }); + } @@ -406,4 +423,13 @@ private void sendToClipboard(String contents, Button copyCounter) { } + public static void stopServices() { + if(task!=null){ + if(task.isRunning()){ + task.cancel(); + task=null; + } + } + + } } diff --git a/src/main/java/uk/co/compendiumdev/javafortesters/javafx/County.java b/src/main/java/uk/co/compendiumdev/javafortesters/javafx/County.java new file mode 100644 index 0000000..3c3de4a --- /dev/null +++ b/src/main/java/uk/co/compendiumdev/javafortesters/javafx/County.java @@ -0,0 +1,41 @@ +package uk.co.compendiumdev.javafortesters.javafx; + +import uk.co.compendiumdev.javafortesters.counterstrings.CounterString; +import uk.co.compendiumdev.javafortesters.counterstrings.CounterStringRangeListIterator; +import uk.co.compendiumdev.javafortesters.counterstrings.CounterStringRangeStruct; + +import java.awt.*; +import java.util.List; + +public class County { + + private List range; + private CounterStringRangeListIterator ranger; + private CounterString counterstring; + private String spacer; + private Robot robot; + + public void createCounterStringRangesFor(int counterStringLength, String spacer) { + this.counterstring = new CounterString(); + this.spacer = counterstring.getSingleCharSpacer(spacer); + this.range = counterstring.createCounterStringRangesFor(counterStringLength, spacer); + this.ranger = new CounterStringRangeListIterator(range); + try { + this.robot = new Robot(); + } catch (AWTException e) { + e.printStackTrace(); + } + } + + public boolean hasAnotherValueInRangeList() { + return this.ranger.hasAnotherValueInRangeList(); + } + + public String getNextCounterStringEntry() { + return counterstring.getCounterStringRepresentationOfNumber(ranger.getNextCounterStringValue(), this.spacer); + } + + public Robot getRobot(){ + return this.robot; + } +} diff --git a/src/main/java/uk/co/compendiumdev/javafortesters/javafx/MainGui.java b/src/main/java/uk/co/compendiumdev/javafortesters/javafx/MainGui.java index 0709231..9df15f0 100644 --- a/src/main/java/uk/co/compendiumdev/javafortesters/javafx/MainGui.java +++ b/src/main/java/uk/co/compendiumdev/javafortesters/javafx/MainGui.java @@ -1,20 +1,24 @@ package uk.co.compendiumdev.javafortesters.javafx; import javafx.application.Application; +import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; +import javafx.scene.control.Alert; import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; import javafx.scene.control.Tooltip; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.stage.Stage; +import javafx.stage.WindowEvent; public class MainGui extends Application{ - //TODO: Prompt "Are you sure?" when closing main form, then exit app if YES + //DONE: Prompt "Are you sure?" when closing main form, then exit app if YES //TODO: Repeat strings //DONE: counterstring generator //TODO: string generator to file @@ -79,6 +83,10 @@ public void start(Stage stage) { BorderPane root = new BorderPane(); Scene scene = new Scene(root, 400, 100); + + stage.setOnCloseRequest(exitApplicationHandler()); + + VBox buttonList = new VBox(10); HBox buttonsRow1 = new HBox(); @@ -177,6 +185,33 @@ public void handle(ActionEvent e) { }); } + private EventHandler exitApplicationHandler() { + return new EventHandler() { + @Override + public void handle(WindowEvent event) { + + Alert alert = new Alert(Alert.AlertType.CONFIRMATION); + alert.setTitle("Confirm Application Exit"); + alert.setHeaderText("Are you sure you want to quit the application?"); + alert.setContentText("Press OK to exit the application. Press Cancel to exit this dialog and keep the application running."); + alert.showAndWait().ifPresent(rs -> { + if (rs == ButtonType.OK) { + + + CounterStringStage.stopServices(); + Platform.exit(); + System.exit(0); + }else{ + event.consume(); + } + }); + + + } + }; + + } + public static void main(String[] args) { launch(args); } diff --git a/src/main/java/uk/co/compendiumdev/javafortesters/javafx/StringGeneratorStage.java b/src/main/java/uk/co/compendiumdev/javafortesters/javafx/StringGeneratorStage.java index a1810d4..3e90bce 100644 --- a/src/main/java/uk/co/compendiumdev/javafortesters/javafx/StringGeneratorStage.java +++ b/src/main/java/uk/co/compendiumdev/javafortesters/javafx/StringGeneratorStage.java @@ -23,9 +23,6 @@ public class StringGeneratorStage extends Stage { - - // TODO Warning STring generator can cause display errors, often best to go direct to clipboard - private static StringGeneratorStage stringGeneratorSingletonStage=null; public static void singletonActivate() { @@ -59,7 +56,7 @@ public StringGeneratorStage(boolean hidden){ HBox asciiControlCharToCharInputs = new HBox(); final Label firstCharLbl = new Label("First Value:"); final TextField firstCharTxt = new TextField (); - firstCharTxt.setText("0"); + firstCharTxt.setText("1"); final Label secondCharLbl = new Label("Second Value:"); final TextField secondCharTxt = new TextField (); secondCharTxt.setText("255"); @@ -92,7 +89,7 @@ public StringGeneratorStage(boolean hidden){ asciiControlCharToCharInputs.setSpacing(10); asciiControlCharToCharButtons.setSpacing(10); - final Label warning = new Label("Warning: unicode values can cause rendering issues in this control"); + final Label warning = new Label("Warning: unicode values can cause rendering issues in this control, and '0' will not render to clipboard"); final Button clearTextArea = new Button(); clearTextArea.setText("Clear"); @@ -131,7 +128,7 @@ public void handle(ActionEvent e) { } } }); - + copyToClipboard.setOnAction( new EventHandler() { @Override @@ -279,6 +276,7 @@ private void alertFirstOrSecondCharNotNumeric() { private void sendToClipboard(String contents, Button copyCounter) { copyCounter.setText("Copying"); Clipboard clipboard = Clipboard.getSystemClipboard(); + clipboard.clear(); ClipboardContent content = new ClipboardContent(); content.putString(contents); clipboard.setContent(content); diff --git a/src/main/java/uk/co/compendiumdev/javafortesters/javafx/UrlLauncherGridStage.java b/src/main/java/uk/co/compendiumdev/javafortesters/javafx/UrlLauncherGridStage.java index 032ca78..9822ec4 100644 --- a/src/main/java/uk/co/compendiumdev/javafortesters/javafx/UrlLauncherGridStage.java +++ b/src/main/java/uk/co/compendiumdev/javafortesters/javafx/UrlLauncherGridStage.java @@ -21,9 +21,6 @@ import javafx.util.Callback; -/** - * Created by alan on 12/03/15. - */ public class UrlLauncherGridStage extends Stage { private static UrlLauncherGridStage urlLauncherGridSingletonStage=null; diff --git a/src/main/java/uk/co/compendiumdev/javafortesters/launcher/LauncherUrlLoader.java b/src/main/java/uk/co/compendiumdev/javafortesters/launcher/LauncherUrlLoader.java index 8afbd6b..8a78d0f 100644 --- a/src/main/java/uk/co/compendiumdev/javafortesters/launcher/LauncherUrlLoader.java +++ b/src/main/java/uk/co/compendiumdev/javafortesters/launcher/LauncherUrlLoader.java @@ -6,9 +6,6 @@ import java.util.Map; import java.util.Properties; -/** - * Created by alan on 10/03/15. - */ public class LauncherUrlLoader { public UrlLauncher load() { diff --git a/src/main/java/uk/co/compendiumdev/javafortesters/launcher/LauncherUrlSet.java b/src/main/java/uk/co/compendiumdev/javafortesters/launcher/LauncherUrlSet.java index 7ae933d..aad7c45 100644 --- a/src/main/java/uk/co/compendiumdev/javafortesters/launcher/LauncherUrlSet.java +++ b/src/main/java/uk/co/compendiumdev/javafortesters/launcher/LauncherUrlSet.java @@ -4,9 +4,6 @@ import java.util.HashMap; import java.util.Map; -/** - * Created by alan on 10/03/15. - */ public class LauncherUrlSet { private static final int DEFAULT_MILLIS = 1000; private static final int DEFAULT_RETRIES = 3; diff --git a/src/test/java/uk/co/compendiumdev/javafortesters/counterstrings/CounterstringCreationTest.java b/src/test/java/uk/co/compendiumdev/javafortesters/counterstrings/CounterstringCreationTest.java index fcf8f69..6ffb427 100644 --- a/src/test/java/uk/co/compendiumdev/javafortesters/counterstrings/CounterstringCreationTest.java +++ b/src/test/java/uk/co/compendiumdev/javafortesters/counterstrings/CounterstringCreationTest.java @@ -4,9 +4,6 @@ import org.junit.Ignore; import org.junit.Test; -/** - * Created by alan on 08/12/2014. - */ public class CounterstringCreationTest { @Test diff --git a/src/test/java/uk/co/compendiumdev/javafortesters/launcher/UrlLauncherTest.java b/src/test/java/uk/co/compendiumdev/javafortesters/launcher/UrlLauncherTest.java index 240e5dc..231635e 100644 --- a/src/test/java/uk/co/compendiumdev/javafortesters/launcher/UrlLauncherTest.java +++ b/src/test/java/uk/co/compendiumdev/javafortesters/launcher/UrlLauncherTest.java @@ -8,9 +8,7 @@ import java.util.*; import java.util.List; -/** - * Created by alan on 09/03/15. - */ + public class UrlLauncherTest { // Todo, need assertions and mocks etc. in these tests as url launching not tested by this