Rudimentary saving and loading
Signed-off-by: AKP <tom@tdpain.net>
This commit is contained in:
parent
44735c0446
commit
e34b937866
7 changed files with 116 additions and 6 deletions
|
@ -20,6 +20,11 @@
|
||||||
<artifactId>javafx-fxml</artifactId>
|
<artifactId>javafx-fxml</artifactId>
|
||||||
<version>19</version>
|
<version>19</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.json</groupId>
|
||||||
|
<artifactId>json</artifactId>
|
||||||
|
<version>20220924</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
@ -41,7 +46,7 @@
|
||||||
<!-- Usage: mvn clean javafx:run -->
|
<!-- Usage: mvn clean javafx:run -->
|
||||||
<id>default-cli</id>
|
<id>default-cli</id>
|
||||||
<configuration>
|
<configuration>
|
||||||
<mainClass>net.akpain.todo.App</mainClass>
|
<mainClass>qakpain.todo.App</mainClass>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module net.akpain.todo {
|
module net.akpain.todo {
|
||||||
requires javafx.controls;
|
requires javafx.controls;
|
||||||
requires javafx.fxml;
|
requires javafx.fxml;
|
||||||
|
requires org.json;
|
||||||
|
|
||||||
opens net.akpain.todo to javafx.fxml;
|
opens net.akpain.todo to javafx.fxml;
|
||||||
exports net.akpain.todo;
|
exports net.akpain.todo;
|
||||||
|
|
|
@ -10,12 +10,16 @@ import javafx.scene.input.MouseEvent;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class Controller {
|
public class Controller {
|
||||||
|
|
||||||
public VBox todoDisplayBox;
|
public VBox todoDisplayBox;
|
||||||
public TextField todoTextField;
|
public TextField todoTextField;
|
||||||
|
private StorageController storage;
|
||||||
|
|
||||||
public Controller() {
|
public Controller() {
|
||||||
|
storage = new StorageController();
|
||||||
todoDisplayBox = new VBox();
|
todoDisplayBox = new VBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +40,18 @@ public class Controller {
|
||||||
|
|
||||||
todoDisplayBox.getChildren().add(p);
|
todoDisplayBox.getChildren().add(p);
|
||||||
todoTextField.clear();
|
todoTextField.clear();
|
||||||
|
|
||||||
|
storage.addTodo(new TodoObject(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void saveAll() {
|
||||||
|
try {
|
||||||
|
storage.save();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO: 06/02/2023 handle this with an error dialog or similar
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBoxChecked(MouseEvent event) {
|
private void checkBoxChecked(MouseEvent event) {
|
||||||
|
|
11
openjfx-todo/src/main/java/net/akpain/todo/LoadError.java
Normal file
11
openjfx-todo/src/main/java/net/akpain/todo/LoadError.java
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package net.akpain.todo;
|
||||||
|
|
||||||
|
public class LoadError extends Exception {
|
||||||
|
public LoadError(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoadError() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,10 @@
|
||||||
package net.akpain.todo;
|
package net.akpain.todo;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONTokener;
|
||||||
|
import org.json.JSONWriter;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
public class StorageController {
|
public class StorageController {
|
||||||
|
@ -10,16 +15,62 @@ public class StorageController {
|
||||||
todos = new LinkedList<>();
|
todos = new LinkedList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load() {
|
private File getDefaultDirectory() throws IOException {
|
||||||
|
File dir = new File(System.getProperty("user.home"));
|
||||||
|
dir = new File(dir, ".local/share/openjfx-todo");
|
||||||
|
dir.mkdirs();
|
||||||
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load(String filename) {
|
private File getDefaultFilename() throws IOException {
|
||||||
|
return new File(getDefaultDirectory(), "todos.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void save() {
|
public void load() throws LoadError, IOException {
|
||||||
|
load(getDefaultFilename().getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(String filename) throws LoadError, IOException {
|
||||||
|
FileInputStream file;
|
||||||
|
try {
|
||||||
|
file = new FileInputStream(filename);
|
||||||
|
} catch (FileNotFoundException __) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONTokener jtok = new JSONTokener(file);
|
||||||
|
JSONArray jarr = new JSONArray(jtok);
|
||||||
|
|
||||||
|
this.todos = new LinkedList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < jarr.length(); i += 1) {
|
||||||
|
this.todos.add(TodoObject.fromJSONObject(jarr.getJSONObject(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() throws IOException {
|
||||||
|
save(getDefaultFilename().getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(String filename) throws IOException {
|
||||||
|
FileWriter fwr = new FileWriter(filename);
|
||||||
|
JSONWriter jwr = new JSONWriter(fwr);
|
||||||
|
|
||||||
|
jwr.array();
|
||||||
|
for (TodoObject todo : this.todos) {
|
||||||
|
jwr.value(todo.toJSONObject());
|
||||||
|
}
|
||||||
|
jwr.endArray();
|
||||||
|
|
||||||
|
fwr.close();
|
||||||
|
|
||||||
|
System.err.printf("Saved to %s\n", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTodo(TodoObject todo) {
|
||||||
|
this.todos.add(todo);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package net.akpain.todo;
|
package net.akpain.todo;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class TodoObject {
|
public class TodoObject {
|
||||||
private String text;
|
private String text;
|
||||||
private boolean completed;
|
private boolean completed;
|
||||||
|
@ -8,4 +10,27 @@ public class TodoObject {
|
||||||
this.completed = false;
|
this.completed = false;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TodoObject(String text, boolean checked) {
|
||||||
|
this.completed = checked;
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TodoObject fromJSONObject(JSONObject jobj) throws LoadError {
|
||||||
|
boolean cmp = jobj.getBoolean("completed");
|
||||||
|
String txt = jobj.getString("text");
|
||||||
|
|
||||||
|
if ("".equals(txt)) {
|
||||||
|
throw new LoadError("missing description");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TodoObject(txt, cmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject toJSONObject() {
|
||||||
|
JSONObject jobj = new JSONObject();
|
||||||
|
jobj.put("completed", this.completed);
|
||||||
|
jobj.put("text", this.text);
|
||||||
|
return jobj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
<TextField fx:id="todoTextField" GridPane.columnIndex="1" GridPane.rowIndex="1" GridPane.columnSpan="7" onKeyPressed="#onTextFieldKeyPress" />
|
<TextField fx:id="todoTextField" GridPane.columnIndex="1" GridPane.rowIndex="1" GridPane.columnSpan="7" onKeyPressed="#onTextFieldKeyPress" />
|
||||||
<Button GridPane.columnIndex="8" GridPane.rowIndex="1" text="Add todo" onMouseClicked="#addTodo"/>
|
<Button GridPane.columnIndex="8" GridPane.rowIndex="1" text="Add todo" onMouseClicked="#addTodo"/>
|
||||||
|
<Button GridPane.columnIndex="9" GridPane.rowIndex="1" text="Save" onMouseClicked="#saveAll"/>
|
||||||
|
|
||||||
<VBox fx:id="todoDisplayBox" GridPane.columnIndex="1" GridPane.rowIndex="3" spacing="4" />
|
<VBox fx:id="todoDisplayBox" GridPane.columnIndex="1" GridPane.rowIndex="3" spacing="4" />
|
||||||
</GridPane>
|
</GridPane>
|
Reference in a new issue