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 5462490b23d0347037b73ae04d2edbc822feb800
parent c06d7f0f8831bc37488ffa882c9d02e8f1dd6961
Author: wrycode <wry@mm.st>
Date:   Mon, 20 Apr 2020 20:10:49 -0400

Nick/style (#67)

* Update PrimaryController to conform to style guide

* Update CoursesController to conform to style guide

fix bug

* Remove outdated semester test from Tests.java

* Clarify in Tests.java that EmailAPI works correctly
Diffstat:
MScheduleCreator/Tests.java | 78+++++++++++++++++++++---------------------------------------------------------
MScheduleCreator/controllers/CoursesController.java | 146++++++++++++++++++++++++++++++++++++++++----------------------------------------
MScheduleCreator/controllers/PrimaryController.java | 64++++++++++++++++++++++++++++++++++++++++++----------------------
MScheduleCreator/resources/views/primary.fxml | 25+++++++++++--------------
4 files changed, 147 insertions(+), 166 deletions(-)

diff --git a/ScheduleCreator/Tests.java b/ScheduleCreator/Tests.java @@ -19,11 +19,11 @@ public class Tests { public static void main(String[] args) throws IOException, MailjetException, MailjetSocketTimeoutException { - //regen databse - Admin.regenDB(); + // uncomment and run this once when we add a new semester + // Admin.regenDB(); //test validate method - //emailMethodTestData(); + emailMethodTestData(); } @@ -32,21 +32,21 @@ public class Tests { */ private static void emailMethodTestData() { //edge cases - emailValidationTest(" ", "FAIL"); - emailValidationTest("@", "FAIL"); - emailValidationTest(".com", "FAIL"); - emailValidationTest("@.com", "FAIL"); - emailValidationTest("@.com", "FAIL"); - emailValidationTest("!@#.gov", "FAIL"); - emailValidationTest("123!ABC@test.co", "FAIL"); - emailValidationTest("aBCdE@12AbC.edu", "PASS"); + emailValidationTest(" ", false); + emailValidationTest("@", false); + emailValidationTest(".com", false); + emailValidationTest("@.com", false); + emailValidationTest("@.com", false); + emailValidationTest("!@#.gov", false); + emailValidationTest("123!ABC@test.co", false); + emailValidationTest("aBCdE@12AbC.edu", true); //normal cases - emailValidationTest("test@test.edu", "PASS"); - emailValidationTest("test@test.gov", "PASS"); - emailValidationTest("123@123.co", "PASS"); - emailValidationTest("ABC@123.io", "PASS"); - emailValidationTest("123@ABC.net", "PASS"); - emailValidationTest("123@ABC.org", "PASS"); + emailValidationTest("test@test.edu", true); + emailValidationTest("test@test.gov", true); + emailValidationTest("123@123.co", true); + emailValidationTest("ABC@123.io", true); + emailValidationTest("123@ABC.net", true); + emailValidationTest("123@ABC.org", true); } @@ -58,48 +58,12 @@ public class Tests { * @param _expectedResults What the result should be. * @return */ - private static String emailValidationTest(String _email, String _expectedResults) { + private static void emailValidationTest(String _email, Boolean _expectedResults) { - if (ScheduleCreator.API.EmailAPI.validate(_email)) { - System.out.println("PASSED : \"" + _email + "\" Is a valid email. EXPECTED: " + _expectedResults); - } else { - System.out.println("FAILED : \"" + _email + "\" Is NOT a valid email. EXPECTED: " + _expectedResults); - } - return null; + String status = (ScheduleCreator.API.EmailAPI.validate(_email) == _expectedResults) ? "Test Passed:" + : "Test Failed:"; - } - - public static void testSemester() throws IOException { - - // Example usage of DBAdapter - List<String> semesters = new Translator().getSemesters(); - - System.out.println("Current Semesters are:"); - for (int i = 0; i < semesters.size(); i++) { - System.out.println(semesters.get(i)); - } - - // choose a semester - String semester = semesters.get(0); - - // get courses - List<String> courses = Tests.adapter.getCourses(semester); - - // example course from the semester - String exampleCourse = courses.get(20); - - System.out.println("Example course is: " + exampleCourse); - - // dummy method - we still need to implement this (I think?) - List<String> sections = new Translator().getSections(exampleCourse, semester); - String section = sections.get(0); - - //should return real info for CSC 250 - 01 - System.out.println("Building for " + section + " is: "); - System.out.println(new Translator().getSectionInfo(Translator.choice.BUILDING, semester, section)); - - System.out.println("CRN for " + section + " is: "); - System.out.println(new Translator().getSectionInfo(Translator.choice.CRN, semester, section)); + System.out.println(status + " value of EmailAPI.validate(\"" + _email + "\")" + "should be " + _expectedResults); } } diff --git a/ScheduleCreator/controllers/CoursesController.java b/ScheduleCreator/controllers/CoursesController.java @@ -22,7 +22,6 @@ import ScheduleCreator.models.Schedule; import ScheduleCreator.models.Section; import ScheduleCreator.models.Semester; import java.util.Arrays; -import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; @@ -34,8 +33,6 @@ 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; @@ -60,30 +57,23 @@ import javafx.stage.Stage; public class CoursesController implements Initializable { @FXML - protected ComboBox<String> semesterComboBox; + private ComboBox<String> semesterComboBox; @FXML - protected TextField searchField; + private TextField searchField; @FXML - protected ListView availableCourses; + private ListView availableCourses, selectedCoursesListView, sectionListView; @FXML - protected ListView selectedCoursesListView; + private Button courseButton, removeCourseButton; @FXML - protected ListView sectionListView; + private GridPane scheduleGridPane; @FXML - protected Button courseButton; + private Label scheduleLabel, onlineClassesLabel; @FXML - protected Button removeCourseButton; - - @FXML - protected GridPane scheduleGridPane; - @FXML - protected Label scheduleLabel, onlineClassesLabel; - @FXML - protected TabPane sectionTabPane; + private TabPane sectionTabPane; @FXML - protected VBox CRNContainer, CRNPane; + private VBox CRNContainer, CRNPane; @FXML - protected StackPane mainContent; + private StackPane mainContent; // the following buttons are only here for the buttonSetup() method @FXML @@ -94,17 +84,22 @@ public class CoursesController implements Initializable { private FilteredList<String> courseList; protected static Semester currentSemester; - protected Course focusedCourse; - protected Course currentCourse; - protected Adapter adapter = new Adapter(); + private Course focusedCourse; + private Course currentCourse; + private Adapter adapter = new Adapter(); - protected int NUM_ROWS; - protected int NUM_COLS; + private int NUM_ROWS; + private int NUM_COLS; protected static int currentScheduleIndex; - BorderPane[][] grid; - List<BorderPane> entries = new ArrayList(); + private BorderPane[][] grid; + private List<BorderPane> entries = new ArrayList(); + /** + * Set up the "Build Schedule" view and load the semesters. + * @param url + * @param rb + */ @Override public void initialize(URL url, ResourceBundle rb) { try { @@ -135,30 +130,6 @@ 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. @@ -179,6 +150,11 @@ public class CoursesController implements Initializable { } } + /** + * Called when "Submit" button is clicked; update the list of selected sections + * for generating schedules. + * @param _event + */ public void setSections(ActionEvent _event) { Course course; @@ -201,7 +177,7 @@ public class CoursesController implements Initializable { } /** - * Called when a different semester is chosen and loads appropriate info. + * Called when a different semester is chosen and loads semester and course list. * * @param _event */ @@ -212,7 +188,6 @@ public class CoursesController implements Initializable { this.loadAllCourses(); this.loadSelectedCourses(); - // loadSelectedSections(); // Renders the first generated schedule if there is at least 1 selected course. if (this.currentSemester.getSelectedCourses().size() > 0) { @@ -300,7 +275,6 @@ public class CoursesController implements Initializable { /** * Gets sections for a selected course and adds them to the sections * listview. - * * @param _event */ public void loadCourseSections(ActionEvent _event) { @@ -331,8 +305,7 @@ public class CoursesController implements Initializable { } /* - * Load list of courses into the availableCourses ListBox and connect a few - * things + * Load list of courses into the availableCourses ListBox */ public void loadAllCourses() { @@ -353,22 +326,6 @@ public class CoursesController implements Initializable { // ) searchField.textProperty().addListener(obs -> { - // select the top entry whenever the search term changes, but use - // Platform.runLater() - // so that JavaFX doesn't try to update the selection while it's still building - // the ListView. - // See - // https://stackoverflow.com/questions/11088612/javafx-select-item-in-listview - // for some context - Platform.runLater(new Runnable() { - @Override - public void run() { - // Note: we can't use "this" keyword here - availableCourses.getSelectionModel().select(0); - availableCourses.getFocusModel().focus(0); - } - }); - String filter = searchField.getText().toLowerCase(); // when there's nothing entered yet if (filter == null || filter.length() == 0) { @@ -382,6 +339,10 @@ public class CoursesController implements Initializable { }); } + /** + * Load list of semesters and show them in the dropdown menu + * @throws IOException + */ public void loadSemesters() throws IOException { List<String> semesters = this.adapter.getSemesters(); @@ -402,6 +363,9 @@ public class CoursesController implements Initializable { this.semesterComboBox.setItems(FXCollections.observableList(newList)); } + /** + * Refresh the tabbed section selection box + */ public void loadSelectedCourses() { this.sectionTabPane.getTabs().clear(); this.selectedCoursesListView.setItems(FXCollections.observableList(this.currentSemester.getSelectedCourseStrings())); @@ -463,7 +427,7 @@ public class CoursesController implements Initializable { } /** - * + * Returns true if all sections checkboxes are unchecked * @param _tab */ public boolean allUnselected(Tab _tab) { @@ -479,6 +443,11 @@ public class CoursesController implements Initializable { return true; } + /** + * Check all of the section checkboxes + * @param _option + * @param _tab + */ public void setSelectAll(boolean _option, Tab _tab) { VBox container = (VBox) ((ScrollPane) _tab.getContent()).getContent(); @@ -489,6 +458,9 @@ public class CoursesController implements Initializable { } } + /** + * Draw the week schedule grid. + */ public void drawGrid() { for (int i = 1; i < this.NUM_ROWS; i++) { @@ -501,6 +473,10 @@ public class CoursesController implements Initializable { } } + /** + * Show the current list of CRNs to the user when they click on the "Show CRNs" button + * @param _event + */ public void showCRNs(ActionEvent _event) { if (this.currentSemester == null) { return; @@ -520,10 +496,18 @@ public class CoursesController implements Initializable { this.CRNPane.toFront(); } + /** + * Hide the list of CRNs. + */ public void hideCRNs() { this.CRNPane.setVisible(false); } + /** + * Draw a colored box for a course in the week schedule. + * @param _section + * @param _numberOfCampusCourses + */ public void addEntry(Section _section, int _numberOfCampusCourses) { String color = this.assignColor(_numberOfCampusCourses); @@ -624,6 +608,11 @@ public class CoursesController implements Initializable { return color; } + /** + * Update the grid and other UI elements on the right side to reflect + * the currently selected sections. + * @param _schedule + */ public void loadSchedule(Schedule _schedule) { this.hideCRNs(); this.clearScheduleGrid(); @@ -645,6 +634,10 @@ public class CoursesController implements Initializable { this.onlineClassesLabel.setText(label.toString()); } + /** + * Load schedule for the next semester + * @param _event + */ public void loadNextSchedule(ActionEvent _event) { if (this.currentSemester != null) { if (this.currentScheduleIndex < this.currentSemester.getSchedules().size() - 1) { @@ -654,6 +647,10 @@ public class CoursesController implements Initializable { } } + /** + * Load schedule for the previous semester + * @param _event + */ public void loadPrevSchedule(ActionEvent _event) { if (this.currentScheduleIndex > 0) { this.currentScheduleIndex--; @@ -661,7 +658,10 @@ public class CoursesController implements Initializable { } } - //Calls popup fxml for the email api + /** + * Open the popup for when the user clicks "Email CRN" + * @param event + */ public void popupAction(ActionEvent event) { //if no courses are selected, and the email button is pressed then thier is nothing to email, an error box is thrown if (this.currentSemester == null || this.currentSemester.getSelectedCourses().size() == 0) { diff --git a/ScheduleCreator/controllers/PrimaryController.java b/ScheduleCreator/controllers/PrimaryController.java @@ -7,6 +7,7 @@ package ScheduleCreator.controllers; * * Last Updated: 4/19/2020 */ + import com.sun.javafx.css.StyleManager; import javafx.event.ActionEvent; import javafx.fxml.FXMLLoader; @@ -28,25 +29,25 @@ import javafx.scene.layout.VBox; public class PrimaryController implements Initializable { @FXML - private ToggleButton darkmode; + private ToggleButton darkMode; @FXML - protected StackPane mainContent; + private StackPane mainContent; @FXML - protected ToggleButton toggleMenu; + private ToggleButton toggleMenu; @FXML - protected VBox menuBox; + private VBox menuBox; @FXML - protected GridPane mainBox; + private GridPane mainBox; @FXML - protected HBox schedMenuItem, advMenuItem, regMenuItem, currentMenuItem; + private HBox schedMenuItem, advMenuItem, regMenuItem, currentMenuItem; @FXML - protected Label schedMenuItemLabel, advMenuItemLabel, regMenuItemLabel; - protected HashMap<HBox, Label> menuItems = new HashMap(); - protected boolean showMenu = false; + private Label schedMenuItemLabel, advMenuItemLabel, regMenuItemLabel; + private HashMap<HBox, Label> menuItems = new HashMap(); + private boolean showMenu = false; /** - * Set's the current view of the app to the course selection view. - * @throws Exception + * Sets the current view of the app to the course selection view. + * @throws Exception */ public void changeToSelectCourses() throws Exception { @@ -59,9 +60,9 @@ public class PrimaryController implements Initializable { /** * Sets the current menu item to the given argument. - * @param _menuItem + * @param _menuItem */ - public void setCurrentItem(HBox _menuItem) { + private void setCurrentItem(HBox _menuItem) { if (this.currentMenuItem != null) this.unhighlight(this.currentMenuItem); this.currentMenuItem = _menuItem; this.highlight(this.currentMenuItem); @@ -69,25 +70,25 @@ public class PrimaryController implements Initializable { /** * Changes the appropriate text color to white to indicate current focus. - * @param _menuItem + * @param _menuItem */ - public void highlight(HBox _menuItem) { + private void highlight(HBox _menuItem) { Label label = this.menuItems.get(_menuItem); label.setStyle("-fx-text-fill: white"); } /** * Undoes highlighting of previously focused item. - * @param _menuItem + * @param _menuItem */ - public void unhighlight(HBox _menuItem) { + private void unhighlight(HBox _menuItem) { Label label = this.menuItems.get(_menuItem); label.setStyle("-fx-text-fill:black"); } /** * Changes application view to registration - * @throws Exception + * @throws Exception */ public void changeToRegistrationScreen() throws Exception { Parent root = FXMLLoader.load(getClass().getResource("/ScheduleCreator/resources/views/registration_screen.fxml")); @@ -96,19 +97,31 @@ public class PrimaryController implements Initializable { this.setCurrentItem(this.regMenuItem); } + /** + * Highlight menu item when user mouses over it + * @param _event + */ public void hoverItem(MouseEvent _event) { HBox item = (HBox) _event.getSource(); this.highlight(item); } + /** + * Unhighlight menu item when user mouses over it + * @param _event + */ public void unhoverItem(MouseEvent _event) { HBox item = (HBox) _event.getSource(); if (item != this.currentMenuItem) this.unhighlight(item); } + /** + * Toggle visibility of menu with the toggleMenu ToggleButton + * @param _event + */ @FXML - public void toggleMenu(ActionEvent _event) { + private void toggleMenu(ActionEvent _event) { if (!this.showMenu) { this.mainBox.getColumnConstraints().get(0).setMaxWidth(200); this.menuBox.setVisible(true); @@ -120,10 +133,12 @@ public class PrimaryController implements Initializable { } } - //toggle and untoggle darkmode css to defult theme from button + /** + * Toggle darkMode css with the toggleDarkMode ToggleButton + */ @FXML - public void toggleDarkMode(ActionEvent event) { - if (darkmode.isSelected()) { + private void toggleDarkMode(ActionEvent event) { + if (darkMode.isSelected()) { Application.setUserAgentStylesheet(Application.STYLESHEET_MODENA); StyleManager.getInstance().addUserAgentStylesheet("ScheduleCreator/resources/Darkmode.css"); } else { @@ -132,6 +147,11 @@ public class PrimaryController implements Initializable { } } + /** + * Set up the primary view with the menu and the "Build Schedule" window visible by default + * @param url + * @param rb + */ @Override public void initialize(URL url, ResourceBundle rb) { try { diff --git a/ScheduleCreator/resources/views/primary.fxml b/ScheduleCreator/resources/views/primary.fxml @@ -1,22 +1,19 @@ <?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.geometry.Insets?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.SplitPane?> <?import javafx.scene.control.ToggleButton?> -<?import javafx.scene.image.Image?> -<?import javafx.scene.image.ImageView?> -<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.ColumnConstraints?> +<?import javafx.scene.layout.GridPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.RowConstraints?> +<?import javafx.scene.layout.StackPane?> +<?import javafx.scene.layout.VBox?> <?import javafx.scene.text.Font?> <?import javafx.scene.text.Text?> -<StackPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ScheduleCreator.controllers.PrimaryController"> +<StackPane xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ScheduleCreator.controllers.PrimaryController"> <children> <GridPane fx:id="mainBox"> <columnConstraints> @@ -48,7 +45,7 @@ </children> </VBox> - <ToggleButton fx:id="darkmode" mnemonicParsing="false" onAction="#toggleDarkMode" text="Dark Mode" GridPane.halignment="RIGHT" /> + <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">