package caltool.view.schedule; import caltool.model.schedule.*; import caltool.view.*; import mvp.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; /**** * * Class ScheduleAppointmentDialog provides a view of Appointment as an input * to the scheduleAppointment method. Hence, the dialog is a view of both an * Appointment object as well as the scheduleAppointment method. The * data-entry components of the dialog constitute the Appointment view. The * 'OK' button is the view of the ScheduleAppointment method. *
* The data components consist of JLabels, JTextFields, JComboBoxes, * JCheckBoxes, and a JTextArea. The 'OK', 'Clear', and 'Cancel' buttons are * JButtons. The description of the compose method * has details of how the components are laid out in the dialog window. *
* For organizational clarity, two of the rows in the ScheduleAppointment * Dialog are defined in separate classes. These are the RecurringInfoSubdialog and RemindInfoSubdialog classes. *
* The companion model for ScheduleAppointmentDialog is the Schedule class, since Schedule has the * method that is invoked from the 'OK' button action listener. See class * OKScheduleAppointmentButtonListener for details of how the * Schedule.scheduleAppointment method is invoked. * */ public class ScheduleAppointmentDialog extends CalendarToolWindow { /** * Construct this with the given Schedule as companion model. Construct * the two subviews for recurring info and reminder info. */ public ScheduleAppointmentDialog(Screen screen, Schedule schedule, CalendarToolUI calToolUI) { super(screen, schedule, calToolUI); recurringInfo = new RecurringInfoSubdialog(screen, this); remindInfo = new RemindInfoSubdialog(screen, this); /* * Set the maximum component height and width. The height value was * empiricaly derived, i.e., I fiddled around with it while looking at * the display. The width value is presumably as big as the biggest * screen we'll come across. If not, deal with it. */ maxComponentHeight = 1.9; maxComponentWidth = 3000; } /** * Compose this in six parts: (1) a top part consisting of the title, date, * end date, start time, and duration components; (2) a part consisting of * recurring info components; (3) a middle part with category, location, * security, and priority; (4) reminder info components; (5) details * components; (6) the bottom row consisting of the 'OK', 'Clear', and * 'Cancel' buttons. */ public Component compose() { /* * Add a JPanel to this' window, which was created in the parent class' * constructor. JPanel is the standard background container for * holding Swing components. */ panel = new JPanel(); window.add(panel); /* * Set the layout style of the panel to be a vertical box. */ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); /* * Compose the content rows. */ composeRows(); /* * Set the window titlebar. */ window.setTitle("Schedule an Appointment"); /* * Call JFrame.pack to have Java size up the window properly. */ window.pack(); /* * Return the window to the caller. */ return window; } /** * Compose each of the rows and add to the vertically laid out panel. * Put some around spacing between each row, in the form of a vertical * strut. */ protected void composeRows() { panel.add(Box.createVerticalStrut(15)); panel.add(composeTopPart()); panel.add(Box.createVerticalStrut(15)); panel.add(composeRecurringInfo()); panel.add(Box.createVerticalStrut(15)); panel.add(composeMiddlePart()); panel.add(Box.createVerticalStrut(15)); panel.add(composeRemindInfo()); panel.add(Box.createVerticalStrut(15)); panel.add(composeDetails()); panel.add(Box.createVerticalStrut(15)); panel.add(composeButtonRow()); panel.add(Box.createVerticalStrut(15)); } /** * Compose the top part of the dialog, consisting of the title, date, start * time, end date, and duration. The components are laid out in a * three-row vertical box. The title row is on top; it is composed as a * horizontal box containing a JLabel and JTextField. The second row of * top-part components is a horizontal box, composed in turn of two * horizontal boxes containing JLabel/JTextField pairs for the date and * start time. The third row consists of a JLabel/JTextField pairs for the * end date and the duration. The duration is in turn a horizontal box * consisting of a JLabel, and two vertical box JLabel/JTextField pairs for * the hour and minute components of the duration. */ protected Box composeTopPart() { Box vbox = Box.createVerticalBox(); vbox.add(composeTitleRow()); vbox.add(Box.createVerticalStrut(15)); vbox.add(composeStartDateRow()); vbox.add(Box.createVerticalStrut(15)); vbox.add(composeEndDateRow()); return vbox; } /** * Compose the title row as an hbox with label and text field. */ protected Box composeTitleRow() { Box hbox = Box.createHorizontalBox(); /* * Construct the label and text field. */ JLabel label = new JLabel("Title: "); titleTextField = new JTextField(); /* * Set the label font color to black, since I don't care for the * default "Java blue". */ label.setForeground(Color.black); /* * Set the max height of the text field to keep it from resizing * vertically in the vertical box layout of the panel. */ titleTextField.setMaximumSize( new Dimension(maxComponentWidth, (int)(maxComponentHeight * titleTextField.getFont().getSize()))); /* * Add the label and text field to the hbox and return it. Use * horizontal struts for spacing. */ hbox.add(Box.createHorizontalStrut(15)); hbox.add(label); hbox.add(titleTextField); hbox.add(Box.createHorizontalStrut(15)); return hbox; } /** * Compose the start date row using two pairs of labels and text fields. * Cf. * ScheduleEventDialg.composeStartAndEndDateRow . */ protected Box composeStartDateRow() { Box hbox = Box.createHorizontalBox(); /* * Construct the labels and text fields. See internal comments in the * composeTitle method for further explanatory details. */ startDateLabel = new JLabel("Date: "); startDateLabel.setForeground(Color.black); startDateTextField = new JTextField(15); startDateTextField.setMaximumSize( new Dimension(maxComponentWidth, (int)(maxComponentHeight * startDateTextField.getFont().getSize()))); JLabel startTimeLabel = new JLabel("Start Time: "); startTimeLabel.setForeground(Color.black); startTimeTextField = new JTextField(15); startTimeTextField.setMaximumSize( new Dimension(maxComponentWidth, (int)(maxComponentHeight * startTimeTextField.getFont().getSize()))); /* * Add them to the hbox and return it. */ hbox.add(Box.createHorizontalStrut(15)); hbox.add(startDateLabel); hbox.add(startDateTextField); hbox.add(Box.createHorizontalStrut(10)); hbox.add(startTimeLabel); hbox.add(startTimeTextField); hbox.add(Box.createHorizontalStrut(15)); return hbox; } /** * Compose the end date row using two pairs of labels and text fields. */ protected Box composeEndDateRow() { Box hbox = Box.createHorizontalBox(); /* * Construct the labels and text fields. See internal comments in the * composeTitle method for further explanatory details. */ endDateLabel = new JLabel("End Date: "); endDateLabel.setForeground(Color.black); endDateLabel.setEnabled(false); endDateTextField = new JTextField(15); endDateTextField.setMaximumSize( new Dimension(maxComponentWidth, (int)(maxComponentHeight * endDateTextField.getFont().getSize()))); endDateTextField.setEnabled(false); JLabel durationLabel = new JLabel("Duration: "); durationLabel.setForeground(Color.black); durationTextField = new JTextField(15); durationTextField.setMaximumSize( new Dimension(maxComponentWidth, (int)(maxComponentHeight * durationTextField.getFont().getSize()))); /* * Add them to the hbox and return it. */ hbox.add(Box.createHorizontalStrut(15)); hbox.add(endDateLabel); hbox.add(endDateTextField); hbox.add(Box.createHorizontalStrut(10)); hbox.add(durationLabel); hbox.add(durationTextField); hbox.add(Box.createHorizontalStrut(15)); return hbox; } /** * Have the recurring info subdialog compose itself. */ protected Component composeRecurringInfo() { return recurringInfo.compose(); } /** * Compose the middle part of the dialog, consisting of the category, * location, security, and priority. The category and security are combo * boxes, laid out in a horizontal box. Location and priority are also * combo boxes in a horizontal box. Location is editable. See the * description of * composeTopPart for a more detailed description of component layout. */ protected Box composeMiddlePart() { Box vbox = Box.createVerticalBox(); vbox.add(composeCategorySecurityRow()); vbox.add(Box.createVerticalStrut(15)); vbox.add(composeLocationPriorityRow()); return vbox; } /** * Compose the category/seurity row using two pairs of labels and text * fields. */ protected Box composeCategorySecurityRow() { Box hbox = Box.createHorizontalBox(); JLabel categoryLabel = new JLabel("Category: "); categoryLabel.setForeground(Color.black); categoryComboBox = new JComboBox(); categoryComboBox.addItem("none"); categoryComboBox.addItem(""); categoryComboBox.addItem("Edit ..."); categoryComboBox.setMaximumSize( new Dimension(maxComponentWidth, (int)(maxComponentHeight * categoryComboBox.getFont().getSize()))); JLabel securityLabel = new JLabel("Security: "); securityLabel.setForeground(Color.black); String[] selections2 = {"public", "title only", "confidential", "private"}; securityComboBox = new JComboBox(selections2); securityComboBox.setMaximumSize( new Dimension(maxComponentWidth, (int)(maxComponentHeight * securityComboBox.getFont().getSize()))); hbox.add(Box.createHorizontalStrut(15)); hbox.add(categoryLabel); hbox.add(categoryComboBox); hbox.add(Box.createHorizontalStrut(10)); hbox.add(securityLabel); hbox.add(securityComboBox); hbox.add(Box.createHorizontalStrut(15)); return hbox; } /** * Compose the location/priority row using two pairs of labels and text * fields. */ protected Box composeLocationPriorityRow() { Box hbox = Box.createHorizontalBox(); JLabel locationLabel = new JLabel("Location: "); locationLabel.setForeground(Color.black); locationComboBox = new JComboBox(); locationComboBox.setEditable(true); locationComboBox.setMaximumSize( new Dimension(maxComponentWidth, (int)(maxComponentHeight * locationComboBox.getFont().getSize()))); JLabel priorityLabel = new JLabel("Priority: "); priorityLabel.setForeground(Color.black); String[] selections = {"must", "optional"}; priorityComboBox = new JComboBox(selections); priorityComboBox.setMaximumSize( new Dimension(maxComponentWidth, (int)(maxComponentHeight * priorityComboBox.getFont().getSize()))); hbox.add(Box.createHorizontalStrut(15)); hbox.add(locationLabel); hbox.add(locationComboBox); hbox.add(Box.createHorizontalStrut(10)); hbox.add(priorityLabel); hbox.add(priorityComboBox); hbox.add(Box.createHorizontalStrut(15)); return hbox; } /** * Have the remind info subdialog compose itself. */ protected Component composeRemindInfo() { return remindInfo.compose(); } /** * Compose the details area as a labeled, scrolling text area. The label * and the text area are in a left-aligned vbox. The vbox is in a hbox * with horizontal spacing on each side */ protected Box composeDetails() { Box hbox = Box.createHorizontalBox(); Box vbox = Box.createVerticalBox(); JLabel label = new JLabel("Details:"); label.setForeground(Color.black); label.setAlignmentX(Box.LEFT_ALIGNMENT); detailsTextArea = new JTextArea(6, 40); JScrollPane scrollPane = new JScrollPane(detailsTextArea); scrollPane.setAlignmentX(Box.LEFT_ALIGNMENT); vbox.add(label); vbox.add(scrollPane); hbox.add(Box.createHorizontalStrut(15)); hbox.add(vbox); hbox.add(Box.createHorizontalStrut(15)); return hbox; } /** * Compose the buttons row with three JButtons. The action listeners for * Clear and Cancel buttons are straightforward. The action listener for * the OK button is responsible for communication with the Schedule model. * See the description of * OKScheduleAppointmentButtonListener for explanatory details. */ protected Box composeButtonRow() { Box hbox = Box.createHorizontalBox(); /* * Construct the three buttons. */ JButton okButton = new JButton("OK"); JButton clearButton = new JButton("Clear"); JButton cancelButton = new JButton("Cancel"); /* * Attach the appropriate action listeners to each button. */ okButton.addActionListener( new OKScheduleAppointmentButtonListener((Schedule) model, this)); clearButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { clear(); } } ); cancelButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { hide(); } } ); /* * Add them to the hbox and return it. */ hbox.add(okButton); hbox.add(Box.createHorizontalStrut(30)); hbox.add(clearButton); hbox.add(Box.createHorizontalStrut(30)); hbox.add(cancelButton); return hbox; } /** * Clear each of the text fields of this to empty. Reset the combo box to * no selection. NOTE: This method needs to be refined to use default * values for clearing, once options and defaults functionality is * implemented. It also needs to be refined to clear the recurring and * remind check boxes and associated components. */ protected void clear() { titleTextField.setText(""); startDateTextField.setText(""); endDateTextField.setText(""); startTimeTextField.setText(""); durationTextField.setText(""); categoryComboBox.setSelectedItem("none"); locationComboBox.setSelectedItem(null); securityComboBox.setSelectedIndex(0); detailsTextArea.setText(""); } /** The background panel of this */ protected JPanel panel; /** The title text field */ protected JTextField titleTextField; /** The (start) date label. This needs to be a persistent data field since it changes from "Date" to "Start Date" for recurring appointments. Also, it has different text in the ScheduleMeetingDialog, subclass. */ protected JLabel startDateLabel; /** The (start) date text field */ protected JTextField startDateTextField; /** The start time text field. */ protected JTextField startTimeTextField; /** The end date label. This needs to be a persistent data field since it's enabled or disabled depending on whether the appointment is recurring. Also, it has different text in the ScheduleMeetingDialog, subclass. */ protected JLabel endDateLabel; /** The end date text field */ protected JTextField endDateTextField; /** The start time text field */ protected JTextField durationTextField; /** Subview for recurring info */ protected RecurringInfoSubdialog recurringInfo; /** The category combo box */ protected JComboBox categoryComboBox; /** The security combo box */ protected JComboBox securityComboBox; /** The location combo box */ protected JComboBox locationComboBox; /** The priority combo box */ protected JComboBox priorityComboBox; /** Subview for recurring info */ protected RemindInfoSubdialog remindInfo; /** The details text area */ protected JTextArea detailsTextArea; /** The max height of a text field or combobox; this is necessary since these components stretch when the outer frame is resized, and look very funky when they do */ protected final double maxComponentHeight; /** The max width of any component; this is only necessary because the max height cannot be set separately, so we must pick some max width. */ protected final int maxComponentWidth; }