I've created a simple text editor that autosaves txt files every minute and also spell checks the TextArea with the languagetool java api. I'd like to have the autosaving done when the user stops typing and also have the spellchecking done when the user stops typing as well. I think I can do it some way with the OnKeyPressed and OnKeyRealesed methods associated with the textarea and use System.currentTimeMillis method but I have not been able to figure that out. I also thought it’d be best to do these processes in another thread but I was unsure how to implement that.
The auto saving and spell checking is done with the AutoSave and AutoSaveMac Class that use TimerTask to create a task that then runs every min. These Classes are used in the runAutoSave() function that runs on app initialization.
So I guess my question is how can I run the saving and spell checking in another thread when the user stops typing?
Please let me know if I can answer any other questions whatsoever.
EDIT: I've since started testing with the lines of code for the languagetool api removed/commented out. (In FXMLController.java and pom.xml) Way quicker for testing as the languagetool api takes a bit to load on run. I figure if i can get saving working when user stops typing then i'll easily be able to add the languagetool api code.
FXMLController.java
package com.mycompany.maveneditormre;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javax.swing.JFileChooser;
//import org.languagetool.JLanguageTool;
//import org.languagetool.language.BritishEnglish;
//import org.languagetool.rules.RuleMatch;
public class FXMLController implements Initializable {
String opSystem = new String();
String documentsPath = new JFileChooser().getFileSystemView().getDefaultDirectory().toString();
@FXML public TextArea textArea;
@FXML public TextArea spellcheckTextArea;
@FXML public TextField textFieldFileFolderName;
private final TextArea textArea2 = new TextArea();
public static volatile int keyPressTime = 00;
public static volatile int keyReleaseTime = 00;
// JLanguageTool langTool = new JLanguageTool(new BritishEnglish());
public class FirstThread implements Runnable {
public FirstThread(){
}
public void run(){
System.out.println("MyThread running");
}
}
@FXML
private void handleKeyPressed() throws IOException {
keyPressTime = (int) System.currentTimeMillis();
}
@FXML
private void handleKeyReleased() throws IOException{
keyReleaseTime = (int) System.currentTimeMillis();
}
private void Save(String content, File file){
try {
FileWriter fileWriter;
fileWriter = new FileWriter(file);
fileWriter.write(content);
fileWriter.close();
} catch (IOException ex) {
Logger.getLogger(FXMLController.class
.getName()).log(Level.SEVERE, null, ex);
}
}
private void runAutoSave(){
if (this.opSystem.contains("mac")){
Timer timer = new Timer();
TimerTask task = new AutoSaveMac();
timer.schedule(task, 2000, 60000);
} else {
Timer timer = new Timer();
TimerTask task = new AutoSave();
timer.schedule(task, 2000, 60000);
}
}
class AutoSave extends TimerTask {
@Override
public void run() {
if(textArea2.getText().equals(textArea.getText())){
// do nothing
} else {
// autosave new folder and file if needed
// String[] firstLineOfTextArea = textArea.getText().split("\\n");
String[] firstLineOfTextArea = textFieldFileFolderName.getText().split("\\n");
String[] folderAndFileName = firstLineOfTextArea[0].split("-", 2);
Path path = Paths.get(documentsPath + "\\ssef\\" + folderAndFileName[0]);
if (Files.exists(path)) {
// Do nothing
} else {
new File(documentsPath + "\\ssef\\" + folderAndFileName[0]).mkdir();
}
File file = new File(String.format(documentsPath + "\\ssef\\" + folderAndFileName[0]+ "\\%s.txt", folderAndFileName[1] ));
Save(textArea.getText().replaceAll("\n", System.getProperty("line.separator")), file);
textArea2.setText(textArea.getText());
// spell check
// List<RuleMatch> matches = null;
// try {
// matches = langTool.check(textArea.getText());
// System.out.println(matches);
// } catch (IOException ex) {
// Logger.getLogger(FXMLController.class.getName()).log(Level.SEVERE, null, ex);
// }
//
// if (matches.isEmpty() == true) {
// spellcheckTextArea.clear();
// }
//
// for (RuleMatch match : matches) {
// spellcheckTextArea.setText(spellcheckTextArea.getText() + "\n" + "Potential error at characters " + match.getFromPos() + "-" + match.getToPos() + ": " + match.getMessage() + "\n" + "Suggested correction(s): " + match.getSuggestedReplacements());
//
// System.out.println("Potential error at characters " + match.getFromPos() + "-" + match.getToPos() + ": " + match.getMessage());
// System.out.println("Suggested correction(s): " + match.getSuggestedReplacements());
// }
}
}
}
class AutoSaveMac extends TimerTask {
@Override
public void run() {
if(textArea2.getText().equals(textArea.getText())){
// do nothing
} else {
// autosave new folder and file if needed
String[] firstLineOfTextArea = textFieldFileFolderName.getText().split(System.getProperty("line.separator"));
System.out.println(firstLineOfTextArea[0] + " first line of textarea");
String[] folderAndFileName = firstLineOfTextArea[0].split("-", 2);
Path path = Paths.get(documentsPath + "/Documents" + "/ssef/" + folderAndFileName[0]);
if (Files.exists(path)) {
// Do nothing
} else {
new File(documentsPath + "/Documents" + "/ssef/" + folderAndFileName[0]).mkdir();
}
File file = new File(documentsPath + "/Documents" + "/ssef/" + folderAndFileName[0] + "/" + folderAndFileName[1]+ ".txt" );
Save(textArea.getText().replaceAll("/n", System.getProperty("line.separator")), file);
textArea2.setText(textArea.getText());
// List<RuleMatch> matches = null;
// try {
// matches = langTool.check(textArea.getText());
// System.out.println(matches);
// } catch (IOException ex) {
// Logger.getLogger(FXMLController.class.getName()).log(Level.SEVERE, null, ex);
// }
//
// if (matches.isEmpty() == true) {
// spellcheckTextArea.clear();
// }
//
// for (RuleMatch match : matches) {
// spellcheckTextArea.setText(spellcheckTextArea.getText() + "\n" + "Potential error at characters " + match.getFromPos() + "-" + match.getToPos() + ": " + match.getMessage() + "\n" + "Suggested correction(s): " + match.getSuggestedReplacements());
//
// System.out.println("Potential error at characters " + match.getFromPos() + "-" + match.getToPos() + ": " + match.getMessage());
// System.out.println("Suggested correction(s): " + match.getSuggestedReplacements());
// }
}
}
}
private void createOpeningFolder(){
if (opSystem.contains("mac")) {
Path path = Paths.get(documentsPath + "/Documents" + "/ssef");
if (Files.exists(path)) {
// Do nothing
} else {
new File(documentsPath + "/Documents" + "/ssef").mkdir();
}
} else {
Path path = Paths.get(documentsPath + "\\ssef");
if (Files.exists(path)) {
// Do nothing
} else {
new File(documentsPath + "\\ssef").mkdir();
}
}
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
String osName = System.getProperty("os.name").toLowerCase();
this.opSystem = osName;
System.out.println("Operating System: " + this.opSystem);
textFieldFileFolderName.setFocusTraversable(true);
textArea.setWrapText(true);
Runnable firstThread = new FirstThread();
new Thread(firstThread).start();
createOpeningFolder();
runAutoSave();
}
}
scene.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane fx:id="borderPaneRoot" prefHeight="600.0" prefWidth="1000.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.mycompany.maveneditormre.FXMLController">
<center>
<GridPane>
<children>
<TextField fx:id="textFieldFileFolderName" prefWidth="200.0" promptText="foldername-filename" GridPane.columnIndex="0" GridPane.rowIndex="0" />
<TextArea fx:id="textArea" prefWidth="200.0" promptText="note taking" wrapText="true" GridPane.columnIndex="0" GridPane.rowIndex="1" onKeyPressed="#handleKeyPressed" onKeyReleased="#handleKeyReleased" />
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="202.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="376.0" minHeight="10.0" prefHeight="376.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
</center>
<bottom>
<TextArea fx:id="spellcheckTextArea" editable="false" promptText="spellchecking" wrapText="true" />
</bottom>
</BorderPane>
Be sure to add the following to pom.xml
<dependencies>
<dependency>
<groupId>org.languagetool</groupId>
<artifactId>language-en</artifactId>
<version>4.8</version>
</dependency>
</dependencies>