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

Last change on this file since 14039 was 14039, checked in by xiao, 17 years ago

Change made in the method getElementAt() not to get element from the 'cache' but directly from the 'children' list because when an element is deleted from the internal DOM tree, 'children' is up to date but 'cache' is not.

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