001package edu.pdx.cs410J.family;
002
003import java.awt.BorderLayout;
004import java.awt.Container;
005import java.awt.GridLayout;
006import java.awt.event.ActionEvent;
007import java.awt.event.ActionListener;
008import java.awt.event.MouseAdapter;
009import java.awt.event.MouseEvent;
010import java.text.DateFormat;
011import java.text.ParseException;
012import java.util.Date;
013
014import javax.swing.BorderFactory;
015import javax.swing.Box;
016import javax.swing.BoxLayout;
017import javax.swing.JButton;
018import javax.swing.JDialog;
019import javax.swing.JFrame;
020import javax.swing.JLabel;
021import javax.swing.JOptionPane;
022import javax.swing.JPanel;
023import javax.swing.JTextField;
024import javax.swing.border.Border;
025
026/**
027 * This is a dialog for editing a <code>Marriage</code>.
028 *
029 * @author David Whitlock
030 * @version $Revision: 1.6 $
031 * @since Fall 2000
032 */
033@SuppressWarnings("serial")
034public class EditMarriageDialog extends JDialog {
035
036  // The Marriage we're editing
037  private Marriage marriage = null;
038
039  private Person husband = null;
040  private Person wife = null;
041
042  private boolean changeHusband = true;
043  private boolean changeWife = true;
044
045  // GUI components we need to hold on to
046  private JTextField husbandField = new JTextField("Click to choose");
047  private JTextField wifeField = new JTextField("Click to choose");
048  private JTextField dateField = new JTextField();
049  private JTextField locationField = new JTextField();
050
051  /**
052   * Creates a new <code>EditMarriageField</code> for adding a new
053   * <code>Marriage</code> to a family tree.
054   */
055  public EditMarriageDialog(JFrame owner, FamilyTree tree) {
056    this(owner, "Add New Marriage", tree);
057  }
058
059  /**
060   * Creates a new <code>EditMarriageDialog</code> for creating a new
061   * marriage involving one person.
062   */
063  public EditMarriageDialog(Person spouse, JFrame owner, 
064                            FamilyTree tree) {
065    this(owner, "Creating Marriage", tree);
066
067    if (spouse.getGender() == Person.MALE) {
068      // husband
069      this.husband = spouse;
070      this.husbandField.setText(this.husband.getFullName());
071      this.husbandField.setEditable(false);
072      this.changeHusband = false;
073
074    } else {
075      // wife
076      this.wife = spouse;
077      this.wifeField.setText(this.wife.getFullName());
078      this.wifeField.setEditable(false);
079      this.changeWife = false;
080    }
081
082    this.marriage = null;
083  }
084
085  /**
086   * Creates a new <code>EditMarriageDialog</code> for editing an
087   * existing marriage.
088   */
089  public EditMarriageDialog(Marriage marriage, JFrame owner, 
090                            FamilyTree tree) {
091    this(owner, "Edit Marriage", tree);
092    this.marriage = marriage;
093
094    // Fill in information about the marriage
095    this.husband = marriage.getHusband();
096    this.husbandField.setText(this.husband.getFullName());
097    this.husbandField.setEditable(false);
098
099    this.wife = marriage.getWife();
100    this.wifeField.setText(this.wife.getFullName());
101    this.wifeField.setEditable(false);
102    
103    Date date = marriage.getDate();
104    if (date != null) {
105      DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
106      this.dateField.setText(df.format(date));
107    }
108
109    String location = marriage.getLocation();
110    this.locationField.setText(location);
111  }
112
113  /**
114   * General constructor called by others
115   */
116  private EditMarriageDialog(JFrame owner, String title, 
117                             FamilyTree tree) {
118    super(owner, title, true /* modal */);
119    setupComponents(tree);
120  }
121
122  /**
123   * Adds all of the components to this <code>EditMarriageDialog</code>.
124   */
125  private void setupComponents(final FamilyTree tree) {
126    Container pane = this.getContentPane();
127    pane.setLayout(new BorderLayout());
128
129    JPanel infoPanel = new JPanel();
130    infoPanel.setLayout(new GridLayout(4, 2));
131    Border infoBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5);
132    infoPanel.setBorder(infoBorder);
133
134    infoPanel.add(new JLabel("Husband:"));
135    husbandField.setEditable(false);
136    husbandField.addMouseListener(new MouseAdapter() {
137        public void mouseClicked(MouseEvent e) {
138          if (!changeHusband) {
139            return;
140          }
141
142          ChoosePersonDialog dialog =
143            new ChoosePersonDialog(tree, EditMarriageDialog.this);
144
145          dialog.pack();
146          dialog.setLocationRelativeTo(EditMarriageDialog.this);
147          dialog.setVisible(true);
148         
149          Person husband = dialog.getPerson();
150          if (husband != null) {
151            EditMarriageDialog.this.husband = husband;
152            String husbandName =
153              EditMarriageDialog.this.husband.getFullName();
154            EditMarriageDialog.this.husbandField.setText(husbandName);
155          }
156        }
157      });
158    infoPanel.add(husbandField);
159
160    infoPanel.add(new JLabel("Wife:"));
161    wifeField.setEditable(false);
162    wifeField.addMouseListener(new MouseAdapter() {
163        public void mouseClicked(MouseEvent e) {
164          if (!changeWife) {
165            return;
166          }
167
168          ChoosePersonDialog dialog =
169            new ChoosePersonDialog(tree, EditMarriageDialog.this);
170
171          dialog.pack();
172          dialog.setLocationRelativeTo(EditMarriageDialog.this);
173          dialog.setVisible(true);
174         
175          Person wife = dialog.getPerson();
176          if (wife != null) {
177            EditMarriageDialog.this.wife = wife;
178            String wifeName =
179              EditMarriageDialog.this.wife.getFullName();
180            EditMarriageDialog.this.wifeField.setText(wifeName);
181          }
182        }
183      });
184    infoPanel.add(wifeField);
185
186    infoPanel.add(new JLabel("Date:"));
187    infoPanel.add(dateField);
188
189    infoPanel.add(new JLabel("Location:"));
190    infoPanel.add(locationField);
191
192    pane.add(infoPanel, BorderLayout.NORTH);
193
194    // "OK" and "Cancel" buttons
195    JPanel buttonPanel = new JPanel();
196    buttonPanel.setLayout(new BoxLayout(buttonPanel,
197                                        BoxLayout.X_AXIS));
198    buttonPanel.add(Box.createHorizontalGlue());
199
200    JButton okButton = new JButton("OK");
201    okButton.addActionListener(new ActionListener() {
202        public void actionPerformed(ActionEvent e) {
203          // Create a new marriage based on the information entered in
204          // this dialog
205          if (husband == null) {
206            error("Missing husband");
207            return;
208          }
209
210          if (wife == null) {
211            error("Missing wife");
212            return;
213          }
214
215          String text = null;
216
217          text = dateField.getText();
218          Date date = null;
219          if (text != null && !text.equals("")) {
220            date = parseDate(text);
221            if (date == null) {
222              // Parse error
223              return;
224            }
225          }
226          
227          // Everything parsed alright
228          if (marriage == null) {
229            marriage = new Marriage(husband, wife);
230            husband.addMarriage(marriage);
231            wife.addMarriage(marriage);
232          }
233
234          marriage.setDate(date);
235          marriage.setLocation(locationField.getText());
236
237          // We're all happy
238          EditMarriageDialog.this.dispose();
239        }
240      });
241    buttonPanel.add(okButton);
242
243    buttonPanel.add(Box.createHorizontalGlue());
244
245    JButton cancelButton = new JButton("Cancel");
246    cancelButton.addActionListener(new ActionListener() {
247        public void actionPerformed(ActionEvent e) {
248          // Read my lips, no new Marriage!
249
250          EditMarriageDialog.this.marriage = null;
251
252          EditMarriageDialog.this.dispose();
253        }
254      });
255    buttonPanel.add(cancelButton);
256
257    buttonPanel.add(Box.createHorizontalGlue());
258
259    pane.add(buttonPanel, BorderLayout.SOUTH);
260  }
261
262  /**
263   * Returns the <code>Marriage</code> edited by this
264   * <code>EditMarriageDialog</code>.
265   */
266  public Marriage getMarriage() {
267    return this.marriage;
268  }
269
270  /**
271   * Tries very, very hard to parse the a date.  We assume that the
272   * text is neither empty nor <code>null</code>.
273   */
274  private Date parseDate(String text) {
275    DateFormat formats[] = new DateFormat[] {
276      DateFormat.getDateInstance(DateFormat.SHORT),
277      DateFormat.getDateInstance(DateFormat.MEDIUM),
278      DateFormat.getDateInstance(DateFormat.LONG),
279      DateFormat.getDateInstance(DateFormat.FULL),
280    };
281
282    for (int i = 0; i < formats.length; i++) {
283      DateFormat df = formats[i];
284      try {
285        Date date = df.parse(text);
286        return date;
287
288      } catch (ParseException ex) {
289        continue;
290      }
291    }
292
293    error("Could not parse date: " + text);
294    return null;
295  }
296
297  /**
298   * Pops up a dialog box with an error message in it.
299   */
300  private void error(String message) {
301    JOptionPane.showMessageDialog(this, new String[] { message}, 
302                                  "Error.",
303                                  JOptionPane.ERROR_MESSAGE);
304  }
305
306}