Changeset 25576 for main


Ignore:
Timestamp:
2012-05-11T15:13:09+12:00 (12 years ago)
Author:
sjm84
Message:

The editing area of the format features panel is now resizeable

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/gli/src/org/greenstone/gatherer/cdm/Format4gs3Manager.java

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