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

Last change on this file since 26129 was 26129, checked in by sjm84, 12 years ago

Removing a line that was added by accident 4 weeks ago

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