Schedule-Creator

Java GUI to create schedules for UNCG students
git clone git://git.wrycode.com/wrycode/archive/Schedule-Creator.git
Log | Files | Refs | README

commit 7ef91cfb001edf07f26eb0b743935188476b9f7d
parent 93cd9592c1cf500685d31fc834f9501b3767dc58
Author: jamisonv93 <47033011+jamisonv93@users.noreply.github.com>
Date:   Mon, 20 Apr 2020 11:09:45 -0400

Completed Version of New Design (#65)

* prototyping for new design

* add and implement toggle Menu Button

* modify menu expansion feature

* correct resizing issue

* add comments in model classes

* implement new design
Diffstat:
MScheduleCreator/controllers/CoursesController.java | 29+++++++++++++++++++++++++++++
MScheduleCreator/controllers/PrimaryController.java | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
MScheduleCreator/controllers/RegistrationController.java | 17-----------------
MScheduleCreator/models/Course.java | 32+++++++++++++++++++++++++++++---
MScheduleCreator/models/Section.java | 24++++++++++++++++++------
MScheduleCreator/resources/views/primary.fxml | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
MScheduleCreator/resources/views/registration_screen.fxml | 1-
7 files changed, 246 insertions(+), 68 deletions(-)

diff --git a/ScheduleCreator/controllers/CoursesController.java b/ScheduleCreator/controllers/CoursesController.java @@ -33,6 +33,8 @@ import javafx.geometry.HPos; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.geometry.VPos; +import javafx.scene.Node; +import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Button; @@ -79,6 +81,8 @@ public class CoursesController implements Initializable { protected TabPane sectionTabPane; @FXML protected VBox CRNContainer, CRNPane; + @FXML + protected StackPane mainContent; // List of courses for current semester. FilteredList<String> courseList; @@ -109,6 +113,31 @@ public class CoursesController implements Initializable { } } + + public void changeToSelectClasses(ActionEvent _event) throws Exception { + + //new FXML loader and scene for new screen + Parent root = FXMLLoader.load(getClass().getResource("/ScheduleCreator/resources/views/select_courses.fxml")); + Scene classViewScene = new Scene(root); + + + //Get window object and refresh to show the new scene + Stage window = (Stage) ((Node) _event.getSource()).getScene().getWindow(); + window.setScene(classViewScene); + window.show(); + } + + public void changeToRegistrationScreen(ActionEvent _event) throws Exception { + + Parent root = FXMLLoader.load(getClass().getResource("/ScheduleCreator/resources/views/registration_screen.fxml")); + Scene scene = new Scene(root); + + //Get window object and refresh to show the new scene + Stage stage = (Stage) ((Node) _event.getSource()).getScene().getWindow(); + stage.setScene(scene); + stage.show(); + } + /** * Called when "Add Course" button is clicked; Add selected course to the * listview and saves in database. diff --git a/ScheduleCreator/controllers/PrimaryController.java b/ScheduleCreator/controllers/PrimaryController.java @@ -5,53 +5,124 @@ package ScheduleCreator.controllers; * * @author Jamison Valentine * - * Last Updated: 3/18/2020 + * Last Updated: 4/19/2020 */ import com.sun.javafx.css.StyleManager; import javafx.event.ActionEvent; import javafx.fxml.FXMLLoader; -import javafx.scene.Node; import javafx.scene.Parent; -import javafx.scene.Scene; -import javafx.stage.Stage; import java.net.URL; +import java.util.HashMap; import java.util.ResourceBundle; import javafx.application.Application; import javafx.fxml.FXML; import javafx.fxml.Initializable; +import javafx.scene.control.Label; import javafx.scene.control.ToggleButton; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; public class PrimaryController implements Initializable { @FXML private ToggleButton darkmode; + @FXML + protected StackPane mainContent; + @FXML + protected ToggleButton toggleMenu; + @FXML + protected VBox menuBox; + @FXML + protected GridPane mainBox; + @FXML + protected HBox schedMenuItem, advMenuItem, regMenuItem, currentMenuItem; + @FXML + protected Label schedMenuItemLabel, advMenuItemLabel, regMenuItemLabel; + protected HashMap<HBox, Label> menuItems = new HashMap(); + protected boolean showMenu = false; - public void changeToSelectClasses(ActionEvent _event) throws Exception { + /** + * Set's the current view of the app to the course selection view. + * @throws Exception + */ + public void changeToSelectCourses() throws Exception { - //new FXML loader and scene for new screen + //New FXML Loader to render the next view. Parent root = FXMLLoader.load(getClass().getResource("/ScheduleCreator/resources/views/select_courses.fxml")); - Scene classViewScene = new Scene(root); + mainContent.getChildren().clear(); + mainContent.getChildren().add(root); + this.setCurrentItem(this.schedMenuItem); + } - //Get window object and refresh to show the new scene - Stage window = (Stage) ((Node) _event.getSource()).getScene().getWindow(); - window.setScene(classViewScene); - window.show(); + /** + * Sets the current menu item to the given argument. + * @param _menuItem + */ + public void setCurrentItem(HBox _menuItem) { + if (this.currentMenuItem != null) this.unhighlight(this.currentMenuItem); + this.currentMenuItem = _menuItem; + this.highlight(this.currentMenuItem); } - public void changeToRegistrationScreen(ActionEvent _event) throws Exception { + /** + * Changes the appropriate text color to white to indicate current focus. + * @param _menuItem + */ + public void highlight(HBox _menuItem) { + Label label = this.menuItems.get(_menuItem); + label.setStyle("-fx-text-fill: white"); + } + + /** + * Undoes highlighting of previously focused item. + * @param _menuItem + */ + public void unhighlight(HBox _menuItem) { + Label label = this.menuItems.get(_menuItem); + label.setStyle("-fx-text-fill:black"); + } + /** + * Changes application view to registration + * @throws Exception + */ + public void changeToRegistrationScreen() throws Exception { Parent root = FXMLLoader.load(getClass().getResource("/ScheduleCreator/resources/views/registration_screen.fxml")); - Scene scene = new Scene(root); + mainContent.getChildren().clear(); + mainContent.getChildren().add(root); + this.setCurrentItem(this.regMenuItem); + } + + public void hoverItem(MouseEvent _event) { + HBox item = (HBox) _event.getSource(); + this.highlight(item); + } - //Get window object and refresh to show the new scene - Stage stage = (Stage) ((Node) _event.getSource()).getScene().getWindow(); - stage.setScene(scene); - stage.show(); + public void unhoverItem(MouseEvent _event) { + HBox item = (HBox) _event.getSource(); + if (item != this.currentMenuItem) + this.unhighlight(item); + } + + @FXML + public void toggleMenu(ActionEvent _event) { + if (!this.showMenu) { + this.mainBox.getColumnConstraints().get(0).setMaxWidth(200); + this.menuBox.setVisible(true); + this.showMenu = true; + } else { + this.menuBox.setVisible(false); + this.mainBox.getColumnConstraints().get(0).setMaxWidth(0); + this.showMenu = false; + } } //toggle and untoggle darkmode css to defult theme from button @FXML - void toggleDarkMode(ActionEvent event) { + public void toggleDarkMode(ActionEvent event) { if (darkmode.isSelected()) { Application.setUserAgentStylesheet(Application.STYLESHEET_MODENA); StyleManager.getInstance().addUserAgentStylesheet("ScheduleCreator/resources/Darkmode.css"); @@ -63,6 +134,16 @@ public class PrimaryController implements Initializable { @Override public void initialize(URL url, ResourceBundle rb) { + try { + this.menuItems.put(this.schedMenuItem, this.schedMenuItemLabel); + this.menuItems.put(this.advMenuItem, this.advMenuItemLabel); + this.menuItems.put(this.regMenuItem, this.regMenuItemLabel); + this.mainBox.getColumnConstraints().get(0).setMaxWidth(0); + this.changeToSelectCourses(); + System.out.println("initialized"); + } catch (Exception e) { + System.out.println("Something went wrong"); + } } } diff --git a/ScheduleCreator/controllers/RegistrationController.java b/ScheduleCreator/controllers/RegistrationController.java @@ -30,23 +30,6 @@ public class RegistrationController { private WebEngine engine; - //Button to take user back to the main screen - @FXML - void backToPrimary(ActionEvent _event) { - - try { - Parent root = FXMLLoader.load(getClass().getResource("/ScheduleCreator/resources/views/primary.fxml")); - Scene primaryScene = new Scene(root); - - //Get window object and refresh to show the new scene - Stage window = (Stage) ((Node) _event.getSource()).getScene().getWindow(); - window.setScene(primaryScene); - window.show(); - } catch (IOException ex) { - Logger.getLogger(RegistrationController.class.getName()).log(Level.SEVERE, null, ex); - } - } - //loads the uncg geine webpage as soon as the user acesses the registration screen public void initialize() { engine = webview.getEngine(); diff --git a/ScheduleCreator/models/Course.java b/ScheduleCreator/models/Course.java @@ -5,7 +5,7 @@ package ScheduleCreator.models; * * @author Jamison Valentine * - * Last Updated: 3/27/2020 + * Last Updated: 4/19/2020 */ import ScheduleCreator.Adapter; @@ -33,32 +33,58 @@ public class Course { //================= GETTERS =============== + /** + * Returns course abbreviation and number. + * @return + */ public String getID() { return this.id; } + /** + * Returns course abbreviation, number, and title + * such as "CSC 340 - Software Engineering" + * @return + */ public String getFullText() { return this.fullText; } - public String getabbreviation() { + /** + * Returns department/course abbreviation (i.e. CSC) + * @return + */ + public String getAbbreviation() { return abbreviation; } + /** + * Returns appropriate course number by itself. + * @return + */ public String getCourseNumber() { return courseNumber; } + /** + * Returns available sections corresponding to this course. + * @return + */ public List<Section> getSections() { return this.sections; } + /** Loads available sections corresponding to this class for the + * given semester + * + * @param _semester + */ private void loadSectionsFromFile(String _semester) { List<String> sectionStrings = this.adapter.getSections(this.id, _semester); this.sections = new ArrayList(); Pattern p = Pattern.compile(".*([0-9]{5}).*- ([0-9]{2})\\s*(\\S* [ap]m - \\S* [ap]m)\\s*(\\S*)(.*)=(.*)"); - //This pattern is to be matched with Courses with "TBA" as location and meeting times" + //This pattern is to be matched with Courses with "TBA" as location and meeting times" such as online classes Pattern p2 = Pattern.compile(".*([0-9]{5}).*- ([0-9]{2})\\s*(TBA\\s*TBA )=(.*)"); Matcher m, m2; diff --git a/ScheduleCreator/models/Section.java b/ScheduleCreator/models/Section.java @@ -1,14 +1,15 @@ package ScheduleCreator.models; -import java.util.Scanner; - /** * This class models information for course sections. * * @author Jamison Valentine * - * Last Updated: 3/31/2020 + * Last Updated: 4/19/2020 */ + +import java.util.Scanner; + public class Section { protected final String courseID; @@ -23,7 +24,8 @@ public class Section { protected final String sectionNumber; protected final Boolean isOnline; - public Section(String _courseID, String _sectionNumber, String _daysAndTimes, String _location, String _instructor, String _CRN, Boolean _isOnline) { + public Section(String _courseID, String _sectionNumber, String _daysAndTimes, + String _location, String _instructor, String _CRN, Boolean _isOnline) { this.courseID = _courseID; this.location = _location; this.instructor = _instructor; @@ -41,6 +43,10 @@ public class Section { return this.id; } + /** + * Return class time as a decimal (i.e. 1.5 hours) + * @return + */ public double getDurationHours() { double difference = this.endTime - this.startTime; double hours = (int) (difference / 100); @@ -94,14 +100,20 @@ public class Section { String string = ""; if (!this.isOnline) { - string = this.sectionNumber + " | " + this.daysAndTimes + " | " + this.location + " | " + this.instructor + " | " + this.CRN; + string = this.sectionNumber + " | " + this.daysAndTimes + " | " + + this.location + " | " + this.instructor + " | " + this.CRN; } else { - string = this.sectionNumber + " | Online | " + this.instructor + " | " + this.CRN; + string = this.sectionNumber + " | Online | " + this.instructor + " | " + + this.CRN; } return string; } //========================= SETTERS ============================= + + /** + * Extracts time from string with course meeting days and time information. + */ private void setTimes() { if (this.isOnline) { diff --git a/ScheduleCreator/resources/views/primary.fxml b/ScheduleCreator/resources/views/primary.fxml @@ -1,5 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> +<?import javafx.scene.effect.*?> +<?import javafx.geometry.*?> +<?import javafx.scene.*?> +<?import java.lang.*?> +<?import javafx.scene.control.*?> +<?import javafx.scene.image.*?> +<?import javafx.scene.layout.*?> +<?import javafx.scene.text.*?> <?import javafx.scene.control.Button?> <?import javafx.scene.control.ToggleButton?> <?import javafx.scene.image.Image?> @@ -8,26 +16,66 @@ <?import javafx.scene.text.Font?> <?import javafx.scene.text.Text?> -<AnchorPane id="AnchorPane" prefHeight="560" prefWidth="1090" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ScheduleCreator.controllers.PrimaryController"> - <children> - <Button layoutX="366.0" layoutY="256.0" onAction="#changeToSelectClasses" prefHeight="39.0" prefWidth="286.0" text="Schedule Generator"> - <font> - <Font size="18.0" /> - </font></Button> - <Button layoutX="366.0" layoutY="322.0" onAction="#changeToRegistrationScreen" prefHeight="39.0" prefWidth="286.0" text="My Registration Details"> - <font> - <Font size="18.0" /> - </font></Button> - <Text layoutX="349.0" layoutY="222.0" strokeType="OUTSIDE" strokeWidth="0.0" text="UNCG Schedule Creator" wrappingWidth="451.1748046875"> - <font> - <Font name="System Italic" size="37.0" /> - </font> - </Text> - <ImageView fitHeight="114.0" fitWidth="66.0" layoutX="696.0" layoutY="252.0" pickOnBounds="true" preserveRatio="true"> - <image> - <Image url="@../uncg_emblem_3-color-174x300.png" /> - </image> - </ImageView> - <ToggleButton fx:id="darkmode" layoutX="999.0" layoutY="525.0" mnemonicParsing="false" onAction="#toggleDarkMode" text="Dark Mode" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="10.0" /> - </children> -</AnchorPane> +<StackPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ScheduleCreator.controllers.PrimaryController"> + <children> + <GridPane fx:id="mainBox"> + <columnConstraints> + <ColumnConstraints hgrow="ALWAYS" maxWidth="63.0" minWidth="0.0" prefWidth="63.0" /> + <ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="-Infinity" /> + </columnConstraints> + <rowConstraints> + <RowConstraints minHeight="10.0" vgrow="SOMETIMES" /> + </rowConstraints> + <children> + <GridPane alignment="CENTER" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS" HBox.hgrow="NEVER"> + <columnConstraints> + <ColumnConstraints hgrow="ALWAYS" /> + <ColumnConstraints /> + </columnConstraints> + <rowConstraints> + <RowConstraints fillHeight="false" maxHeight="200.0" minHeight="0.0" prefHeight="60.0" vgrow="NEVER" /> + <RowConstraints minHeight="10.0" prefHeight="666.0" vgrow="SOMETIMES" /> + </rowConstraints> + <children> + <Text layoutX="186.0" layoutY="54.0" strokeType="OUTSIDE" strokeWidth="0.0" text="UNCG Schedule Creator" wrappingWidth="451.1748046875" GridPane.columnSpan="2" GridPane.halignment="CENTER" GridPane.valignment="CENTER"> + <font> + <Font name="System Italic" size="37.0" /> + </font> + </Text> + <VBox prefHeight="169.0" prefWidth="275.0" spacing="10.0" GridPane.rowIndex="1"> + <children> + <StackPane fx:id="mainContent" prefHeight="150.0" VBox.vgrow="ALWAYS" /> + + </children> + </VBox> + <ToggleButton fx:id="darkmode" mnemonicParsing="false" onAction="#toggleDarkMode" text="Dark Mode" GridPane.halignment="RIGHT" /> + </children> + </GridPane> + <VBox fx:id="menuBox" alignment="CENTER" fillWidth="false" layoutX="57.0" layoutY="39.0" maxWidth="200.0" minHeight="200.0" minWidth="0.0" prefHeight="727.0" prefWidth="34.0" spacing="10.0" style="-fx-background-color:rgb(6,42,87);" visible="false" SplitPane.resizableWithParent="false"> + <children> + <HBox fx:id="schedMenuItem" alignment="CENTER" onMouseClicked="#changeToSelectCourses" onMouseEntered="#hoverItem" onMouseExited="#unhoverItem" prefHeight="50.0" prefWidth="200.0" style="-fx-background-color: rgb(229,191,16); -fx-border-color: black;"> + <children> + <Label fx:id="schedMenuItemLabel" alignment="CENTER" contentDisplay="CENTER" text="Build Schedule" /> + </children> + </HBox> + <HBox fx:id="advMenuItem" alignment="CENTER" maxWidth="1.7976931348623157E308" onMouseEntered="#hoverItem" onMouseExited="#unhoverItem" style="-fx-background-color: rgb(229,191,16); -fx-border-color: black;"> + <children> + <Label fx:id="advMenuItemLabel" alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" prefHeight="50.0" prefWidth="200.0" text="Contact Advisor" /> + </children> + </HBox> + <HBox fx:id="regMenuItem" alignment="CENTER" onMouseClicked="#changeToRegistrationScreen" onMouseEntered="#hoverItem" onMouseExited="#unhoverItem" style="-fx-background-color: rgb(229,191,16); -fx-border-color: black;"> + <children> + <Label fx:id="regMenuItemLabel" alignment="CENTER" contentDisplay="CENTER" prefHeight="50.0" prefWidth="200.0" text="Registration" /> + </children> + </HBox> + </children> + </VBox> + </children> + </GridPane> + <ToggleButton fx:id="toggleMenu" mnemonicParsing="false" onAction="#toggleMenu" text="Menu" StackPane.alignment="TOP_LEFT"> + <StackPane.margin> + <Insets left="15.0" top="15.0" /> + </StackPane.margin> + </ToggleButton> + </children> +</StackPane> diff --git a/ScheduleCreator/resources/views/registration_screen.fxml b/ScheduleCreator/resources/views/registration_screen.fxml @@ -6,7 +6,6 @@ <AnchorPane id="AnchorPane" prefHeight="560" prefWidth="1090" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ScheduleCreator.controllers.RegistrationController"> <children> - <Button layoutY="1.0" onAction="#backToPrimary" prefHeight="27.0" prefWidth="163.0" text="Back To Main Screen" AnchorPane.leftAnchor="1.0" AnchorPane.topAnchor="1.0" /> <WebView fx:id="webview" layoutX="6.0" layoutY="30.0" prefHeight="500.0" prefWidth="1088.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="1.0" AnchorPane.rightAnchor="1.0" AnchorPane.topAnchor="30.0" /> <Button layoutX="14.0" layoutY="525.0" mnemonicParsing="false" onAction="#goBackWeb" prefHeight="27.0" prefWidth="318.0" text="Back" AnchorPane.bottomAnchor="1.0" AnchorPane.leftAnchor="1.0" /> <Button layoutX="594.0" layoutY="535.0" mnemonicParsing="false" onAction="#goForwardWeb" prefHeight="27.0" prefWidth="329.0" text="Forward" AnchorPane.bottomAnchor="1.0" AnchorPane.rightAnchor="1.0" />