source: trunk/gli/src/org/greenstone/gatherer/gui/OptionsPane.java@ 4346

Last change on this file since 4346 was 4346, checked in by kjdon, 21 years ago

added in a log history list for build messages

  • Property svn:keywords set to Author Date Id Revision
File size: 27.0 KB
Line 
1package org.greenstone.gatherer.gui;
2/**
3 *#########################################################################
4 *
5 * A component of the Gatherer application, part of the Greenstone digital
6 * library suite from the New Zealand Digital Library Project at the
7 * University of Waikato, New Zealand.
8 *
9 * <BR><BR>
10 *
11 * Author: John Thompson, Greenstone Digital Library, University of Waikato
12 *
13 * <BR><BR>
14 *
15 * Copyright (C) 1999 New Zealand Digital Library Project
16 *
17 * <BR><BR>
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * <BR><BR>
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 *
31 * <BR><BR>
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36 *########################################################################
37 */
38import java.awt.*;
39import java.awt.event.*;
40import java.io.*;
41import java.util.*;
42import javax.swing.*;
43import javax.swing.event.*;
44import org.greenstone.gatherer.Gatherer;
45import org.greenstone.gatherer.cdm.Argument;
46import org.greenstone.gatherer.checklist.CheckList;
47import org.greenstone.gatherer.collection.BuildOptions;
48import org.greenstone.gatherer.collection.Collection;
49import org.greenstone.gatherer.collection.CollectionManager;
50import org.greenstone.gatherer.msm.ElementWrapper;
51import org.greenstone.gatherer.util.Utility;
52import org.w3c.dom.*;
53/** This class serves as the data holder for all subclasses of option panes, such as Import options or All options. It also contains methods for creating each of the option lines as they would appear in the subpane. Futhermore it has a method for considering all the arguments and generating a <strong>String[]</strong> to allow you to pass them to the <strong>GShell</strong>.
54 * @author John Thompson, Greenstone Digital Library, University of Waikato
55 * @version 2.2
56 */
57final public class OptionsPane
58 extends JPanel {
59 /** The <strong>BuildOptions</strong> data object contains all the option settings we wish to persist between Gatherer sessions (and thus is stored in <strong>Collection</strong>). */
60 private BuildOptions build_options = null;
61 /** the log pane - we only create it once now, not each time */
62 private JPanel log_pane = null;
63 /** the list of previous log messages */
64 private JList log_list = null;
65 /** whether that currently showing log is changed or not */
66 private boolean is_log_changed = false;
67 /** the list entry that is currently displayed */
68 private FileEntry displayed_log = null;
69 /** a listener for changes in the log text */
70 private LogChangeListener log_change_listener = null;
71 /** All process messages are written to this log text area. */
72 private JTextArea log_display = null;
73
74 static final public char SUCCESSFUL = 's';
75 static final public char UNSUCCESSFUL = 'u';
76 static final public char CANCELLED = 'c';
77
78 static private int BUILD = 0;
79 static private int IMPORT = 1;
80 static private Dimension LABEL_SIZE = new Dimension(180, 25);
81 static private Dimension LOG_SIZE = new Dimension(610, 360);
82 /** The minimum size of a options pane, to prevent refresh problems around the bottom of shorter panes. */
83 static private Dimension PANE_SIZE = new Dimension(610, 350);
84 static private Dimension ROW_SIZE = new Dimension(610, 25);
85 static private Dimension SPINNER_SIZE = new Dimension(100, 25);
86 static private String DESCRIPTION_SEP = " + ";
87
88
89 /** The default constructor creates the few session length options, but either retrieves the rest from the current collection, or creates a default set of options. */
90 public OptionsPane(JTextArea log, BuildOptions build_options) {
91 this.log_display = log;
92 this.build_options = build_options;
93 this.log_change_listener = new LogChangeListener();
94 //this.target_pane = target_pane;
95 }
96
97 /** creates a new log from the text in log. The new file is named
98 * build_log.<current time>.txt. A new FileEntry is added to teh log list
99 * and made selected. A fresh listener is added to teh document */
100 public void addNewLog(char success) {
101 ///ystem.out.println("add new log");
102
103 // create the file name
104 long time = System.currentTimeMillis();
105 StringBuffer name = new StringBuffer();
106 name.append("build_log.");
107 name.append(time);
108 name.append(success);
109 name.append(".txt");
110 File f = new File(Gatherer.c_man.getCollectionLog()+name.toString());
111 // just in case there is no log directory
112 File parent_file = f.getParentFile();
113 parent_file.mkdirs();
114
115 // save the log text to the file
116 saveLogFile(f);
117 is_log_changed=false;
118 log_display.getDocument().addDocumentListener(log_change_listener);
119
120 // create the file entry and add it to the list at pos 0 - it will always be the newest one created
121 FileEntry fe = new FileEntry(f);
122 ((DefaultListModel)log_list.getModel()).add(0, fe);
123 log_list.setSelectedIndex(0);
124 displayed_log = fe;
125
126 }
127
128 /** This method creates the panel with all the build only options on it.
129 * @return A <strong>JPanel</strong> which can be used to display all the build only options.
130 */
131 public JPanel buildBuild() {
132 JPanel pane = new JPanel();
133 pane.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
134 pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
135 int build_argument_count = build_options.getBuildArgumentCount();
136 pane.setLayout(new GridLayout(build_argument_count, 1, 0, 0));
137 int total_height = PANE_SIZE.height;
138 for(int i = 0; i < build_argument_count; i++) {
139 // Retrieve the argument so we know how to format the control.
140 Argument argument = build_options.getBuildArgument(i);
141 // Now attempt to retrieve any existing value for this argument.
142 boolean enabled = build_options.getBuildValueEnabled(argument.getName());
143 String value = build_options.getBuildValue(argument.getName());
144 ArgumentControl argument_control = new ArgumentControl(BUILD, argument, enabled, value);
145 total_height = total_height - argument_control.getPreferredSize().height;
146 pane.add(argument_control);
147 }
148 if(total_height > 0) {
149 JPanel filler = new JPanel();
150 filler.setPreferredSize(new Dimension(100, total_height));
151 filler.setSize(filler.getPreferredSize());
152 pane.add(filler);
153 }
154 return pane;
155 }
156 /** This method creates the panel with all the import only options on it.
157 * @return A <strong>JPanel</strong> which can be used to display all the import only options.
158 */
159 public JPanel buildImport() {
160 JPanel pane = new JPanel();
161 pane.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
162 pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
163 int import_argument_count = build_options.getImportArgumentCount();
164 pane.setLayout(new GridLayout(import_argument_count, 1, 0, 0));
165 int total_height = PANE_SIZE.height;
166 for(int i = 0; i < import_argument_count; i++) {
167 // Retrieve the argument so we know how to format the control.
168 Argument argument = build_options.getImportArgument(i);
169 // Now attempt to retrieve any existing value for this argument.
170 boolean enabled = build_options.getImportValueEnabled(argument.getName());
171 String value = build_options.getImportValue(argument.getName());
172 ArgumentControl argument_control = new ArgumentControl(IMPORT, argument, enabled, value);
173 total_height = total_height - argument_control.getPreferredSize().height;
174 pane.add(argument_control);
175 }
176 if(total_height > 0) {
177 JPanel filler = new JPanel();
178 filler.setPreferredSize(new Dimension(100, total_height));
179 filler.setSize(filler.getPreferredSize());
180 pane.add(filler);
181 }
182 return pane;
183 }
184 /** This method is used to build a panel based on the message log, which is nothing like any of the other panels.
185 * @return A <strong>JPanel</strong> containing a scrollable text area which represents the shell process message log.
186 */
187 public JPanel buildLog() {
188 // we now save the log pane
189 if (log_pane == null) {
190 log_pane = new JPanel(new BorderLayout());
191
192 // Build a list of the log files available, ordering by last modified. Log files are like build_log.date.txt
193 DefaultListModel contents = new DefaultListModel();
194 File log_directory = new File(Gatherer.c_man.getCollectionLog());
195 File children[] = log_directory.listFiles();
196 for(int i = 0; children != null && i < children.length; i++) {
197 if(children[i].getName().startsWith("build_log")&&children[i].getName().endsWith(".txt") ) {
198 FileEntry entry = new FileEntry(children[i]);
199 // We are about to insert it. But where.
200 boolean found = false;
201 for(int j = 0; j < contents.size(); j++) {
202 FileEntry sibling = (FileEntry) contents.getElementAt(j);
203 int order = entry.compareTo(sibling);
204 if(order > 0) {
205 contents.insertElementAt(entry, j);
206 found = true;
207 break;
208 }
209 }
210 if(!found) {
211 contents.addElement(entry);
212 }
213 }
214 }
215
216 log_list = new JList(contents);
217 log_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
218 log_list.setLayoutOrientation(JList.VERTICAL);
219 log_list.setVisibleRowCount(3);
220 log_list.addListSelectionListener(new LogListListener());
221
222 JScrollPane list_scroller = new JScrollPane(log_list);
223
224 // If log is not empty and we have something in displayed_log - make that element selected
225 if (log_display.getText().length()>0 && displayed_log != null) {
226 int index = contents.indexOf(displayed_log);
227 if (index != -1) {
228 log_list.setSelectedIndex(index);
229 }
230
231 }
232 log_pane.add(new JScrollPane(log_display), BorderLayout.CENTER);
233 JLabel log_history_label = new JLabel(get("LogHistory"));
234 JPanel log_history_pane = new JPanel();
235 log_history_pane.setLayout(new BorderLayout());
236 log_history_pane.add(log_history_label, BorderLayout.NORTH);
237 log_history_pane.add(list_scroller, BorderLayout.SOUTH);
238 log_pane.add(log_history_pane, BorderLayout.SOUTH);
239 }
240 return log_pane;
241 }
242
243 /** This method retrieves a phrase from the dictionary based apon the key.
244 * @param key A <strong>String</strong> used as a reference to the correct phrase.
245 * @return A phrase, matching the key, as a <strong>String</strong>.
246 */
247 private String get(String key) {
248 return get(key, null);
249 }
250 /** This method retrieves a phrase from the dictionary based apon the key and arguments.
251 * @param key A <strong>String</strong> used as a reference to the correct phrase.
252 * @param args A <strong>String[]</strong> whose contents are often substituted into the phrase before it is returned.
253 * @return A phrase, matching the key and constructed using the arguments, as a <strong>String</strong>.
254 * @see org.greenstone.gatherer.Dictionary
255 * @see org.greenstone.gatherer.Gatherer
256 */
257 private String get(String key, String args[]) {
258 if(key.indexOf(".") == -1) {
259 key = "OptionsPane." + key;
260 }
261 return Gatherer.dictionary.get(key, args);
262 }
263 /** Attempts to discover the latest document count.
264 * @return An <strong>int</strong> detailing the number of documents in this collection.
265 */
266 public int getDocumentCount() {
267 if(Gatherer.c_man.ready()) {
268 int count = Gatherer.c_man.getCollection().getDocumentCount();
269 if(count != 0) {
270 return count;
271 }
272 }
273 return 1;
274 }
275
276 /** Loads a new log into the log text - saves the currently showing one,
277 * and loads the new one, adding a fresh listener to the document
278 * Note, we need to remove any listener before making the changes, then
279 * add a listener back in
280 */
281 public void loadSelectedLog(FileEntry fe) {
282 ///ystem.out.println("load selected log");
283 if (is_log_changed) {
284 saveLogFile(displayed_log.getFile());
285 } else {
286 log_display.getDocument().removeDocumentListener(log_change_listener);
287 }
288
289 displayed_log = fe;
290 if (fe != null) {
291 log_display.setText(fe.getFileText());
292 } else {
293 log_display.setText("");
294 }
295 is_log_changed=false;
296 log_display.getDocument().addDocumentListener(log_change_listener);
297
298 }
299
300 /** Neutralizes the log list - saves any unsaved changes to the current log
301 * clears the log text, unselects the log list, and adds a fresh listener
302 * to the log's document
303 * Note, we need to remove any listener before making the changes, then
304 * add a listener back in */
305 public void resetLogList() {
306 ///ystem.out.println("reset log");
307 if (is_log_changed) {
308 saveLogFile(displayed_log.getFile());
309 } else {
310 log_display.getDocument().removeDocumentListener(log_change_listener);
311 }
312 log_display.setText("");
313 displayed_log = null;
314 if (log_list != null) {
315 log_list.clearSelection();
316 }
317 is_log_changed=false;
318 log_display.getDocument().addDocumentListener(log_change_listener);
319
320 }
321
322 /** saves the current text in log to the File specified */
323 public void saveLogFile(File file) {
324
325 try {
326 BufferedWriter out = new BufferedWriter(new FileWriter(file)); // uses the default encoding
327 String log_text = log_display.getText();
328 // set teh return delims to true, then swap them for newLine() (platform dependent) - having return delims set to false seemed to not get empty strings so that empty lines were not preserved.
329 StringTokenizer t = new StringTokenizer(log_text, "\n", true);
330 while (t.hasMoreTokens()) {
331 String token = t.nextToken();
332 if (token.equals("\n")) {
333 out.newLine();
334 } else {
335 out.write(token, 0, token.length());
336 }
337
338 }
339 out.close();
340
341 } catch(Exception e) {
342 System.out.println("Error in saving log file: "+file.toString());
343 e.printStackTrace();
344 }
345
346
347 }
348
349
350 /** Given a panel containing ArgumentControls, update the values associated with them. */
351 public void update(JPanel panel) {
352 if(panel == log_pane) {
353 return;
354 }
355
356 for(int i = 0; i < panel.getComponentCount(); i++) {
357 Component component = panel.getComponent(i);
358 if(component instanceof ArgumentControl) {
359 ((ArgumentControl)component).update();
360 }
361 }
362 }
363
364 private class ArgumentControl
365 extends JPanel {
366 private Argument argument;
367 private int type;
368 private JComponent value_control;
369 private JCheckBox enabled;
370 public ArgumentControl(int type, Argument argument, boolean enable, String value) {
371 super();
372 this.argument = argument;
373 this.type = type;
374 String tooltip = Utility.formatHTMLWidth("<html>" + argument.getDesc() + "</html>", 60);
375 // Because of the dynamic order of component creation/connection/layout, we can't really follow that pattern here.
376 setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
377 setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
378 setLayout(new BorderLayout());
379 setPreferredSize(ROW_SIZE);
380
381 /*
382 JPanel inner_pane = new JPanel();
383 inner_pane.setOpaque(false);
384 */
385
386 // Try to determine what the value_controls value should be.
387 if(value == null) {
388 value = argument.getDefaultValue();
389 }
390 // Create a correct value control based on the argument provided.
391 switch(argument.getType()) {
392 case Argument.ENUM:
393 JComboBox combobox = new JComboBox();
394 combobox.setEnabled(enable);
395 combobox.setToolTipText(tooltip);
396 // Set enabled
397 if(enable) {
398 combobox.setBackground(Color.white);
399 }
400 else {
401 combobox.setBackground(Color.lightGray);
402 }
403 // Build an option model, wrapping each entry of the list table.
404 HashMap arg_list = argument.getList();
405 Iterator it = arg_list.keySet().iterator();
406 while(it.hasNext()) {
407 combobox.addItem((String) it.next());
408 }
409 // Connect this up first, so that if a value is selected the tooltip updates accordingly.
410 combobox.addActionListener(new ToolTipUpdater(arg_list));
411 if(value != null) {
412 // Set the selected string. However since they are all strings we had best iterate ourselves.
413 for(int i = 0; i < combobox.getItemCount(); i++) {
414 if(combobox.getItemAt(i).toString().equals(value)) {
415 combobox.setSelectedIndex(i);
416 }
417 }
418 }
419 // Layout
420 add(combobox, BorderLayout.CENTER);
421 // And remember
422 value_control = combobox;
423 break;
424 case Argument.FLAG:
425 // Only need the check box.
426 value_control = null;
427 break;
428 case Argument.INTEGER:
429 // Build a spinner
430 JSpinner spinner = new JSpinner();
431 spinner.setEnabled(enable);
432 spinner.setPreferredSize(SPINNER_SIZE);
433 spinner.setToolTipText(tooltip);
434 // Set enabled
435 JComponent c = spinner.getEditor();
436 if ( c instanceof JSpinner.DefaultEditor ) {
437 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
438 JFormattedTextField field = editor.getTextField();
439 field.setEditable(enable);
440 if(enable) {
441 field.setBackground(Color.white);
442 }
443 else {
444 field.setBackground(Color.lightGray);
445 }
446 }
447 // If there was an original value, set it.
448 if(value != null) {
449 try {
450 spinner.setValue(new Integer(value));
451 }
452 catch (Exception error) {
453 }
454 }
455 // Layout
456 add(new JLabel(), BorderLayout.CENTER);
457 add(spinner, BorderLayout.EAST);
458 // And remember it
459 value_control = spinner;
460 break;
461 case Argument.STRING:
462 // Use a standard text field
463 JTextField textfield = new JTextField();
464 textfield.setEnabled(enable);
465 textfield.setToolTipText(tooltip);
466 // Set enabled
467 if(enable) {
468 textfield.setBackground(Color.white);
469 }
470 else {
471 textfield.setBackground(Color.lightGray);
472 }
473 // If there was an original value, set it.
474 if(value != null) {
475 textfield.setText(value);
476 }
477 // Layout
478 add(textfield, BorderLayout.CENTER);
479 // And remember it
480 value_control = textfield;
481 break;
482 }
483
484 // If the argument is required, then you don't get a choice of whether it is enabled.
485 if(argument.isRequired()) {
486 JLabel label = new JLabel(argument.getName());
487 label.setOpaque(false);
488 label.setPreferredSize(LABEL_SIZE);
489 label.setToolTipText(tooltip);
490 add(label, BorderLayout.WEST);
491 }
492 else {
493 enabled = new JCheckBox(argument.getName(), enable);
494 enabled.setOpaque(false);
495 enabled.setPreferredSize(LABEL_SIZE);
496 enabled.setToolTipText(tooltip);
497 // Connect
498 enabled.addActionListener(new EnabledListener(value_control));
499 // Layout
500 add(enabled, BorderLayout.WEST);
501 }
502 }
503
504 /** Update the values stored in the collection so as to rememebr the current state of this argument. */
505 public void update() {
506 String name = argument.getName();
507 boolean enable = true;
508 if(enabled != null) {
509 enable = enabled.isSelected();
510 }
511 String value = null;
512 if(value_control == null) {
513 // Flag value, nothing to do.
514 }
515 else if(value_control instanceof JTextField) {
516 value = ((JTextField)value_control).getText();
517 }
518 else if(value_control instanceof JSpinner) {
519 value = ((JSpinner)value_control).getValue().toString();
520 }
521 else if(value_control instanceof JComboBox) {
522 value = (String) ((JComboBox)value_control).getSelectedItem();
523 }
524 // If this argument was a flag, but is now disabled, remove from the build options altogether
525 if(!enable && value == null) {
526 if(type == BUILD) {
527 build_options.removeBuildValue(name);
528 }
529 else {
530 build_options.removeImportValue(name);
531 }
532 }
533 // Otherwise update the argument value
534 else {
535 if(type == BUILD) {
536 build_options.setBuildValue(name, enable, value);
537 }
538 else {
539 build_options.setImportValue(name, enable, value);
540 }
541 }
542 }
543 }
544
545 /** Listens for actions apon the enable checkbox, and if detected enables or diables control appropriately. */
546 private class EnabledListener
547 implements ActionListener {
548 /** An editor component, such as a JComboBox or JTextField, that might have its enabled state changed by this listener. */
549 private JComponent target = null;
550 /** Constructor. */
551 public EnabledListener(JComponent target) {
552 this.target = target;
553 }
554 /** Any implementation of ActionListener must include this method so that we can be informed when an action has been performed on or registered check box, prompting us to change the state of the other controls as per the users request.
555 * @param event An <strong>ActionEvent</strong> containing information about the click.
556 */
557 public void actionPerformed(ActionEvent event) {
558 JCheckBox source = (JCheckBox)event.getSource();
559 if(target != null) {
560 if(source.isSelected()) {
561 target.setBackground(Color.white);
562 target.setEnabled(true);
563 }
564 else {
565 target.setBackground(Color.lightGray);
566 target.setEnabled(false);
567 }
568 // Special case of stupid JSpinners who don't let their backgrounds change properly.
569 if(target instanceof JSpinner) {
570 JSpinner spinner = (JSpinner) target;
571 JComponent c = spinner.getEditor();
572 if ( c instanceof JSpinner.DefaultEditor ) {
573 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
574 JFormattedTextField field = editor.getTextField();
575 field.setEditable(source.isSelected());
576 if(source.isSelected()) {
577 field.setBackground(Color.white);
578 }
579 else {
580 field.setBackground(Color.lightGray);
581 }
582 }
583 }
584 }
585 }
586 }
587
588 /** holds a File which has a particular naming convention
589 * build_log.date.txt
590 * also keeps a Date corresponding to the date in its name*/
591 private class FileEntry {
592
593 private Date date=null;
594 private File file=null;
595 private String display=null;
596 public FileEntry(File f) {
597 this.file=f;
598 this.date = getDateFromFileName();
599 this.display = createDisplayText();
600
601 }
602
603 /** returns 0 if the dates are the same, -ve number if the current FileEntry is earlier than the fe FileEntry ...*/
604 public int compareTo(FileEntry fe) {
605 Date d = fe.getDate();
606 return date.compareTo(d);
607 }
608
609 public Date getDate() {
610 return this.date;
611 }
612 public File getFile() {
613 return this.file;
614 }
615 /** returns the contents of the file */
616 public String getFileText() {
617 if (!this.file.exists()) {
618 return "";
619 }
620 StringBuffer contents = new StringBuffer();
621 try {
622 BufferedReader in = new BufferedReader(new FileReader(this.file));
623 String line;
624
625 while ((line = in.readLine()) != null) {
626 contents.append(line);
627 contents.append("\n");
628 }
629 } catch (FileNotFoundException fnfe) {
630 System.err.println("Error: log file not found: "+ this.file.toString());
631 return "";
632 } catch (IOException ioe) {
633 System.err.println("Error: exception occurred when trying to read in file "+this.file.toString()+", "+ioe.getMessage());
634
635 }
636
637 return contents.toString();
638 }
639 /** we only want the date out of the file name, not the whole path */
640 public String toString() {
641 return this.display;
642 }
643 /** creates the display text for the list */
644 private String createDisplayText() {
645 StringBuffer d = new StringBuffer();
646 d.append(date.toString());
647 char success= this.file.getName().charAt(23);
648 switch (success) {
649 case OptionsPane.SUCCESSFUL:
650 d.append(get("Successful"));
651 break;
652 case OptionsPane.UNSUCCESSFUL:
653 d.append(get("Unsuccessful"));
654 break;
655 case OptionsPane.CANCELLED:
656 d.append(get("Cancelled"));
657 break;
658 }
659 return d.toString();
660 }
661 /** extracts the date from the file name */
662 private Date getDateFromFileName() {
663 String name = this.file.getName();
664 String date_string = name.substring(10, 23);//name.length()-4);
665 return new Date(Long.parseLong(date_string));
666 }
667
668
669 }
670
671 /** A DocumentListener that listens for changes in the log_display document
672 * if a change is registered, the flag is_log_changed is set to true,
673 * and the listener removes itself from log_display
674 * Because we only want to register user's changes, the listener must be removed before the system makes any changes, and then put back. For example, each time we switchlogs to display, a remove event and an insert event are sent. We dont want to register these as changes to the document, so the listener must be removed before the switch, and added back afterwards */
675 private class LogChangeListener implements DocumentListener {
676
677 public void changedUpdate(DocumentEvent e) {
678 ///ystem.out.println("changed update");
679 registerChange();
680 }
681 public void insertUpdate(DocumentEvent e) {
682 ///ystem.out.println("insert update");
683 registerChange();
684 }
685 public void removeUpdate(DocumentEvent e) {
686 ///ystem.out.println("remove update");
687 registerChange();
688 }
689
690 private void registerChange() {
691 ///ystem.err.println("a change in the doc occurred, removing the listener");
692 is_log_changed = true;
693 log_display.getDocument().removeDocumentListener(this);
694 }
695 }
696
697 /** a ListSelectionListener that triggers the load of a newly selected
698 log */
699 private class LogListListener implements ListSelectionListener {
700
701 public void valueChanged(ListSelectionEvent e) {
702 if (!e.getValueIsAdjusting()) { // we get two events for one change in list selection - use the false one ( the second one)
703 JList source = (JList)e.getSource();
704 FileEntry fe = (FileEntry) source.getSelectedValue();
705 loadSelectedLog(fe);
706 }
707 }
708 }
709
710 /** Listener that sets the tooltip associated to a combobox to the tooltip relevant to the selected item. */
711 private class ToolTipUpdater
712 implements ActionListener {
713 private HashMap arg_list;
714 public ToolTipUpdater(HashMap arg_list) {
715 this.arg_list = arg_list;
716 }
717 /** Any implementation of an ActionListener must include this method so that we can be informed when the selection in a combobox has changed and update the tooltip accordingly.
718 * @param event An <strong>ActionEvent</strong> containing information about the action that fired this call.
719 */
720 public void actionPerformed(ActionEvent event) {
721 JComboBox source = (JComboBox)event.getSource();
722 String key = (String) source.getSelectedItem();
723 if(arg_list != null) {
724 String description = (String) arg_list.get(key);
725 if(description != null) {
726 description = Utility.formatHTMLWidth(DESCRIPTION_SEP + description, 60);
727 String original = source.getToolTipText();
728 if(original == null) {
729 original = "";
730 }
731 // Remove any existing extra description.
732 if(original.indexOf(DESCRIPTION_SEP) != -1) {
733 original = original.substring(0, original.indexOf(DESCRIPTION_SEP));
734 }
735 source.setToolTipText(original + description);
736 }
737 }
738 }
739 }
740
741
742}
Note: See TracBrowser for help on using the repository browser.