/**UserWindow Class*/
import javax.swing.*; import java.awt.*; import java.awt.event.*;
/** * Creates the graphical user interface for the program FindADate. * * DO NOT MODIFY THIS CODE. Feel free to read through it if you'd like. I'd be happy to * discuss it with anyone via email or the message board. * * @author CSC 142 */ public class UserWindow {
private FindADate owner; // private JTextField startDay, startMonth, startYear; private JSpinner startDay, startMonth, startYear; private JButton timeTravel; private JLabel displayArea;
private static final String[] MONTHS = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
/** * Construct a new user interface for the FindADate program. * @param source object that starts the program and responds to user input. */
public UserWindow(FindADate source ) { owner = source; createAndShowGUI( ); }
/** * Replace existing data in the display area with the String value * provided. * @param text the text to be shown */ public void displayText( String text ) { displayArea.setText( text ); }
/** * Display an error pop-up window with the given text * @param text the text to be displayed in the error window */ public void displayErrorWindow(String text) { JOptionPane.showMessageDialog(null, text, "Invalid Input", JOptionPane.ERROR_MESSAGE); }
/** * Returns the day selected by the user. * @return the value from the day spinner */ public int getDayInput( ) { return ((Integer)startDay.getValue()).intValue(); }
/** * Returns the name of the month selected by the user * @return the value from the month spinner */ public String getMonthInput( ) { return ((String)startMonth.getValue()); }
/** * Returns the year selected by the user. * @return the value from the year spinner */ public int getYearInput( ) { return ((Integer)startYear.getValue()).intValue(); }
private void createAndShowGUI( ) { // create and show entire display JFrame win = new JFrame( ); win.setSize(400, 300); JPanel mainPanel = createMainPanel( ); win.add( mainPanel, BorderLayout.CENTER );
win.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); win.setTitle( "Find Me a Date!" ); win. validate( ); win.setVisible( true ); win.toFront(); }
private JPanel createMainPanel( ) { Dimension d = new Dimension(80, 20); // for the JLabels to line up Dimension d2 = new Dimension(100,20); Color c = new Color(153, 255, 153); //a pale green Color back = Color.blue;
// 3 JSpinners for input startDay = new JSpinner(new SpinnerNumberModel(1, 1, 31, 1)); SpinnerListModel m = new SpinnerListModel(MONTHS); startMonth = new JSpinner(m);
// make it wider //Tweak the spinner's formatted text field. JFormattedTextField ftf = getTextField(startMonth); if (ftf != null ) { ftf.setColumns(6); //specify more width than we need ftf.setHorizontalAlignment(JTextField.CENTER); }
startYear = new JSpinner(new SpinnerNumberModel(2000, 1950, 2050, 1)); //Make the year be formatted without a thousands separator. startYear.setEditor(new JSpinner.NumberEditor(startYear, "#"));
// 3 labels JLabel dayLabel = new JLabel( " Day " ); dayLabel.setHorizontalAlignment(SwingConstants.CENTER); dayLabel.setPreferredSize(d); dayLabel.setOpaque(true); dayLabel.setBackground(c);
JLabel monthLabel = new JLabel("Month"); monthLabel.setHorizontalAlignment(SwingConstants.CENTER); monthLabel.setPreferredSize(d); monthLabel.setOpaque(true); monthLabel.setBackground(c);
JLabel yearLabel = new JLabel("Year"); yearLabel.setHorizontalAlignment(SwingConstants.CENTER); yearLabel.setPreferredSize(d); yearLabel.setOpaque(true); yearLabel.setBackground(c);
// bundle label/spinners JPanel dayPanel = new JPanel( ); dayPanel.add( dayLabel ); dayPanel.add( startDay); dayPanel.setBackground(back);
JPanel monthPanel = new JPanel( ); monthPanel.add( monthLabel ); monthPanel.add( startMonth); monthPanel.setBackground(back);
JPanel yearPanel = new JPanel( ); yearPanel.add( yearLabel ); yearPanel.add( startYear); yearPanel.setBackground(back);
// create display label and area JButton result = new JButton("Date in 30 days" ); result.addActionListener(new GoListener()); displayArea = new JLabel(); displayArea.setOpaque(true); displayArea.setBackground(Color.white); displayArea.setPreferredSize(d2);
//bundle these 2 up JPanel bottomPanel = new JPanel(); bottomPanel.add(result); bottomPanel.add(displayArea); bottomPanel.setBackground(back);
// bundle both input area and display area JPanel controlPanel = new JPanel(); controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS)); controlPanel.add(monthPanel); controlPanel.add(dayPanel); controlPanel.add(yearPanel); controlPanel.add(bottomPanel); controlPanel.setBackground(back);
return controlPanel; }
/** * Return the formatted text field used by the editor, or * null if the editor doesn't descend from JSpinner.DefaultEditor. */ private JFormattedTextField getTextField(JSpinner spinner) { JComponent editor = spinner.getEditor(); if (editor instanceof JSpinner.DefaultEditor) { return ((JSpinner.DefaultEditor)editor).getTextField(); } else { System.err.println("Unexpected editor type: " + spinner.getEditor().getClass() + " isn't a descendant of DefaultEditor"); return null; } }
/* For those brave students who venture down here... * There classes are MEMBERS of the UserWindow class, that's why the keyword private * There are advantages to a design like this that I'd be happy to discuss */ private class GoListener implements ActionListener { /* Responds to user hitting the enter key from the JTextFields * Need to validate user input that they are ints. If so * send control to owner.takeAction() who will test for valid date * Otherwise, pop up error window */ public void actionPerformed(ActionEvent e) { owner.respondToUser(); // callback to client
} }
}
/**FindADate class*/
/** * Top-level client -- controls the application. This GUI program prompts * the user for a date and then determines the date * 30 days in the future. * * This is the file you need to modify to complete the assignment. The majority * of your work will be in the method respondToUser(), though you may decide * to add code in other places as well * * To start the program, call the main() method. * * @author CSC 142 */ public class FindADate { private UserWindow window;
/** * Create a new FindADate object */ public FindADate( ) { window = new UserWindow(this); } /** * Perform the task of determining 30 days from the given day. */ public void respondToUser() { System.out.println("You've downloaded and compiled correctly"); } // NO NEED TO CHANGE ANY CODE BELOW THIS LINE. /** * Allows this application to be run as a stand-alone program, and * also starts it up in a 'thread-safe" way. */ public static void main( String[] args ) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { FindADate pa = new FindADate( ); } }); } }
This assignment has 2 parts. In part 1, you'll implement a class to a given specification. In part 2, you'll modify starter code to complete a stand-alone program using the class you wrote in part 1. In both classes, you are limited to the topics covered so far this quarter: chapters 1 - 5, & chapter 8. Part 1 You are going to write a class named Date to the following specification: class Date
day month year /* Class invariants: The year must be 1600 or later The day must be legal for the month The day and month must be legal for the year For example, if the month is June, the day should never be 31. If the month is February, the day can only be 29 if it is a leap year. All methods that affect the state of a Date object must ensure this. */ + void setDay( int day) -- update the day of this Date. If the parameter value is invalid for the rest of the state, throw an IllegalArgumentException that contains an error string specific to the issue. void setMonth mth) -- update the month of this te. If parameter value invalid for the rest the state, throw an IllegalArgumentException contains a an error string specific to issue. + void setYear( int yr) -- update the year of this Date. If the parameter value is invalid, throw an illegalArgumentException that contains an error string specific to the issue. Determining a leap year A year is a leap year if it is divisible by 4, except if it is divisible by 100. If a year is divisible by 100, then it must be divisible by 400 to be a leap year. For example, the following are leap years: 1976, 1600, and 2000. 1982 and 1900 are not leap years. There are a number of tasks in the Date class that you'll find yourself repeating in different places. This is a perfect place for decomposition. Part 2 To complete the program, you first need to download the starter code. This code creates a graphical user interface (GUI) that allows the user to interact with the program. To start the program, compile the given files, then choose the main() method from the FindADate class. You should see a window open with some text, 3 areas for input, and a button at the bottom (Date in 30 days). Click the button and it should display a message to System.out. If you've gotten this far then you know that the starter code works. Blue J Virtual Machine Find Me a Date! Month January Blue: Terminal Window - FindADateStar You've downloaded and compiled correctly Day 1 Year 20000 Date in 30 days Your task is to modify the FindADate class so that it gets the input and displays the correct result to the GUI window. The class that controls the GUI window is the UserWindow class; FindADate class will be a client of the UserWindow class. I recommend opening UserWindow to the documentation view in Blue). FindADate is also a client of your Date class so make sure you've tested it well. Though the user interface restricts user input somewhat, there is still the chance that the input is invalid. Make sure your client code calls isLegal() before trying to construct or update a Date object. We don't know yet how to "recover" in client code from a thrown exception. If FindADate determines that the input is invalid, have it display an error message to the user, using the error window method in User Window. Finally, don't be surprised if there are methods in Date that this client program doesn't use. That's ok, but those methods should still work. Your supplier class may be used in a different application that will need those methods, so test your class definition thoroughly. Documentation & Style From this homework forward, you must use Javadoc comments for each class description and before each method definition. Use the author, @param, @return, and @throws tags as appropriate. Refer to week 4's additional reading as well as the Documentation and Style Guidelines under Course Resources in Canvas. Include internal comments of your algorithms in both the Date class and the FindADate class. Use class constants as appropriate. Since you will be modifying FindADate, make sure to include your name with the author tag. Something like @author CSC 142, modified by Jane Doe. Document 2 test cases for the daysFromDate() method. Include these as comments in your class file. These can be as simple as listing the state of the starting date, the argument for the call, and the state of the returned Date. Suggestions You must build the Date class first in order to complete part 2, so start there. As in the past, implement and test each method one at a time to prevent going too far down a wrong path. Make sure to have a good sense of your algorithm design before starting to code. Use either pseudocode or flowcharts or any way you like to get your logic on paper. You can't build a bridge without plans! As mentioned above, you'll need to test your Date class thoroughly. I encourage you to include a static test method in that class. This way, you write your test code once, and then call it as often as you'd like. This is more efficient than repeatedly using Blue J's object bench. This assignment has 2 parts. In part 1, you'll implement a class to a given specification. In part 2, you'll modify starter code to complete a stand-alone program using the class you wrote in part 1. In both classes, you are limited to the topics covered so far this quarter: chapters 1 - 5, & chapter 8. Part 1 You are going to write a class named Date to the following specification: class Date day month year /* Class invariants: The year must be 1600 or later The day must be legal for the month The day and month must be legal for the year For example, if the month is June, the day should never be 31. If the month is February, the day can only be 29 if it is a leap year. All methods that affect the state of a Date object must ensure this. */ + void setDay( int day) -- update the day of this Date. If the parameter value is invalid for the rest of the state, throw an IllegalArgumentException that contains an error string specific to the issue. void setMonth mth) -- update the month of this te. If parameter value invalid for the rest the state, throw an IllegalArgumentException contains a an error string specific to issue. + void setYear( int yr) -- update the year of this Date. If the parameter value is invalid, throw an illegalArgumentException that contains an error string specific to the issue. Determining a leap year A year is a leap year if it is divisible by 4, except if it is divisible by 100. If a year is divisible by 100, then it must be divisible by 400 to be a leap year. For example, the following are leap years: 1976, 1600, and 2000. 1982 and 1900 are not leap years. There are a number of tasks in the Date class that you'll find yourself repeating in different places. This is a perfect place for decomposition. Part 2 To complete the program, you first need to download the starter code. This code creates a graphical user interface (GUI) that allows the user to interact with the program. To start the program, compile the given files, then choose the main() method from the FindADate class. You should see a window open with some text, 3 areas for input, and a button at the bottom (Date in 30 days). Click the button and it should display a message to System.out. If you've gotten this far then you know that the starter code works. Blue J Virtual Machine Find Me a Date! Month January Blue: Terminal Window - FindADateStar You've downloaded and compiled correctly Day 1 Year 20000 Date in 30 days Your task is to modify the FindADate class so that it gets the input and displays the correct result to the GUI window. The class that controls the GUI window is the UserWindow class; FindADate class will be a client of the UserWindow class. I recommend opening UserWindow to the documentation view in Blue). FindADate is also a client of your Date class so make sure you've tested it well. Though the user interface restricts user input somewhat, there is still the chance that the input is invalid. Make sure your client code calls isLegal() before trying to construct or update a Date object. We don't know yet how to "recover" in client code from a thrown exception. If FindADate determines that the input is invalid, have it display an error message to the user, using the error window method in User Window. Finally, don't be surprised if there are methods in Date that this client program doesn't use. That's ok, but those methods should still work. Your supplier class may be used in a different application that will need those methods, so test your class definition thoroughly. Documentation & Style From this homework forward, you must use Javadoc comments for each class description and before each method definition. Use the author, @param, @return, and @throws tags as appropriate. Refer to week 4's additional reading as well as the Documentation and Style Guidelines under Course Resources in Canvas. Include internal comments of your algorithms in both the Date class and the FindADate class. Use class constants as appropriate. Since you will be modifying FindADate, make sure to include your name with the author tag. Something like @author CSC 142, modified by Jane Doe. Document 2 test cases for the daysFromDate() method. Include these as comments in your class file. These can be as simple as listing the state of the starting date, the argument for the call, and the state of the returned Date. Suggestions You must build the Date class first in order to complete part 2, so start there. As in the past, implement and test each method one at a time to prevent going too far down a wrong path. Make sure to have a good sense of your algorithm design before starting to code. Use either pseudocode or flowcharts or any way you like to get your logic on paper. You can't build a bridge without plans! As mentioned above, you'll need to test your Date class thoroughly. I encourage you to include a static test method in that class. This way, you write your test code once, and then call it as often as you'd like. This is more efficient than repeatedly using Blue J's object bench