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

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

Changing the default format statement to include some templates for document display

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