The Controller Class

Next, we’ll take a closer look at DateCalculatorUI, which is the UI Controller class as identified in the DateCalculatorUI.fxml file.  This object contains data and methods to accomplish the following:

  • Initialize all data fields, including populating the ChoiceBox items (month, day, hour, minute and second).
  • Set event handlers for actionable controls (buttons, primarily, although I defined the Year fields as Actionable so that up and down arrows decrement and increment the year value).
  • Set handlers for menu selections (the File menu).
  • Set the date field(s) to the current date/time if the “Use Current Date/Time” CheckBox is checked.
  • Reset all date fields to blank or a default value when the Reset button is selected.
  • Validate input data (there is code to set the maximum day from its default value of 31 based on the selected month, for example).
  • Call a dialog window if the User chooses to Load an Event from the Data Store, or if the User chooses to save the Start Date or Finish Date as an Event.
  • Call a dialog window if the User elects to display the Help file.
  • Populate all the output fields with the result of the calculation.

I’ll consider only some key JavaFX concepts in this class; most of it is straightforward Java code.  Let’s consider the global declarations and required initialize() method first:

package datecalculator;
 
import com.sun.glass.ui.Application;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Separator;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import dcops.CalendarOps;
import dcops.CutoverOps;
import dcops.EventListManager;
import dcops.EventCalendar;
  
/**
 * The DateCalculatorUI is the main user interface (UI) class for 
 * the Date Difference Calculator. The essential UI components and layout are
 * defined in the corresponding FXML file DateCalculatorUI.fxml. This class
 * identifies all UI elements (referenced or not), initializes all element data, 
 * and handles all user interactions.
 *
 * @author Philip Nau
 */
public class DateCalculatorUI extends Stage implements Initializable {
    /**
     * URL of the main application in the context of the deployment hierarchy.
     */
    private URL appURL;
    private ResourceBundle appRB;
 
    private Stage applicationStage;
   
    private EventListManager eventListManager = null;
   
    private String eventFileNotFound = "Event Calendar File could not be read, or is corrupt.";
    private String helpFileNotFound = "Help File could not be read, or is corrupt.";
       
    // All items in the DateCalculatorUI FXML file are referenced here.
    // The top-level AnchorPane is the Controller for this Stage.
    @FXML private AnchorPane dateCalcPane;
 
    @FXML private  TitledPane startDTPane;
    @FXML private  Label startDTLabel;
    @FXML private  ChoiceBox startMonthSelect;
    @FXML private  ChoiceBox startDaySelect;
    @FXML private  ChoiceBox startHourSelect;
    @FXML private  ConstrainedNumericTextField startYearSelect;
    @FXML private  ChoiceBox startMinuteSelect;
    @FXML private  ChoiceBox startSecondSelect;
    @FXML private  ChoiceBox startZoneSelect;
    @FXML private  CheckBox startUseCurrentDT;
    @FXML private  Label startEventLabel;
    @FXML private  TextField startEventField;
    @FXML private  TitledPane finishDTPane;
    @FXML private  Label finishDTLabel;
    @FXML private  ChoiceBox finishMonthSelect;
    @FXML private  ChoiceBox finishDaySelect;
    @FXML private  ConstrainedNumericTextField finishYearSelect;
    @FXML private  ChoiceBox finishHourSelect;
    @FXML private  ChoiceBox finishMinuteSelect;
    @FXML private  ChoiceBox finishSecondSelect;
    @FXML private  ChoiceBox finishZoneSelect;
    @FXML private  CheckBox finishUseCurrentDT;
    @FXML private  Label finishEventLabel;
    @FXML private  TextField finishEventField;
    @FXML private  Button calculateButton;
    @FXML private  Button resetButton;
    @FXML private  Button closeButton;
    @FXML private  Separator resultPanelSeparator;
    @FXML private  AnchorPane resultPane;
    @FXML private  Label fromLabel;
    @FXML private  TextField fromField;
    @FXML private  Label toLabel;
    @FXML private  TextField toField;
    @FXML private  Label resultPanel;
    @FXML private  Label totalTimeLabel;
    @FXML private  Label yearsLabel;
    @FXML private  Label monthsLabel;
    @FXML private  Label weeksLabel;
    @FXML private  Label daysLabel;
    @FXML private  Label hoursLabel;
    @FXML private  Label minutesLabel;
    @FXML private  Label secondsLabel;
    @FXML private  TextField totalTimeField;
    @FXML private  TextField yearsField;
    @FXML private  TextField monthsField;
    @FXML private  TextField weeksField;
    @FXML private  TextField daysField;
    @FXML private  TextField hoursField;
    @FXML private  TextField minutesField;
    @FXML private  TextField secondsField;
    @FXML private  Label statusLabel;
    @FXML private  TextField statusField;
    @FXML private  MenuBar calcMenuBar;
    @FXML private  Menu fileMenu;
    @FXML private  MenuItem saveStart;
    @FXML private  MenuItem saveFinish;
    @FXML private  SeparatorMenuItem saveSeparator;
    @FXML private  MenuItem loadStart;
    @FXML private  MenuItem loadFinish;
    @FXML private  SeparatorMenuItem loadSeparator;
    @FXML private  MenuItem exitApp;
    @FXML private  Menu optionsMenu;
    @FXML private  Menu helpMenu;
    @FXML private  MenuItem helpInfo;
    @FXML private  MenuItem aboutInfo;
    @FXML private  MenuItem toDoInfo;
   
    /**
     * UI entry point.  Calls local methods to perform UI initialization.
     *
     * @param url Uniform Resource Locator of Resource Bundle.
     * @param rb  TODO: DateCalculatorUI text needs to go in a resource bundle.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        appURL = url;
        appRB = rb;
       
        initializeFields();   
        setButtonActions();
        setNavigationAids();
        setMenuSelectionActions();
        initYearFields();
    }

   

Listing 4 – DateCalculatorUI Class declarations

Note that the class extends Stage and implements the Initializable interface.  The interface requires only one method, initialize(), which establishes the URL of the application root path and the Resource Bundle that provides language-specific text.  At this point in development, I haven’t implemented the Resource Bundle capability; all text is in English, although adding the RB would be a straightforward implementation.  I call other  private initialization methods here as well.

Also I reference every field in the FXML file with an explicit @FXML - this tag identifies Controller member fields and handler methods for use by FXML markup (of course it’s only necessary to reference elements that are actually used in the code).