aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile10
-rw-r--r--dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/Control.java94
-rw-r--r--dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/Main.java75
-rw-r--r--dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/model/GUI.java62
-rw-r--r--dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/model/Person.java18
-rw-r--r--dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/view/Window.java120
6 files changed, 352 insertions, 27 deletions
diff --git a/Makefile b/Makefile
index 402cd21..f8f2ecf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,17 @@
PROJECT = dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/Main
-CLASSPATHS = .
+MODULEPATHS = /usr/share/openjfx/lib
+JAVAMODULES = $(addprefix javafx.,base controls graphics)
DOCUMENTS = delivery1
include _make/*.mk
+# silence security restriction warning
+JAVAFLAGS += --enable-native-access=javafx.graphics
+
+# silence warnig specific to JDK 23-24
+# @see <https://stackoverflow.com/a/79526038/18619283>
+JAVAFLAGS += --sun-misc-unsafe-memory-access=allow
+
all:: render
render:
diff --git a/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/Control.java b/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/Control.java
new file mode 100644
index 0000000..09019e4
--- /dev/null
+++ b/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/Control.java
@@ -0,0 +1,94 @@
+// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer;
+
+import java.util.List;
+
+import dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.model.GUI;
+import dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.view.Window;
+
+/// Bachelorizer - Controller
+public class Control{
+
+ /// Application model
+ // (declared explicitly only to silence javadoc)
+ private GUI model;
+
+ /// Application view
+ private Window view;
+
+ /// Parameters passed on command-line and in JNLP file
+ private List<String> parameters;
+
+ /// Default constructor
+ ///
+ /// @param model Application model
+ /// @param view Application view
+ public Control(GUI model, Window view){
+ this.model = model;
+ this.view = view;
+ }
+
+ /// parse application parameters
+ ///
+ /// parse parameters as GNU-style options and arguments,
+ /// i.e. treat dash-prefixed words as options
+ /// until an optional first bare "--",
+ /// taking first non-option argument as name of student
+ /// and remaining ones as activity selections
+ ///
+ /// @param parameters Application parameters
+ public void setParameters(List<String> parameters) {
+ boolean optionsDone = false;
+ boolean studentAssigned = false;
+ for (String item : parameters) {
+ if (!optionsDone && item.matches("--")) {
+ optionsDone = true;
+ } else if (!item.startsWith("-")) {
+ if (!studentAssigned) {
+ model.addStudent(item);
+ studentAssigned = true;
+ showStudent();
+ } else {
+ model.addActivity(item);
+ showActivities();
+ }
+ }
+ }
+ }
+
+ /// Enter activity
+ ///
+ /// @param s String entered
+ public void enterActivity(String s){
+ model.addActivity(s);
+ view.clearActivityEntry();
+ showActivities();
+ }
+
+ /// Display student
+ public void showStudent() {
+ view.setStudentName(model.getStudentName());
+ }
+
+ /// Display list of activity entries
+ public void showActivities() {
+ String toarea = "";
+ for (String t : model.getActivities())
+ toarea += t + "\n";
+ view.setArea(toarea);
+ }
+
+ /// drop last activity entry
+ public void delOne(){
+ model.delOneActivity();
+ showActivities();
+ }
+
+ /// drop all activity entries
+ public void delAll(){
+ model.delAllActivities();
+ showActivities();
+ }
+}
diff --git a/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/Main.java b/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/Main.java
index 633f5f7..d5da2b7 100644
--- a/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/Main.java
+++ b/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/Main.java
@@ -3,39 +3,48 @@
package dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer;
+import java.lang.UnsupportedOperationException;
import java.util.Arrays;
+/* TODO
+import dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.view.Oneshot;
+import dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.view.Prompt;
+import dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.view.Pipe;
+import dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.view.Screen;
+*/
+import dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.view.Window;
+
/// Bachelorizer - bachelor programme registrar
///
/// Tool for registering students
/// for activities in their bachelor programme.
///
-/// Core class usable in several ways
-/// * as self-contained executable via method main()
-/// * embedded in a larger system by instantiating Bachelorizer()
+/// Runner class spawning an interactive or non-interactive application
+/// based on passed arguments
+///
+/// Multi-framework MVC structure inspired by project Криптоанализатор
+/// written by Александр Хмелев <akhmelev@gmail.com>.
///
/// * v0.0.1-draft
/// * initial release, as part of delivery "Portfolio 1"
///
/// @version 0.0.1-draft
/// @see <https://moodle.ruc.dk/mod/assign/view.php?id=523186>
+/// @see <https://github.com/demologin/CryptoAnalyzerLed>
public class Main {
- /// Student name
- public String name;
-
- /// Student activity list
- public String[] activities;
-
- /// Main constructor
+ /// Default constructor
///
/// @param args command-line arguments or default demo data
public Main(final String[] args) {
- if (args.length > 0 && args[0] != null) {
- this.name = args[0];
- if (args.length > 1 && args[1] != null) {
- this.activities = Arrays.copyOfRange(
- args, 1, args.length);
+
+ switch (uiFromArgs(args)) {
+ case "gui" -> { Window.main(args); }
+// TODO case "tui" -> { Screen.main(args); }
+// TODO case "cli" -> { Line.main(args); }
+ default -> {
+ throw new UnsupportedOperationException(
+ "Not yet implemented.");
}
}
}
@@ -45,23 +54,37 @@ public class Main {
/// @param args command-line arguments
public static void main(String[] args) {
- if (args.length == 0)
+ // inject initial sample data unless passed as arguments
+ if ((args.length == 0)
+ || (!Arrays.stream(args).anyMatch(
+ s -> s != null && !s.startsWith("-")))
+ ) {
args = new String[] {
"Jonas Smedegaard",
"CS-SMC2",
"CS-SMC3",
};
+ }
- Main session = new Main(args);
+ new Main(args);
+ }
+
+ /// minimal argument parser to detect explicit UI choice
+ ///
+ /// @param args command-line arguments
+ /// @return choice of UI as String
+ public static String uiFromArgs(String[] args) {
+ // TODO: make "cli" the default when implemented
+ String defaultUI = "gui";
+
+ for (String arg : args) {
+ if (arg.matches("--(gui|tui|cli)")) {
+ return (arg.length() == 2)
+ ? defaultUI
+ : arg.substring(2);
+ }
+ }
- // minimal viable product
- System.out.printf("Hi %s%n",
- (session.name != null)
- ? session.name
- : "stranger");
- System.out.printf("You chose these activities: %s%n",
- (session.activities != null)
- ? Arrays.toString(session.activities)
- : "[nothing]");
+ return defaultUI;
}
}
diff --git a/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/model/GUI.java b/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/model/GUI.java
new file mode 100644
index 0000000..8abfec9
--- /dev/null
+++ b/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/model/GUI.java
@@ -0,0 +1,62 @@
+// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.model;
+
+import java.util.ArrayList;
+
+import dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.model.Person;
+
+/// Bachelorizer - GUI model
+public class GUI{
+
+ /// Default constructor
+ // (declared explicitly only to silence javadoc)
+ public GUI(){
+ }
+
+ /// Activity list
+ private Person student;
+
+ /// Activity list
+ private ArrayList<String> list = new ArrayList<>();
+
+ /// Add student
+ ///
+ /// @param name Name of student
+ public void addStudent(String name){
+ student = new Person(name);
+ }
+
+ /// Get student name
+ ///
+ /// @return name of student
+ public String getStudentName(){
+ return student.name;
+ }
+
+ /// Add activity to list
+ ///
+ /// @param s Activity to add
+ public void addActivity(String s){
+ list.add(s);
+ }
+
+ /// Get list of activities
+ ///
+ /// @return activity list
+ public ArrayList<String> getActivities(){
+ return list;
+ }
+
+ /// Delete last activity from list
+ public void delOneActivity(){
+ if(list.size()>0)
+ list.remove(list.size()-1);
+ }
+
+ /// Delete all activities from list
+ public void delAllActivities(){
+ list.clear();
+ }
+}
diff --git a/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/model/Person.java b/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/model/Person.java
new file mode 100644
index 0000000..294af3f
--- /dev/null
+++ b/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/model/Person.java
@@ -0,0 +1,18 @@
+// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.model;
+
+/// Bachelorizer - Person model
+public class Person {
+
+ /// Person name
+ public String name;
+
+ /// Constructor
+ ///
+ /// @param name Name of person
+ public Person (String name) {
+ this.name = name;
+ }
+}
diff --git a/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/view/Window.java b/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/view/Window.java
new file mode 100644
index 0000000..bf2af3d
--- /dev/null
+++ b/dk/abcdefghijklmnopqrstuvxyzæøå/bachelorizer/view/Window.java
@@ -0,0 +1,120 @@
+// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.view;
+
+import java.util.List;
+import javafx.application.Application;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextArea;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+
+import dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.Control;
+import dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.model.GUI;
+
+/// Bachelorizer - JavaFX Window view
+// Class is final to forbid subclassing,
+// because object is passed to controller during instatiation
+public final class Window extends Application { // the View
+
+ /// Default constructor
+ // (declared explicitly only to silence javadoc)
+ public Window() {
+ }
+
+ /// Label styling
+ public static String LABEL_STYLE =
+ "-fx-font-weight: bold; -fx-font-size: 20;";
+
+ /// Application model
+ private GUI model = new GUI();
+
+ /// Application controller
+ private Control control = new Control(model, this);
+
+ /// Name of student
+ private TextField nameEntry = new TextField();
+
+ /// Text entry for adding an activity
+ private TextField activityEntry = new TextField();
+
+ /// Text area for activity entries
+ private TextArea area = new TextArea();
+
+ /// Button to delete one activity
+ private Button delOne = new Button("Delete one");
+
+ /// Button to delete all activities
+ private Button delAll = new Button("Delete all");
+
+ /// Application instantiation
+ ///
+ /// @param args application parameters
+ public static void main(String[] args) {
+ launch(args);
+ }
+
+ @Override
+ public void start(Stage stage) {
+
+ // pass application parameters to controller
+ control.setParameters(getParameters().getRaw());
+
+ // add listeners
+// NameEntry.setOnAction(e -> control.enterName(
+// activityEntry.getText()));
+ activityEntry.setOnAction(e -> control.enterActivity(
+ activityEntry.getText()));
+ delOne.setOnAction(e -> control.delOne());
+ delAll.setOnAction(e -> control.delAll());
+
+ // add buttons
+ VBox root = new VBox(10,
+ ourHBox("Student", nameEntry),
+ ourHBox("Add activity", activityEntry),
+ new HBox(10, delOne, delAll),
+ area);
+
+ // compose stage
+ Scene scene = new Scene(root, 500, 500);
+ stage.setTitle("JavaFX Demo");
+ stage.setScene(scene);
+ stage.show();
+ }
+
+ /// action to apply student name
+ ///
+ /// @param s Text to apply
+ public void setStudentName(String s) {
+ nameEntry.setText(s);
+ }
+
+ /// action to apply text to area
+ ///
+ /// @param s Text to apply
+ public void setArea(String s) {
+ area.setText(s);
+ }
+
+ /// Button action to clear field
+ public void clearActivityEntry() {
+ activityEntry.setText("");
+ }
+
+ /// Styled HBox with label and TextField
+ ///
+ /// @param s Label string
+ /// @param f Text field
+ /// @return HBox containing styled label and text field
+ public HBox ourHBox(String s, TextField f) {
+ Label label = new Label(s+":");
+ label.setStyle(LABEL_STYLE);
+
+ return new HBox(10, label, f);
+ }
+}