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

Last change on this file since 25682 was 25682, checked in by davidb, 12 years ago

Changed to using RSyntaxTextArea to get coloured highlighting and other goodies for the Greenstone3 format manager

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