source: gli/branches/2.81-fixed/src/org/greenstone/gatherer/cdm/FormatManager.java@ 18837

Last change on this file since 18837 was 18837, checked in by anna, 15 years ago

committing bugfix 18835 so that format statements can be set to empty, eg. to get rid of the detach and nohighlight buttons.

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