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 c06d7f0f8831bc37488ffa882c9d02e8f1dd6961
parent 7ef91cfb001edf07f26eb0b743935188476b9f7d
Author: wrycode <wry@mm.st>
Date:   Mon, 20 Apr 2020 17:57:42 -0400

Make most of the UI keyboard-navigable (#66)


Diffstat:
MScheduleCreator/controllers/CoursesController.java | 46++++++++++++++++++++++++++--------------------
MScheduleCreator/resources/views/select_courses.fxml | 20++++++++++----------
2 files changed, 36 insertions(+), 30 deletions(-)

diff --git a/ScheduleCreator/controllers/CoursesController.java b/ScheduleCreator/controllers/CoursesController.java @@ -21,6 +21,7 @@ import ScheduleCreator.models.Course; 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; @@ -48,7 +49,6 @@ import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.control.TextArea; import javafx.scene.control.TextField; -import javafx.scene.input.KeyEvent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.Priority; @@ -62,6 +62,8 @@ public class CoursesController implements Initializable { @FXML protected ComboBox<String> semesterComboBox; @FXML + protected TextField searchField; + @FXML protected ListView availableCourses; @FXML protected ListView selectedCoursesListView; @@ -71,8 +73,7 @@ public class CoursesController implements Initializable { protected Button courseButton; @FXML protected Button removeCourseButton; - @FXML - protected TextField searchField; + @FXML protected GridPane scheduleGridPane; @FXML @@ -84,8 +85,13 @@ public class CoursesController implements Initializable { @FXML protected StackPane mainContent; + // the following buttons are only here for the buttonSetup() method + @FXML + private Button addCourseButton, removeAllCoursesButton, selectAllButton, + previousButton, nextButton, showCRNButton, emailCRNButton, sectionsButton; + // List of courses for current semester. - FilteredList<String> courseList; + private FilteredList<String> courseList; protected static Semester currentSemester; protected Course focusedCourse; @@ -108,18 +114,33 @@ public class CoursesController implements Initializable { this.grid = new BorderPane[NUM_ROWS][NUM_COLS]; this.drawGrid(); this.CRNPane.toFront(); + + // final tweaks to make buttons keyboard-navigable + this.buttonSetup(); + } catch (Exception ex) { Logger.getLogger(CoursesController.class.getName()).log(Level.SEVERE, null, ex); } } + /** + * Run the action for each button if it's selected and the user types "Enter" + */ + private void buttonSetup() { + Arrays.asList(addCourseButton, removeCourseButton, removeAllCoursesButton, selectAllButton, + sectionsButton, previousButton, nextButton, showCRNButton, emailCRNButton).forEach((button) -> { + // temporarily set the button as the default button (only while the button is in focus) + // https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Button.html#defaultButtonProperty + button.defaultButtonProperty().bind(button.focusedProperty()); + }); + } 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(); @@ -227,7 +248,6 @@ public class CoursesController implements Initializable { * * @param _event */ - // TODO: connect "delete" while in the selectedCourses ListView to this method public void removeSelectedCourse(ActionEvent _event) { if (this.selectedCoursesListView.getSelectionModel().getSelectedItem() != null) { @@ -325,20 +345,6 @@ public class CoursesController implements Initializable { // connect availableCourses ListView to the courseList this.availableCourses.setItems(this.courseList); - // make up or down arrow on the keyboard begin to scroll the search results - this.searchField.setOnKeyReleased(new javafx.event.EventHandler<KeyEvent>() { - @Override - public void handle(KeyEvent event) { - switch (event.getCode()) { - case UP: - case DOWN: - availableCourses.requestFocus(); - default: - break; - } - } - }); - // Connect search bar filtering to the courseList FilteredList (this uses // lambdas, it's adapted from // https://stackoverflow.com/questions/28448851/how-to-use-javafx-filteredlist-in-a-listview diff --git a/ScheduleCreator/resources/views/select_courses.fxml b/ScheduleCreator/resources/views/select_courses.fxml @@ -31,20 +31,20 @@ <children> <GridPane hgap="10.0" maxHeight="1.7976931348623157E308" vgap="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" GridPane.columnIndex="1"> <children> - <TextField fx:id="searchField" onAction="#addSelectedCourse" prefHeight="25.0" prefWidth="262.0" promptText="Search" GridPane.columnSpan="2" GridPane.rowIndex="1" /> <ComboBox fx:id="semesterComboBox" onAction="#switchSemester" prefHeight="26.0" prefWidth="692.0" promptText="Choose Semester" GridPane.columnSpan="2" GridPane.hgrow="ALWAYS" /> + <TextField fx:id="searchField" onAction="#addSelectedCourse" prefHeight="25.0" prefWidth="262.0" promptText="Search" GridPane.columnSpan="2" GridPane.rowIndex="1" /> + <ListView fx:id="availableCourses" prefHeight="184.0" prefWidth="271.0" GridPane.columnSpan="2" GridPane.rowIndex="2" /> + <Button fx:id="addCourseButton" mnemonicParsing="false" onAction="#addSelectedCourse" prefHeight="26.0" prefWidth="635.0" text="Add Course" GridPane.columnSpan="2" GridPane.rowIndex="3" /> <ListView fx:id="selectedCoursesListView" maxHeight="1.7976931348623157E308" prefHeight="114.0" prefWidth="454.0" GridPane.columnSpan="2" GridPane.rowIndex="4" /> - <Button maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#removeSelectedCourse" prefHeight="72.0" prefWidth="172.0" text="Remove" GridPane.hgrow="NEVER" GridPane.rowIndex="5" GridPane.vgrow="NEVER" /> - <Button mnemonicParsing="false" onAction="#selectAll" prefHeight="79.0" prefWidth="517.0" text="Select/Deselect All" GridPane.hgrow="NEVER" GridPane.rowIndex="7" GridPane.vgrow="NEVER" /> + <Button fx:id="removeCourseButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#removeSelectedCourse" prefHeight="72.0" prefWidth="172.0" text="Remove" GridPane.hgrow="NEVER" GridPane.rowIndex="5" GridPane.vgrow="NEVER" /> + <Button fx:id="removeAllCoursesButton" mnemonicParsing="false" onAction="#removeAllCourses" prefHeight="26.0" prefWidth="421.0" text="Remove All" GridPane.columnIndex="1" GridPane.rowIndex="5" /> + <Button fx:id="selectAllButton" mnemonicParsing="false" onAction="#selectAll" prefHeight="79.0" prefWidth="517.0" text="Select/Deselect All" GridPane.hgrow="NEVER" GridPane.rowIndex="7" GridPane.vgrow="NEVER" /> <Button fx:id="sectionsButton" mnemonicParsing="false" onAction="#setSections" prefHeight="43.0" prefWidth="248.0" text="Submit" GridPane.columnIndex="1" GridPane.hgrow="NEVER" GridPane.rowIndex="7" GridPane.vgrow="NEVER" /> - <ListView fx:id="availableCourses" prefHeight="184.0" prefWidth="271.0" GridPane.columnSpan="2" GridPane.rowIndex="2" /> - <Button mnemonicParsing="false" onAction="#addSelectedCourse" prefHeight="26.0" prefWidth="635.0" text="Add Course" GridPane.columnSpan="2" GridPane.rowIndex="3" /> <TabPane fx:id="sectionTabPane" prefHeight="200.0" prefWidth="200.0" style="-fx-border-color: grey;" tabClosingPolicy="UNAVAILABLE" GridPane.columnSpan="2" GridPane.rowIndex="6"> <tabs> </tabs> </TabPane> - <Button mnemonicParsing="false" onAction="#removeAllCourses" prefHeight="26.0" prefWidth="421.0" text="Remove All" GridPane.columnIndex="1" GridPane.rowIndex="5" /> </children> <columnConstraints> <ColumnConstraints hgrow="SOMETIMES" maxWidth="469.0" minWidth="10.0" prefWidth="289.0" /> @@ -128,7 +128,7 @@ <children> <BorderPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1"> <center> - <Button mnemonicParsing="false" onAction="#loadPrevSchedule" text="Previous" BorderPane.alignment="CENTER" /> + <Button fx:id="previousButton" mnemonicParsing="false" onAction="#loadPrevSchedule" text="Previous" BorderPane.alignment="CENTER" /> </center> <padding> <Insets left="100.0" /> @@ -136,7 +136,7 @@ </BorderPane> <BorderPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="1"> <center> - <Button mnemonicParsing="false" onAction="#loadNextSchedule" text=" Next " BorderPane.alignment="CENTER"> + <Button fx:id="nextButton" mnemonicParsing="false" onAction="#loadNextSchedule" text=" Next " BorderPane.alignment="CENTER"> <BorderPane.margin> <Insets right="100.0" /> </BorderPane.margin> @@ -160,8 +160,8 @@ <RowConstraints maxHeight="27.33331298828125" minHeight="10.0" prefHeight="27.33331298828125" vgrow="SOMETIMES" /> </rowConstraints> </GridPane> - <Button mnemonicParsing="false" onAction="#showCRNs" text="Show CRNs" translateX="-50.0" GridPane.columnSpan="2" GridPane.halignment="CENTER" GridPane.rowIndex="2" /> - <Button mnemonicParsing="false" onAction="#popupAction" prefHeight="27.0" prefWidth="97.0" text="Email CRNs" GridPane.columnIndex="1" GridPane.rowIndex="2" /> + <Button fx:id="showCRNButton" mnemonicParsing="false" onAction="#showCRNs" text="Show CRNs" translateX="-50.0" GridPane.columnSpan="2" GridPane.halignment="CENTER" GridPane.rowIndex="2" /> + <Button fx:id="emailCRNButton" mnemonicParsing="false" onAction="#popupAction" prefHeight="27.0" prefWidth="97.0" text="Email CRNs" GridPane.columnIndex="1" GridPane.rowIndex="2" /> </children> <columnConstraints> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />