aboutsummaryrefslogtreecommitdiff
path: root/src/dk.biks.bachelorizer/dk/biks/bachelorizer/Window.java
blob: 2da85b3655f235c36b986355b0fb2405e2744368 (plain)
  1. // SPDX-FileCopyrightText: 2025 <Alexander Marthin Klemensen stud-marthin@ruc.dk>
  2. // SPDX-FileCopyrightText: 2025 <Ian Valentin Christensen stud-ianc@ruc.dk>
  3. // SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk>
  4. // SPDX-FileCopyrightText: 2025 <Zahed Noos zahed@ruc.dk>
  5. // SPDX-License-Identifier: GPL-3.0-or-later
  6. package dk.biks.bachelorizer;
  7. import javafx.application.Application;
  8. import javafx.scene.Scene;
  9. import javafx.scene.control.ComboBox;
  10. import javafx.scene.control.Label;
  11. import javafx.scene.control.TextArea;
  12. import javafx.scene.layout.HBox;
  13. import javafx.scene.layout.VBox;
  14. import javafx.stage.Stage;
  15. import java.io.IOException;
  16. import java.util.List;
  17. /// Bachelorizer - JavaFX Window view
  18. // Class is final to forbid subclassing,
  19. // because object is passed to controller during instantiation
  20. public final class Window extends Application {
  21. /// Default constructor
  22. // (declared explicitly only to silence javadoc)
  23. public Window() { }
  24. /// window width
  25. private static final int WINDOW_WIDTH = 1000;
  26. /// window height
  27. private static final int WINDOW_HEIGHT = 500;
  28. /// box width
  29. private static final int LIST_WIDTH = 250;
  30. /// box height
  31. private static final int LIST_HEIGHT = 35;
  32. /// Label styling
  33. private static final String LABEL_STYLE =
  34. "-fx-font-weight: bold;"
  35. + "-fx-font-size: 18;"
  36. + "-fx-padding: 10";
  37. /// Storage model
  38. private Storage store = new Database();
  39. /// UI model
  40. ///
  41. /// Must be subclass GUI to cover columns.
  42. private GUI ui = new GUI();
  43. /// Application controller
  44. private Controller control = new Controller(store, ui, this);
  45. /// column state data as List of ActivityColumn objects
  46. private List<ActivityColumn> columns;
  47. /// Application instantiation
  48. ///
  49. /// @param args application parameters
  50. public static void main(final String[] args) {
  51. launch(args);
  52. }
  53. @Override
  54. public void start(final Stage stage) throws IOException {
  55. // pass application parameters to controller
  56. control.setParameters(getParameters().getRaw());
  57. // clear old insertions into participation table
  58. control.initialize();
  59. // define list of columns based on their names
  60. columns = List.of(
  61. new ActivityColumn(GUI.Section.PROGRAM),
  62. new ActivityColumn(GUI.Section.SUBJECT1),
  63. new ActivityColumn(GUI.Section.SUBJECT2),
  64. new ActivityColumn(GUI.Section.ELECTIVE)
  65. );
  66. // define button functionality for each activity column
  67. for (ActivityColumn col : columns) {
  68. col.nameLabel.setStyle(LABEL_STYLE);
  69. col.ectsLabel.setStyle(LABEL_STYLE);
  70. col.categoryCombo.setPrefSize(
  71. LIST_WIDTH, LIST_HEIGHT);
  72. col.activitySelect.setPrefSize(
  73. LIST_WIDTH, LIST_HEIGHT);
  74. col.area.setPrefWidth(LIST_WIDTH);
  75. // all boxes share same activity logic
  76. col.activitySelect.setOnAction(event -> {
  77. control.onActivitySelected(
  78. col.categoryCombo,
  79. col.activitySelect.getValue(),
  80. col.area);
  81. control.updateEcts(
  82. col.ectsLabel,
  83. col.categoryCombo);
  84. });
  85. // handle each category box
  86. switch (col.section) {
  87. case GUI.Section.PROGRAM -> {
  88. col.categoryCombo.getItems().addAll(
  89. "HumTek", "NatBach");
  90. col.categoryCombo.setOnAction(event -> {
  91. control.onCategorySelected(
  92. col.section,
  93. col.categoryCombo.getValue());
  94. });
  95. }
  96. // TODO: use the list for filling the box
  97. case GUI.Section.SUBJECT1 -> {
  98. col.categoryCombo.getItems().addAll(
  99. "Computer Science",
  100. "Informatik",
  101. "Astrology");
  102. col.categoryCombo.setOnAction(event -> {
  103. control.onSubjectModuleSelected(
  104. col.categoryCombo,
  105. columns.get(
  106. GUI.Section.SUBJECT2.column)
  107. .categoryCombo);
  108. control.onCategorySelected(
  109. col.section,
  110. col.categoryCombo.getValue());
  111. });
  112. }
  113. case GUI.Section.SUBJECT2 -> {
  114. col.categoryCombo.getItems().addAll(
  115. "Computer Science",
  116. "Informatik",
  117. "Astrology");
  118. // TODO: figure out a better way...
  119. col.categoryCombo.setOnAction(event -> {
  120. control.onSubjectModuleSelected(
  121. col.categoryCombo,
  122. columns.get(
  123. GUI.Section.SUBJECT1.column)
  124. .categoryCombo);
  125. control.onCategorySelected(
  126. col.section,
  127. col.categoryCombo.getValue());
  128. });
  129. }
  130. case GUI.Section.ELECTIVE -> {
  131. // hide useless box
  132. col.categoryCombo.setVisible(false);
  133. control.fillElective(col.activitySelect);
  134. }
  135. }
  136. }
  137. // define HBox and scene for columns
  138. HBox root = new HBox(
  139. columns.get(GUI.Section.PROGRAM.column)
  140. .asVBox(),
  141. columns.get(GUI.Section.SUBJECT1.column)
  142. .asVBox(),
  143. columns.get(GUI.Section.SUBJECT2.column)
  144. .asVBox(),
  145. columns.get(GUI.Section.ELECTIVE.column)
  146. .asVBox());
  147. Scene scene = new Scene(
  148. root, WINDOW_WIDTH, WINDOW_HEIGHT);
  149. stage.setTitle("Bachelorizer - RUC Course Selector");
  150. stage.setScene(scene);
  151. stage.show();
  152. }
  153. /// column of activities
  154. ///
  155. /// @param section structural section for column
  156. /// @param nameLabel display text
  157. /// @param categoryCombo dropdown list for categories
  158. /// @param activitySelect dropdown list for activities
  159. /// @param area description of chosen activities
  160. /// @param ectsLabel text to display ECTS points
  161. private record ActivityColumn(
  162. GUI.Section section,
  163. Label nameLabel,
  164. ComboBox<String> categoryCombo,
  165. ComboBox<String> activitySelect,
  166. TextArea area,
  167. Label ectsLabel
  168. ) {
  169. /// column of activities
  170. ///
  171. /// @param section structural section for column
  172. ActivityColumn(final GUI.Section section) {
  173. this(
  174. section,
  175. new Label(section.label),
  176. new ComboBox<>(),
  177. new ComboBox<>(),
  178. new TextArea(),
  179. new Label()
  180. );
  181. }
  182. /// activity columne as VBox
  183. ///
  184. /// @return column of activities as VBox
  185. VBox asVBox() {
  186. return new VBox(
  187. nameLabel,
  188. categoryCombo,
  189. activitySelect,
  190. area,
  191. ectsLabel);
  192. }
  193. }
  194. /// populate activities for a category
  195. ///
  196. /// @param section structural section to operate on
  197. /// @param activities activities to apply as string
  198. public void setOptions(
  199. final GUI.Section section, final List<String> activities
  200. ) {
  201. // clear the activity selection box
  202. columns.get(section.column).activitySelect
  203. .getItems().clear();
  204. // fill activity box from data in store
  205. columns.get(section.column).activitySelect
  206. .getItems().addAll(activities);
  207. }
  208. /// remove selections from a category
  209. ///
  210. /// @param section structural section to operate on
  211. public void clearSelections(final GUI.Section section) {
  212. // clear text area
  213. columns.get(section.column).area.clear();
  214. }
  215. }