View Javadoc

1   /*
2   @See License.txt@
3    */
4   
5   package spellcast.ui;
6   
7   import java.awt.BorderLayout;
8   import java.awt.Container;
9   import java.awt.Dimension;
10  import java.awt.GridBagConstraints;
11  import java.awt.GridBagLayout;
12  import java.awt.Insets;
13  import java.awt.event.ActionEvent;
14  import java.awt.event.ActionListener;
15  import java.beans.PropertyChangeListener;
16  import java.io.BufferedReader;
17  import java.io.BufferedWriter;
18  import java.io.File;
19  import java.io.FileReader;
20  import java.io.FileWriter;
21  import java.io.LineNumberReader;
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import javax.swing.ComboBoxModel;
25  import javax.swing.DefaultComboBoxModel;
26  import javax.swing.DefaultListModel;
27  import javax.swing.JButton;
28  import javax.swing.JComboBox;
29  import javax.swing.JDialog;
30  import javax.swing.JFrame;
31  import javax.swing.JLabel;
32  import javax.swing.JList;
33  import javax.swing.JPanel;
34  import javax.swing.JScrollPane;
35  import javax.swing.JTextField;
36  import javax.swing.ListSelectionModel;
37  import javax.swing.WindowConstants;
38  import javax.swing.event.ListSelectionEvent;
39  import javax.swing.event.ListSelectionListener;
40  import javax.swing.event.SwingPropertyChangeSupport;
41  import org.apache.log4j.Logger;
42  import spellcast.beings.Gender;
43  import spellcast.util.TextUtil;
44  
45  /***
46   * Display the profiles stored in <b>user.home</b>/.spellcast/Profiles.txt.
47   * New profiles can be added via the save button, or deleted by the delete button.
48   * When the user selects which profile to use it is written to <b>user.home</b>/.spellcast/Profiles-default.txt
49   * <p>
50   * Format of <b>user.home</b>/.spellcast/Profiles.txt:<br>
51   * This file contains wizard profiles, one per line.
52   * Each line is of the format <Gender String><space><Name>.
53   *
54   * @author Barrie Treloar
55   */
56  public class WizardProfiles extends JDialog implements UIProperties {
57      public static final File profilesFile =
58          new File(System.getProperty("user.home") + "/.spellcast/Profiles.txt");
59      public static final File defaultProfileFile =
60          new File(System.getProperty("user.home") + "/.spellcast/Default-Profile.txt");
61  
62      /***
63       * The preffered size for the profile list.  Since the list goes in the SOUTH
64       * section the height field is ignored.
65       */
66      private static final Dimension LIST_PREFERRED_SIZE = new Dimension(100, 100);
67  
68      private GridBagLayout gridbag;
69  
70      private JList profileList;
71      private DefaultListModel profileModel = new DefaultListModel();
72      private JTextField wizardName;
73      private JComboBox genders;
74      private ComboBoxModel genderModel =
75          new DefaultComboBoxModel(Gender.GENDERS_AS_STRINGS);
76      private SwingPropertyChangeSupport propertySupport;
77  
78      private static final Logger logger = Logger.getLogger("client.ui");
79  
80      public WizardProfiles() {
81          super((JFrame) null, "Spellcast: Wizard Profiles", true);
82          propertySupport = new SwingPropertyChangeSupport(this);
83          java.util.List profiles = loadProfiles();
84          if (profiles.size() == 0) {
85              setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
86          }
87          Iterator profileIterator = profiles.listIterator();
88          while (profileIterator.hasNext()) {
89              profileModel.addElement(profileIterator.next());
90          }
91  
92          Container dialogPanel = getContentPane();
93  
94          profileList = new JList(profileModel);
95          profileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
96          profileList.setPreferredSize(LIST_PREFERRED_SIZE);
97          JScrollPane s =
98              new JScrollPane(
99                  profileList,
100                 JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
101                 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
102         dialogPanel.add(s, BorderLayout.WEST);
103 
104         JPanel centerPanel = new JPanel();
105         gridbag = new GridBagLayout();
106         centerPanel.setLayout(gridbag);
107         GridBagConstraints c = new GridBagConstraints();
108         // Common constraints
109         c.insets = new Insets(2, 2, 2, 2);
110 
111         c.anchor = GridBagConstraints.WEST;
112         JLabel nameLabel = new JLabel("Name:");
113         gridbag.setConstraints(nameLabel, c);
114         centerPanel.add(nameLabel);
115 
116         c.gridwidth = GridBagConstraints.REMAINDER;
117         wizardName = new JTextField(15);
118         gridbag.setConstraints(wizardName, c);
119         centerPanel.add(wizardName);
120         nameLabel.setLabelFor(wizardName);
121 
122         c.gridwidth = 1;
123         JLabel genderLabel = new JLabel("Gender:");
124         gridbag.setConstraints(genderLabel, c);
125         centerPanel.add(genderLabel);
126 
127         c.gridwidth = GridBagConstraints.REMAINDER;
128         genders = new JComboBox(genderModel);
129         genders.setEditable(false);
130         gridbag.setConstraints(genders, c);
131         centerPanel.add(genders);
132         genderLabel.setLabelFor(genders);
133 
134         c.insets = new Insets(5, 2, 2, 2);
135         c.gridwidth = 1;
136         c.weightx = 1.0;
137         c.anchor = GridBagConstraints.EAST;
138         final JButton use = new JButton("Use");
139         use.setEnabled(false);
140         use.addActionListener(new ActionListener() {
141             public void actionPerformed(ActionEvent e) {
142                 saveDefaultProfile((WizardProfile) profileList.getSelectedValue());
143                 setVisible(false);
144             }
145         });
146         gridbag.setConstraints(use, c);
147         centerPanel.add(use);
148 
149         c.weightx = 0.0;
150         c.anchor = GridBagConstraints.CENTER;
151         JButton save = new JButton("Save");
152         save.addActionListener(new ActionListener() {
153             public void actionPerformed(ActionEvent e) {
154                 addProfile(wizardName.getText().trim(), (String) genders.getSelectedItem());
155                 saveProfiles();
156             }
157         });
158         gridbag.setConstraints(save, c);
159         centerPanel.add(save);
160 
161         JButton delete = new JButton("Delete");
162         delete.addActionListener(new ActionListener() {
163             public void actionPerformed(ActionEvent e) {
164                 WizardProfile p = (WizardProfile) profileList.getSelectedValue();
165                 if (p != null) {
166                     profileModel.removeElement(p);
167                     saveProfiles();
168                 }
169             }
170         });
171         gridbag.setConstraints(delete, c);
172         centerPanel.add(delete);
173 
174         c.gridwidth = GridBagConstraints.REMAINDER;
175         JButton clear = new JButton("Clear");
176         clear.addActionListener(new ActionListener() {
177             public void actionPerformed(ActionEvent e) {
178                 wizardName.setText("");
179             }
180         });
181         gridbag.setConstraints(clear, c);
182         centerPanel.add(clear);
183 
184         dialogPanel.add(centerPanel, BorderLayout.CENTER);
185 
186         profileList.addListSelectionListener(new ListSelectionListener() {
187             public void valueChanged(ListSelectionEvent e) {
188                 int index = profileList.getSelectedIndex();
189                 if (index != -1) {
190                     WizardProfile p = (WizardProfile) profileModel.elementAt(index);
191                     wizardName.setText(p.wizardName);
192                     genderModel.setSelectedItem(p.gender);
193                     use.setEnabled(true);
194                 }
195                 else {
196                     use.setEnabled(false);
197                 }
198             }
199         });
200         profileList.setSelectedValue(loadDefaultProfile(), true);
201         pack();
202     }
203 
204     public void addPropertyChangeListener(PropertyChangeListener listener) {
205         propertySupport.addPropertyChangeListener(listener);
206     }
207 
208     public void removePropertyChangeListener(PropertyChangeListener listener) {
209         propertySupport.removePropertyChangeListener(listener);
210     }
211 
212     /***
213      * Add the profile to the model.
214      * First checks to see if the wizard name already exists and if so just
215      * updates the profiles gender.
216      * If it doesn't exist in the model then add it.
217      */
218     private void addProfile(String wizardName, String gender) {
219         if (wizardName == null || wizardName.equals("")) {
220             return;
221         }
222 
223         boolean found = false;
224         for (int i = 0; i < profileModel.size(); i++) {
225             WizardProfile p = (WizardProfile) profileModel.get(i);
226             if (p.wizardName.equals(wizardName)) {
227                 found = true;
228                 p.gender = gender;
229             }
230         }
231         if (!found) {
232             WizardProfile wp = new WizardProfile(wizardName, gender);
233             profileModel.addElement(wp);
234             profileList.setSelectedValue(wp, true);
235         }
236     }
237 
238     /***
239      * Return a list of WizardProfiles.  If there are no entries the list will be size == 0.
240      */
241     public static java.util.List loadProfiles() {
242         LineNumberReader r = null;
243         ArrayList result = new ArrayList(10);
244         try {
245             if (profilesFile.exists()) {
246                 r = new LineNumberReader(new FileReader(profilesFile));
247                 String line = null;
248                 while ((line = r.readLine()) != null) {
249                     // Ensure line in correct format ( <Gender><space><Wizard Name> )
250                     String gender = TextUtil.getGender(line);
251                     String wizardName = TextUtil.getWizardName(line);
252                     if (Gender.getGender(gender) == null) {
253                         logger.warn(
254                             "Malformed line (" + r.getLineNumber() + ") expecting valid gender.");
255                     }
256                     else
257                         if (wizardName == null || wizardName.equals("")) {
258                             logger.warn(
259                                 "Malformed line (" + r.getLineNumber() + ") expecting valid wizard name.");
260                         }
261                         else {
262                             result.add(new WizardProfile(wizardName, gender));
263                         }
264                 }
265             }
266         }
267         catch (Exception e) {
268             logger.error("Could not load Profiles.", e);
269         }
270         finally {
271             try {
272                 if (r != null) {
273                     r.close();
274                 }
275             }
276             catch (Exception e) {
277                 logger.error("Unexpected error in Reader.close().", e);
278             }
279         }
280         return result;
281     }
282 
283     private void saveProfiles() {
284         BufferedWriter w = null;
285 
286         try {
287             // Creates only if does not exist
288             profilesFile.createNewFile();
289 
290             if (profilesFile.exists()) {
291                 w = new BufferedWriter(new FileWriter(profilesFile));
292                 for (int i = 0; i < profileModel.size(); i++) {
293                     WizardProfile p = (WizardProfile) profileModel.get(i);
294                     w.write(p.gender);
295                     w.write(" ");
296                     w.write(p.wizardName);
297                     w.newLine();
298                 }
299             }
300         }
301         catch (Exception e) {
302             logger.error("Could not save Profiles.", e);
303         }
304         finally {
305             try {
306                 if (w != null) {
307                     w.flush();
308                     w.close();
309                 }
310             }
311             catch (Exception e) {
312                 logger.error("Unexpected error in Writer.close().", e);
313             }
314         }
315     }
316 
317     /***
318      * Return the default wizard profile, or null if it does not exist.
319      */
320     public static WizardProfile loadDefaultProfile() {
321         WizardProfile result = null;
322         BufferedReader r = null;
323         try {
324             if (defaultProfileFile.exists()) {
325                 r = new BufferedReader(new FileReader(defaultProfileFile));
326                 String line = r.readLine();
327                 if (line != null) {
328                     // Ensure line in correct format ( <Gender><space><Wizard Name> )
329                     String gender = TextUtil.getGender(line);
330                     String wizardName = TextUtil.getWizardName(line);
331                     if (Gender.getGender(gender) == null) {
332                         logger.warn("Malformed default profile.  Expecting valid gender.");
333                     }
334                     else if (wizardName == null || wizardName.equals("")) {
335                         logger.warn("Malformed default profile.  Expecting valid wizard name.");
336                     }
337                     else {
338                         result = new WizardProfile(wizardName, gender);
339                     }
340                 }
341             }
342         }
343         catch (Exception e) {
344             logger.error("Could not load default profile.", e);
345         }
346         finally {
347             try {
348                 if (r != null) {
349                     r.close();
350                 }
351             }
352             catch (Exception e) {
353                 logger.error("Unexpected error in Reader.close().", e);
354             }
355         }
356         return result;
357     }
358 
359     /***
360      * Save the default profile
361      */
362     private void saveDefaultProfile(WizardProfile wp) {
363         BufferedWriter w = null;
364 
365         if (wp == null) {
366             return;
367         }
368 
369         try {
370             // Creates only if does not exist
371             defaultProfileFile.createNewFile();
372 
373             if (defaultProfileFile.exists()) {
374                 w = new BufferedWriter(new FileWriter(defaultProfileFile));
375                 w.write(wp.gender);
376                 w.write(" ");
377                 w.write(wp.wizardName);
378                 w.newLine();
379             }
380         }
381         catch (Exception e) {
382             logger.error("Could not save Default Profiles.", e);
383         }
384         finally {
385             try {
386                 if (w != null) {
387                     w.flush();
388                     w.close();
389                 }
390             }
391             catch (Exception e) {
392                 logger.error("Unexpected error in Writer.close().", e);
393             }
394         }
395     }
396 
397 }