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

Last change on this file since 7999 was 7999, checked in by mdewsnip, 20 years ago

Removed some dead code.

  • Property svn:keywords set to Author Date Id Revision
File size: 29.9 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.gui;
38
39import java.awt.*;
40import java.awt.event.*;
41import java.io.*;
42import java.util.*;
43import javax.swing.*;
44import javax.swing.event.*;
45import javax.swing.text.*;
46import org.greenstone.gatherer.Configuration;
47import org.greenstone.gatherer.Dictionary;
48import org.greenstone.gatherer.Gatherer;
49import org.greenstone.gatherer.cdm.Argument;
50import org.greenstone.gatherer.collection.BuildOptions;
51import org.greenstone.gatherer.collection.Collection;
52import org.greenstone.gatherer.collection.CollectionManager;
53import org.greenstone.gatherer.util.AppendLineOnlyFileDocument;
54import org.greenstone.gatherer.util.AppendLineOnlyFileDocumentOwner;
55import org.greenstone.gatherer.util.Utility;
56
57/** 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>.
58 * @author John Thompson, Greenstone Digital Library, University of Waikato
59 * @version 2.2
60 */
61public class OptionsPane
62 extends JPanel
63 implements AppendLineOnlyFileDocumentOwner, MouseListener {
64
65 static final public char SUCCESSFUL = 's';
66 static final public char UNSUCCESSFUL = 'u';
67 static final public char CANCELLED = 'c';
68 static final public char UNKNOWN = 'x';
69
70 static private int BUILD = 0;
71 static private int IMPORT = 1;
72 static private int MINIMUM_ROWS = 11;
73 static private Dimension LABEL_SIZE = new Dimension(180, 25);
74 static private Dimension ROW_SIZE = new Dimension(610, 30);
75 static private Dimension SPINNER_SIZE = new Dimension(100, 25);
76 static private String DESCRIPTION_SEP = " + ";
77
78 /** All process messages are written to this log text area. */
79 public JTextArea log_textarea = null;
80
81 private ArrayList current_controls;
82
83 /** 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>). */
84 private BuildOptions build_options = null;
85
86 private FileEntry file_entry = null;
87
88 /** the log pane - we only create it once now, not each time */
89 private JPanel log_pane = null;
90 /** the list of previous log messages */
91 private JList log_list = null;
92 private Vector writing_documents;
93
94
95 /** 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. */
96 public OptionsPane(BuildOptions build_options) {
97 this.build_options = build_options;
98 this.current_controls = new ArrayList();
99 this.writing_documents = new Vector();
100
101 // Have to do this here, not in display, as the message log view may not have been displayed yet.
102 log_textarea = new JTextArea();
103 log_textarea.setEditable(false);
104 }
105
106 /** This method creates the panel with all the build only options on it.
107 * @param pane a JPanel which already has previous arguments available on it, to allow for lower moes to concatenate all of the arguments together
108 * @return a JPanel which can be used to display all the build only options
109 * @see org.greenstone.gatherer.Configuration#EXPERT_MODE
110 * @see org.greenstone.gatherer.Configuration#getColor
111 * @see org.greenstone.gatherer.Configuration#getMode
112 * @see org.greenstone.gatherer.Gatherer#config
113 * @see org.greenstone.gatherer.cdm.Argument
114 * @see org.greenstone.gatherer.collection.BuildOptions#getBuildArgument
115 * @see org.greenstone.gatherer.collection.BuildOptions#getBuildArgumentCount
116 * @see org.greenstone.gatherer.collection.BuildOptions#getBuildValue
117 * @see org.greenstone.gatherer.collection.BuildOptions#getBuildValueEnabled
118 * @see org.greenstone.gatherer.gui.OptionsPane.ArgumentControl
119 */
120 public JPanel buildBuild(JPanel pane) {
121 // Reset the arguments
122 if(pane == null) {
123 current_controls.clear();
124 }
125 ArrayList build_arguments = new ArrayList();
126 int current_mode = Gatherer.config.getMode();
127 int total_build_argument_count = build_options.getBuildArgumentCount();
128 for(int i = 0; i < total_build_argument_count; i++) {
129 // Retrieve the argument so we know how to format the control.
130 Argument argument = build_options.getBuildArgument(i);
131 if(!argument.isHiddenGLI() && argument.getModeLevel() <= current_mode) {
132 // Now attempt to retrieve any existing value for this argument.
133 boolean enabled = build_options.getBuildValueEnabled(argument.getName());
134 String value = build_options.getBuildValue(argument.getName());
135 ArgumentControl argument_control = new ArgumentControl(BUILD, argument, enabled, value);
136 build_arguments.add(argument_control);
137 }
138 }
139 current_controls.addAll(build_arguments);
140 // Now that we know how many arguments there are we can build the pane to view them on. Modes lower than EXPERT can provide a previous pane on which to add the arguments.
141 if(pane == null || current_mode >= Configuration.EXPERT_MODE) {
142 pane = new JPanel();
143 pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
144 pane.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
145 int argument_count = build_arguments.size();
146 // If in any of the higher detail modes, and assuming we don't want super phat argument controls, we better ensure there is a minimum number or lines in the grid layout
147 if(current_mode >= Configuration.EXPERT_MODE) {
148 if(argument_count < MINIMUM_ROWS) {
149 argument_count = MINIMUM_ROWS;
150 }
151 pane.setLayout(new GridLayout(argument_count, 1, 5, 5));
152 }
153 // Otherwise we're just going to throw them on one after another and chuck it in a scroll pane anyway
154 else {
155 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
156 }
157 }
158 for(int j = 0; j < build_arguments.size(); j++) {
159 pane.add((JComponent)build_arguments.get(j));
160 }
161 pane.addMouseListener(this);
162 build_arguments = null;
163 return pane;
164 }
165
166 /** This method creates the panel with all the import only options on it.
167 * @param pane a JPanel which already has previous arguments available on it, to allow for lower moes to concatenate all of the arguments together
168 * @return a JPanel which can be used to display all the build only options
169 * @see org.greenstone.gatherer.Configuration#EXPERT_MODE
170 * @see org.greenstone.gatherer.Configuration#getColor
171 * @see org.greenstone.gatherer.Configuration#getMode
172 * @see org.greenstone.gatherer.Gatherer#config
173 * @see org.greenstone.gatherer.cdm.Argument
174 * @see org.greenstone.gatherer.collection.BuildOptions#getImportArgument
175 * @see org.greenstone.gatherer.collection.BuildOptions#getImportArgumentCount
176 * @see org.greenstone.gatherer.collection.BuildOptions#getImportValue
177 * @see org.greenstone.gatherer.collection.BuildOptions#getImportValueEnabled
178 * @see org.greenstone.gatherer.gui.OptionsPane.ArgumentControl
179 */
180 public JPanel buildImport(JPanel pane) {
181 // Reset the arguments
182 if(pane == null) {
183 current_controls.clear();
184 }
185 ArrayList import_arguments = new ArrayList();
186 int current_mode = Gatherer.config.getMode();
187 int total_import_argument_count = build_options.getImportArgumentCount();
188 for(int i = 0; i < total_import_argument_count; i++) {
189 // Retrieve the argument so we know how to format the control.
190 Argument argument = build_options.getImportArgument(i);
191 if(!argument.isHiddenGLI() && argument.getModeLevel() <= current_mode) {
192 // Now attempt to retrieve any existing value for this argument.
193 boolean enabled = build_options.getImportValueEnabled(argument.getName());
194 String value = build_options.getImportValue(argument.getName());
195 ArgumentControl argument_control = new ArgumentControl(IMPORT, argument, enabled, value);
196 import_arguments.add(argument_control);
197 }
198 }
199 current_controls.addAll(import_arguments);
200 // Now that we know how many arguments there are we can build the pane to view them on. Modes lower than EXPERT can provide a previous pane on which to add the arguments.
201 if(pane == null || current_mode >= Configuration.EXPERT_MODE) {
202 pane = new JPanel();
203 pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
204 pane.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
205 int argument_count = import_arguments.size();
206 // If in any of the higher detail modes, and assuming we don't want super phat argument controls, we better ensure there is a minimum number or lines in the grid layout
207 if(current_mode >= Configuration.EXPERT_MODE) {
208 if(argument_count < MINIMUM_ROWS) {
209 argument_count = MINIMUM_ROWS;
210 }
211 pane.setLayout(new GridLayout(argument_count, 1, 5, 5));
212 }
213 // Otherwise we're just going to throw them on one after another and chuck it in a scroll pane anyway
214 else {
215 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
216 }
217 }
218 for(int j = 0; j < import_arguments.size(); j++) {
219 pane.add((JComponent)import_arguments.get(j));
220 }
221 pane.addMouseListener(this);
222 import_arguments = null;
223 return pane;
224 }
225
226 /** This method is used to build a panel based on the message log, which is nothing like any of the other panels.
227 * @return A <strong>JPanel</strong> containing a scrollable text area which represents the shell process message log.
228 */
229 public JPanel buildLog() {
230 // we now save the log pane
231 if (log_pane == null) {
232 log_pane = new JPanel(new BorderLayout());
233
234 // Build a list of the log files available, ordering by last modified. Log files are like build_log.date.txt
235 DefaultListModel contents = new DefaultListModel();
236 File log_directory = new File(Gatherer.c_man.getCollectionLog());
237 File children[] = log_directory.listFiles();
238 for(int i = 0; children != null && i < children.length; i++) {
239 String filename = children[i].getName();
240 if(filename.startsWith("build_log.") && filename.endsWith(".txt") ) {
241 String datestamp = filename.substring(filename.indexOf(".") + 1, filename.lastIndexOf(".")).toLowerCase();
242 if(datestamp.indexOf("s") == -1 && datestamp.indexOf("u") == -1 && datestamp.indexOf("c") == -1 && datestamp.indexOf("x") == -1) {
243 FileEntry entry = new FileEntry(children[i].getName(), children[i].getAbsolutePath());
244 // We are about to insert it. But where.
245 boolean found = false;
246 for(int j = 0; !found && j < contents.size(); j++) {
247 FileEntry sibling = (FileEntry) contents.getElementAt(j);
248 int order = entry.compareTo(sibling);
249 if(order > 0) {
250 contents.insertElementAt(entry, j);
251 found = true;
252 }
253 }
254 if(!found) {
255 contents.addElement(entry);
256 }
257 }
258 }
259 }
260
261 log_list = new JList(contents);
262 log_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
263 log_list.setLayoutOrientation(JList.VERTICAL);
264 log_list.setPreferredSize(new Dimension(600, 100));
265 log_list.setVisibleRowCount(3);
266 log_list.addListSelectionListener(new LogListListener());
267
268 JLabel log_history_label = new JLabel();
269 Dictionary.registerText(log_history_label, "OptionsPane.LogHistory");
270 JPanel log_history_pane = new JPanel();
271 log_history_pane.setPreferredSize(new Dimension(600, 100));
272 log_history_pane.setLayout(new BorderLayout());
273 log_history_pane.add(log_history_label, BorderLayout.NORTH);
274 log_history_pane.add(new JScrollPane(log_list), BorderLayout.CENTER);
275
276 log_pane.add(new JScrollPane(log_textarea), BorderLayout.CENTER);
277 log_pane.add(log_history_pane, BorderLayout.SOUTH);
278 }
279 return log_pane;
280 }
281
282 public AppendLineOnlyFileDocument createNewLogDocument() {
283 long time = System.currentTimeMillis();
284 StringBuffer name = new StringBuffer();
285 name.append("build_log.");
286 name.append(time);
287 name.append(".txt");
288 // just in case there is no log directory
289 File file = new File(Gatherer.c_man.getCollectionLog() + name.toString());
290 File parent_file = file.getParentFile();
291 parent_file.mkdirs();
292 parent_file = null;
293 // create the file entry and add it to the list at pos 0 - it will always be the newest one created
294 file_entry = new FileEntry(name.toString(), file.getAbsolutePath());
295 ((DefaultListModel)log_list.getModel()).add(0, file_entry);
296 log_list.setSelectedIndex(0);
297 // Finally retrieve and return the document associated with this file entry
298 return file_entry.getDocument();
299 }
300
301
302 /** Attempts to discover the latest document count.
303 * @return An <strong>int</strong> detailing the number of documents in this collection.
304 */
305 public int getDocumentCount() {
306 if(Gatherer.c_man.ready()) {
307 int count = Gatherer.c_man.getCollection().getDocumentCount();
308 if(count != 0) {
309 return count;
310 }
311 }
312 return 1;
313 }
314
315 /** Called by our magic log documents after they have finished writing themselves to file, whereapon it is no longer necessary to hold a reference to them. */
316 public void remove(AppendLineOnlyFileDocument document) {
317 writing_documents.remove(document);
318 }
319
320 public void resetFileEntry() {
321 if(file_entry != null) {
322 file_entry.reset();
323 }
324 }
325
326 /** Given a panel containing ArgumentControls, update the values associated with them. */
327 public void update(JPanel panel) {
328 if(panel == log_pane) {
329 return;
330 }
331
332 for(int i = 0; i < panel.getComponentCount(); i++) {
333 Component component = panel.getComponent(i);
334 if(component instanceof ArgumentControl) {
335 ((ArgumentControl)component).update();
336 }
337 }
338 }
339
340 /** Implementation side-effect
341 * @param e a MouseEvent
342 */
343 public void mouseClicked(MouseEvent e) {}
344
345 /** Implementation side-effect
346 * @param e a MouseEvent
347 */
348 public void mouseEntered(MouseEvent e) {}
349
350 /** Implemented to ensure that, by the time the mouse pointer leaves the current build options screen, ang changes to the value the JSpinners have been commited
351 * @param e a MouseEvent
352 */
353 public void mouseExited(MouseEvent e) {
354 // Loop through the controls, and if the current control is a JSpinner, commit its current editing
355 for(int i = 0; i < current_controls.size(); i++) {
356 ArgumentControl control = (ArgumentControl) current_controls.get(i);
357 JComponent value_control = control.getValueControl();
358 if(value_control instanceof JSpinner) {
359 try {
360 ((JSpinner)value_control).commitEdit();
361 }
362 catch(Exception exception) {
363 Gatherer.println("Exception in OptionsPane.mouseExited() - unexpected");
364 Gatherer.printStackTrace(exception);
365 }
366 }
367 value_control = null;
368 control = null;
369 }
370 }
371
372 /** Implementation side-effect
373 * @param e a MouseEvent
374 */
375 public void mousePressed(MouseEvent e) {}
376
377 /** Implementation side-effect
378 * @param e a MouseEvent
379 */
380 public void mouseReleased(MouseEvent e) {}
381
382 private class ArgumentControl
383 extends JPanel {
384 private Argument argument;
385 private int type;
386 private JComponent value_control;
387 private JCheckBox enabled;
388 public ArgumentControl(int type, Argument argument, boolean enable, String value) {
389 super();
390 this.argument = argument;
391 this.type = type;
392 String tooltip = Utility.formatHTMLWidth("<html>" + argument.getDescription() + "</html>", 60);
393 // Because of the dynamic order of component creation/connection/layout, we can't really follow that pattern here.
394 setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
395 setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
396 setLayout(new BorderLayout());
397 setPreferredSize(ROW_SIZE);
398 setMaximumSize(ROW_SIZE);
399
400 // Try to determine what the value_controls value should be.
401 if(value == null) {
402 value = argument.getDefaultValue();
403 }
404 // Create a correct value control based on the argument provided.
405 switch(argument.getType()) {
406 case Argument.ENUM:
407 JComboBox combobox = new JComboBox();
408 combobox.setEnabled(enable);
409 combobox.setToolTipText(tooltip);
410 // Set enabled
411 if(enable) {
412 combobox.setBackground(Color.white);
413 }
414 else {
415 combobox.setBackground(Color.lightGray);
416 }
417 // Build an option model, wrapping each entry of the list table.
418 HashMap arg_list = argument.getOptions();
419 Iterator it = arg_list.keySet().iterator();
420 while(it.hasNext()) {
421 combobox.addItem((String) it.next());
422 }
423 // Connect this up first, so that if a value is selected the tooltip updates accordingly.
424 combobox.addActionListener(new ToolTipUpdater(arg_list));
425 if(value != null) {
426 // Set the selected string. However since they are all strings we had best iterate ourselves.
427 for(int i = 0; i < combobox.getItemCount(); i++) {
428 if(combobox.getItemAt(i).toString().equals(value)) {
429 combobox.setSelectedIndex(i);
430 }
431 }
432 }
433 // Layout
434 add(combobox, BorderLayout.CENTER);
435 // And remember
436 value_control = combobox;
437 break;
438 case Argument.FLAG:
439 // Only need the check box.
440 value_control = null;
441 break;
442 case Argument.INTEGER:
443 // Build a spinner
444 int initial_value=0;
445 if (value != null) {
446 try {
447 initial_value = Integer.parseInt(value);
448 } catch (Exception exception) {
449 }
450 }
451 if (initial_value < argument.getMinimum()) {
452 initial_value = argument.getMinimum();
453 } else if (initial_value > argument.getMaximum()) {
454 initial_value = argument.getMaximum();
455 }
456 JSpinner spinner = new JSpinner(new SpinnerNumberModel(initial_value, argument.getMinimum(), argument.getMaximum(), 1));
457 spinner.setEnabled(enable);
458 spinner.setPreferredSize(SPINNER_SIZE);
459 spinner.setToolTipText(tooltip);
460 // Set enabled
461 JComponent c = spinner.getEditor();
462 if ( c instanceof JSpinner.DefaultEditor ) {
463 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
464 JFormattedTextField field = editor.getTextField();
465 field.setEditable(enable);
466 if(enable) {
467 field.setBackground(Color.white);
468 }
469 else {
470 field.setBackground(Color.lightGray);
471 }
472 }
473 // Layout
474 add(new JLabel(), BorderLayout.CENTER);
475 add(spinner, BorderLayout.EAST);
476 // And remember it
477 value_control = spinner;
478 break;
479 case Argument.STRING:
480 // Use a standard text field
481 JTextField textfield = new JTextField();
482 textfield.setEnabled(enable);
483 textfield.setToolTipText(tooltip);
484 // Set enabled
485 if(enable) {
486 textfield.setBackground(Color.white);
487 }
488 else {
489 textfield.setBackground(Color.lightGray);
490 }
491 // If there was an original value, set it.
492 if(value != null) {
493 textfield.setText(value);
494 }
495 // Layout
496 add(textfield, BorderLayout.CENTER);
497 // And remember it
498 value_control = textfield;
499 break;
500 case Argument.METADATUM:
501 GComboBox gcombobox = new GComboBox(Gatherer.c_man.getCollection().msm.getAssignedElements(), false);
502 gcombobox.setEnabled(enable);
503 // Now ensure we have the existing value or default value selected if either exist.
504 if(value != null) {
505 boolean found = selectValue(gcombobox, value);
506 // Its possible that this is a custom value and so doesn't exist in the combobox. If so add it and then select it
507 if(!found) {
508 gcombobox.addItem(value);
509 gcombobox.setSelectedItem(value);
510 }
511 }
512 add(gcombobox, BorderLayout.CENTER);
513 value_control = gcombobox;
514 break;
515 }
516
517 // If the argument is required, then you don't get a choice of whether it is enabled.
518 if(argument.isRequired()) {
519 JLabel label = new JLabel(argument.getName());
520 label.setOpaque(false);
521 label.setPreferredSize(LABEL_SIZE);
522 label.setToolTipText(tooltip);
523 add(label, BorderLayout.WEST);
524 }
525 else {
526 enabled = new JCheckBox(argument.getName(), enable);
527 enabled.setOpaque(false);
528 enabled.setPreferredSize(LABEL_SIZE);
529 enabled.setToolTipText(tooltip);
530 // Connect
531 enabled.addActionListener(new EnabledListener(value_control));
532 // Layout
533 add(enabled, BorderLayout.WEST);
534 }
535 }
536
537 /** Retrieve the control used for storing values.
538 * @return JComponent
539 */
540 public JComponent getValueControl() {
541 return value_control;
542 }
543
544 /** Method to ensure that a certain value is selected, if it exists within that combobox to begin with.
545 * @param combobox the JComboBox whose selection we are trying to preset
546 * @param target The desired value of the selection as a String
547 * @return true if the item was found and selected, false otherwise
548 */
549 public boolean selectValue(JComboBox combobox, String target) {
550 for(int i = 0; i < combobox.getItemCount(); i++) {
551 if(combobox.getItemAt(i).toString().equals(target)) {
552 combobox.setSelectedIndex(i);
553 return true;
554 }
555 }
556 return false;
557 }
558
559 /** Update the values stored in the collection so as to rememebr the current state of this argument. */
560 public void update() {
561 String name = argument.getName();
562 boolean enable = true;
563 if(enabled != null) {
564 enable = enabled.isSelected();
565 }
566 String value = null;
567 if(value_control == null) {
568 // Flag value, nothing to do.
569 }
570 else if(value_control instanceof JTextField) {
571 value = ((JTextField)value_control).getText();
572 }
573 else if(value_control instanceof JSpinner) {
574 value = ((JSpinner)value_control).getValue().toString();
575 }
576 else if(value_control instanceof JComboBox) {
577 value = (((JComboBox)value_control).getSelectedItem()).toString();
578 }
579 // If this argument was a flag, but is now disabled, remove from the build options altogether
580 if(!enable && value == null) {
581 if(type == BUILD) {
582 build_options.removeBuildValue(name);
583 }
584 else {
585 build_options.removeImportValue(name);
586 }
587 }
588 // Otherwise update the argument value
589 else {
590 if(type == BUILD) {
591 build_options.setBuildValue(name, enable, value);
592 }
593 else {
594 build_options.setImportValue(name, enable, value);
595 }
596 }
597 }
598 }
599
600 /** Listens for actions apon the enable checkbox, and if detected enables or diables control appropriately. */
601 private class EnabledListener
602 implements ActionListener {
603 /** An editor component, such as a JComboBox or JTextField, that might have its enabled state changed by this listener. */
604 private JComponent target = null;
605 /** Constructor. */
606 public EnabledListener(JComponent target) {
607 this.target = target;
608 }
609 /** 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.
610 * @param event An <strong>ActionEvent</strong> containing information about the click.
611 */
612 public void actionPerformed(ActionEvent event) {
613 JCheckBox source = (JCheckBox)event.getSource();
614 if(target != null) {
615 if(source.isSelected()) {
616 target.setBackground(Color.white);
617 target.setEnabled(true);
618 }
619 else {
620 target.setBackground(Color.lightGray);
621 target.setEnabled(false);
622 }
623 // Special case of stupid JSpinners who don't let their backgrounds change properly.
624 if(target instanceof JSpinner) {
625 JSpinner spinner = (JSpinner) target;
626 JComponent c = spinner.getEditor();
627 if ( c instanceof JSpinner.DefaultEditor ) {
628 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
629 JFormattedTextField field = editor.getTextField();
630 field.setEditable(source.isSelected());
631 if(source.isSelected()) {
632 field.setBackground(Color.white);
633 }
634 else {
635 field.setBackground(Color.lightGray);
636 }
637 }
638 }
639 }
640 }
641 }
642
643 /** Holds a File which has a particular naming convention build_log.date.txt also keeps a Date corresponding to the date in its name*/
644 private class FileEntry {
645
646 private AppendLineOnlyFileDocument current_document;
647 private Date date;
648 private long last_modified;
649 private String display;
650 private String filename;
651 private String filepath;
652
653 public FileEntry(String filename, String filepath) {
654 this.date = null;
655 this.display = null;
656 this.filename = filename;
657 this.filepath = filepath;
658 this.last_modified = 0L;
659 }
660
661 /** returns 0 if the dates are the same, -ve number if the current FileEntry is earlier than the fe FileEntry ...*/
662 public int compareTo(FileEntry file_entry) {
663 Date our_date = getDate();
664 Date other_date = file_entry.getDate();
665 return our_date.compareTo(other_date);
666 }
667
668 public Date getDate() {
669 if(date == null) {
670 // Need to exclude first '.'
671 int first_index = filename.indexOf(".") + 1;
672 // Need to exclude the last '.'
673 int last_index = filename.lastIndexOf(".");
674 if(first_index > 0 && last_index > 0 && first_index < last_index) {
675 String date_string = filename.substring(first_index, last_index);
676 date = new Date(Long.parseLong(date_string));
677 }
678 else {
679 date = new Date(); // Current date
680 }
681 }
682 return date;
683 }
684
685 public AppendLineOnlyFileDocument getDocument() {
686 if(current_document == null) {
687 current_document = new AppendLineOnlyFileDocument(filepath);
688 }
689 return current_document;
690 }
691
692 public void reset() {
693 display = null;
694 }
695
696 /** we only want the date out of the file name, not the whole path */
697 public String toString() {
698 File file = new File(filename);
699 if(display == null) {
700 last_modified = file.lastModified();
701 StringBuffer d = new StringBuffer();
702 Date date = getDate();
703 d.append(date.toString());
704 char success = UNKNOWN;
705 File the_file = new File(filepath);
706 if(the_file.exists()) {
707 try {
708 FileInputStream in = new FileInputStream(the_file);
709 success = (char) in.read();
710 in.close();
711 in = null;
712 }
713 catch(Exception error) {
714 ///ystem.err.println("Log '" + filepath + "' not found!");
715 ///atherer.printStackTrace(error);
716 }
717 }
718 the_file = null;
719 switch (success) {
720 case SUCCESSFUL:
721 d.append(Dictionary.get("OptionsPane.Successful"));
722 break;
723 case UNSUCCESSFUL:
724 d.append(Dictionary.get("OptionsPane.Unsuccessful"));
725 break;
726 case CANCELLED:
727 d.append(Dictionary.get("OptionsPane.Cancelled"));
728 break;
729 default:
730 d.append(Dictionary.get("OptionsPane.Unknown"));
731 }
732 display = d.toString();
733 }
734 return display;
735 }
736 }
737
738 /** a ListSelectionListener that triggers the load of a newly selected log */
739 private class LogListListener implements ListSelectionListener {
740
741 public void valueChanged(ListSelectionEvent e) {
742 if (!e.getValueIsAdjusting()) { // we get two events for one change in list selection - use the false one ( the second one)
743 ///ystem.err.println("Log change detected.");
744 JList source = (JList)e.getSource();
745 file_entry = (FileEntry) source.getSelectedValue();
746 // First we determine if the old log has been completely written to file
747 Document document = log_textarea.getDocument();
748 ///ystem.err.println(" * current document: " + document);
749 ///ystem.err.println(" * new document: " + file_entry.getDocument());
750 // If we are dealing with the same document don't do anything.
751 if(document != file_entry.getDocument()) {
752 if(document instanceof AppendLineOnlyFileDocument) {
753 AppendLineOnlyFileDocument append_line_only_file_document = (AppendLineOnlyFileDocument) document;
754 if(append_line_only_file_document.isStillWriting()) {
755 ///ystem.err.println("Current log is still active... finishing.");
756 writing_documents.add(append_line_only_file_document); // We have to maintain a reference until they are all done.
757 append_line_only_file_document.setOwner(OptionsPane.this);
758 append_line_only_file_document.setExit();
759 }
760 else {
761 ///ystem.err.println("Current log is complete. Nothing to do.");
762 }
763 }
764 // Load the new log
765 log_textarea.setDocument(file_entry.getDocument());
766 }
767 }
768 }
769 }
770
771 /** Listener that sets the tooltip associated to a combobox to the tooltip relevant to the selected item. */
772 private class ToolTipUpdater
773 implements ActionListener {
774 private HashMap arg_list;
775 public ToolTipUpdater(HashMap arg_list) {
776 this.arg_list = arg_list;
777 }
778 /** 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.
779 * @param event An <strong>ActionEvent</strong> containing information about the action that fired this call.
780 */
781 public void actionPerformed(ActionEvent event) {
782 JComboBox source = (JComboBox)event.getSource();
783 String key = (String) source.getSelectedItem();
784 if(arg_list != null) {
785 String description = (String) arg_list.get(key);
786 if(description != null) {
787 description = Utility.formatHTMLWidth(DESCRIPTION_SEP + description, 60);
788 String original = source.getToolTipText();
789 if(original == null) {
790 original = "";
791 }
792 // Remove any existing extra description.
793 if(original.indexOf(DESCRIPTION_SEP) != -1) {
794 original = original.substring(0, original.indexOf(DESCRIPTION_SEP));
795 }
796 source.setToolTipText(original + description);
797 }
798 }
799 }
800 }
801}
Note: See TracBrowser for help on using the repository browser.