source: trunk/gli/src/org/greenstone/gatherer/cdm/FormatManager.java@ 12468

Last change on this file since 12468 was 12449, checked in by kjdon, 18 years ago

Classifier.toString no longer has classify in front, so don't need to remove this when doing Entry.toString

  • Property svn:keywords set to Author Date Id Revision
File size: 40.7 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 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.cdm;
28
29import java.awt.*;
30import java.awt.event.*;
31import java.util.*;
32import javax.swing.*;
33import javax.swing.event.*;
34import javax.swing.undo.*;
35import org.greenstone.gatherer.Configuration;
36import org.greenstone.gatherer.DebugStream;
37import org.greenstone.gatherer.Dictionary;
38import org.greenstone.gatherer.Gatherer;
39import org.greenstone.gatherer.gui.DesignPaneHeader;
40import org.greenstone.gatherer.gui.GLIButton;
41import org.greenstone.gatherer.metadata.MetadataElement;
42import org.greenstone.gatherer.metadata.MetadataSetManager;
43import org.greenstone.gatherer.util.StaticStrings;
44import org.w3c.dom.*;
45
46/** This class maintains a list of format statements, and allows the addition and removal of these statements.
47 * @author John Thompson, Greenstone Digital Library, University of Waikato
48 * @version 2.3
49 */
50public class FormatManager
51 extends DOMProxyListModel {
52
53 static final private String BLANK = "blank";
54 static final private String FLAG = "flag";
55 static final private String VALUE = "value";
56
57 static final private String DATELIST = "DateList";
58 static final private String DATELIST_DEFAULT_FORMAT = "<td>[link][icon][/link]</td>\n<td>[highlight]{Or}{[dls.Title],[dc.Title],[ex.Title],Untitled}[/highlight]</td>\n<td>[ex.Date]</td>";
59 static final private String HLIST = "HList";
60 static final private String HLIST_DEFAULT_FORMAT = "[link][highlight][ex.Title][/highlight][/link]";
61 static final private String VLIST = "VList";
62 static final private String VLIST_DEFAULT_FORMAT = "<td valign=\"top\">[link][icon][/link]</td>\n<td valign=\"top\">[ex.srclink]{Or}{[ex.thumbicon],[ex.srcicon]}[ex./srclink]</td>\n<td valign=\"top\">[highlight]\n{Or}{[dls.Title],[dc.Title],[ex.Title],Untitled}\n[/highlight]{If}{[ex.Source],<br><i>([ex.Source])</i>}</td>";
63 // static final private String INVISIBLE = "Invisible";
64 //static final private String INVISIBLE_DEFAULT_FORMAT = "";
65
66 static final private String DOCUMENTHEADING = "DocumentHeading";
67 static final private String DOCUMENTHEADING_DEFAULT_FORMAT = "{Or}{[parent(Top):Title],[Title],untitled}<br>";
68
69 static final private String DOCUMENTTEXT = "DocumentText";
70 static final private String DOCUMENTTEXT_DEFAULT_FORMAT = "[Text]";
71
72 static final private String DOCUMENTBUTTONS = "DocumentButtons";
73 static final private String DOCUMENTBUTTONS_DEFAULT_FORMAT = "Detach|Highlight";
74 static final private String SEARCHTYPES = "SearchTypes";
75 static final private String SEARCHTYPES_DEFAULT_FORMAT = "plain,form";
76
77 static private HashMap format_map = null ;
78
79 /** The controls used to edit the format commands. */
80 private Control controls = null;
81 /** A reference to ourselves so inner classes can get at the model. */
82 private DOMProxyListModel model = null;
83
84
85 /** Constructor. */
86 public FormatManager() {
87 super(CollectionDesignManager.collect_config.getDocumentElement(), CollectionConfiguration.FORMAT_ELEMENT, new Format());
88 this.model = this;
89
90 format_map = new HashMap();
91 format_map.put(DATELIST,"<td>[link][icon][/link]</td>\n<td>[highlight]{Or}{[dls.Title],[dc.Title],[ex.Title],Untitled}[/highlight]</td>\n<td>[ex.Date]</td>");
92 format_map.put(HLIST,"[link][highlight][ex.Title][/highlight][/link]");
93 format_map.put(VLIST,"<td valign=\"top\">[link][icon][/link]</td>\n<td valign=\"top\">[ex.srclink]{Or}{[ex.thumbicon],[ex.srcicon]}[ex./srclink]</td>\n<td valign=\"top\">[highlight]\n{Or}{[dls.Title],[dc.Title],[ex.Title],Untitled}\n[/highlight]{If}{[ex.Source],<br><i>([ex.Source])</i>}</td>");
94 format_map.put(DOCUMENTHEADING,"{Or}{[parent(Top):Title],[Title],untitled}<br>");
95 format_map.put(DOCUMENTTEXT,"[Text]");
96 format_map.put( DOCUMENTBUTTONS,"Detach|Highlight");
97 format_map.put( "","");
98
99 DebugStream.println("FormatManager: parsed " + getSize() + " format statements.");
100 // Establish all of the format objects, so that classifier indexes are initially correct (subsequent refreshes of the model will be sufficient to keep these up to date, as long as we start with a live reference to a classifier.
101 int size = getSize();
102 for(int i = 0; i < size; i++) {
103 getElementAt(i);
104 }
105
106 // Ensure the default formats for DateList, HList and VList are assigned
107 if (getFormat(DATELIST) == null) {
108 addFormat(new Format("",DATELIST,DATELIST_DEFAULT_FORMAT));
109 }
110
111
112 if (getFormat(HLIST) == null) {
113 addFormat(new Format("",HLIST,HLIST_DEFAULT_FORMAT));
114 }
115
116
117 if (getFormat(VLIST) == null) {
118 addFormat(new Format("",VLIST,VLIST_DEFAULT_FORMAT));
119 }
120
121
122 if (getFormat(DOCUMENTHEADING) == null) {
123 addFormat(new Format(DOCUMENTHEADING, "", DOCUMENTHEADING_DEFAULT_FORMAT));
124 }
125
126
127 if (getFormat(DOCUMENTTEXT)== null) {
128 addFormat(new Format(DOCUMENTTEXT,"",DOCUMENTTEXT_DEFAULT_FORMAT));
129 }
130
131
132
133 if (getFormat(DOCUMENTBUTTONS) == null) {
134 addFormat(new Format(DOCUMENTBUTTONS,"",DOCUMENTBUTTONS_DEFAULT_FORMAT));
135
136 }
137
138 // only for mgpp and lucene colls - change!
139 if (getFormat(SEARCHTYPES)==null) {
140 addFormat(new Format(SEARCHTYPES, "", SEARCHTYPES_DEFAULT_FORMAT));
141 }
142
143 }
144
145 /** Method to add a new format to this manager.
146 * @param format The <strong>Format</strong> to add.
147 */
148 private void addFormat(Format format) {
149 if(!contains(format)) {
150 Element element = format.getElement();
151 // Locate where we should insert this new classifier.
152 Node target_node = CollectionConfiguration.findInsertionPoint(element);
153 add(root, format, target_node);
154 Gatherer.c_man.configurationChanged();
155 }
156 }
157
158
159 public void destroy() {
160 if(controls != null) {
161 controls.destroy();
162 controls = null;
163 }
164 }
165
166 private Format getFormat(String name) {
167 int model_size = getSize();
168 for(int index = 0; index < model_size; index++) {
169 Format format = (Format) getElementAt(index);
170 if(format.getName().equals(name)) {
171 return format;
172 }
173 }
174 return null;
175 }
176
177 /** Method to retrieve this managers controls.
178 * @return the Control for this collection.
179 */
180 public Control getControls() {
181 if(controls == null) {
182 controls = new FormatControl();
183 }
184 return controls;
185 }
186
187 /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
188 * @param mode the new mode as an int
189 */
190 public void modeChanged(int mode) {
191
192 }
193
194
195 /** updates the format model */
196 public synchronized void refresh() {
197 for(int i = 0; i < getSize(); i++) {
198 Format format = (Format) getElementAt(i);
199 format.update();
200 format = null;
201 }
202 super.refresh();
203 }
204 /** Method to remove a format.
205 * @param format The <strong>Format</strong> to remove.
206 */
207 private void removeFormat(Format format) {
208 remove(format);
209 Gatherer.c_man.configurationChanged();
210
211 }
212
213 private ArrayList buildFeatureModel() {
214 // Rebuild feature model.
215 ArrayList feature_model = new ArrayList();
216 // Add the set options
217 for(int i = 0; i < Format.DEFAULT_FEATURES.length; i++) {
218 feature_model.add(new Entry(Format.DEFAULT_FEATURES[i]));
219 }
220 // Now the classifiers.
221 for(int j = 0; j < CollectionDesignManager.classifier_manager.getSize(); j++) {
222 feature_model.add(new Entry(CollectionDesignManager.classifier_manager.getClassifier(j)));
223 }
224 Collections.sort(feature_model);
225 return feature_model;
226 }
227
228 private ArrayList buildPartModel() {
229 DebugStream.println("buildPartModel(): replace me with something that reads in a data xml file.");
230 ArrayList part_model = new ArrayList();
231 part_model.add(new Part("", ""));
232 part_model.add(new Part(DATELIST, DATELIST_DEFAULT_FORMAT));
233 part_model.add(new Part(HLIST, HLIST_DEFAULT_FORMAT));
234 //part_model.add(new Part(INVISIBLE, INVISIBLE_DEFAULT_FORMAT));
235 part_model.add(new Part(VLIST, VLIST_DEFAULT_FORMAT));
236 return part_model;
237 }
238
239 private ArrayList buildVariableModel()
240 {
241 ArrayList variable_model = new ArrayList();
242 variable_model.add("");
243 variable_model.add("[Text]");
244 ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
245 for (int i = 0; i < every_metadata_set_element.size(); i++) {
246 variable_model.add("[" + ((MetadataElement) every_metadata_set_element.get(i)).getFullName() + "]");
247 }
248 variable_model.add("[link]");
249 variable_model.add("[/link]");
250 variable_model.add("[icon]");
251 variable_model.add("[numleafdocs]");
252 variable_model.add("[num]");
253 variable_model.add("[parent():_]");
254 variable_model.add("[parent(Top):_]");
255 variable_model.add("[parent(All'_'):_]");
256 variable_model.add("[child():_]");
257 variable_model.add("[child(All'_'):_]");
258 variable_model.add("[sibling():_]");
259 variable_model.add("[sibling(All'_'):_]");
260
261 return variable_model;
262 }
263
264 public class FormatControl
265 extends JPanel
266 implements Control{
267
268 private ArrayList feature_model;
269 private ArrayList part_model;
270 private ArrayList variable_model;
271 private boolean ignore_event = false;
272 private boolean ready = false; // Are these controls available to be refreshed
273 private CardLayout card_layout;
274 private JButton add_button;
275 private JButton insert_button;
276 private JButton remove_button;
277 private JButton default_button;
278 private JButton undo_button;
279 private JButton redo_button;
280 private JCheckBox enabled_checkbox;
281 private JComboBox feature_combobox;
282 private JComboBox part_combobox;
283 private JComboBox variable_combobox;
284 private JList format_list;
285 private JTextArea editor_textarea;
286 private JPanel blank_pane;
287 private JPanel control_pane;
288 private JPanel part_pane;
289 private JPanel selection_pane;
290 private String view_type;
291 private final Dimension FIELD_SIZE = new Dimension(200, 30);
292 private final UndoManager undo = new UndoManager();
293 private boolean newtext = true;
294 private Format previousFormat = null;
295 private Format currentFormat = null;
296 private boolean fresh = true;
297
298 public FormatControl() {
299 feature_model = buildFeatureModel();
300 part_model = buildPartModel();
301 variable_model = buildVariableModel();
302
303 // Create
304 JPanel header_pane = new DesignPaneHeader("CDM.GUI.Formats", "formatstatements");
305
306 format_list = new JList(model);
307
308 selection_pane = new JPanel();
309 JPanel feature_pane = new JPanel();
310 JLabel feature_label = new JLabel(Dictionary.get("CDM.FormatManager.Feature"));
311
312 feature_combobox = new JComboBox(feature_model.toArray());
313 feature_combobox.setPreferredSize(FIELD_SIZE);
314 feature_combobox.setEditable(false);
315 feature_combobox.setToolTipText(Dictionary.get("CDM.FormatManager.Feature_Tooltip"));
316
317 part_pane = new JPanel();
318 JLabel part_label = new JLabel(Dictionary.get("CDM.FormatManager.Part"));
319 part_combobox = new JComboBox(part_model.toArray());
320 part_combobox.setPreferredSize(FIELD_SIZE);
321 part_combobox.setEditable(false);
322 part_combobox.setToolTipText(Dictionary.get("CDM.FormatManager.Part_Tooltip"));
323
324 blank_pane = new JPanel();
325
326 JPanel center_pane = new JPanel();
327
328 card_layout = new CardLayout();
329 control_pane = new JPanel();
330
331 JPanel blank_pane = new JPanel();
332
333 JPanel editor_pane = new JPanel();
334 JPanel editor_header_pane = new JPanel();
335 JLabel editor_label = new JLabel(Dictionary.get("CDM.FormatManager.Editor"));
336
337 editor_textarea = new JTextArea();
338 editor_textarea.setBackground(Configuration.getColor("coloring.editable_background", false));
339 editor_textarea.setCaretPosition(0);
340 editor_textarea.setLineWrap(true);
341 editor_textarea.setRows(6);
342 editor_textarea.setWrapStyleWord(false);
343 editor_textarea.setToolTipText(Dictionary.get("CDM.FormatManager.Add_Tooltip"));
344
345 JPanel variable_pane = new JPanel();
346 JLabel variable_label = new JLabel(Dictionary.get("CDM.FormatManager.Variable"));
347
348 variable_combobox = new JComboBox(variable_model.toArray());
349 variable_combobox.setToolTipText(Dictionary.get("CDM.FormatManager.Variable_Tooltip"));
350
351 insert_button = new GLIButton(Dictionary.get("CDM.FormatManager.Insert"), Dictionary.get("CDM.FormatManager.Insert_Tooltip"));
352
353 default_button = new GLIButton(Dictionary.get("CDM.FormatManager.Default"), Dictionary.get("CDM.FormatManager.Default_Tooltip"));
354
355 JPanel flag_pane = new JPanel();
356 enabled_checkbox = new JCheckBox(Dictionary.get("CDM.FormatManager.Enabled"));
357
358 JPanel button_pane = new JPanel();
359 add_button = new GLIButton(Dictionary.get("CDM.FormatManager.Add"), Dictionary.get("CDM.FormatManager.Add_Tooltip"));
360 add_button.setEnabled(false);
361
362 remove_button = new GLIButton(Dictionary.get("CDM.FormatManager.Remove"), Dictionary.get("CDM.FormatManager.Remove_Tooltip"));
363 remove_button.setEnabled(false);
364
365 undo_button = new GLIButton(Dictionary.get("General.Undo"), Dictionary.get("General.Undo_Tooltip"));
366 undo_button.setEnabled(false);
367
368 redo_button = new GLIButton(Dictionary.get("General.Redo"), Dictionary.get("General.Redo_Tooltip"));
369 redo_button.setEnabled(false);
370
371 // Connect
372 add_button.addActionListener(new AddListener());
373 add_button.addActionListener(CollectionDesignManager.collect_cfg_change_listener);
374
375 remove_button.addActionListener(new RemoveListener());
376 remove_button.addActionListener(CollectionDesignManager.collect_cfg_change_listener);
377 default_button.addActionListener(new DefaultListener());
378 default_button.addActionListener(CollectionDesignManager.collect_cfg_change_listener);
379 undo_button.addActionListener(new UndoListener());
380 redo_button.addActionListener(new RedoListener());
381 enabled_checkbox.addActionListener(new EnabledListener());
382 enabled_checkbox.addActionListener(CollectionDesignManager.collect_cfg_change_listener);
383 feature_combobox.addActionListener(new FeatureListener());
384 part_combobox.addActionListener(new PartListener());
385
386 editor_textarea.getDocument().addDocumentListener(new EditorListener());
387 // Listen for undo and redo events
388 editor_textarea.getDocument().addUndoableEditListener(new UndoableEditListener() {
389 public void undoableEditHappened(UndoableEditEvent evt) {
390 undo.addEdit(evt.getEdit());
391 }
392 });
393
394
395 format_list.addListSelectionListener(new FormatListListener());
396 variable_combobox.addActionListener(new VariableListener());
397
398 // Layout
399 JPanel format_list_pane = new JPanel();
400 format_list_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
401 format_list_pane.setLayout(new BorderLayout());
402 format_list_pane.add(new JScrollPane(format_list), BorderLayout.CENTER);
403
404
405 feature_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
406 feature_pane.setLayout(new BorderLayout(5,0));
407 feature_pane.add(feature_label, BorderLayout.WEST);
408 feature_pane.add(feature_combobox, BorderLayout.CENTER);
409
410 part_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
411 part_pane.setLayout(new BorderLayout(5, 0));
412 part_pane.add(part_label, BorderLayout.WEST);
413 part_pane.add(part_combobox, BorderLayout.CENTER);
414
415
416 flag_pane.add(enabled_checkbox);
417
418 editor_header_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
419 editor_header_pane.setLayout(new GridLayout(1,3));
420 editor_header_pane.add(editor_label);
421
422 JPanel rupanel = new JPanel();
423 rupanel.setLayout(new GridLayout(1,2));
424 rupanel.add(undo_button);
425 rupanel.add(redo_button);
426
427 variable_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
428 variable_pane.setLayout(new GridLayout(1,3));
429 variable_pane.add(variable_label);
430 variable_pane.add(variable_combobox);
431 variable_pane.add(rupanel);
432
433 editor_pane.setLayout(new BorderLayout());
434 editor_pane.add(editor_header_pane, BorderLayout.NORTH);
435 editor_pane.add(new JScrollPane(editor_textarea), BorderLayout.CENTER);
436
437 selection_pane.setLayout(new BorderLayout());
438 selection_pane.add(part_pane, BorderLayout.NORTH);
439 selection_pane.add(editor_pane, BorderLayout.CENTER);
440 selection_pane.add(variable_pane, BorderLayout.SOUTH);
441
442 control_pane.setLayout(card_layout);
443 control_pane.add(flag_pane, FLAG);
444 control_pane.add(selection_pane, VALUE);
445 control_pane.add(blank_pane, BLANK);
446
447
448 button_pane.setLayout(new GridLayout(1,3));
449 button_pane.add(add_button);
450 button_pane.add(remove_button);
451 button_pane.add(default_button);
452
453
454 center_pane.setLayout(new BorderLayout());
455 center_pane.add(feature_pane, BorderLayout.NORTH);
456 center_pane.add(control_pane, BorderLayout.CENTER);
457 center_pane.add(button_pane, BorderLayout.SOUTH);
458
459 setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
460 setLayout(new BorderLayout());
461 add(header_pane, BorderLayout.NORTH);
462 add(format_list_pane, BorderLayout.CENTER);
463 add(center_pane, BorderLayout.SOUTH);
464 ready = true;
465 }
466
467 public void destroy() {
468 }
469
470
471
472 /** Overriden to ensure that the instructions pane is scrolled to the top.
473 */
474 public void gainFocus() {
475 // This is only necessary if the components have been realized
476 if(ready) {
477 model.refresh();
478
479 // Update the feature model, trying to maintain the same selected object
480 Object selected_feature = feature_combobox.getSelectedItem();
481 feature_model = buildFeatureModel();
482 feature_combobox.setModel(new DefaultComboBoxModel(feature_model.toArray()));
483 feature_combobox.setSelectedItem(selected_feature);
484
485 // Update the variable model, trying to maintain the same selected object
486 Object selected_variable = variable_combobox.getSelectedItem();
487 variable_model = buildVariableModel();
488 variable_combobox.setModel(new DefaultComboBoxModel(variable_model.toArray()));
489 variable_combobox.setSelectedItem(selected_variable);
490 }
491 }
492
493 public void loseFocus() {
494 // Force all of the Formats to update their names with the correct values.
495 // do we need to do this on loseFocus???
496 model.refresh();
497 }
498
499 public Format getCurrentFormat() {
500 return (Format)format_list.getSelectedValue();
501
502 }
503
504 /** Listens for clicks on the add button, and if the relevant details are provided adds a new format. Note that formats are responsible for codecing the values into something that can be a) stored in a DOM and b) written to file */
505 private class AddListener
506 implements ActionListener {
507
508 public void actionPerformed(ActionEvent event)
509 {
510
511 ignore_event = true; // Prevent format_list excetera propagating events
512
513 Entry entry = (Entry) feature_combobox.getSelectedItem();
514 Object f = entry.getFeature();
515 String p = "";
516 if (entry.canHavePart()) {
517 p = ((Part)part_combobox.getSelectedItem()).getName();
518 }
519
520 // Add a new format string of the appropriate type
521 Format format = null;
522 if (view_type.equals(FLAG)) {
523 format = new Format(f, p, enabled_checkbox.isSelected());
524 }
525 else {
526 format = new Format(f, p, editor_textarea.getText());
527
528 }
529
530
531 addFormat(format);
532 existingFormat();
533 // Save the collection configuration file immediately
534
535 Gatherer.c_man.configurationChanged();
536
537 // Update list selection
538 format_list.setSelectedValue(format, true);
539 format = null;
540 p = null;
541 f = null;
542 entry = null;
543 ignore_event = false;
544 }
545 }
546
547 private class EditorListener
548 implements DocumentListener {
549
550 public void changedUpdate(DocumentEvent e) {
551
552 update();
553 }
554
555 public void insertUpdate(DocumentEvent e) {
556 update();
557 updateUndo("insert");
558
559 }
560
561 public void removeUpdate(DocumentEvent e) {
562 update();
563 updateUndo("remove");
564
565 }
566
567 private void updateUndo(String from){
568
569 if (!newtext){
570 undo_button.setEnabled(true);
571 }
572
573 if (editor_textarea.getText().length()!=0 && newtext){
574 newtext = false;
575 }
576 }
577
578 public void update() {
579
580 // Determine if replace should be enabled
581 if(!format_list.isSelectionEmpty()) {
582 Format format = (Format)format_list.getSelectedValue();
583 boolean shouldSave = !format.isParamType();
584
585 if (shouldSave){
586 format.setValue(editor_textarea.getText());
587 Gatherer.c_man.configurationChanged();
588 model.refresh((DOMProxyListEntry)format);
589 }
590
591 }
592 else {
593 add_button.setEnabled(false);
594
595 }
596
597 }
598 }
599
600 private class EnabledListener
601 implements ActionListener {
602
603 public void actionPerformed(ActionEvent event) {
604 // If there is a current format selected, and the value of enable_checkbox is now different than to value in it, then enable to replace button.
605 if(!format_list.isSelectionEmpty()) {
606 Format format = (Format)format_list.getSelectedValue();
607 boolean shouldSave = format.isParamType();
608 if (shouldSave){
609 format.setState(enabled_checkbox.isSelected());
610 Gatherer.c_man.configurationChanged();
611 model.refresh((DOMProxyListEntry)format);
612 }
613 }
614
615 // Thats it. Add would have been enabled upon feature/part selection depending if no existing format, um, existed.
616 }
617 }
618
619 private class FeatureListener
620 implements ActionListener {
621 public void actionPerformed(ActionEvent event) {
622 undo_button.setEnabled(false);
623 redo_button.setEnabled(false);
624 default_button.setEnabled(true);
625 newtext = true;
626
627 if(!ignore_event) {
628 ignore_event = true;
629 Entry entry = (Entry) feature_combobox.getSelectedItem();
630
631 // Step one: reset part
632 if (entry.canHavePart()) {
633 part_combobox.setEnabled(true);
634 part_combobox.setSelectedIndex(part_combobox.getModel().getSize()-1);
635
636 } else {
637 part_combobox.setEnabled(false);
638 part_combobox.setSelectedIndex(0);
639 }
640 // Step two: the rest
641
642 String name = entry.toString();
643 // Add is only enabled if there isn't already a format for the choosen feature and part. Create a dummy format and test if itsa already in the model
644 Object f = entry.getFeature();
645 Part part = (Part)part_combobox.getSelectedItem();
646 String pname = part.getName();
647 // You can never add anything to blank-blank
648 if(f.toString().length() == 0 && pname.length() == 0) {
649 add_button.setEnabled(false);
650 remove_button.setEnabled(false);
651 }
652 else {
653
654 Format format = getFormat(Format.generateName(f, pname));
655 // If there is an existing feature, select it, and use it to determine what controls are visible
656
657 if(format != null) {
658 ///ystem.err.println("There is an existing format!");
659 format_list.setSelectedValue(format, true);
660 // Now use type to determine what controls are visible, and what have initial values.
661 if(format.isParamType()) {
662 ///ystem.err.println("Flag type");
663 // Flags first.
664 ///election_pane.remove(part_pane);
665 card_layout.show(control_pane, FLAG);
666 view_type = FLAG;
667 // Initial value
668 enabled_checkbox.setSelected(format.getState());
669 }
670 else {
671 ///ystem.err.println("Value type");
672 ///election_pane.add(part_pane);
673 card_layout.show(control_pane, VALUE);
674 view_type = VALUE;
675 // Initial value
676
677 editor_textarea.setText(format.getValue());
678 editor_textarea.setCaretPosition(0);
679
680 }
681 existingFormat();
682 control_pane.updateUI();
683 }
684 // Otherwise there is no existing format, so we proceed by checking against the feature name
685 else {
686 ///ystem.err.println("No existing format");
687 format_list.clearSelection();
688 if(Format.isParamType(name)) {
689 ///ystem.err.println("Flag type");
690 // Flags first.
691 ///election_pane.remove(part_pane);
692 card_layout.show(control_pane, FLAG);
693 view_type = FLAG;
694 // Initial value
695 enabled_checkbox.setSelected(false);
696 enabled_checkbox.setEnabled(false);
697 }
698 else {
699 ///ystem.err.println("Value type");
700 ///election_pane.add(part_pane);
701 card_layout.show(control_pane, VALUE);
702 view_type = VALUE;
703 // Initial value
704
705 editor_textarea.setText(part.getDefaultFormat());
706 editor_textarea.setCaretPosition(0);
707
708 }
709 newFormat();
710 }
711 format = null;
712 name = null;
713 }
714 part = null;
715 pname = null;
716 f = null;
717 name = null;
718 entry = null;
719 ignore_event = false;
720 }
721 undo.discardAllEdits();
722 }
723 }
724
725 private class FormatListListener
726 implements ListSelectionListener {
727 public void valueChanged(ListSelectionEvent event) {
728 undo_button.setEnabled(false);
729 redo_button.setEnabled(false);
730 default_button.setEnabled(true);
731 newtext = true;
732
733 if(!ignore_event && !event.getValueIsAdjusting()) {
734
735 if(!format_list.isSelectionEmpty()) {
736 existingFormat();
737 ignore_event = true;
738 Format format = (Format)format_list.getSelectedValue();
739 // Try to match the target, remembering the entries within are Entry's
740 Entry an_entry = new Entry(format.getFeature());
741 feature_combobox.setSelectedItem(an_entry);
742 // If we didn't match anything, add it and select it again
743 Entry result_entry = (Entry) feature_combobox.getSelectedItem();
744 if(!an_entry.equals(result_entry)) {
745 feature_combobox.insertItemAt(an_entry, feature_combobox.getItemCount());
746 feature_combobox.setSelectedItem(an_entry);
747 }
748
749 // Now use type to determine what controls are visible, and what have initial values.
750 ///ystem.err.println("Determine the correct type.");
751 if(format.isParamType()) {
752 ///ystem.err.println("Flag type - remove part");
753 // Flags first.
754 ///SwingUtilities.invokeLater(new GUIChangeTask(/election_pane, part_pane, blank_pane, false));
755 card_layout.show(control_pane, FLAG);
756 view_type = FLAG;
757 // Initial value
758 enabled_checkbox.setSelected(format.getState());
759 }
760 else {
761 ///ystem.err.println("Value type - show part");
762 ///SwingUtilities.invokeLater(new GUIChangeTask(/election_pane, part_pane, blank_pane, true));
763 card_layout.show(control_pane, VALUE);
764 view_type = VALUE;
765 // Initial values
766 // do we have a part?
767 if (format.canHavePart()) {
768 part_combobox.setEnabled(true);
769 // Try to match the part.
770 String part_entry = format.getPart();
771 // Set Selected Item doesn't work so I'll do this manually
772 boolean found = false;
773 for(int i=0; i < part_combobox.getItemCount(); i++) {
774 Part a_part = (Part) part_combobox.getItemAt(i);
775 if(a_part.equals(part_entry)) {
776 part_combobox.setSelectedItem(a_part);
777 found = true;
778 }
779 a_part = null;
780 }
781 // If we didn't match anything, add it and select it again
782 if(!found) {
783 Part a_part = new Part(part_entry, "");
784 part_combobox.insertItemAt(a_part, part_combobox.getItemCount());
785 part_combobox.setSelectedItem(a_part);
786
787 }
788 } else {
789 part_combobox.setEnabled(false);
790 part_combobox.setSelectedIndex(0);
791 }
792 editor_textarea.setText(format.getValue());
793 editor_textarea.setCaretPosition(0);
794
795 }
796
797 //control_pane.updateUI();
798 ignore_event = false;
799 }
800
801 }
802 undo.discardAllEdits();
803 }
804
805 }
806
807 private void newFormat(){
808 editor_textarea.setEditable(false);
809 editor_textarea.setBackground(Color.lightGray);
810 editor_textarea.setToolTipText(Dictionary.get("CDM.FormatManager.Editor_Disabled_Tooltip"));
811
812 enabled_checkbox.setEnabled(false);
813 undo_button.setEnabled(false);
814 redo_button.setEnabled(false);
815 variable_combobox.setEnabled(false);
816 add_button.setEnabled(true);
817 remove_button.setEnabled(false);
818 default_button.setEnabled(false);
819
820 }
821
822 private void existingFormat(){
823 editor_textarea.setEditable(true);
824 editor_textarea.setBackground(Color.white);
825 editor_textarea.setToolTipText(Dictionary.get("CDM.FormatManager.Editor_Tooltip"));
826 enabled_checkbox.setEnabled(true);
827 variable_combobox.setEnabled(true);
828 add_button.setEnabled(false);
829 remove_button.setEnabled(true);
830 default_button.setEnabled(true);
831
832 }
833
834 private class VariableListener
835 implements ActionListener {
836 public void actionPerformed(ActionEvent event) {
837 String selected_value = (String)variable_combobox.getSelectedItem();
838
839 if (!selected_value.equals("")){
840 editor_textarea.insert(selected_value, editor_textarea.getCaretPosition());
841 undo_button.setEnabled(true);
842
843 }
844 }
845
846 }
847
848 private class PartListener
849 implements ActionListener {
850 public void actionPerformed(ActionEvent event) {
851 undo_button.setEnabled(false);
852 redo_button.setEnabled(false);
853 default_button.setEnabled(true);
854 newtext = true;
855 if(!ignore_event) {
856 // Add is only enabled if there isn't already a format for the choosen feature and part. Create a dummy format and test if its already in the model
857 Entry entry = (Entry) feature_combobox.getSelectedItem();
858 Object f = entry.getFeature();
859 Part part = (Part) part_combobox.getSelectedItem();
860 String pname = part.getName();
861 // You can never add anything to blank-blank
862 if(f.toString().length() == 0 && pname.length() == 0) {
863 add_button.setEnabled(false);
864 remove_button.setEnabled(false);
865 }
866 else {
867 String name = Format.generateName(f, pname);
868 Format format = getFormat(name);
869 // If there is an existing feature, select it.
870 if(format != null) {
871 format_list.setSelectedValue(format, true);
872 // Now use type to determine what controls are visible, and what have initial values.
873 if(format.isParamType()) {
874 // Flags first.
875 ///election_pane.remove(part_pane);
876 card_layout.show(control_pane, FLAG);
877 view_type = FLAG;
878 // Initial value
879 enabled_checkbox.setSelected(format.getState());
880 }
881 else {
882 ///election_pane.add(part_pane);
883 card_layout.show(control_pane, VALUE);
884 view_type = VALUE;
885 // Initial value
886
887 editor_textarea.setText(format.getValue());
888 editor_textarea.setCaretPosition(0);
889
890 }
891 control_pane.updateUI();
892 existingFormat();
893 }
894 else {
895 format_list.clearSelection();
896 if(Format.isParamType(name)) {
897 // Flags first.
898 ///election_pane.remove(part_pane);
899 card_layout.show(control_pane, FLAG);
900 view_type = FLAG;
901 // Initial value
902 enabled_checkbox.setSelected(false);
903 enabled_checkbox.setEnabled(false);
904 }
905 else {
906 ///election_pane.add(part_pane);
907 card_layout.show(control_pane, VALUE);
908 view_type = VALUE;
909 // Initial value
910
911 editor_textarea.setText(part.getDefaultFormat());
912 editor_textarea.setCaretPosition(0);
913
914 }
915 newFormat();
916 }
917 format = null;
918 name = null;
919 }
920
921 pname = null;
922 part = null;
923 f = null;
924 entry = null;
925 }
926 undo.discardAllEdits();
927 }
928 }
929
930 private class RemoveListener
931 implements ActionListener {
932
933 public void actionPerformed(ActionEvent event)
934 {
935 if (!format_list.isSelectionEmpty()) {
936 // Remove the current format
937 removeFormat((Format)format_list.getSelectedValue());
938
939 // Save the collection configuration file immediately
940 Gatherer.c_man.configurationChanged();
941 // Change buttons
942 add_button.setEnabled(true);
943 newFormat();
944
945 }
946 }
947 }
948
949
950
951 private class DefaultListener
952 implements ActionListener {
953
954 public void actionPerformed(ActionEvent event)
955 {
956 newtext = false;
957 if(!ignore_event) {
958 Entry entry = (Entry) feature_combobox.getSelectedItem();
959 Object f = entry.getFeature();
960 String name ="";
961 String pname="";
962 Part part = null;
963
964 if (entry.canHavePart()){
965 part = (Part) part_combobox.getSelectedItem();
966 pname = part.getName();
967 name = Format.generateName(f, pname);
968 }
969 else{
970 name = entry.toString();
971 }
972
973 Format format = getFormat(name);
974 // If there is an existing feature, select it.
975 if(format != null) {
976 remove_button.setEnabled(true);
977 }
978 else {
979
980 add_button.setEnabled(true);
981 }//endif (format !=null)
982
983 if(Format.isParamType(name)) {
984 // Flags first.
985 card_layout.show(control_pane, FLAG);
986 view_type = FLAG;
987 // Initial value
988 enabled_checkbox.setSelected(false);
989 }
990 else {
991 card_layout.show(control_pane, VALUE);
992 view_type = VALUE;
993 // Initial value
994 if (pname !=null && pname.length()!=0 ){
995 editor_textarea.setText((String)format_map.get(pname));
996 editor_textarea.setCaretPosition(0);
997 }
998 else{
999 editor_textarea.setText((String)format_map.get(name));
1000 editor_textarea.setCaretPosition(0);
1001 }
1002 }
1003
1004 }
1005 }
1006
1007 }
1008
1009 private class UndoListener
1010 implements ActionListener {
1011
1012 public void actionPerformed(ActionEvent event)
1013 {
1014 try {
1015 if (undo.canUndo()) {
1016 int pos = editor_textarea.getCaretPosition();
1017 undo.undo();
1018 editor_textarea.setCaretPosition(pos);
1019 redo_button.setEnabled(true);
1020
1021 }
1022 if (!undo.canUndo()){
1023 undo_button.setEnabled(false);
1024 }
1025 else{
1026 undo_button.setEnabled(true);
1027 }
1028
1029 } catch (Exception e) {
1030 }
1031 }
1032 }
1033
1034 private class RedoListener
1035 implements ActionListener {
1036 public void actionPerformed(ActionEvent evt) {
1037 try {
1038 if (undo.canRedo()) {
1039 int pos = editor_textarea.getCaretPosition();
1040 undo.redo();
1041 editor_textarea.setCaretPosition(pos);
1042 }
1043 if (!undo.canRedo()){
1044 redo_button.setEnabled(false);
1045 }
1046 else{
1047 redo_button.setEnabled(true);
1048 }
1049
1050 } catch (Exception e) {}
1051 }
1052 }
1053
1054 }
1055
1056 /** This object provides a wrapping around an entry in the format target control, which is tranparent as to whether it is backed by a String or a Classifier. */
1057 private class Entry
1058 implements Comparable {
1059 private Classifier classifier = null;
1060 private String text = null;
1061
1062 public Entry(Object object) {
1063 if(object instanceof Classifier) {
1064 classifier = (Classifier)object;
1065 }
1066 else if(object instanceof String) {
1067 text = (String)object;
1068 }
1069 else {
1070 text = "";
1071 }
1072 }
1073
1074 public Entry(String text) {
1075 this.text = text;
1076 }
1077
1078 public boolean canHavePart() {
1079 if (classifier !=null) return true;
1080 return Format.canHavePart(text);
1081 }
1082
1083 public int compareTo(Object object) {
1084 if(object == null) {
1085 return 1;
1086 }
1087 if(toString() == null) {
1088 return -1;
1089 }
1090 else {
1091 String object_str = object.toString();
1092 if(object_str == null) {
1093 return 1;
1094 }
1095 return toString().compareTo(object_str);
1096 }
1097 }
1098
1099 public boolean equals(Object object) {
1100 if(compareTo(object) == 0) {
1101 return true;
1102 }
1103 return false;
1104 }
1105
1106 public Classifier getClassifier() {
1107 return classifier;
1108 }
1109
1110 public Object getFeature() {
1111 if(classifier != null) {
1112 return classifier;
1113 }
1114
1115 if (text.startsWith("<html>")){
1116 return "";
1117 }
1118 return text;
1119 }
1120
1121 public String toString() {
1122 if(classifier != null) {
1123 // Return the classifier - with its CL index shown
1124 return classifier.getPositionString() + StaticStrings.COLON_CHARACTER + StaticStrings.SPACE_CHARACTER + classifier.toString();
1125 }
1126 if (text.equals("")) {
1127 return "<html><body><i>"+Dictionary.get("CDM.FormatManager.AllFeatures")+"</i></body></html>";
1128 }
1129 return text;
1130 }
1131 }
1132
1133 /*
1134 private class GUIChangeTask
1135 implements Runnable {
1136 private boolean to_add;
1137 private JPanel child;
1138 private JPanel parent;
1139 private JPanel replacement;
1140
1141 public GUIChangeTask(JPanel parent, JPanel child, JPanel replacement, boolean to_add) {
1142 this.child = child;
1143 this.parent = parent;
1144 this.replacement = replacement;
1145 this.to_add = to_add;
1146 }
1147
1148 public void run() {
1149 if(to_add) {
1150 parent.remove(replacement);
1151 parent.add(child);
1152 parent.updateUI();
1153 }
1154 else {
1155 parent.remove(child);
1156 parent.add(replacement);
1157 parent.updateUI();
1158 }
1159 }
1160 }
1161 */
1162
1163 /** This class encapsulates all of the information associated with a certain component part of a feature within a html page returned from the receptioninst. */
1164 private class Part
1165 implements Comparable {
1166 /** The default format string for this part */
1167 private String default_format = null;
1168 /** The name of this part */
1169 private String name = null;
1170 /** Constructor - must be provided with all of the details of a part as there are no other setter methods.
1171 * @param name the name of this part
1172 * @param default_format the default format string for this part
1173 */
1174 public Part(String name, String default_format) {
1175 this.default_format = default_format;
1176 this.name = name;
1177 }
1178 /** Compare this part to another object in terms of ordering
1179 * @param obj the other Object
1180 * @return <0 if the object is before, 0 if equal to, and >0 if the object is after this part
1181 */
1182 public int compareTo(Object obj) {
1183 if (obj instanceof Part) {
1184 return name.compareTo(((Part)obj).getName());
1185 }
1186 return name.compareTo(obj.toString());
1187 }
1188
1189 /** Determine if the part is equivelent to some other object
1190 * @param obj the other Object
1191 * @return true is the two objects are equal
1192 */
1193 public boolean equals(Object obj) {
1194 if (obj instanceof Part) {
1195 return name.equals(((Part)obj).getName());
1196 }
1197 return name.equals(obj.toString());
1198 }
1199
1200 /** Retrieve the default format string for this part
1201 * @return the default format String
1202 */
1203 public String getDefaultFormat() {
1204 // Retrieve the format for the super format - either VList or HList
1205 Format default_format_object = getFormat(name);
1206 if(default_format_object != null) {
1207 return default_format_object.getValue();
1208 }
1209 else {
1210 return this.default_format;
1211 }
1212 }
1213 /** Retrieve the name of this part
1214 * @return the name as a String
1215 */
1216 public String getName() {
1217 return name;
1218 }
1219 /** Produce a string representation of this part, which in this case is simply the name again
1220 * @return the name as a String
1221 */
1222 public String toString() {
1223 if (name.equals("")) {
1224 return "<html><body><i>"+Dictionary.get("CDM.FormatManager.AllParts")+"</i></body></html>";
1225 }
1226 return name;
1227 }
1228 }
1229}
Note: See TracBrowser for help on using the repository browser.