Changeset 25576

Show
Ignore:
Timestamp:
11.05.2012 15:13:09 (7 years ago)
Author:
sjm84
Message:

The editing area of the format features panel is now resizeable

Files:
1 modified

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