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

Last change on this file since 28995 was 28995, checked in by ak19, 10 years ago

First commit for GLI part of GS2 to GS3 Format Conversion. Contains all the changes needed for the FormatConversionDialog to work, and some cosmetic changes to cdm.Format4gs3Manager.java. Still need to implement undo and redo and think about what needs to happen and how for Remote GS3.

  • 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 removeSurroundingTags(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(removeSurroundingTags(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(removeSurroundingTags(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.