diff --git a/src/main/java/modulo/model/Title.java b/src/main/java/modulo/model/Title.java index 6687ed96fca..7c97de70825 100644 --- a/src/main/java/modulo/model/Title.java +++ b/src/main/java/modulo/model/Title.java @@ -6,6 +6,7 @@ import java.time.format.DateTimeFormatter; import modulo.model.displayable.Displayable; +import modulo.model.module.AcademicYear; /** * Class to section events out by date. @@ -51,6 +52,10 @@ public Title(LocalDateTime localDateTime) { } } + public Title(AcademicYear academicYear) { + this.title = academicYear.toModuleCardFormat(); + } + public String getTitle() { return title; } diff --git a/src/main/java/modulo/model/module/AcademicYear.java b/src/main/java/modulo/model/module/AcademicYear.java index 195d2f830e3..04b17fda0c2 100644 --- a/src/main/java/modulo/model/module/AcademicYear.java +++ b/src/main/java/modulo/model/module/AcademicYear.java @@ -98,4 +98,15 @@ public String toModuleCardFormat() { public String toString() { return getStartYear() + "/" + getEndYear() + "+" + getSemester(); } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof AcademicYear // instanceof handles nulls + && startYear == (((AcademicYear) other).startYear) + && endYear == (((AcademicYear) other).endYear) + && semester == (((AcademicYear) other).semester) + && startDate.equals(((AcademicYear) other).startDate) + && endDate.equals(((AcademicYear) other).endDate)); // state check + } } diff --git a/src/main/java/modulo/ui/DescriptionWindow.java b/src/main/java/modulo/ui/DescriptionWindow.java new file mode 100644 index 00000000000..4718f18f3fb --- /dev/null +++ b/src/main/java/modulo/ui/DescriptionWindow.java @@ -0,0 +1,99 @@ +package modulo.ui; + +import java.util.logging.Logger; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.stage.Stage; +import modulo.commons.core.LogsCenter; + +/** + * Controller for a description page + */ +public class DescriptionWindow extends UiPart { + + private static final Logger logger = LogsCenter.getLogger(DescriptionWindow.class); + private static final String FXML = "DescriptionWindow.fxml"; + + @FXML + private Label description; + + @FXML + private Label moduleName; + + /** + * Creates a new DescriptionWindow. + * + * @param root Stage to use as the root of the DescriptionWindow. + * @param description Description to display. + */ + public DescriptionWindow(Stage root, String description, String moduleName) { + super(FXML, root); + this.moduleName.setText(moduleName); + this.moduleName.setWrapText(true); + this.moduleName.setMaxWidth(600.0); + this.description.setText(description); + this.description.setWrapText(true); + this.description.setMaxWidth(600.0); + } + + /** + * Creates a new empty DescriptionWindow. + */ + public DescriptionWindow() { + this(new Stage(), "", ""); + } + + /** + * Creates a new DescriptionWindow with a description. + */ + public DescriptionWindow(String description, String moduleName) { + this(new Stage(), description, moduleName); + } + + /** + * Shows the help window. + * + * @throws IllegalStateException + */ + public void show() { + logger.fine("Showing help page about the application."); + getRoot().show(); + getRoot().centerOnScreen(); + } + + /** + * Returns true if the help window is currently being shown. + */ + public boolean isShowing() { + return getRoot().isShowing(); + } + + /** + * Hides the help window. + */ + public void hide() { + getRoot().hide(); + } + + /** + * Focuses on the help window. + */ + public void focus() { + getRoot().requestFocus(); + } +} diff --git a/src/main/java/modulo/ui/ListPanel.java b/src/main/java/modulo/ui/ListPanel.java index fe851986ee7..eb731f760bd 100644 --- a/src/main/java/modulo/ui/ListPanel.java +++ b/src/main/java/modulo/ui/ListPanel.java @@ -16,6 +16,7 @@ import modulo.model.displayable.Displayable; import modulo.model.displayable.DisplayablePair; import modulo.model.event.Event; +import modulo.model.module.AcademicYear; import modulo.model.module.Module; /** @@ -33,9 +34,9 @@ public ListPanel(ObservableList displayableList, MainWind super(FXML); ObservableList listViewList; if (!displayableList.isEmpty() && displayableList.get(0) instanceof Event) { - listViewList = processDisplayableList((ObservableList) displayableList); + listViewList = processEventDisplayableList((ObservableList) displayableList); } else { - listViewList = (ObservableList) displayableList; + listViewList = processModuleDisplayableList((ObservableList) displayableList); } listView.setItems(listViewList); listView.setCellFactory(listView -> new ListViewCell(mainWindow)); @@ -44,19 +45,19 @@ public ListPanel(ObservableList displayableList, MainWind /** * Returns a processed Event list with Titles inserted. * - * @param displaybleList List of {@code Event} to process. + * @param displayableList List of {@code Event} to process. * @return List with Titles inserted. */ - private ObservableList processDisplayableList(ObservableList displaybleList) { + private ObservableList processEventDisplayableList(ObservableList displayableList) { final ObservableList result = FXCollections.observableArrayList(); - if (displaybleList.size() == 0) { + if (displayableList.size() == 0) { return result; } - LocalDateTime currentDateTime = ((Event) displaybleList.get(0)).getEventStart(); + LocalDateTime currentDateTime = ((Event) displayableList.get(0)).getEventStart(); LocalDate currentDate = currentDateTime.toLocalDate(); result.add(0, new Title(currentDateTime)); - for (int i = 0; i < displaybleList.size(); i++) { - Event event = (Event) displaybleList.get(i); + for (int i = 0; i < displayableList.size(); i++) { + Event event = (Event) displayableList.get(i); LocalDateTime localDateTime = event.getEventStart(); LocalDate localDate = localDateTime.toLocalDate(); if (!localDate.isEqual(currentDate)) { @@ -68,6 +69,31 @@ private ObservableList processDisplayableList(ObservableList processModuleDisplayableList(ObservableList displayableList) { + final ObservableList result = FXCollections.observableArrayList(); + if (displayableList.size() == 0) { + return result; + } + AcademicYear currentAcademicYear = ((Module) displayableList.get(0)).getAcademicYear(); + result.add(0, new Title(currentAcademicYear)); + for (int i = 0; i < displayableList.size(); i++) { + Module module = (Module) displayableList.get(i); + AcademicYear academicYear = module.getAcademicYear(); + if (!academicYear.equals(currentAcademicYear)) { + result.add(new Title(academicYear)); + currentAcademicYear = academicYear; + } + result.add(new DisplayablePair<>(module, i)); + } + return result; + } + /** * Selects displayable at given index. * @@ -125,14 +151,15 @@ protected void updateItem(Displayable listItem, boolean empty) { setGraphic(null); setText(null); } else if (listItem instanceof DisplayablePair) { - @SuppressWarnings("unchecked") - DisplayablePair item = (DisplayablePair) listItem; - setGraphic(new EventCard(item.getFirst(), item.getSecond() + 1).getRoot()); - setOnMouseClicked(event -> mainWindow.handleListClick(item.getSecond())); - setDisable(false); - } else if (listItem instanceof Module) { - setGraphic(new ModuleCard((Module) listItem, getIndex() + 1).getRoot()); - setOnMouseClicked(event -> mainWindow.handleListClick(getIndex())); + DisplayablePair item = (DisplayablePair) listItem; + Integer index = ((Integer) item.getSecond()); + if (item.getFirst() instanceof Event) { + setGraphic(new EventCard((Event) item.getFirst(), index + 1).getRoot()); + } else { + assert item.getFirst() instanceof Module; + setGraphic(new ModuleCard((Module) item.getFirst(), index + 1).getRoot()); + } + setOnMouseClicked(event -> mainWindow.handleListClick(index)); setDisable(false); } else if (listItem instanceof Title) { setGraphic(new TitleCard((Title) listItem).getRoot()); diff --git a/src/main/java/modulo/ui/MainWindow.java b/src/main/java/modulo/ui/MainWindow.java index b0d5bbdb1e3..c59235db9a0 100644 --- a/src/main/java/modulo/ui/MainWindow.java +++ b/src/main/java/modulo/ui/MainWindow.java @@ -34,6 +34,7 @@ public class MainWindow extends UiPart { private ListPanel listPanel; private ResultDisplay resultDisplay; private HelpWindow helpWindow; + private DescriptionWindow descriptionWindow; private RightPanel rightPanel; @FXML @@ -78,6 +79,7 @@ public MainWindow(Stage primaryStage, Logic logic) { setWindowDefaultSize(logic.getGuiSettings()); helpWindow = new HelpWindow(); + descriptionWindow = new DescriptionWindow(); } public Stage getPrimaryStage() { @@ -139,6 +141,19 @@ public void handleHelp() { } } + /** + * Opens the description window with the given description. + * + * @param description Description to show. + */ + public void handleDescription(String description, String moduleName) { + if (descriptionWindow.isShowing()) { + descriptionWindow.hide(); + } + descriptionWindow = new DescriptionWindow(description, moduleName); + descriptionWindow.show(); + } + void show() { primaryStage.show(); } @@ -153,6 +168,7 @@ private void handleExit() { logic.setGuiSettings(guiSettings); helpWindow.hide(); primaryStage.hide(); + descriptionWindow.hide(); } public ListPanel getListPanel() { @@ -195,6 +211,7 @@ private CommandResult executeCommand(String commandText) throws CommandException /** * Shows event list as callback from EventButton. */ + @FXML public void handleEventButton() { try { this.executeCommand("list e"); @@ -207,6 +224,7 @@ public void handleEventButton() { /** * Shows module list as callback from ModuleButton. */ + @FXML public void handleModuleButton() { try { this.executeCommand("list m"); diff --git a/src/main/java/modulo/ui/RightPanel.java b/src/main/java/modulo/ui/RightPanel.java index 788d5d3bdbd..1cb935f80f0 100644 --- a/src/main/java/modulo/ui/RightPanel.java +++ b/src/main/java/modulo/ui/RightPanel.java @@ -18,7 +18,7 @@ */ public class RightPanel extends UiPart { - private static final String FXML = "DetailsWindow.fxml"; + private static final String FXML = "RightPanel.fxml"; private ObservableList eventList; private MainWindow mainWindow; @@ -42,22 +42,7 @@ public RightPanel(Displayable displayable, MainWindow mainWindow) { } else { deadlineListView.setItems(FXCollections.emptyObservableList()); } - rightPanelDescription = new RightPanelDescription(displayable); - slideEventCard.getChildren().setAll(rightPanelDescription.getRoot()); - deadlineListView.setCellFactory(listView -> new ListViewCell(mainWindow)); - } - - /** - * Updates this component. - */ - public void updateStatus() { - if (displayable instanceof Event) { - deadlineListView.setItems(FXCollections.observableArrayList(((Event) displayable).getDeadlines())); - } else { - assert displayable instanceof Module; - deadlineListView.setItems(FXCollections.observableArrayList(((Module) displayable).getEvents())); - } - rightPanelDescription = new RightPanelDescription(displayable); + rightPanelDescription = new RightPanelDescription(displayable, mainWindow); slideEventCard.getChildren().setAll(rightPanelDescription.getRoot()); deadlineListView.setCellFactory(listView -> new ListViewCell(mainWindow)); } diff --git a/src/main/java/modulo/ui/RightPanelDeadlineCard.java b/src/main/java/modulo/ui/RightPanelDeadlineCard.java index d6bddb58aac..826b62a21bf 100644 --- a/src/main/java/modulo/ui/RightPanelDeadlineCard.java +++ b/src/main/java/modulo/ui/RightPanelDeadlineCard.java @@ -12,7 +12,7 @@ */ public class RightPanelDeadlineCard extends UiPart { - private static final String FXML = "DeadlineListCard.fxml"; + private static final String FXML = "RightPanelDeadlineCard.fxml"; public final Deadline deadline; diff --git a/src/main/java/modulo/ui/RightPanelDescription.java b/src/main/java/modulo/ui/RightPanelDescription.java index b64234a5bc3..335d707cdb0 100644 --- a/src/main/java/modulo/ui/RightPanelDescription.java +++ b/src/main/java/modulo/ui/RightPanelDescription.java @@ -4,6 +4,7 @@ import javafx.fxml.FXML; import javafx.scene.control.Label; +import javafx.scene.input.MouseEvent; import javafx.scene.layout.Region; import javafx.scene.layout.VBox; import modulo.model.deadline.Deadline; @@ -16,9 +17,10 @@ */ public class RightPanelDescription extends UiPart { - private static final String FXML = "DetailsWindow.fxml"; - public final Event eventViewed; - public final Module moduleViewed; + private static final String FXML = "RightPanel.fxml"; + private final Event eventViewed; + private final Module moduleViewed; + private final MainWindow mainWindow; @FXML private VBox slideEventCard; @@ -36,9 +38,9 @@ public class RightPanelDescription extends UiPart { private Label eventTypeDescription; - public RightPanelDescription(Displayable eventOrModule) { + public RightPanelDescription(Displayable eventOrModule, MainWindow mainWindow) { super(FXML); - + this.mainWindow = mainWindow; if (eventOrModule instanceof Event) { this.eventViewed = (Event) eventOrModule; this.moduleViewed = null; @@ -54,6 +56,7 @@ public RightPanelDescription(Displayable eventOrModule) { completionStatus.getStyleClass().add("allComplete"); } venue.setText(this.eventViewed.getLocation().toString()); + venue.getStyleClass().remove("moduleDescription"); eventTypeDescription.setText("Prepare for " + this.eventViewed.getName().toString() + " by doing:"); } else if (eventOrModule instanceof Module) { this.moduleViewed = (Module) eventOrModule; @@ -67,7 +70,11 @@ public RightPanelDescription(Displayable eventOrModule) { completionStatus.getStyleClass().add("hidden"); } completionStatus.getStyleClass().remove("allComplete"); - venue.setText(null); + venue.setText("Click to view description"); + if (!venue.getStyleClass().contains("moduleDescription")) { + venue.getStyleClass().add("moduleDescription"); + } + venue.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> openDescription()); eventTypeDescription.setText("Events under this module:"); } else { this.eventViewed = null; @@ -87,4 +94,11 @@ public RightPanelDescription(Displayable eventOrModule) { eventTypeDescription.setText(""); } } + + @FXML + private void openDescription() { + if (moduleViewed != null && eventViewed == null) { + mainWindow.handleDescription(moduleViewed.getDescription(), moduleViewed.getName().toString()); + } + } } diff --git a/src/main/java/modulo/ui/RightPanelEventCard.java b/src/main/java/modulo/ui/RightPanelEventCard.java index 06a9ec542e9..5c18fb95f76 100644 --- a/src/main/java/modulo/ui/RightPanelEventCard.java +++ b/src/main/java/modulo/ui/RightPanelEventCard.java @@ -13,7 +13,7 @@ */ public class RightPanelEventCard extends UiPart { - private static final String FXML = "EventListSidePanelCard.fxml"; + private static final String FXML = "RightPanelEventCard.fxml"; /** * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX. As a consequence, UI diff --git a/src/main/resources/view/Default.css b/src/main/resources/view/Default.css index 40c79451c98..7b99055e38f 100644 --- a/src/main/resources/view/Default.css +++ b/src/main/resources/view/Default.css @@ -153,7 +153,7 @@ -fx-background-color: transparent; } -.eventDuration { +.eventDuration, .moduleAcadYear, .eventLocation { -fx-padding: 0 0 0 10; } @@ -162,6 +162,7 @@ } /** Right Panel **/ + /** Details **/ #slideEventCard { -fx-font-size: 12pt; @@ -177,6 +178,22 @@ -fx-font-family: 'Poppins Light'; } +.slideEventVenue.moduleDescription { + -fx-font-family: 'Poppins'; + -fx-padding: 10 0 0 0; +} + +.moduleDescriptionName { + -fx-font-family: 'Poppins Bold'; + -fx-font-size: 14pt; + -fx-padding: 0 0 5 0; +} + +.slideEventVenue.moduleDescription:hover { + -fx-text-fill: #6842E4; + -fx-cursor: hand; +} + .slideEventDescription { -fx-font-family: 'Poppins Medium'; } diff --git a/src/main/resources/view/DescriptionWindow.fxml b/src/main/resources/view/DescriptionWindow.fxml new file mode 100644 index 00000000000..85c75cc488c --- /dev/null +++ b/src/main/resources/view/DescriptionWindow.fxml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/EventListCard.fxml b/src/main/resources/view/EventListCard.fxml index d36c17600da..f06d61b63a2 100644 --- a/src/main/resources/view/EventListCard.fxml +++ b/src/main/resources/view/EventListCard.fxml @@ -29,9 +29,19 @@