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

Last change on this file since 4293 was 4293, checked in by jmt12, 21 years ago

Initial revision

  • Property svn:keywords set to Author Date Id Revision
File size: 17.5 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 /** This <strong>JPanel</strong> is used to display the varying options panes. */
62 private JPanel target_pane = null;
63 /** All process messages are written to this log text area. */
64 private JTextArea log = null;
65 static private int BUILD = 0;
66 static private int IMPORT = 1;
67 static private Dimension LABEL_SIZE = new Dimension(180, 25);
68 static private Dimension LOG_SIZE = new Dimension(610, 360);
69 /** The minimum size of a options pane, to prevent refresh problems around the bottom of shorter panes. */
70 static private Dimension PANE_SIZE = new Dimension(610, 350);
71 static private Dimension ROW_SIZE = new Dimension(610, 25);
72 static private Dimension SPINNER_SIZE = new Dimension(100, 25);
73 static private String DESCRIPTION_SEP = " + ";
74 /** 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. */
75 public OptionsPane(JPanel target_pane, JTextArea log, BuildOptions build_options) {
76 this.log = log;
77 this.build_options = build_options;
78 this.target_pane = target_pane;
79 }
80 /** This method creates the panel with all the build only options on it.
81 * @return A <strong>JPanel</strong> which can be used to display all the build only options.
82 */
83 public JPanel buildBuild() {
84 JPanel pane = new JPanel();
85 pane.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
86 pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
87 int build_argument_count = build_options.getBuildArgumentCount();
88 pane.setLayout(new GridLayout(build_argument_count, 1, 0, 0));
89 int total_height = PANE_SIZE.height;
90 for(int i = 0; i < build_argument_count; i++) {
91 // Retrieve the argument so we know how to format the control.
92 Argument argument = build_options.getBuildArgument(i);
93 // Now attempt to retrieve any existing value for this argument.
94 boolean enabled = build_options.getBuildValueEnabled(argument.getName());
95 String value = build_options.getBuildValue(argument.getName());
96 ArgumentControl argument_control = new ArgumentControl(BUILD, argument, enabled, value);
97 total_height = total_height - argument_control.getPreferredSize().height;
98 pane.add(argument_control);
99 }
100 if(total_height > 0) {
101 JPanel filler = new JPanel();
102 filler.setPreferredSize(new Dimension(100, total_height));
103 filler.setSize(filler.getPreferredSize());
104 pane.add(filler);
105 }
106 return pane;
107 }
108 /** This method creates the panel with all the import only options on it.
109 * @return A <strong>JPanel</strong> which can be used to display all the import only options.
110 */
111 public JPanel buildImport() {
112 JPanel pane = new JPanel();
113 pane.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
114 pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
115 int import_argument_count = build_options.getImportArgumentCount();
116 pane.setLayout(new GridLayout(import_argument_count, 1, 0, 0));
117 int total_height = PANE_SIZE.height;
118 for(int i = 0; i < import_argument_count; i++) {
119 // Retrieve the argument so we know how to format the control.
120 Argument argument = build_options.getImportArgument(i);
121 // Now attempt to retrieve any existing value for this argument.
122 boolean enabled = build_options.getImportValueEnabled(argument.getName());
123 String value = build_options.getImportValue(argument.getName());
124 ArgumentControl argument_control = new ArgumentControl(IMPORT, argument, enabled, value);
125 total_height = total_height - argument_control.getPreferredSize().height;
126 pane.add(argument_control);
127 }
128 if(total_height > 0) {
129 JPanel filler = new JPanel();
130 filler.setPreferredSize(new Dimension(100, total_height));
131 filler.setSize(filler.getPreferredSize());
132 pane.add(filler);
133 }
134 return pane;
135 }
136 /** This method is used to build a panel based on the message log, which is nothing like any of the other panel.
137 * @return A <strong>JPanel</strong> containing a scrollable text area which represents the shell process message log.
138 */
139 public JPanel buildLog() {
140 JPanel pane = new JPanel(new BorderLayout());
141 /*
142 // Build a list of the log files available, ordering by last modified. Log files end .log (duh!)
143 DefaultComboBoxModel model = new DefaultComboBoxModel();
144 File etc_directory = new File(gatherer.c_man.getCollectionEtc());
145 File children[] = etc_directory.listFiles();
146 for(int i = 0; children != null && i < children.length; i++) {
147 if(children[i].getName().endsWith(".log")) {
148 FileEntry entry = new FileEntry(children[i]);
149 // We are about to insert it. But where.
150 boolean found = false;
151 for(int j = 0; j < model.getSize(); j++) {
152 FileEntry sibling = (FileEntry) model.getElementAt(i);
153 int order = entry.compareTo(sibling);
154 if(order < 0) {
155 model.insertElementAt(entry, j);
156 found = true;
157 }
158 }
159 if(!found) {
160 model.addElement(entry);
161 }
162 }
163 }
164 JComboBox logs_box = new JComboBox(model);
165 // If log is empty, reload the most recent log.
166 if(log.getText().length() == 0 && model.getSize() > 0) {
167 loadLog(model.getElementAt(0));
168 }
169 */
170 pane.add(log, BorderLayout.CENTER);
171 //pane.add(logs_box, BorderLayout.SOUTH);
172 return pane;
173 }
174 /** Attempts to discover the latest document count.
175 * @return An <strong>int</strong> detailing the number of documents in this collection.
176 */
177 public int getDocumentCount() {
178 if(Gatherer.c_man.ready()) {
179 int count = Gatherer.c_man.getCollection().getDocumentCount();
180 if(count != 0) {
181 return count;
182 }
183 }
184 return 1;
185 }
186
187 public void saveLog() {
188 /*
189 try {
190 long name_long = System.currentTimeMillis();
191 String name = name_long + ".log";
192 File;
193 FileOutputStream fos = new FileOutputStream(file);
194 }
195 catch(Exception error) {
196 }
197 */
198 }
199
200 /** Given a panel containing ArgumentControls, update the values associated with them. */
201 public void update(JPanel panel) {
202 for(int i = 0; i < panel.getComponentCount(); i++) {
203 Component component = panel.getComponent(i);
204 if(component instanceof ArgumentControl) {
205 ((ArgumentControl)component).update();
206 }
207 }
208 }
209
210 private class ArgumentControl
211 extends JPanel {
212 private Argument argument;
213 private int type;
214 private JComponent value_control;
215 private JCheckBox enabled;
216 public ArgumentControl(int type, Argument argument, boolean enable, String value) {
217 super();
218 this.argument = argument;
219 this.type = type;
220 String tooltip = Utility.formatHTMLWidth("<html>" + argument.getDesc() + "</html>", 60);
221 // Because of the dynamic order of component creation/connection/layout, we can't really follow that pattern here.
222 setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
223 setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
224 setLayout(new BorderLayout());
225 setPreferredSize(ROW_SIZE);
226
227 /*
228 JPanel inner_pane = new JPanel();
229 inner_pane.setOpaque(false);
230 */
231
232 // Try to determine what the value_controls value should be.
233 if(value == null) {
234 value = argument.getDefaultValue();
235 }
236 // Create a correct value control based on the argument provided.
237 switch(argument.getType()) {
238 case Argument.ENUM:
239 JComboBox combobox = new JComboBox();
240 combobox.setEnabled(enable);
241 combobox.setToolTipText(tooltip);
242 // Set enabled
243 if(enable) {
244 combobox.setBackground(Color.white);
245 }
246 else {
247 combobox.setBackground(Color.lightGray);
248 }
249 // Build an option model, wrapping each entry of the list table.
250 HashMap arg_list = argument.getList();
251 Iterator it = arg_list.keySet().iterator();
252 while(it.hasNext()) {
253 combobox.addItem((String) it.next());
254 }
255 // Connect this up first, so that if a value is selected the tooltip updates accordingly.
256 combobox.addActionListener(new ToolTipUpdater(arg_list));
257 if(value != null) {
258 // Set the selected string. However since they are all strings we had best iterate ourselves.
259 for(int i = 0; i < combobox.getItemCount(); i++) {
260 if(combobox.getItemAt(i).toString().equals(value)) {
261 combobox.setSelectedIndex(i);
262 }
263 }
264 }
265 // Layout
266 add(combobox, BorderLayout.CENTER);
267 // And remember
268 value_control = combobox;
269 break;
270 case Argument.FLAG:
271 // Only need the check box.
272 value_control = null;
273 break;
274 case Argument.INTEGER:
275 // Build a spinner
276 JSpinner spinner = new JSpinner();
277 spinner.setEnabled(enable);
278 spinner.setPreferredSize(SPINNER_SIZE);
279 spinner.setToolTipText(tooltip);
280 // Set enabled
281 JComponent c = spinner.getEditor();
282 if ( c instanceof JSpinner.DefaultEditor ) {
283 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
284 JFormattedTextField field = editor.getTextField();
285 field.setEditable(enable);
286 if(enable) {
287 field.setBackground(Color.white);
288 }
289 else {
290 field.setBackground(Color.lightGray);
291 }
292 }
293 // If there was an original value, set it.
294 if(value != null) {
295 try {
296 spinner.setValue(new Integer(value));
297 }
298 catch (Exception error) {
299 }
300 }
301 // Layout
302 add(new JLabel(), BorderLayout.CENTER);
303 add(spinner, BorderLayout.EAST);
304 // And remember it
305 value_control = spinner;
306 break;
307 case Argument.STRING:
308 // Use a standard text field
309 JTextField textfield = new JTextField();
310 textfield.setEnabled(enable);
311 textfield.setToolTipText(tooltip);
312 // Set enabled
313 if(enable) {
314 textfield.setBackground(Color.white);
315 }
316 else {
317 textfield.setBackground(Color.lightGray);
318 }
319 // If there was an original value, set it.
320 if(value != null) {
321 textfield.setText(value);
322 }
323 // Layout
324 add(textfield, BorderLayout.CENTER);
325 // And remember it
326 value_control = textfield;
327 break;
328 }
329
330 // If the argument is required, then you don't get a choice of whether it is enabled.
331 if(argument.isRequired()) {
332 JLabel label = new JLabel(argument.getName());
333 label.setOpaque(false);
334 label.setPreferredSize(LABEL_SIZE);
335 label.setToolTipText(tooltip);
336 add(label, BorderLayout.WEST);
337 }
338 else {
339 enabled = new JCheckBox(argument.getName(), enable);
340 enabled.setOpaque(false);
341 enabled.setPreferredSize(LABEL_SIZE);
342 enabled.setToolTipText(tooltip);
343 // Connect
344 enabled.addActionListener(new EnabledListener(value_control));
345 // Layout
346 add(enabled, BorderLayout.WEST);
347 }
348 }
349
350 /** Update the values stored in the collection so as to rememebr the current state of this argument. */
351 public void update() {
352 String name = argument.getName();
353 boolean enable = true;
354 if(enabled != null) {
355 enable = enabled.isSelected();
356 }
357 String value = null;
358 if(value_control == null) {
359 // Flag value, nothing to do.
360 }
361 else if(value_control instanceof JTextField) {
362 value = ((JTextField)value_control).getText();
363 }
364 else if(value_control instanceof JSpinner) {
365 value = ((JSpinner)value_control).getValue().toString();
366 }
367 else if(value_control instanceof JComboBox) {
368 value = (String) ((JComboBox)value_control).getSelectedItem();
369 }
370 // If this argument was a flag, but is now disabled, remove from the build options altogether
371 if(!enable && value == null) {
372 if(type == BUILD) {
373 build_options.removeBuildValue(name);
374 }
375 else {
376 build_options.removeImportValue(name);
377 }
378 }
379 // Otherwise update the argument value
380 else {
381 if(type == BUILD) {
382 build_options.setBuildValue(name, enable, value);
383 }
384 else {
385 build_options.setImportValue(name, enable, value);
386 }
387 }
388 }
389 }
390
391 /** Listens for actions apon the enable checkbox, and if detected enables or diables control appropriately. */
392 private class EnabledListener
393 implements ActionListener {
394 /** An editor component, such as a JComboBox or JTextField, that might have its enabled state changed by this listener. */
395 private JComponent target = null;
396 /** Constructor. */
397 public EnabledListener(JComponent target) {
398 this.target = target;
399 }
400 /** 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.
401 * @param event An <strong>ActionEvent</strong> containing information about the click.
402 */
403 public void actionPerformed(ActionEvent event) {
404 JCheckBox source = (JCheckBox)event.getSource();
405 if(target != null) {
406 if(source.isSelected()) {
407 target.setBackground(Color.white);
408 target.setEnabled(true);
409 }
410 else {
411 target.setBackground(Color.lightGray);
412 target.setEnabled(false);
413 }
414 // Special case of stupid JSpinners who don't let their backgrounds change properly.
415 if(target instanceof JSpinner) {
416 JSpinner spinner = (JSpinner) target;
417 JComponent c = spinner.getEditor();
418 if ( c instanceof JSpinner.DefaultEditor ) {
419 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
420 JFormattedTextField field = editor.getTextField();
421 field.setEditable(source.isSelected());
422 if(source.isSelected()) {
423 field.setBackground(Color.white);
424 }
425 else {
426 field.setBackground(Color.lightGray);
427 }
428 }
429 }
430 }
431 }
432 }
433
434 /** Listener that sets the tooltip associated to a combobox to the tooltip relevant to the selected item. */
435 private class ToolTipUpdater
436 implements ActionListener {
437 private HashMap arg_list;
438 public ToolTipUpdater(HashMap arg_list) {
439 this.arg_list = arg_list;
440 }
441 /** 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.
442 * @param event An <strong>ActionEvent</strong> containing information about the action that fired this call.
443 */
444 public void actionPerformed(ActionEvent event) {
445 JComboBox source = (JComboBox)event.getSource();
446 String key = (String) source.getSelectedItem();
447 if(arg_list != null) {
448 String description = (String) arg_list.get(key);
449 if(description != null) {
450 description = Utility.formatHTMLWidth(DESCRIPTION_SEP + description, 60);
451 String original = source.getToolTipText();
452 if(original == null) {
453 original = "";
454 }
455 // Remove any existing extra description.
456 if(original.indexOf(DESCRIPTION_SEP) != -1) {
457 original = original.substring(0, original.indexOf(DESCRIPTION_SEP));
458 }
459 source.setToolTipText(original + description);
460 }
461 }
462 }
463 }
464}
Note: See TracBrowser for help on using the repository browser.