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

Last change on this file since 13074 was 13052, checked in by shaoqun, 18 years ago

make the redo button enabled properly

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