KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ca > commons > cbutil > CBSaveLoadTemplate


1 package com.ca.commons.cbutil;
2
3 import javax.swing.*;
4 import javax.swing.border.TitledBorder JavaDoc;
5 import java.awt.*;
6 import java.awt.event.ActionEvent JavaDoc;
7 import java.awt.event.ActionListener JavaDoc;
8 import java.util.Properties JavaDoc;
9 import java.util.Vector JavaDoc;
10 import java.util.logging.Level JavaDoc;
11 import java.util.logging.Logger JavaDoc;
12
13
14 /**
15  * An object of this cunning class can be added as is
16  * to any container containing user-input components
17  * such as text fields, check boxes and so forth. When
18  * it is asked to 'save' a template, it scans through
19  * its parent container, identifies user-input
20  * components, and saves their data to a properties file
21  * with the name 'template name' + 'component number'.These
22  * can be automatically read back later.<p>
23  * <p/>
24  * At the moment it only handles the *swing* components: <br>
25  * JTextField, CBJComboBox, JCheckBox, but it could easily be modified
26  * (would need to change JContainer checks to Container).<p>
27  * <p/>
28  * It will iterate through sub-components, but since there is no
29  * "JContainer" class, all sub-components must be explicitly listed
30  * in the code; at the moment it only handles JPanel.<p>
31  * The fact that it
32  * does not handle JPasswordField is considered a feature.<p>
33  * <p/>
34  * <b>Warning</b> This class is unlikely to correctly handle
35  * non-string data; i.e. combo boxes with icons etc.
36  */

37
38 public class CBSaveLoadTemplate extends JPanel
39 {
40     protected CBButton save, delete, makeDefault;
41     protected CBJComboBox loadops;
42
43     //public String saveFileName; // the name of the properties file
44
public Properties JavaDoc templates; // the properties object, read from the file
45
// String localDir; // the local directory the properties file is stored in.
46
String JavaDoc configFile; // the config file where we load and save stuff...
47

48     int numTemplates; // the number of options saved in the properties file.
49

50     private boolean saveFlag = false; //TE: flag to show when the user has saved...used to stop the auto update of fields.
51

52     Vector JavaDoc illegalComponents = new Vector JavaDoc(); // components that are specifically not to be messed with.
53

54     static final String JavaDoc NUMTEMPLATES = "number_of_templates";
55     static final String JavaDoc TEMPLATENAME = "template_name";
56     static final String JavaDoc DEFAULT = "default";
57
58     private static Logger JavaDoc log = Logger.getLogger(CBSaveLoadTemplate.class.getName());
59
60     /**
61      * Each CBSaveLoadTemplate object must have a file name to
62      * read and load data from...
63      */

64
65     public CBSaveLoadTemplate(String JavaDoc fileName)
66     {
67         save = new CBButton(CBIntText.get("Save"), CBIntText.get("Click here to save current settings."));
68         makeDefault = new CBButton(CBIntText.get("Default"), CBIntText.get("Click here to make the current setting the default."));
69         delete = new CBButton(CBIntText.get("Delete"), CBIntText.get("Click here to delete a previously saved setting."));
70         loadops = new CBJComboBox();
71         templates = new Properties JavaDoc();
72
73         configFile = parseFile(fileName);
74
75         CBPanel main = new CBPanel();
76
77         main.add(save);
78         main.makeHeavy();
79         main.add(loadops);
80         main.makeLight();
81         main.add(delete);
82         main.add(makeDefault);
83
84         setBorder(new TitledBorder JavaDoc(CBIntText.get(" Use a Template ")));
85         setLayout(new BorderLayout());
86         add(main);
87
88         save.addActionListener(new ActionListener JavaDoc()
89         {
90             public void actionPerformed(ActionEvent JavaDoc e)
91             {
92                 saveFlag = true;
93                 save();
94             }
95         });
96
97         loadops.addActionListener(new ActionListener JavaDoc()
98         {
99             public void actionPerformed(ActionEvent JavaDoc e)
100             {
101                 if (!saveFlag) //TE: don't update fields if user has just saved.
102
load();
103                 saveFlag = false;
104             }
105         });
106         loadops.setToolTipText(CBIntText.get("Click here to load a previously saved setting."));
107
108         delete.addActionListener(new ActionListener JavaDoc()
109         {
110             public void actionPerformed(ActionEvent JavaDoc e)
111             {
112                 int response = showMessage();
113
114                 if (response != JOptionPane.YES_OPTION) //TE: delete confirmation dialog.
115
return;
116
117                 delete();
118             }
119         });
120
121         makeDefault.addActionListener(new ActionListener JavaDoc()
122         {
123             public void actionPerformed(ActionEvent JavaDoc e)
124             {
125                 makeDefault();
126             }
127         });
128     }
129
130
131     /**
132      * Expose the root combo box for the use of adding listeners 'n stuff.
133      */

134
135     public CBJComboBox getLoadComboBox()
136     {
137         return loadops;
138     }
139
140     public CBButton getSaveButton()
141     {
142         return save;
143     }
144
145     /**
146      * Opens an dialog that asks if the user wants to delete the template.
147      *
148      * @return the user response as an integer (see JOptionPane)
149      */

150
151     public int showMessage()
152     {
153         return JOptionPane.showConfirmDialog(this, CBIntText.get("Are you sure you want to delete the template?"),
154                 CBIntText.get("Delete Confirmation"), JOptionPane.YES_NO_OPTION);
155     }
156
157
158     /**
159      * Loads the dafault set up (if one has been saved).
160      * - equivalent to manually loading the template
161      * named 'default'.
162      */

163     public void loadDefault()
164     {
165         String JavaDoc defaultName = templates.getProperty(DEFAULT);
166         if ((defaultName != null) && (defaultName.length() != 0))
167             loadTemplateName(defaultName);
168     }
169
170
171     /*
172      * parses a file and loads the data into a Properties object,
173      * and then into the loadops combo box.
174      * Returns the full path of the config file.
175      */

176
177     protected String JavaDoc parseFile(String JavaDoc fileName)
178     {
179         String JavaDoc configFile = CBUtility.getPropertyConfigPath(fileName);
180         if (configFile == null)
181         {
182             CBUtility.error(this, "Unable to read user home directory ", null);
183             return fileName;
184         }
185
186         templates = CBUtility.readPropertyFile(configFile);
187         if (templates.size() == 0)
188         {
189             log.info("Initialising config file: " + configFile);
190             return configFile;
191         }
192
193         String JavaDoc temp = templates.getProperty(NUMTEMPLATES);
194         if (temp == null)
195         {
196             CBUtility.error(this, "Unable to read number of templates paramater from: " + configFile, null);
197             return configFile;
198         }
199
200
201         numTemplates = Integer.parseInt(temp);
202
203         for (int i = 0; i < numTemplates; i++)
204         {
205             temp = templates.getProperty(TEMPLATENAME + i);
206             loadops.addItem(temp);
207         }
208         // make sure the default option is currently shown by the combo box.
209
String JavaDoc defaultName = templates.getProperty(DEFAULT);
210         loadops.setSelectedItem(defaultName);
211
212         return configFile;
213     }
214
215     public String JavaDoc getCurrentTemplateName()
216     {
217         String JavaDoc currentTemplateName = (String JavaDoc) loadops.getSelectedItem();
218         if (currentTemplateName == null) return "";
219         return currentTemplateName;
220     }
221
222     /**
223      * saves a dialog windows state by working through all the
224      * components held by the parent container, and if they are
225      * (selected) User Input objects (TextFields etc.) saving
226      * their contents to a properties list.
227      */

228
229     public void save()
230     {
231         String JavaDoc currentTemplateName = getCurrentTemplateName();
232         String JavaDoc templateName = (String JavaDoc) JOptionPane.showInputDialog(this, CBIntText.get("Enter template name") + ":", CBIntText.get("Replace/Create Template"), JOptionPane.QUESTION_MESSAGE, null, null, currentTemplateName);
233         if (templateName == null) return; // user cancelled.
234
saveTemplateName(templateName);
235         loadops.setSelectedItem(templateName); //TE: make sure the saved template is the current selection in the combo box.
236
}
237
238     public void saveTemplateName(String JavaDoc templateName)
239     {
240         templateName = templateName.replace('.', '-'); // el hack. We use dots to do magic with... so bar user from using them and hope no-one ever notices...
241
if (templateName == null) return; // user selected 'cancel'
242
Container parent = getParent();
243         saveContainerInfo(parent, templateName); // save parent container
244

245         /*
246          * Use a brute-force search to discover if we already have
247          * a template with the newly entered name (i.e. user is
248          * updating an existing entry) by iterating through all
249          * template name properties until we find a matching one (or not).
250          */

251         boolean we_already_got_one = false;
252         for (int i = 0; i < numTemplates; i++)
253         {
254             String JavaDoc test = (String JavaDoc) templates.getProperty(TEMPLATENAME + i);
255             if ((test != null) && (test.equals(templateName)))
256             {
257                 we_already_got_one = true;
258                 break;
259             }
260         }
261
262         if (we_already_got_one == false)
263         {
264             templates.setProperty(TEMPLATENAME + numTemplates, templateName);
265             numTemplates++;
266             templates.setProperty(NUMTEMPLATES, Integer.toString(numTemplates));
267             loadops.addItem(templateName);
268         }
269
270         CBUtility.writePropertyFile(configFile, templates, "");
271
272     }
273
274     /**
275      * iterates through a container, saving user-entry components as it goes.
276      *
277      * @param myContainer container to save
278      * @param templateName unique name for this template and component
279      */

280
281     public void saveContainerInfo(Container myContainer, String JavaDoc templateName)
282     {
283         if (myContainer == null)
284         {
285             log.warning("Unexpected error in CBSaveLoadTemplate.save() - no parent found");
286             return;
287         } // should never happen
288
Component[] components = myContainer.getComponents();
289         for (int i = 0; i < components.length; i++)
290         {
291             Component c = components[i];
292
293             saveComponent(c, i, templateName);
294
295         }
296     }
297
298     /**
299      * This method handles the saving of a particular component. If
300      * the class needs to be extended, extra handling for particular
301      * components may need to be added, in which case this method
302      * can be extended.
303      *
304      * @param c the component to save
305      * @param componentNo the index of the component
306      * @param templateName the name of the template being saved to.
307      */

308
309     protected void saveComponent(Component c, int componentNo, String JavaDoc templateName)
310     {
311         if ((c instanceof JPanel) && (c != this)) // if it's a container (and not this component), recurse and save those...
312
{
313             saveContainerInfo((Container) c, templateName + "." + componentNo);
314         }
315         else if ((c instanceof JScrollPane) && (c != this))
316         {
317             saveContainerInfo((Container) c, templateName + "." + componentNo);
318         }
319         else if ((c instanceof JViewport) && (c != this))
320         {
321             saveContainerInfo((Container) c, templateName + "." + componentNo);
322         }
323         else
324         {
325             String JavaDoc saveText = getComponentText(c);
326             if (saveText != null)
327                 templates.setProperty(templateName + "." + componentNo, saveText);
328         }
329     }
330
331
332     /**
333      * this ftn returns the text to save for a given component, and
334      * is the sister ftn to 'loadComponentText'. New components
335      * (including awt components) can be added here, by
336      * extracting their value as text, and making sure that loadComponentText
337      * correctly translates that value when loading.
338      *
339      * @param c the component to retrieve a text value for.
340      * @return the text value of the component.
341      */

342     public String JavaDoc getComponentText(Component c)
343     {
344         if (c == null) return null; // don't get null components
345

346         if (illegalComponents.contains(c)) return null; // don't get forbidden components.
347

348         try
349         {
350             if (c instanceof JPasswordField) // don't save passwords
351
return "";
352             else if (c instanceof JTextField)
353                 return ((JTextField) c).getText();
354             else if (c instanceof JTextArea)
355                 return ((JTextArea) c).getText();
356             else if (c instanceof TextField)
357                 return ((TextField) c).getText();
358             else if (c instanceof JToggleButton)
359                 return String.valueOf(((JToggleButton) c).isSelected());
360             else if (c instanceof CBJComboBox)
361                 return ((CBJComboBox) c).getSelectedItem().toString();
362             else
363                 return null; // unknown component
364
}
365         catch (Exception JavaDoc e)
366         {
367             return null;
368         } // possibility of uninitialised objects above...may cause problems.
369
}
370
371
372     /**
373      * Takes a template name, and attempts to read all the (string)
374      * values belonging to that template, and toss them in the
375      * appropriate numbered component.
376      */

377
378     public void load()
379     {
380         String JavaDoc templateName = getCurrentTemplateName();
381
382         if (templateName.length() == 0)
383         {
384             CBUtility.error(this, CBIntText.get("No template selected!"), null);
385             return;
386         }
387         loadTemplateName(templateName);
388     }
389
390     public void loadTemplateName(String JavaDoc templateName)
391     {
392         Container parent = getParent();
393
394         loadContainerInfo(parent, templateName);
395     }
396
397     public void loadContainerInfo(Container myContainer, String JavaDoc templateName)
398     {
399         if (myContainer == null)
400         {
401             log.warning("Unexpected error in CBSaveLoadTemplate.load() - no parent found");
402             return;
403         } // should never happen
404
Component[] components = myContainer.getComponents();
405
406         for (int i = 0; i < components.length; i++)
407         {
408             Component c = components[i];
409             loadComponent(c, i, templateName);
410         }
411     }
412
413
414     /**
415      * This method handles the loading of a particular component. If
416      * the class needs to be extended, extra handling for particular
417      * components may need to be added, in which case this method
418      * can be extended.
419      *
420      * @param c the component to load
421      * @param componentNo the index of the component
422      * @param templateName the name of the template being loaded from.
423      */

424
425     protected void loadComponent(Component c, int componentNo, String JavaDoc templateName)
426     {
427         if (c instanceof JPanel) // recurse into container details.
428
{
429             loadContainerInfo((Container) c, templateName + "." + componentNo);
430         }
431         else if ((c instanceof JScrollPane))
432         {
433             loadContainerInfo((Container) c, templateName + "." + componentNo);
434         }
435         else if ((c instanceof JViewport))
436         {
437             loadContainerInfo((Container) c, templateName + "." + componentNo);
438         }
439         else
440         {
441             String JavaDoc text = (String JavaDoc) templates.get(templateName + "." + componentNo); // often there won't be a value...
442
if (text != null) // ... if there is, load the data up!
443
{
444                 loadComponentText(c, text);
445             }
446         }
447     }
448
449     public void loadComponentText(Component c, String JavaDoc text)
450     {
451         if (illegalComponents.contains(c)) return; // don't load forbidden components.
452

453         if (c instanceof JTextField)
454             ((JTextField) c).setText(text);
455         else if (c instanceof JTextArea)
456             ((JTextArea) c).setText(text);
457         else if (c instanceof TextField)
458             ((TextField) c).setText(text);
459         else if (c instanceof JToggleButton)
460             ((JToggleButton) c).setSelected("true".equalsIgnoreCase(text));
461         else if (c instanceof CBJComboBox)
462         {
463             ((CBJComboBox) c).setSelectedItem(text);
464         }
465     }
466
467     public void delete()
468     {
469         String JavaDoc templateName = getCurrentTemplateName();
470         if (templateName.length() == 0)
471         {
472             CBUtility.error(this, "No template selected!", null);
473             return;
474         }
475
476         Container parent = getParent();
477         if (parent == null)
478         {
479             log.warning("Unexpected error in CBSaveLoadTemplate.delete() - no parent found");
480             return;
481         } // should never happen
482
deleteComponentInfo(parent, templateName);
483
484         for (int i = 0; i < numTemplates; i++)
485         {
486             if (templateName.equals((String JavaDoc) templates.get(TEMPLATENAME + i)))
487             {
488                 templates.remove(TEMPLATENAME + i);
489                 numTemplates--;
490                 templates.put(NUMTEMPLATES, Integer.toString(numTemplates));
491                 loadops.removeItem(templateName);
492
493                 // and shuffle down all the values from above!
494
// (you know, there's got to be a neater way of doing this...)
495
for (int j = i + 1; j <= numTemplates; j++)
496                 {
497                     templateName = (String JavaDoc) templates.get(TEMPLATENAME + j);
498                     templates.put(TEMPLATENAME + (j - 1), templateName);
499                 }
500                 templates.remove(TEMPLATENAME + numTemplates);
501
502                 break;
503             }
504         }
505         CBUtility.writePropertyFile(configFile, templates, null);
506     }
507
508     public void deleteComponentInfo(Container myContainer, String JavaDoc templateName)
509     {
510         Component[] components = myContainer.getComponents();
511
512
513         // Brute force delete - most of these don't exist, but attempting deletion does no harm...
514
for (int i = 0; i < components.length; i++)
515         {
516             if (components[i] instanceof JPanel)
517                 deleteComponentInfo((Container) components[i], templateName + "." + i);
518             else if ((components[i] instanceof JScrollPane))
519                 deleteComponentInfo((Container) components[i], templateName + "." + i);
520             else if ((components[i] instanceof JViewport))
521                 deleteComponentInfo((Container) components[i], templateName + "." + i);
522             else
523                 deleteComponentInfo(templateName + "." + i);//templates.remove(templateName + "." + i);
524
}
525
526         try
527         { //TE: if the default template is being deleted, also delete the 'defaul' entry in the property file.
528
if (templates.getProperty("default") != null && templates.getProperty("default").equalsIgnoreCase(templateName))
529                 templates.remove("default");
530         }
531         catch (Exception JavaDoc e)
532         {
533             log.log(Level.WARNING, "No default template. ", e);
534         }
535     }
536
537
538     /**
539      * Deletes a template that is saved in the property file. Can be extended
540      * to account for individual component handling e.g. combo box visibility.
541      *
542      * @param templateName the name of the template that is to be deleted from the property file.
543      */

544
545     public void deleteComponentInfo(String JavaDoc templateName)
546     {
547         templates.remove(templateName);
548     }
549
550     public void makeDefault()
551     {
552         templates.setProperty(DEFAULT, getCurrentTemplateName());
553         CBUtility.writePropertyFile(configFile, templates, "");
554     }
555
556     public void addIllegalComponent(Component c)
557     {
558         illegalComponents.add(c);
559     }
560
561 }
Popular Tags