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

Last change on this file since 14745 was 14745, checked in by anna, 16 years ago

When a format variable is set to empty string, recover to its default statement.

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