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

Last change on this file since 25733 was 25733, checked in by davidb, 12 years ago

Greenstone 2 version of GLI changed to use RsyntaxTextArea so coloured highlighting and other goodies available to the use, including ctrl-Z for undo

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