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

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

fixed a bug that when the user accidentally deletes the content of VList and sets it to blank, the library crashes with Windows and weird stuff displayed with Linux (modification in EditorListener.update() method).

  • Property svn:keywords set to Author Date Id Revision
File size: 42.6 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 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.setOpaque(!Utility.isMac());
302 feature_combobox.setPreferredSize(FIELD_SIZE);
303 feature_combobox.setEditable(false);
304 feature_combobox.setToolTipText(Dictionary.get("CDM.FormatManager.Feature_Tooltip"));
305
306 part_pane = new JPanel();
307 JLabel part_label = new JLabel(Dictionary.get("CDM.FormatManager.Part"));
308 part_combobox = new JComboBox(part_model.toArray());
309 part_combobox.setOpaque(!Utility.isMac());
310 part_combobox.setPreferredSize(FIELD_SIZE);
311 part_combobox.setEditable(false);
312 part_combobox.setToolTipText(Dictionary.get("CDM.FormatManager.Part_Tooltip"));
313
314 blank_pane = new JPanel();
315
316 JPanel center_pane = new JPanel();
317
318 card_layout = new CardLayout();
319 control_pane = new JPanel();
320
321 JPanel blank_pane = new JPanel();
322
323 JPanel editor_pane = new JPanel();
324 JPanel editor_header_pane = new JPanel();
325 JLabel editor_label = new JLabel(Dictionary.get("CDM.FormatManager.Editor"));
326
327 editor_textarea = new JTextArea();
328 editor_textarea.setBackground(Configuration.getColor("coloring.editable_background", false));
329 editor_textarea.setCaretPosition(0);
330 editor_textarea.setLineWrap(true);
331 editor_textarea.setRows(6);
332 editor_textarea.setWrapStyleWord(false);
333 editor_textarea.setToolTipText(Dictionary.get("CDM.FormatManager.Add_Tooltip"));
334
335 JPanel variable_pane = new JPanel();
336
337 variable_combobox = new JComboBox(variable_model.toArray());
338 variable_combobox.setOpaque(!Utility.isMac());
339 variable_combobox.setToolTipText(Dictionary.get("CDM.FormatManager.Variable_Tooltip"));
340
341 insert_button = new GLIButton(Dictionary.get("CDM.FormatManager.Insert"), Dictionary.get("CDM.FormatManager.Insert_Tooltip"));
342
343 default_button = new GLIButton(Dictionary.get("CDM.FormatManager.Default"), Dictionary.get("CDM.FormatManager.Default_Tooltip"));
344
345 JPanel flag_pane = new JPanel();
346 enabled_checkbox = new JCheckBox(Dictionary.get("CDM.FormatManager.Enabled"));
347
348 JPanel button_pane = new JPanel();
349 add_button = new GLIButton(Dictionary.get("CDM.FormatManager.Add"), Dictionary.get("CDM.FormatManager.Add_Tooltip"));
350 add_button.setEnabled(false);
351
352 remove_button = new GLIButton(Dictionary.get("CDM.FormatManager.Remove"), Dictionary.get("CDM.FormatManager.Remove_Tooltip"));
353 remove_button.setEnabled(false);
354
355 undo_button = new GLIButton(Dictionary.get("General.Undo"), Dictionary.get("General.Undo_Tooltip"));
356 undo_button.setEnabled(false);
357
358 redo_button = new GLIButton(Dictionary.get("General.Redo"), Dictionary.get("General.Redo_Tooltip"));
359 redo_button.setEnabled(false);
360
361 // Connect
362 add_button.addActionListener(new AddListener());
363 remove_button.addActionListener(new RemoveListener());
364 default_button.addActionListener(new DefaultListener());
365 undo_button.addActionListener(new UndoListener());
366 redo_button.addActionListener(new RedoListener());
367 enabled_checkbox.addActionListener(new EnabledListener());
368 feature_combobox.addActionListener(new FeatureListener());
369 part_combobox.addActionListener(new PartListener());
370
371 editor_textarea.getDocument().addDocumentListener(new EditorListener());
372 // Listen for undo and redo events
373 editor_textarea.getDocument().addUndoableEditListener(new UndoableEditListener() {
374 public void undoableEditHappened(UndoableEditEvent evt) {
375 undo.addEdit(evt.getEdit());
376 }
377 });
378
379
380 format_list.addListSelectionListener(new FormatListListener());
381 variable_combobox.addActionListener(new VariableListener());
382
383 // Layout
384 JPanel format_list_pane = new JPanel();
385 format_list_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
386 format_list_pane.setLayout(new BorderLayout());
387 format_list_pane.add(new JScrollPane(format_list), BorderLayout.CENTER);
388
389
390 feature_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
391 feature_pane.setLayout(new BorderLayout(5,0));
392 feature_pane.add(feature_label, BorderLayout.WEST);
393 feature_pane.add(feature_combobox, BorderLayout.CENTER);
394
395 part_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
396 part_pane.setLayout(new BorderLayout(5, 0));
397 part_pane.add(part_label, BorderLayout.WEST);
398 part_pane.add(part_combobox, BorderLayout.CENTER);
399
400
401 flag_pane.add(enabled_checkbox);
402
403 editor_header_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
404 editor_header_pane.setLayout(new GridLayout(1,3));
405 editor_header_pane.add(editor_label);
406
407 JPanel rupanel = new JPanel();
408 rupanel.setLayout(new GridLayout(1,2));
409 rupanel.add(undo_button);
410 rupanel.add(redo_button);
411
412 variable_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
413 variable_pane.setLayout(new GridLayout(1,3));
414 variable_pane.add(new JPanel());
415 variable_pane.add(variable_combobox);
416 variable_pane.add(rupanel);
417
418 editor_pane.setLayout(new BorderLayout());
419 editor_pane.add(editor_header_pane, BorderLayout.NORTH);
420 editor_pane.add(new JScrollPane(editor_textarea), BorderLayout.CENTER);
421
422 selection_pane.setLayout(new BorderLayout());
423 selection_pane.add(part_pane, BorderLayout.NORTH);
424 selection_pane.add(editor_pane, BorderLayout.CENTER);
425 selection_pane.add(variable_pane, BorderLayout.SOUTH);
426
427 control_pane.setLayout(card_layout);
428 control_pane.add(flag_pane, FLAG);
429 control_pane.add(selection_pane, VALUE);
430 control_pane.add(blank_pane, BLANK);
431
432
433 button_pane.setLayout(new GridLayout(1,3));
434 button_pane.add(add_button);
435 button_pane.add(remove_button);
436 button_pane.add(default_button);
437
438
439 center_pane.setLayout(new BorderLayout());
440 center_pane.add(feature_pane, BorderLayout.NORTH);
441 center_pane.add(control_pane, BorderLayout.CENTER);
442 center_pane.add(button_pane, BorderLayout.SOUTH);
443
444 setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
445 setLayout(new BorderLayout());
446 add(header_pane, BorderLayout.NORTH);
447 add(format_list_pane, BorderLayout.CENTER);
448 add(center_pane, BorderLayout.SOUTH);
449 ready = true;
450 }
451
452 public void destroy() {
453 }
454
455
456
457 /** Overriden to ensure that the instructions pane is scrolled to the top.
458 */
459 public void gainFocus() {
460 // This is only necessary if the components have been realized
461 if(ready) {
462 model.refresh();
463
464 // Update the feature model, trying to maintain the same selected object
465 Object selected_feature = feature_combobox.getSelectedItem();
466 feature_model = buildFeatureModel();
467 feature_combobox.setModel(new DefaultComboBoxModel(feature_model.toArray()));
468 feature_combobox.setSelectedItem(selected_feature);
469
470 // Update the variable model,
471 variable_model = buildVariableModel();
472 variable_combobox.setModel(new DefaultComboBoxModel(variable_model.toArray()));
473 }
474 }
475
476 public void loseFocus() {
477 // Force all of the Formats to update their names with the correct values.
478 // do we need to do this on loseFocus???
479 model.refresh();
480 }
481
482 public Format getCurrentFormat() {
483 return (Format)format_list.getSelectedValue();
484
485 }
486
487 /** 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 */
488 private class AddListener
489 implements ActionListener {
490
491 public void actionPerformed(ActionEvent event) {
492
493 ignore_event = true; // Prevent format_list excetera propagating events
494
495 Entry entry = (Entry) feature_combobox.getSelectedItem();
496 Object f = entry.getFeature();
497 String p = "";
498 if (entry.canHavePart()) {
499 p = ((Part)part_combobox.getSelectedItem()).getName();
500 }
501
502 // Add a new format string of the appropriate type
503 Format format = null;
504 if (view_type.equals(FLAG)) {
505 format = new Format(f, p, enabled_checkbox.isSelected());
506 } else {
507 format = new Format(f, p, editor_textarea.getText());
508
509 }
510
511
512 addFormat(format);
513 existingFormat();
514
515 // Update list selection
516 format_list.setSelectedValue(format, true);
517 format = null;
518 p = null;
519 f = null;
520 entry = null;
521 ignore_event = false;
522 }
523 }
524
525 private class EditorListener
526 implements DocumentListener {
527
528 public void changedUpdate(DocumentEvent e) {
529
530 update();
531 }
532
533 public void insertUpdate(DocumentEvent e) {
534 update();
535 updateUndo("insert");
536
537 }
538
539 public void removeUpdate(DocumentEvent e) {
540 update();
541 updateUndo("remove");
542
543 }
544
545 private void updateUndo(String from){
546
547 if (!newtext){
548 undo_button.setEnabled(true);
549 }
550
551 if (editor_textarea.getText().length()!=0 && newtext){
552 newtext = false;
553 }
554 }
555
556 public void update() {
557
558 // Determine if replace should be enabled
559 if(!format_list.isSelectionEmpty()) {
560 Format format = (Format)format_list.getSelectedValue();
561 boolean shouldSave = !format.isParamType();
562
563 if (shouldSave){
564 String format_str = editor_textarea.getText().trim();
565 format_str = (format_str.equals(""))? VLIST_DEFAULT_FORMAT : format_str;
566 format.setValue(format_str);
567 model.refresh((DOMProxyListEntry)format);
568 }
569
570 } else {
571 add_button.setEnabled(false);
572
573 }
574
575 }
576 }
577
578 private class EnabledListener
579 implements ActionListener {
580
581 public void actionPerformed(ActionEvent event) {
582 // 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.
583 if(!format_list.isSelectionEmpty()) {
584 Format format = (Format)format_list.getSelectedValue();
585 boolean shouldSave = format.isParamType();
586 if (shouldSave){
587 format.setState(enabled_checkbox.isSelected());
588 model.refresh((DOMProxyListEntry)format);
589 }
590 }
591
592 // Thats it. Add would have been enabled upon feature/part selection depending if no existing format, um, existed.
593 }
594 }
595
596 private class FeatureListener
597 implements ActionListener {
598 public void actionPerformed(ActionEvent event) {
599 undo_button.setEnabled(false);
600 redo_button.setEnabled(false);
601 default_button.setEnabled(true);
602 newtext = true;
603
604 if(!ignore_event) {
605 ignore_event = true;
606 Entry entry = (Entry) feature_combobox.getSelectedItem();
607
608 // Step one: reset part
609 if (entry.canHavePart()) {
610 part_combobox.setEnabled(true);
611 part_combobox.setSelectedIndex(part_combobox.getModel().getSize()-1);
612
613 } else {
614 part_combobox.setEnabled(false);
615 part_combobox.setSelectedIndex(0);
616 }
617 // Step two: the rest
618
619 String name = entry.toString();
620 // 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
621 Object f = entry.getFeature();
622 Part part = (Part)part_combobox.getSelectedItem();
623 String pname = part.getName();
624 // You can never add anything to blank-blank
625 if(f.toString().length() == 0 && pname.length() == 0) {
626 add_button.setEnabled(false);
627 remove_button.setEnabled(false);
628 } else {
629
630 Format format = getFormat(Format.generateName(f, pname));
631 // If there is an existing feature, select it, and use it to determine what controls are visible
632
633 if(format != null) {
634 ///ystem.err.println("There is an existing format!");
635 format_list.setSelectedValue(format, true);
636 // Now use type to determine what controls are visible, and what have initial values.
637 if(format.isParamType()) {
638 ///ystem.err.println("Flag type");
639 // Flags first.
640 ///election_pane.remove(part_pane);
641 card_layout.show(control_pane, FLAG);
642 view_type = FLAG;
643 // Initial value
644 enabled_checkbox.setSelected(format.getState());
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 } else {
673 ///ystem.err.println("Value type");
674 ///election_pane.add(part_pane);
675 card_layout.show(control_pane, VALUE);
676 view_type = VALUE;
677 // Initial value
678
679 String feature_default_format = (String) default_format_map.get(f.toString());
680 if (feature_default_format != null) {
681
682 editor_textarea.setText(feature_default_format);
683 } else {
684 editor_textarea.setText(part.getDefaultFormat());
685 }
686 editor_textarea.setCaretPosition(0);
687
688 }
689 newFormat();
690 }
691 format = null;
692 name = null;
693 }
694 part = null;
695 pname = null;
696 f = null;
697 name = null;
698 entry = null;
699 ignore_event = false;
700 }
701 undo.discardAllEdits();
702 }
703 }
704
705 private class FormatListListener
706 implements ListSelectionListener {
707 public void valueChanged(ListSelectionEvent event) {
708 undo_button.setEnabled(false);
709 redo_button.setEnabled(false);
710 default_button.setEnabled(true);
711 newtext = true;
712
713 if(!ignore_event && !event.getValueIsAdjusting()) {
714
715 if(!format_list.isSelectionEmpty()) {
716 existingFormat();
717 ignore_event = true;
718 Format format = (Format)format_list.getSelectedValue();
719 // Try to match the target, remembering the entries within are Entry's
720 Entry an_entry = new Entry(format.getFeature());
721 feature_combobox.setSelectedItem(an_entry);
722 // If we didn't match anything, add it and select it again
723 Entry result_entry = (Entry) feature_combobox.getSelectedItem();
724 if(!an_entry.equals(result_entry)) {
725 feature_combobox.insertItemAt(an_entry, feature_combobox.getItemCount());
726 feature_combobox.setSelectedItem(an_entry);
727 }
728
729 // Now use type to determine what controls are visible, and what have initial values.
730 ///ystem.err.println("Determine the correct type.");
731 if(format.isParamType()) {
732 ///ystem.err.println("Flag type - remove part");
733 // Flags first.
734 ///SwingUtilities.invokeLater(new GUIChangeTask(/election_pane, part_pane, blank_pane, false));
735 card_layout.show(control_pane, FLAG);
736 view_type = FLAG;
737 // Initial value
738 enabled_checkbox.setSelected(format.getState());
739 } else {
740 ///ystem.err.println("Value type - show part");
741 ///SwingUtilities.invokeLater(new GUIChangeTask(/election_pane, part_pane, blank_pane, true));
742 card_layout.show(control_pane, VALUE);
743 view_type = VALUE;
744 // Initial values
745 // do we have a part?
746 if (format.canHavePart()) {
747 part_combobox.setEnabled(true);
748 // Try to match the part.
749 String part_entry = format.getPart();
750 // Set Selected Item doesn't work so I'll do this manually
751 boolean found = false;
752 for(int i=0; i < part_combobox.getItemCount(); i++) {
753 Part a_part = (Part) part_combobox.getItemAt(i);
754 if(a_part.equals(part_entry)) {
755 part_combobox.setSelectedItem(a_part);
756 found = true;
757 }
758 a_part = null;
759 }
760 // If we didn't match anything, add it and select it again
761 if(!found) {
762 Part a_part = new Part(part_entry, "");
763 part_combobox.insertItemAt(a_part, part_combobox.getItemCount());
764 part_combobox.setSelectedItem(a_part);
765
766 }
767 } else {
768 part_combobox.setEnabled(false);
769 part_combobox.setSelectedIndex(0);
770 }
771 editor_textarea.setText(format.getValue());
772 editor_textarea.setCaretPosition(0);
773
774 }
775
776 //control_pane.updateUI();
777 ignore_event = false;
778 }
779
780 }
781 undo.discardAllEdits();
782 }
783
784 }
785
786 private void newFormat(){
787 editor_textarea.setEditable(false);
788 editor_textarea.setBackground(Color.lightGray);
789 editor_textarea.setToolTipText(Dictionary.get("CDM.FormatManager.Editor_Disabled_Tooltip"));
790
791 enabled_checkbox.setEnabled(false);
792 undo_button.setEnabled(false);
793 redo_button.setEnabled(false);
794 variable_combobox.setEnabled(false);
795 add_button.setEnabled(true);
796 remove_button.setEnabled(false);
797 default_button.setEnabled(false);
798
799 }
800
801 private void existingFormat(){
802 editor_textarea.setEditable(true);
803 editor_textarea.setBackground(Color.white);
804 editor_textarea.setToolTipText(Dictionary.get("CDM.FormatManager.Editor_Tooltip"));
805 enabled_checkbox.setEnabled(true);
806 variable_combobox.setEnabled(true);
807 add_button.setEnabled(false);
808 remove_button.setEnabled(true);
809 default_button.setEnabled(true);
810
811 }
812
813 private class VariableListener
814 implements ActionListener {
815 public void actionPerformed(ActionEvent event) {
816 int selected_index = variable_combobox.getSelectedIndex();
817 if (selected_index == 0) return;
818 String selected_value = (String)variable_combobox.getSelectedItem();
819 editor_textarea.insert(selected_value, editor_textarea.getCaretPosition());
820 undo_button.setEnabled(true);
821 variable_combobox.setSelectedIndex(0);
822 }
823
824 }
825
826 private class PartListener
827 implements ActionListener {
828 public void actionPerformed(ActionEvent event) {
829 undo_button.setEnabled(false);
830 redo_button.setEnabled(false);
831 default_button.setEnabled(true);
832 newtext = true;
833 if(!ignore_event) {
834 // 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
835 Entry entry = (Entry) feature_combobox.getSelectedItem();
836 Object f = entry.getFeature();
837 Part part = (Part) part_combobox.getSelectedItem();
838 String pname = part.getName();
839 // You can never add anything to blank-blank
840 if(f.toString().length() == 0 && pname.length() == 0) {
841 add_button.setEnabled(false);
842 remove_button.setEnabled(false);
843 } else {
844 String name = Format.generateName(f, pname);
845 Format format = getFormat(name);
846 // If there is an existing feature, select it.
847 if(format != null) {
848 format_list.setSelectedValue(format, true);
849 // Now use type to determine what controls are visible, and what have initial values.
850 if(format.isParamType()) {
851 // Flags first.
852 ///election_pane.remove(part_pane);
853 card_layout.show(control_pane, FLAG);
854 view_type = FLAG;
855 // Initial value
856 enabled_checkbox.setSelected(format.getState());
857 } else {
858 ///election_pane.add(part_pane);
859 card_layout.show(control_pane, VALUE);
860 view_type = VALUE;
861 // Initial value
862
863 editor_textarea.setText(format.getValue());
864 editor_textarea.setCaretPosition(0);
865
866 }
867 control_pane.updateUI();
868 existingFormat();
869 } else {
870 format_list.clearSelection();
871 if(Format.isParamType(name)) {
872 // Flags first.
873 ///election_pane.remove(part_pane);
874 card_layout.show(control_pane, FLAG);
875 view_type = FLAG;
876 // Initial value
877 enabled_checkbox.setSelected(false);
878 enabled_checkbox.setEnabled(false);
879 } else {
880 ///election_pane.add(part_pane);
881 card_layout.show(control_pane, VALUE);
882 view_type = VALUE;
883 // Initial value
884
885 editor_textarea.setText(part.getDefaultFormat());
886 editor_textarea.setCaretPosition(0);
887
888 }
889 newFormat();
890 }
891 format = null;
892 name = null;
893 }
894
895 pname = null;
896 part = null;
897 f = null;
898 entry = null;
899 }
900 undo.discardAllEdits();
901 }
902 }
903
904 private class RemoveListener
905 implements ActionListener {
906
907 public void actionPerformed(ActionEvent event) {
908 if (!format_list.isSelectionEmpty()) {
909 // Remove the current format
910 removeFormat((Format)format_list.getSelectedValue());
911
912 // Change buttons
913 add_button.setEnabled(true);
914 newFormat();
915 }
916 }
917 }
918
919
920
921 private class DefaultListener
922 implements ActionListener {
923
924 public void actionPerformed(ActionEvent event) {
925 newtext = false;
926 if(!ignore_event) {
927 Entry entry = (Entry) feature_combobox.getSelectedItem();
928 Object f = entry.getFeature();
929 String name ="";
930 String pname="";
931 Part part = null;
932
933 if (entry.canHavePart()){
934 part = (Part) part_combobox.getSelectedItem();
935 pname = part.getName();
936 name = Format.generateName(f, pname);
937 } else{
938 name = entry.toString();
939 }
940
941 Format format = getFormat(name);
942 // If there is an existing feature, select it.
943 if(format != null) {
944 remove_button.setEnabled(true);
945 } else {
946
947 add_button.setEnabled(true);
948 }//endif (format !=null)
949
950 if(Format.isParamType(name)) {
951 // Flags first.
952 card_layout.show(control_pane, FLAG);
953 view_type = FLAG;
954 // Initial value
955 enabled_checkbox.setSelected(false);
956 } else {
957 card_layout.show(control_pane, VALUE);
958 view_type = VALUE;
959 // Initial value
960 if (pname !=null && pname.length()!=0 ){
961 editor_textarea.setText((String) default_format_map.get(pname));
962 editor_textarea.setCaretPosition(0);
963 } else{
964 editor_textarea.setText((String) default_format_map.get(name));
965 editor_textarea.setCaretPosition(0);
966 }
967 }
968
969 }
970 }
971
972 }
973
974 private class UndoListener
975 implements ActionListener {
976
977 public void actionPerformed(ActionEvent event) {
978 try {
979 if (undo.canUndo()) {
980 int pos = editor_textarea.getCaretPosition();
981 redo_button.setEnabled(true);
982 undo.undo();
983 if (pos > 0)
984 editor_textarea.setCaretPosition(pos-1);
985 else
986 editor_textarea.setCaretPosition(pos);
987 }
988 if (!undo.canUndo()){
989 undo_button.setEnabled(false);
990 } else{
991 undo_button.setEnabled(true);
992 }
993
994 } catch (Exception e) {
995
996 }
997 }
998 }
999
1000 private class RedoListener
1001 implements ActionListener {
1002 public void actionPerformed(ActionEvent evt) {
1003 try {
1004 if (undo.canRedo()) {
1005 int pos = editor_textarea.getCaretPosition();
1006 undo.redo();
1007 editor_textarea.setCaretPosition(pos);
1008 }
1009 if (!undo.canRedo()){
1010 redo_button.setEnabled(false);
1011 } else{
1012 redo_button.setEnabled(true);
1013 }
1014
1015 } catch (Exception e) {}
1016 }
1017 }
1018
1019 }
1020
1021 /** 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. */
1022 private class Entry
1023 implements Comparable {
1024 private Classifier classifier = null;
1025 private String text = null;
1026
1027 public Entry(Object object) {
1028 if(object instanceof Classifier) {
1029 classifier = (Classifier)object;
1030 } else if(object instanceof String) {
1031 text = (String)object;
1032 } else {
1033 text = "";
1034 }
1035 }
1036
1037 public Entry(String text) {
1038 this.text = text;
1039 }
1040
1041 public boolean canHavePart() {
1042 if (classifier !=null) return true;
1043 return Format.canHavePart(text);
1044 }
1045
1046 public int compareTo(Object object) {
1047 if(object == null) {
1048 return 1;
1049 }
1050 if(toString() == null) {
1051 return -1;
1052 } else {
1053 String object_str = object.toString();
1054 if(object_str == null) {
1055 return 1;
1056 }
1057 return toString().compareTo(object_str);
1058 }
1059 }
1060
1061 public boolean equals(Object object) {
1062 if(compareTo(object) == 0) {
1063 return true;
1064 }
1065 return false;
1066 }
1067
1068 public Classifier getClassifier() {
1069 return classifier;
1070 }
1071
1072 public Object getFeature() {
1073 if(classifier != null) {
1074 return classifier;
1075 }
1076
1077 if (text.startsWith("<html>")){
1078 return "";
1079 }
1080 return text;
1081 }
1082
1083 public String toString() {
1084 if(classifier != null) {
1085 // Return the classifier - with its CL index shown
1086 return classifier.getPositionString() + StaticStrings.COLON_CHARACTER + StaticStrings.SPACE_CHARACTER + classifier.toString();
1087 }
1088 if (text.equals("")) {
1089 return "<html><body><i>"+Dictionary.get("CDM.FormatManager.AllFeatures")+"</i></body></html>";
1090 }
1091 return text;
1092 }
1093 }
1094
1095 /*
1096 private class GUIChangeTask
1097 implements Runnable {
1098 private boolean to_add;
1099 private JPanel child;
1100 private JPanel parent;
1101 private JPanel replacement;
1102
1103 public GUIChangeTask(JPanel parent, JPanel child, JPanel replacement, boolean to_add) {
1104 this.child = child;
1105 this.parent = parent;
1106 this.replacement = replacement;
1107 this.to_add = to_add;
1108 }
1109
1110 public void run() {
1111 if(to_add) {
1112 parent.remove(replacement);
1113 parent.add(child);
1114 parent.updateUI();
1115 }
1116 else {
1117 parent.remove(child);
1118 parent.add(replacement);
1119 parent.updateUI();
1120 }
1121 }
1122 }
1123 */
1124
1125 /** This class encapsulates all of the information associated with a certain component part of a feature within a html page returned from the receptioninst. */
1126 private class Part
1127 implements Comparable {
1128 /** The default format string for this part */
1129 private String default_format = null;
1130 /** The name of this part */
1131 private String name = null;
1132 /** Constructor - must be provided with all of the details of a part as there are no other setter methods.
1133 * @param name the name of this part
1134 * @param default_format the default format string for this part
1135 */
1136 public Part(String name, String default_format) {
1137 this.default_format = default_format;
1138 this.name = name;
1139 }
1140 /** Compare this part to another object in terms of ordering
1141 * @param obj the other Object
1142 * @return <0 if the object is before, 0 if equal to, and >0 if the object is after this part
1143 */
1144 public int compareTo(Object obj) {
1145 if (obj instanceof Part) {
1146 return name.compareTo(((Part)obj).getName());
1147 }
1148 return name.compareTo(obj.toString());
1149 }
1150
1151 /** Determine if the part is equivelent to some other object
1152 * @param obj the other Object
1153 * @return true is the two objects are equal
1154 */
1155 public boolean equals(Object obj) {
1156 if (obj instanceof Part) {
1157 return name.equals(((Part)obj).getName());
1158 }
1159 return name.equals(obj.toString());
1160 }
1161
1162 /** Retrieve the default format string for this part
1163 * @return the default format String
1164 */
1165 public String getDefaultFormat() {
1166 // Retrieve the format for the super format - either VList or HList
1167 Format default_format_object = getFormat(name);
1168 if(default_format_object != null) {
1169 return default_format_object.getValue();
1170 } else {
1171 return this.default_format;
1172 }
1173 }
1174 /** Retrieve the name of this part
1175 * @return the name as a String
1176 */
1177 public String getName() {
1178 return name;
1179 }
1180 /** Produce a string representation of this part, which in this case is simply the name again
1181 * @return the name as a String
1182 */
1183 public String toString() {
1184 if (name.equals("")) {
1185 return "<html><body><i>"+Dictionary.get("CDM.FormatManager.AllParts")+"</i></body></html>";
1186 }
1187 return name;
1188 }
1189 }
1190}
Note: See TracBrowser for help on using the repository browser.