source: main/trunk/gli/src/org/greenstone/gatherer/cdm/Format4gs3Manager.java@ 26356

Last change on this file since 26356 was 26356, checked in by kjdon, 12 years ago

tidied up some default format

  • Property svn:keywords set to Author Date Id Revision
File size: 32.2 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 * Copyright (C) 1999 New Zealand Digital Library Project
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *########################################################################
24 */
25package org.greenstone.gatherer.cdm;
26
27import java.awt.*;
28import java.awt.event.*;
29import java.util.*;
30import javax.swing.*;
31import javax.swing.event.*;
32import javax.swing.undo.*;
33import javax.xml.parsers.DocumentBuilderFactory;
34
35import org.fife.ui.rsyntaxtextarea.*;
36
37import org.greenstone.gatherer.Configuration;
38import org.greenstone.gatherer.DebugStream;
39import org.greenstone.gatherer.Dictionary;
40import org.greenstone.gatherer.Gatherer;
41import org.greenstone.gatherer.gui.DesignPaneHeader;
42import org.greenstone.gatherer.gui.GLIButton;
43import org.greenstone.gatherer.gui.FormatPane;
44import org.greenstone.gatherer.metadata.MetadataElement;
45import org.greenstone.gatherer.metadata.MetadataSetManager;
46import org.greenstone.gatherer.util.StaticStrings;
47import org.greenstone.gatherer.util.Utility;
48import org.greenstone.gatherer.util.XMLTools;
49import org.w3c.dom.*;
50import org.xml.sax.InputSource;
51
52import java.awt.FontMetrics;
53import java.awt.Graphics;
54import java.awt.Insets;
55import java.awt.Rectangle;
56import java.io.ByteArrayInputStream;
57
58/**
59 * This class maintains a list of format statements, and allows the addition and
60 * removal of these statements. This is the greenstone 3 equivalent class of
61 * FormatManager.java which is used by greenstone 2
62 */
63public class Format4gs3Manager implements SharedByTwoFormatManager
64{
65 // The default global format
66 static final private String GLOBAL_FORMAT;
67 static
68 {
69 // @formatter:off
70 String GLOBAL_FORMAT_TEMP = "" +
71 "<gsf:template name=\"choose-title\">" +
72 "<gsf:choose-metadata>" +
73 "<gsf:metadata name=\"dc.Title\"/>" +
74 "<gsf:metadata name=\"exp.Title\"/>" +
75 "<gsf:metadata name=\"ex.dc.Title\"/>" +
76 "<gsf:metadata name=\"Title\"/>" +
77 "<gsf:default>Untitled</gsf:default>" +
78 "</gsf:choose-metadata>" +
79 "</gsf:template>";
80 GLOBAL_FORMAT = GLOBAL_FORMAT_TEMP;
81 // @formatter:on
82 }
83 static final private String GLOBAL = "global";
84 //The default search format
85 static final private String SEARCH_FORMAT;
86 static
87 {
88 // @formatter:off
89 String SEARCH_FORMAT_TEMP = "" +
90 "<gsf:template match=\"documentNode\">" +
91 "<td valign=\"top\">" +
92 "<gsf:link type=\"document\">" +
93 "<gsf:icon type=\"document\"/>" +
94 "</gsf:link>" +
95 "</td>" +
96 "<td>" +
97 "<gsf:link type=\"document\">" +
98 "<xsl:call-template name=\"choose-title\"/>" +
99 "</gsf:link>" +
100 "</td>" +
101 "</gsf:template>";
102 SEARCH_FORMAT = SEARCH_FORMAT_TEMP;
103 // @formatter:on
104 }
105 static final private String SEARCH = "search";
106 static final private String DISPLAY_DEFAULT_FORMAT;
107 static
108 {
109 // @formatter:off
110 String DISPLAY_DEFAULT_FORMAT_TEMP = "" +
111 "<gsf:option name=\"TOC\" value=\"true\"/>" +
112 "<!--" +
113 "Overwriting this template allows you to change the heading of the document." +
114 "-->" +
115 "<!--" +
116 "<gsf:template name=\"documentHeading\">" +
117 "<span style=\"font-weight:bold; font-size: 120%;\">" +
118 "<xsl:call-template name=\"choose-title\"/>" +
119 "</span>" +
120 "</gsf:template>" +
121 "-->" +
122 "<!--" +
123 "Overwriting this template can be used to redefine the content of the whole document." +
124 "This is useful for simple documents, but not recommended for more complex documents" +
125 "(e.g. hierachical and paged documents) as it can prevent any sub-sections from showing." +
126 "-->" +
127 "<!--" +
128 "<gsf:template name=\"documentContent\">" +
129 "<xsl:call-template name=\"wrappedSectionImage\"/>" +
130 "<xsl:call-template name=\"wrappedSectionText\"/>" +
131 "</gsf:template>" +
132 "-->" +
133 "<!--" +
134 "Overwriting this template can be used to change the content of section headings." +
135 "-->" +
136 "<!--" +
137 "<gsf:template name=\"sectionHeading\">" +
138 "<xsl:call-template name=\"choose-title\"/>" +
139 "</gsf:template>" +
140 "-->" +
141 "<!--" +
142 "Overwriting this template can be used to change the content of the top-level section." +
143 "-->" +
144 "<!--" +
145 "<gsf:template name=\"topLevelSectionContent\">" +
146 "<xsl:call-template name=\"wrappedSectionImage\"/>" +
147 "<xsl:call-template name=\"wrappedSectionText\"/>" +
148 "</gsf:template>" +
149 "-->" +
150 "<!--" +
151 "Overwriting this template can be used to change the content of sections." +
152 "-->" +
153 "<!--" +
154 "<gsf:template name=\"sectionContent\">" +
155 "<xsl:call-template name=\"wrappedSectionImage\"/>" +
156 "<xsl:call-template name=\"wrappedSectionText\"/>" +
157 "</gsf:template>" +
158 "-->";
159 // @formatter:on
160
161 DISPLAY_DEFAULT_FORMAT = DISPLAY_DEFAULT_FORMAT_TEMP;
162 }
163 static final private String DISPLAY = "display";
164
165 //The default browse format
166 static final private String CLASSIFIER_DEFAULT_FORMAT;
167 static
168 {
169 // @formatter:off
170 String CLASSIFIER_DEFAULT_FORMAT_TEMP = "" +
171 "<gsf:template match=\"documentNode\">" +
172 "<td valign=\"top\">" +
173 "<gsf:link type=\"document\">" +
174 "<gsf:icon type=\"document\"/>" +
175 "</gsf:link>" +
176 "</td>" +
177 "<td valign=\"top\">" +
178 "<gsf:link type=\"source\">" +
179 "<gsf:choose-metadata>" +
180 "<gsf:metadata name=\"thumbicon\"/>" +
181 "<gsf:metadata name=\"srcicon\"/>" +
182 "</gsf:choose-metadata>" +
183 "</gsf:link>" +
184 "</td>" +
185 "<td valign=\"top\">" +
186 "<gsf:link type=\"document\">" +
187 "<xsl:call-template name=\"choose-title\"/>" +
188 "</gsf:link>" +
189 "<gsf:switch>" +
190 "<gsf:metadata name=\"Source\"/>" +
191 "<gsf:when test=\"exists\"><br/><i>(<gsf:metadata name=\"Source\"/>)</i></gsf:when>" +
192 "</gsf:switch>" +
193 "</td>" +
194 "</gsf:template>" +
195 "<gsf:template match=\"classifierNode[@classifierStyle = 'VList']\">" +
196 "<td valign=\"top\">" +
197 "<gsf:link type=\"classifier\">" +
198 "<gsf:icon type=\"classifier\"/>" +
199 "</gsf:link>" +
200 "</td>" +
201 "<td valign=\"top\">" +
202 "<gsf:metadata name=\"Title\"/>" +
203 "</td>" +
204 "</gsf:template>" +
205 "<gsf:template match=\"classifierNode[@classifierStyle = 'HList']\">" +
206 "<gsf:link type=\"classifier\">" +
207 "<gsf:metadata name=\"Title\"/>" +
208 "</gsf:link>" +
209 "</gsf:template>";
210 CLASSIFIER_DEFAULT_FORMAT = CLASSIFIER_DEFAULT_FORMAT_TEMP;
211 // @formatter:on
212 }
213 static final private String CLASSIFIER_DEFAULT = "browse";
214 static final private String SEARCHTYPE_FORMAT = "plain,simpleform,advancedform";
215 static final private String SEARCHTYPE = "searchType";
216 static final private String[] FEATURE_NAME = { SEARCH, GLOBAL, DISPLAY, CLASSIFIER_DEFAULT, SEARCHTYPE };
217 static final private String[] FEATURE_FORMAT = { SEARCH_FORMAT, GLOBAL_FORMAT, DISPLAY_DEFAULT_FORMAT, CLASSIFIER_DEFAULT_FORMAT, SEARCHTYPE_FORMAT };
218
219 static private HashMap default_format_map = null;
220 static private HashMap default_format_formated_map = null;
221
222 /** The controls used to edit the format commands. */
223 private Control controls = null;// an interface
224 /** A reference */
225 private DOMProxyListModel format_list_model = null;
226
227 //private DOMProxyListModel feature_list_model = null;
228
229 /** Constructor. */
230 public Format4gs3Manager()
231 {//pass the internal structure
232 Element root = CollectionDesignManager.collect_config.getDocumentElement();
233 format_list_model = new DOMProxyListModel(root, StaticStrings.FORMAT_STR, new Format4gs3());
234 initDefault(format_list_model, FEATURE_NAME, FEATURE_FORMAT);
235 initFormatMap(FEATURE_NAME, FEATURE_FORMAT);
236
237 }
238
239 private void initFormatMap(String[] feature_name, String[] feature_format)
240 {
241 default_format_map = new HashMap();
242 default_format_formated_map = new HashMap();
243 for (int i = 0; i < feature_name.length; i++)
244 {
245 default_format_map.put(feature_name[i], feature_format[i]);
246 default_format_formated_map.put(feature_name[i], Format4gs3.toFormatedFormat(feature_format[i]));
247 }
248
249 }
250
251 public void initDefault(DOMProxyListModel model, String[] feature_name, String[] feature_format)
252 {
253 // Establish all of the format objects.
254 for (int i = 0; i < model.getSize(); i++)
255 {
256 model.getElementAt(i);//get those objects cached
257 }
258 for (int i = 0; i < feature_name.length; i++)
259 {
260 if (getFormat(model, feature_name[i]) == null)
261 {
262 model.add(new Format4gs3(feature_name[i], feature_format[i]));
263
264 }
265 }
266 }
267
268 /**
269 * Method to remove a format.
270 *
271 * @param format
272 * The <strong>Format</strong> to remove.
273 */
274 private void removeFormat(DOMProxyListModel model, Format4gs3 format)
275 {
276 model.remove(format);
277 }
278
279 private Format4gs3 getFormat(DOMProxyListModel model, String name)
280 {
281
282 for (int index = 0; index < model.getSize(); index++)
283 {
284 Format4gs3 format = (Format4gs3) model.getElementAt(index);
285 if (format.getFeatureName().equals(name))
286 {
287 return format;
288 }
289 }
290 return null;
291 }
292
293 private void addFormat(Element parent, Format4gs3 format)
294 {
295 if (!format_list_model.contains(format))
296 {
297
298 format_list_model.add(parent, format, null);
299 }
300 }
301
302 public void destroy()
303 {
304 if (controls != null)
305 {
306 controls.destroy();
307 controls = null;
308 }
309 }
310
311 /**
312 * Method to retrieve this managers controls.
313 *
314 * @return the Control for this collection.
315 */
316 public Control getControls()
317 {
318 if (controls == null)
319 {
320 controls = new FormatControl();
321 }
322 //controls.gainFocus();
323 return controls;
324 }
325
326 /**
327 * Called when the detail mode has changed which in turn may cause several
328 * design elements to be available/hidden
329 *
330 * @param mode
331 * the new mode as an int
332 */
333 public void modeChanged(int mode)
334 {
335
336 }
337
338 /** updates the format and feature model */
339 public synchronized void refresh()
340 {
341 for (int i = 0; i < format_list_model.getSize(); i++)
342 {
343 Format4gs3 format = (Format4gs3) format_list_model.getElementAt(i);
344 format.update();
345 format = null;
346 }
347 //call the gainFocus() and in turn the buildFeatureModel() method to get the feature combobox refreshed as well
348 if (controls == null)
349 {
350 controls = new FormatControl();
351 }
352 controls.gainFocus();
353
354 //format_list_model.refresh(); //this call is not necessary as it is included in gainFocus()
355 }
356
357 private ArrayList buildFeatureModel()
358 {
359 // Rebuild feature model.
360 ArrayList feature_model = new ArrayList();
361 //This will display 'choose a feature' and is used when the format feature panel is first gained focus
362 feature_model.add(new Entry(""));
363
364 for (int i = 0; i < format_list_model.getSize(); i++)
365 {
366 Format4gs3 format = (Format4gs3) format_list_model.getElementAt(i);
367 String feature_name = format.getFeatureName();
368 if (!feature_name.startsWith(Classifier.CLASSIFIER_PREFIX))
369 {
370 feature_model.add(new Entry(format.getFeatureName()));
371
372 }
373 }
374 // Now the classifiers.
375 Element root = CollectionDesignManager.collect_config.getDocumentElement();
376 NodeList classifier_list = root.getElementsByTagName(StaticStrings.CLASSIFY_ELEMENT);
377 for (int j = 0; j < classifier_list.getLength(); j++)
378 {
379 feature_model.add(new Entry(CollectionDesignManager.classifier_manager.getClassifier(j)));
380
381 }
382 //Collections.sort (feature_model);
383 return feature_model;
384 }
385
386 private String addSurroundingTags(String xml)
387 {
388 return "<ROOTELEMENT>" + xml + "</ROOTELEMENT>";
389 }
390
391 private String removeSurrondingTags(String xml)
392 {
393 return xml.replace("<ROOTELEMENT>\n", "").replace("<ROOTELEMENT>", "").replace("</ROOTELEMENT>", "").replace("<ROOTELEMENT/>","");
394 }
395
396 public class FormatControl extends JPanel implements Control
397 {
398
399 private ArrayList feature_model;
400 private boolean ignore_event = false;
401 private boolean ready = false; // Are these controls available to be refreshed
402 private JButton add_button;
403 private JButton remove_button;
404 private JButton default_button;
405 private JButton undo_button;
406 private JButton redo_button;
407 private JComboBox feature_combobox;
408 private JList format_list;
409 private NumberedJTextArea editor_textarea;
410 private JTextArea editor_msgarea;
411 private JPanel validation_msg_panel;
412 private JPanel selection_pane;
413 private final Dimension FIELD_SIZE = new Dimension(200, 30);
414 private final UndoManager undo = new UndoManager();
415 private boolean newtext = true;
416 private Format4gs3 previousFormat = null;
417 private Format4gs3 currentFormat = null;
418 private boolean fresh = true;
419
420 public FormatControl()
421 {
422 feature_model = buildFeatureModel();
423
424 // Create
425 JPanel header_pane = new DesignPaneHeader("CDM.GUI.Formats", "formatstatements");
426
427 format_list = new JList(format_list_model);
428
429 selection_pane = new JPanel();
430 JPanel feature_pane = new JPanel();
431 JLabel feature_label = new JLabel(Dictionary.get("CDM.FormatManager.Feature"));
432
433 feature_combobox = new JComboBox(feature_model.toArray());
434 feature_combobox.setOpaque(!Utility.isMac());
435 feature_combobox.setPreferredSize(FIELD_SIZE);
436 feature_combobox.setEditable(false);
437 feature_combobox.setToolTipText(Dictionary.get("CDM.FormatManager.Feature_Tooltip"));
438
439 JPanel center_pane = new JPanel();
440 JPanel editor_pane = new JPanel();
441
442 editor_textarea = new NumberedJTextArea();
443
444 /* Fields specific to RSyntaxQuery inherited class */
445 editor_textarea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML);
446 editor_textarea.setBracketMatchingEnabled(true);
447 editor_textarea.setAnimateBracketMatching(true);
448 editor_textarea.setAntiAliasingEnabled(true);
449 editor_textarea.setAutoIndentEnabled(true);
450 editor_textarea.setPaintMarkOccurrencesBorder(false);
451
452 /* Standard fields to JTextArea */
453 editor_textarea.setOpaque(false);
454 editor_textarea.setBackground(Configuration.getColor("coloring.editable_background", false));
455 editor_textarea.setCaretPosition(0);
456 editor_textarea.setLineWrap(true);
457 editor_textarea.setRows(11);
458 editor_textarea.setWrapStyleWord(false);
459 editor_textarea.setToolTipText(Dictionary.get("CDM.FormatManager.Add_Tooltip"));
460
461 default_button = new GLIButton(Dictionary.get("CDM.FormatManager.Default"), Dictionary.get("CDM.FormatManager.Default_Tooltip"));
462 JPanel button_pane = new JPanel();
463 add_button = new GLIButton(Dictionary.get("CDM.FormatManager.Add"), Dictionary.get("CDM.FormatManager.Add_Tooltip"));
464 add_button.setEnabled(false);
465
466 remove_button = new GLIButton(Dictionary.get("CDM.FormatManager.Remove"), Dictionary.get("CDM.FormatManager.Remove_Tooltip"));
467 remove_button.setEnabled(false);
468
469 undo_button = new GLIButton(Dictionary.get("General.Undo"), Dictionary.get("General.Undo_Tooltip"));
470 undo_button.setEnabled(false);
471
472 redo_button = new GLIButton(Dictionary.get("General.Redo"), Dictionary.get("General.Redo_Tooltip"));
473 redo_button.setEnabled(false);
474
475 // Connect
476 add_button.addActionListener(new AddListener());
477 remove_button.addActionListener(new RemoveListener());
478 default_button.addActionListener(new DefaultListener());
479 undo_button.addActionListener(new UndoListener());
480 redo_button.addActionListener(new RedoListener());
481 feature_combobox.addActionListener(new FeatureListener());
482 editor_textarea.getDocument().addDocumentListener(new EditorListener());
483 // Listen for undo and redo events
484 editor_textarea.getDocument().addUndoableEditListener(new UndoableEditListener()
485 {
486 public void undoableEditHappened(UndoableEditEvent evt)
487 {
488 undo.addEdit(evt.getEdit());
489 }
490 });
491
492 format_list.addListSelectionListener(new FormatListListener());
493
494 // Layout
495 JPanel format_list_pane = new JPanel();
496 format_list_pane.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
497 format_list_pane.setLayout(new BorderLayout());
498 format_list_pane.add(new JScrollPane(format_list), BorderLayout.CENTER);
499
500 feature_pane.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
501 feature_pane.setLayout(new BorderLayout(5, 0));
502 feature_pane.add(feature_label, BorderLayout.WEST);
503 feature_pane.add(feature_combobox, BorderLayout.CENTER);
504
505 JPanel rupanel = new JPanel();
506 rupanel.setLayout(new GridLayout(1, 2));
507 rupanel.add(undo_button);
508 rupanel.add(redo_button);
509
510 editor_pane.setLayout(new BorderLayout());
511 editor_pane.add(new JScrollPane(editor_textarea), BorderLayout.CENTER);
512
513 validation_msg_panel = new JPanel();
514 JLabel validation_label = new JLabel(Dictionary.get("CDM.FormatManager.MessageBox"));
515 editor_msgarea = new JTextArea();
516
517 editor_msgarea.setCaretPosition(0);
518 editor_msgarea.setLineWrap(true);
519 editor_msgarea.setRows(3);
520 editor_msgarea.setWrapStyleWord(false);
521 editor_msgarea.setEditable(false);
522 editor_msgarea.setToolTipText(Dictionary.get("CDM.FormatManager.MessageBox_Tooltip"));
523 validation_msg_panel.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
524 validation_msg_panel.setLayout(new BorderLayout(5, 0));
525 validation_msg_panel.add(validation_label, BorderLayout.WEST);
526 validation_msg_panel.add(new JScrollPane(editor_msgarea), BorderLayout.CENTER);
527
528 selection_pane.setLayout(new BorderLayout());
529 selection_pane.add(validation_msg_panel, BorderLayout.NORTH);
530 selection_pane.add(rupanel, BorderLayout.SOUTH);
531 selection_pane.add(editor_pane, BorderLayout.CENTER);
532
533 button_pane.setLayout(new GridLayout(1, 3));
534 button_pane.add(add_button);
535 button_pane.add(remove_button);
536 button_pane.add(default_button);
537
538 center_pane.setLayout(new BorderLayout());
539 center_pane.add(feature_pane, BorderLayout.NORTH);
540 center_pane.add(selection_pane, BorderLayout.CENTER);
541 center_pane.add(button_pane, BorderLayout.SOUTH);
542
543 JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
544 splitPane.add(format_list_pane, JSplitPane.TOP);
545 splitPane.add(center_pane, JSplitPane.BOTTOM);
546 splitPane.setDividerLocation(150);
547
548 setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
549 setLayout(new BorderLayout());
550 add(header_pane, BorderLayout.NORTH);
551 add(splitPane, BorderLayout.CENTER);
552 ready = true;
553 }
554
555 public void destroy()
556 {
557 }
558
559 /**
560 * Overriden to ensure that the instructions pane is scrolled to the
561 * top.
562 */
563 public void gainFocus()
564 {
565 if (ready)
566 {
567
568 format_list_model.refresh();
569 // Update the feature model, trying to maintain the same selected object
570 Object selected_feature = feature_combobox.getSelectedItem();
571 feature_combobox.setSelectedItem(selected_feature);
572 feature_model = buildFeatureModel();
573 feature_combobox.setModel(new DefaultComboBoxModel(feature_model.toArray()));
574 }
575 }
576
577 public void loseFocus()
578 {
579 //validate the templates. If not wellformed, pop up an alert; otherwise, do nothing.
580 String msg = XMLTools.parse(editor_textarea.getText());
581 if (msg.startsWith(XMLTools.NOTWELLFORMED))
582 {
583 JOptionPane.showMessageDialog(null, msg, XMLTools.NOTWELLFORMED, JOptionPane.ERROR_MESSAGE);
584 }
585 format_list_model.refresh();
586 }
587
588 public Format4gs3 getCurrentFormat()
589 {
590 return (Format4gs3) format_list.getSelectedValue();
591
592 }
593
594 /**
595 * Listens for clicks on the add button, and if the relevant details are
596 * provided adds a new format. Note that formats are responsible for
597 * codecing the values into something that can be a) stored in a DOM and
598 * b) written to file
599 */
600 private class AddListener implements ActionListener
601 {
602
603 public void actionPerformed(ActionEvent event)
604 {
605
606 ignore_event = true; // Prevent format_list excetera propagating events
607
608 String format_str = editor_textarea.getText();
609 Entry entry = (Entry) feature_combobox.getSelectedItem();
610 String feature_name = entry.getClassifier().getPositionString();
611
612 Format4gs3 format = new Format4gs3(feature_name, format_str);
613 Element e = format.getClassifyElement();
614 addFormat(e, format);
615 existingFormat(format.getFeatureName().startsWith(Classifier.CLASSIFIER_PREFIX)); // set the appropriate enable/disable on the interface
616
617 // Update list selection (make the new added format highlighted on the format list panel)
618 format_list.setSelectedValue(format, true);
619
620 format = null;
621
622 ignore_event = false;
623 }
624 }
625
626 private class EditorListener implements DocumentListener
627 {
628
629 public void changedUpdate(DocumentEvent e)
630 {
631 update();
632 }
633
634 public void insertUpdate(DocumentEvent e)
635 {
636 update();
637 updateUndo("insert");
638
639 }
640
641 public void removeUpdate(DocumentEvent e)
642 {
643 update();
644 updateUndo("remove");
645
646 }
647
648 private void updateUndo(String from)
649 {
650
651 if (!newtext)
652 {
653 undo_button.setEnabled(true);
654 }
655
656 if (editor_textarea.getText().length() != 0 && newtext)
657 {
658 newtext = false;
659 }
660 }
661
662 public void update()
663 {
664 if (!format_list.isSelectionEmpty())
665 {
666 Format4gs3 format = (Format4gs3) format_list.getSelectedValue();
667 String format_str = editor_textarea.getText();
668 String msg = XMLTools.parse(format_str);
669 editor_msgarea.setText(msg);
670
671 if (msg.startsWith(XMLTools.WELLFORMED))
672 {
673 format.setPureFormat(format_str);
674 format.update();
675 format_list_model.refresh(format);
676 editor_msgarea.setBackground(Color.white);
677 FormatPane.setPreviewButton(true);
678 }
679 else
680 {
681 editor_msgarea.setBackground(Color.red);
682 FormatPane.setPreviewButton(false);
683 }
684 }
685 else
686 {
687 add_button.setEnabled(false);
688 }
689 }
690 }
691
692 private class FeatureListener implements ActionListener
693 {
694 public void actionPerformed(ActionEvent event)
695 {
696 undo_button.setEnabled(false);
697 redo_button.setEnabled(false);
698 default_button.setEnabled(true);
699 newtext = true;
700
701 if (ignore_event == true)
702 {
703 undo.discardAllEdits();
704 return;
705 }
706
707 ignore_event = true;
708 // Add is only enabled if there isn't already a format for the choosen feature and part.
709 //Create a dummy format and test if itsa already in the model
710 Entry entry = (Entry) feature_combobox.getSelectedItem();
711 String feature_name = entry.getFeatureName();
712
713 Format4gs3 format = getFormat(format_list_model, feature_name);
714
715 if (format != null)
716 {
717 ///ystem.err.println("There is an existing format!");
718 format_list.setSelectedValue(format, true);
719 Element formatElem = null;
720 try
721 {
722 InputSource is = new InputSource(new ByteArrayInputStream(addSurroundingTags(format.getPureFormat()).getBytes("utf-8")));
723 formatElem = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is).getDocumentElement();
724 }
725 catch (Exception ex)
726 {
727 ex.printStackTrace();
728 }
729
730 if (formatElem != null)
731 {
732 StringBuffer sb = new StringBuffer();
733 XMLTools.xmlNodeToString(sb, formatElem, true, " ", 0);
734 editor_textarea.setText(removeSurrondingTags(sb.toString()));
735 }
736 else
737 {
738 editor_textarea.setText(format.getPureFormat());
739 }
740 editor_textarea.setCaretPosition(0);
741
742 existingFormat(feature_name.startsWith(Classifier.CLASSIFIER_PREFIX));
743 }
744 // Otherwise there is no existing format, then this feature must be a classifier (CL1, 2, ...)
745 // we display the ClassifierDefault for this format
746 else
747 {
748 //Fist reset the format list panel
749 format_list.clearSelection();
750
751 if (feature_name.equals(""))
752 {
753 editor_textarea.setText("");
754
755 }
756 else
757 {
758 //Only for debugging purposes
759 if (entry.getClassifier() == null)
760 {
761 DebugStream.println("It should be a classifier or choose a feature. What is it? " + entry.toString());
762 }
763
764 editor_textarea.setText(Format4gs3.toFormatedFormat(CLASSIFIER_DEFAULT_FORMAT));
765 editor_textarea.setCaretPosition(0);
766 newFormat();
767 }
768 }
769 ignore_event = false;
770 undo.discardAllEdits();
771 }
772 }
773
774 private class FormatListListener implements ListSelectionListener
775 {
776 public void valueChanged(ListSelectionEvent event)
777 {
778 undo_button.setEnabled(false);
779 redo_button.setEnabled(false);
780 default_button.setEnabled(true);
781 newtext = true;
782
783 if (!ignore_event && !event.getValueIsAdjusting())
784 {
785
786 if (!format_list.isSelectionEmpty())
787 {
788 ignore_event = true;
789 Format4gs3 format = (Format4gs3) format_list.getSelectedValue();
790 String feature_name = format.getFeatureName();
791 Entry entry = null;
792 if (feature_name.startsWith(Classifier.CLASSIFIER_PREFIX))
793 {
794 entry = new Entry(format.getClassifier());
795 }
796 else
797 {
798 entry = new Entry(feature_name);
799 }
800 feature_combobox.setSelectedItem(entry);
801
802 existingFormat(format.getFeatureName().startsWith(Classifier.CLASSIFIER_PREFIX));
803
804 Element formatElem = null;
805 try
806 {
807 InputSource is = new InputSource(new ByteArrayInputStream(addSurroundingTags(format.getPureFormat()).getBytes("utf-8")));
808 formatElem = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is).getDocumentElement();
809 }
810 catch (Exception ex)
811 {
812 ex.printStackTrace();
813 }
814
815 if (formatElem != null)
816 {
817 StringBuffer sb = new StringBuffer();
818 XMLTools.xmlNodeToString(sb, formatElem, true, " ", 0);
819 editor_textarea.setText(removeSurrondingTags(sb.toString()));
820 }
821 else
822 {
823 editor_textarea.setText(format.getPureFormat());
824 }
825 editor_textarea.setCaretPosition(0);
826
827 ignore_event = false;
828 }
829
830 }
831 undo.discardAllEdits();
832 }
833
834 }
835
836 private class RemoveListener implements ActionListener
837 {
838 public void actionPerformed(ActionEvent event)
839 {
840 if (!format_list.isSelectionEmpty())
841 {
842 // Remove the current format
843 Format4gs3 format = (Format4gs3) format_list.getSelectedValue();
844 removeFormat(format_list_model, format);
845 // Change buttons
846 add_button.setEnabled(true);
847 feature_combobox.setSelectedItem(new Entry(""));
848 newFormat();
849 }
850 }
851 }
852
853 private class DefaultListener implements ActionListener
854 {
855 public void actionPerformed(ActionEvent event)
856 {
857 newtext = false;
858 if (!ignore_event)
859 {
860 Entry entry = (Entry) feature_combobox.getSelectedItem();
861 String feature_name = entry.getFeatureName();
862 Format4gs3 format = getFormat(format_list_model, feature_name);
863
864 if (format != null)
865 {
866 if (format.isClassifier() == true)
867 {
868 editor_textarea.setText((String) default_format_formated_map.get(CLASSIFIER_DEFAULT));
869 editor_textarea.setCaretPosition(0);
870 remove_button.setEnabled(true);
871 }
872 else
873 {
874 editor_textarea.setText((String) default_format_formated_map.get(format.getFeatureName()));
875 editor_textarea.setCaretPosition(0);
876 remove_button.setEnabled(false);
877 }
878 }
879 else
880 {
881 editor_textarea.setText((String) default_format_formated_map.get(CLASSIFIER_DEFAULT));
882 editor_textarea.setCaretPosition(0);
883 remove_button.setEnabled(false);
884 add_button.setEnabled(true);
885 }
886 }
887 }
888 }
889
890 private class UndoListener implements ActionListener
891 {
892
893 public void actionPerformed(ActionEvent event)
894 {
895 try
896 {
897 if (undo.canUndo())
898 {
899 int pos = editor_textarea.getCaretPosition();
900 redo_button.setEnabled(true);
901 undo.undo();
902 if (pos > 0)
903 editor_textarea.setCaretPosition(pos - 1);
904 else
905 editor_textarea.setCaretPosition(pos);
906 }
907 if (!undo.canUndo())
908 {
909 undo_button.setEnabled(false);
910 }
911 else
912 {
913 undo_button.setEnabled(true);
914 }
915
916 }
917 catch (Exception e)
918 {
919
920 }
921 }
922 }
923
924 private class RedoListener implements ActionListener
925 {
926 public void actionPerformed(ActionEvent evt)
927 {
928 try
929 {
930 if (undo.canRedo())
931 {
932 int pos = editor_textarea.getCaretPosition();
933 undo.redo();
934 editor_textarea.setCaretPosition(pos);
935 }
936 if (!undo.canRedo())
937 {
938 redo_button.setEnabled(false);
939 }
940 else
941 {
942 redo_button.setEnabled(true);
943 }
944
945 }
946 catch (Exception e)
947 {
948 }
949 }
950 }
951
952 private void newFormat()
953 {
954 editor_textarea.setEditable(false);
955 editor_textarea.setBackground(Color.lightGray);
956 editor_textarea.setToolTipText(Dictionary.get("CDM.FormatManager.Editor_Disabled_Tooltip"));
957
958 undo_button.setEnabled(false);
959 redo_button.setEnabled(false);
960 add_button.setEnabled(true);
961 remove_button.setEnabled(false);
962 default_button.setEnabled(false);
963 FormatPane.setPreviewButton(true);
964 }
965
966 private void existingFormat(boolean enableRemoveButton)
967 {
968 editor_textarea.setEditable(true);
969 editor_textarea.setBackground(Color.white);
970 editor_textarea.setToolTipText(Dictionary.get("CDM.FormatManager.Editor_Tooltip"));
971 add_button.setEnabled(false);
972 remove_button.setEnabled(enableRemoveButton);
973 default_button.setEnabled(true);
974 FormatPane.setPreviewButton(true);
975 }
976
977 /**
978 * A textarea with the line number next to each line of the text
979 */
980 public class NumberedJTextArea extends RSyntaxTextArea /* JTextArea */
981 {
982 public void paintComponent(Graphics g)
983 {
984 Insets insets = getInsets();
985 Rectangle rectangle = g.getClipBounds();
986 g.setColor(Color.white);
987 g.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
988
989 super.paintComponent(g);
990
991 if (rectangle.x < insets.left)
992 {
993 FontMetrics font_metrics = g.getFontMetrics();
994 int font_height = font_metrics.getHeight();
995 int y = font_metrics.getAscent() + insets.top;
996 int line_number_start_point = ((rectangle.y + insets.top) / font_height) + 1;
997 if (y < rectangle.y)
998 {
999 y = line_number_start_point * font_height - (font_height - font_metrics.getAscent());
1000 }
1001 int y_axis_end_point = y + rectangle.height + font_height;
1002 int x_axis_start_point = insets.left;
1003 x_axis_start_point -= getFontMetrics(getFont()).stringWidth(Math.max(getRows(), getLineCount() + 1) + " ");
1004 if (!this.getText().trim().equals(""))
1005 {
1006 g.setColor(Color.DARK_GRAY);
1007 }
1008 else
1009 {
1010 g.setColor(Color.white);
1011 }
1012 int length = ("" + Math.max(getRows(), getLineCount() + 1)).length();
1013 while (y < y_axis_end_point)
1014 {
1015 g.drawString(line_number_start_point + " ", x_axis_start_point, y);
1016 y += font_height;
1017 line_number_start_point++;
1018 }
1019 }
1020 }
1021
1022 public Insets getInsets()
1023 {
1024 Insets insets = super.getInsets(new Insets(0, 0, 0, 0));
1025 insets.left += getFontMetrics(getFont()).stringWidth(Math.max(getRows(), getLineCount() + 1) + " ");
1026 return insets;
1027 }
1028 }
1029 }
1030
1031 /**
1032 * This object provides a wrapping around an entry in Format4gs3, which is
1033 * tranparent.
1034 */
1035 // This class is used for display in the feature combobox
1036 private class Entry implements Comparable
1037 {
1038 private Classifier classifier = null;
1039 private String feature_name = null;
1040
1041 public Entry(Object object)
1042 {
1043 if (object instanceof Classifier)
1044 {
1045 classifier = (Classifier) object;
1046 feature_name = classifier.getPositionString();
1047 }
1048 else if (object instanceof String)
1049 {
1050 feature_name = (String) object;
1051 }
1052 else
1053 {
1054 feature_name = "";
1055 }
1056 }
1057
1058 public Entry(String text)
1059 {
1060 this.feature_name = text;
1061 }
1062
1063 public int compareTo(Object object)
1064 {
1065 if (object == null)
1066 {
1067 return 1;
1068 }
1069 if (toString() == null)
1070 {
1071 return -1;
1072 }
1073 else
1074 {
1075 String object_str = object.toString();
1076 if (object_str == null)
1077 {
1078 return 1;
1079 }
1080 return toString().compareTo(object_str);
1081 }
1082 }
1083
1084 public boolean equals(Object object)
1085 {
1086 if (compareTo(object) == 0)
1087 {
1088 return true;
1089 }
1090 return false;
1091 }
1092
1093 public Classifier getClassifier()
1094 {
1095 return classifier;
1096 }
1097
1098 public String toString()
1099 {
1100 if (classifier != null)
1101 {
1102 // Return the classifier name - with its CL index shown, and all its metadata options as well
1103 return classifier.getPositionString() + StaticStrings.SPACE_CHARACTER + classifier.toString();
1104 }
1105 if (feature_name.equals(""))
1106 {
1107 return "<html><body><i>" + "Choose a feature" + "</i></body></html>";
1108 }
1109 return feature_name;
1110 }
1111
1112 public String getFeatureName()
1113 {
1114 return feature_name;
1115 }
1116 }
1117}
Note: See TracBrowser for help on using the repository browser.