001package edu.pdx.cs410J.family;
002
003import edu.pdx.cs410J.family.Person.Gender;
004
005import java.awt.*;
006import java.awt.event.*;
007import java.io.*;
008import java.text.*;
009import java.util.*;
010
011import javax.swing.*;
012import javax.swing.border.*;
013
014/**
015 * This is a dialog for editing a <code>Person</code>.  The
016 * <code>Person</code> may or may not already exist.
017 */
018@SuppressWarnings("serial")
019public class EditPersonDialog extends JDialog {
020
021  // The person we're editing
022  private Person person = null;
023
024  private Person mother;
025  private Person father;
026  private Person child;
027
028  // GUI components we need to hold on to
029  private JTextField idField = new JTextField();
030  private JTextField firstNameField = new JTextField();
031  private JTextField middleNameField = new JTextField();
032  private JTextField lastNameField = new JTextField();
033  private JTextField dobField = new JTextField();
034  private JTextField dodField = new JTextField();
035  private JTextField fatherField = new JTextField("Click to choose");
036  private JTextField motherField = new JTextField("Click to choose");
037  private JTextField childField = new JTextField("Click to choose");
038  private JRadioButton male = new JRadioButton("male", true);
039  private JRadioButton female = new JRadioButton("female");
040
041
042  /**
043   * Creates a new <code>EditPersonDialog</code> for adding a new
044   * <code>Person</code> to a family tree.
045   *
046   * @param owner
047   *        The parent <code>JFrame</code> of this dialog box
048   * @param tree
049   *        The existing family tree
050   */
051  public EditPersonDialog(JFrame owner, FamilyTree tree) {
052    this(owner, "Add New Person", tree);
053  }
054
055  /**
056   * Creates a new <code>EditPersonDialog</code> for editing an
057   * existing Person.
058   */
059  public EditPersonDialog(Person person, JFrame owner, 
060                          FamilyTree tree) {
061    this(owner, "Edit Person " + person.getId(), tree);
062    this.person = person;
063
064    // Fill in information about the person
065    this.idField.setText("" + person.getId());
066    this.idField.setEditable(false);
067
068    if (this.person.getGender() == Person.FEMALE) {
069      female.setSelected(true);
070      female.setEnabled(true);
071      male.setEnabled(false);
072      male.setSelected(false);
073    }
074    
075    if (this.person.getGender() == Person.MALE) {
076      male.setSelected(true);
077      male.setEnabled(true);
078      female.setSelected(false);
079      female.setEnabled(false);
080    }
081
082    this.firstNameField.setText(person.getFirstName());
083    this.middleNameField.setText(person.getMiddleName());
084    this.lastNameField.setText(person.getLastName());
085    
086    DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
087    Date dob = person.getDateOfBirth();
088    if (dob != null) {
089      this.dobField.setText(df.format(dob));
090    }
091    Date dod = person.getDateOfDeath();
092    if (dod != null) {
093      this.dodField.setText(df.format(dod));
094    }
095
096    this.father = person.getFather();
097    if (this.father != null) {
098      this.fatherField.setText(this.father.getFullName());
099    }
100
101    this.mother = person.getMother();
102    if (this.mother != null) {
103      this.motherField.setText(this.mother.getFullName());
104    }
105  }
106
107  /**
108   * General constructor called by others.
109   */ 
110  private EditPersonDialog(JFrame owner, String title, 
111                           FamilyTree tree) {
112    super(owner, title, true /* modal */);
113    setupComponents(tree);
114  }
115
116  /**
117   * Adds all of the components to this <code>EditPersonDialog</code>.
118   */
119  private void setupComponents(final FamilyTree tree) {
120    Container pane = this.getContentPane();
121    pane.setLayout(new BorderLayout());
122
123    JPanel infoPanel = new JPanel();
124    infoPanel.setLayout(new GridLayout(0, 2));
125    Border infoBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5); 
126    infoPanel.setBorder(infoBorder);
127
128    infoPanel.add(new JLabel("id:"));
129    infoPanel.add(idField);
130
131    final ButtonGroup group = new ButtonGroup();
132
133    group.add(male);
134    male.setActionCommand("male");
135    infoPanel.add(male);
136    
137    group.add(female);
138    female.setActionCommand("female");
139    infoPanel.add(female);
140
141    infoPanel.add(new JLabel("First name:"));
142    infoPanel.add(firstNameField);
143
144    infoPanel.add(new JLabel("Middle name:"));
145    infoPanel.add(middleNameField);
146
147    infoPanel.add(new JLabel("Last name:"));
148    infoPanel.add(lastNameField);
149
150    infoPanel.add(new JLabel("Date of Birth:"));
151    infoPanel.add(dobField);
152
153    infoPanel.add(new JLabel("Date of Death:"));
154    infoPanel.add(dodField);
155
156    infoPanel.add(new JLabel("Father:"));
157    fatherField.setEditable(false);
158    fatherField.addMouseListener(new MouseAdapter() {
159        public void mouseClicked(MouseEvent e) {
160          ChoosePersonDialog dialog = 
161            new ChoosePersonDialog(tree, EditPersonDialog.this);
162
163          dialog.pack();
164          dialog.setLocationRelativeTo(EditPersonDialog.this);
165          dialog.setVisible(true);
166          
167          Person father = dialog.getPerson();
168          if (father != null) {
169            EditPersonDialog.this.father = father;
170            String fatherName =
171              EditPersonDialog.this.father.getFullName(); 
172            EditPersonDialog.this.fatherField.setText(fatherName);
173          }
174        }
175      });
176    infoPanel.add(fatherField);
177
178    infoPanel.add(new JLabel("Mother:"));
179    motherField.setEditable(false);
180    motherField.addMouseListener(new MouseAdapter() {
181        public void mouseClicked(MouseEvent e) {
182          ChoosePersonDialog dialog = 
183            new ChoosePersonDialog(tree, EditPersonDialog.this);
184
185          dialog.pack();
186          dialog.setLocationRelativeTo(EditPersonDialog.this);
187          dialog.setVisible(true);
188          
189          Person mother = dialog.getPerson();
190          if (mother != null) {
191            EditPersonDialog.this.mother = mother;
192            String motherName =
193              EditPersonDialog.this.mother.getFullName(); 
194            EditPersonDialog.this.motherField.setText(motherName);
195          }
196        }
197      });
198    infoPanel.add(motherField);
199
200    infoPanel.add(new JLabel("Parent of:"));
201    childField.setEditable(false);
202    childField.addMouseListener(new MouseAdapter() {
203        public void mouseClicked(MouseEvent e) {
204          ChoosePersonDialog dialog = 
205            new ChoosePersonDialog(tree, EditPersonDialog.this);
206
207          dialog.pack();
208          dialog.setLocationRelativeTo(EditPersonDialog.this);
209          dialog.setVisible(true);
210          
211          Person child = dialog.getPerson();
212          if (child != null) {
213            EditPersonDialog.this.child = child;
214            String childName = EditPersonDialog.this.child.getFullName();
215            EditPersonDialog.this.childField.setText(childName);
216          }
217        }
218      });
219    infoPanel.add(childField);
220
221    pane.add(infoPanel, BorderLayout.NORTH);
222
223    // "OK" and "Cancel" buttons
224    JPanel buttonPanel = new JPanel();
225    buttonPanel.setLayout(new BoxLayout(buttonPanel,
226                                        BoxLayout.X_AXIS));
227    buttonPanel.add(Box.createHorizontalGlue());
228
229    JButton okButton = new JButton("OK");
230    okButton.addActionListener(new ActionListener() {
231        public void actionPerformed(ActionEvent e) {
232          // Create a new person based on the information entered in
233          // this dialog
234          int id = 0;
235          try {
236            id = Integer.parseInt(idField.getText());
237
238          } catch (NumberFormatException ex) {
239            error("Invalid id: " + idField.getText());
240            return;
241          }
242
243          String text = null;
244
245          text = dobField.getText();
246          Date dob = null;
247          if (text != null && !text.equals("")) {
248            dob = parseDate(dobField.getText());
249            if (dob == null) {
250              // Parse error
251              return;
252            }
253          }
254
255          text = dodField.getText();
256          Date dod = null;
257          if (text != null && !text.equals("")) {
258            dod = parseDate(dodField.getText());
259            if (dod == null) {
260              // Parse error
261              return;
262            }
263          }
264          
265          Gender gender;
266          if (group.getSelection().getActionCommand().equals("male")) {
267            gender = Person.MALE;
268
269          } else {
270            gender = Person.FEMALE;
271          }
272 
273          // Okay, everything parsed alright
274          if (person == null) {
275            person = new Person(id, gender);
276          }
277
278          person.setFirstName(firstNameField.getText());
279          person.setMiddleName(middleNameField.getText());
280          person.setLastName(lastNameField.getText());
281          person.setDateOfBirth(dob);
282          person.setDateOfDeath(dod);
283
284          if (mother != null) {
285            person.setMother(mother);
286          }
287
288          if (father != null) {
289            person.setFather(father);
290          }
291
292          if (child != null) {
293            if (person.getGender() == Person.MALE) {
294              child.setFather(person);
295
296            } else {
297              child.setMother(person);
298            }
299          }
300
301          // We're all happy
302          EditPersonDialog.this.dispose();
303        }
304      });
305    buttonPanel.add(okButton);
306
307    buttonPanel.add(Box.createHorizontalGlue());
308
309    JButton cancelButton = new JButton("Cancel");
310    cancelButton.addActionListener(new ActionListener() {
311        public void actionPerformed(ActionEvent e) {
312          // Read my lips, no new Person!
313
314          EditPersonDialog.this.person = null;
315
316          EditPersonDialog.this.dispose();
317        }
318      });
319    buttonPanel.add(cancelButton);
320
321    buttonPanel.add(Box.createHorizontalGlue());
322
323    pane.add(buttonPanel, BorderLayout.SOUTH);
324  }
325
326  /**
327   * Returns the <code>Person</code> created by this
328   * <code>EditPersonDialog</code>.
329   */
330  public Person getPerson() {
331    return this.person;
332  }
333
334  /**
335   * Tries very, very hard to parse the a date.  We assume that the
336   * text is neither empty nor <code>null</code>.
337   */
338  private Date parseDate(String text) {
339    DateFormat formats[] = new DateFormat[] {
340      DateFormat.getDateInstance(DateFormat.SHORT),
341      DateFormat.getDateInstance(DateFormat.MEDIUM),
342      DateFormat.getDateInstance(DateFormat.LONG),
343      DateFormat.getDateInstance(DateFormat.FULL),
344    };
345
346    for (int i = 0; i < formats.length; i++) {
347      DateFormat df = formats[i];
348      try {
349        Date date = df.parse(text);
350        return date;
351
352      } catch (ParseException ex) {
353        continue;
354      }
355    }
356
357    error("Could not parse date: " + text);
358    return null;
359  }
360
361  /**
362   * Pops up a dialog box with an error message in it.
363   */
364  private void error(String message) {
365    JOptionPane.showMessageDialog(this, new String[] { message}, 
366                                  "Error.",
367                                  JOptionPane.ERROR_MESSAGE);
368  }
369
370  /**
371   * Simple test program.
372   */
373  public static void main(String[] args) {
374    final JFrame frame = new JFrame("Testing EditPersonDialog");
375    JButton button = new JButton("Click me");
376    button.addActionListener(new ActionListener() {
377        public void actionPerformed(ActionEvent e) {
378          FamilyTree tree = new FamilyTree();
379          EditPersonDialog dialog = 
380            new EditPersonDialog(frame, tree);
381          dialog.pack();
382          dialog.setLocationRelativeTo(frame);
383          dialog.setVisible(true);
384
385          Person person = dialog.getPerson();
386          if (person != null) {
387            tree.addPerson(person);
388            PrettyPrinter pretty = 
389              new PrettyPrinter(new PrintWriter(System.out, true));
390            pretty.dump(tree);
391          }
392        }
393      });
394    frame.getContentPane().add(button);
395
396    frame.addWindowListener(new WindowAdapter() {
397        public void windowClosing(WindowEvent e) {
398          System.exit(1);
399        }
400      });
401    frame.pack();
402    frame.setVisible(true);
403  }
404}