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

Last change on this file since 26067 was 26067, checked in by ak19, 12 years ago

The search format statement can also call the choose-title template.

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