Changeset 2780


Ignore:
Timestamp:
05/15/07 13:12:56 (13 years ago)
Author:
melissa
Message:

First stab at a more usable template editor. Note that there are still a few features missing.

Location:
trunk/loci/ome/notes
Files:
5 added
1 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/loci/ome/notes/Notes.java

    r2764 r2780  
    1 // 
     1//  
    22// Notes.java 
    33// 
    44 
    55/* 
    6 OME Notes library for flexible organization and presentation of OME-XML 
    7 metadata. Copyright (C) 2006-@year@ Melissa Linkert. 
    8  
     6OME Metadata Notes application for exploration and editing of OME-XML and 
     7OME-TIFF metadata. Copyright (C) 2006-@year@ Christopher Peterson. 
     8   
    99This program is free software; you can redistribute it and/or modify 
    1010it under the terms of the GNU Library General Public License as published by 
    1111the Free Software Foundation; either version 2 of the License, or 
    1212(at your option) any later version. 
    13  
     13     
    1414This program is distributed in the hope that it will be useful, 
    1515but WITHOUT ANY WARRANTY; without even the implied warranty of 
    1616MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    1717GNU Library General Public License for more details. 
    18  
     18       
    1919You should have received a copy of the GNU Library General Public License 
    2020along with this program; if not, write to the Free Software 
     
    2727import java.awt.*; 
    2828import java.awt.event.*; 
     29import java.awt.image.BufferedImage; 
    2930import java.io.*; 
    3031import java.util.*; 
     
    3839import org.w3c.dom.*; 
    3940 
    40 /** Main OME Notes window. */ 
     41/** Main notes window. */ 
    4142public class Notes extends JFrame implements ActionListener { 
    4243 
     
    4445 
    4546  /** Template that is loaded automatically. */ 
    46   private static final String DEFAULT_TEMPLATE = "templates/viewer.template"; 
     47  private static final String DEFAULT_TEMPLATE = "templates/viewer.template";  
     48 
     49  private static final CellConstraints CC = new CellConstraints(); 
    4750 
    4851  // -- Fields -- 
     
    6164 
    6265  /** Current template file name. */ 
    63   private String templateName; 
     66  private String templateName;  
    6467 
    6568  /** Foreground (font) color. */ 
     
    7881  private OMENode currentRoot; 
    7982 
    80   // -- Constructor -- 
     83  /** Thumbnails for the current file. */ 
     84  private Vector thumb; 
     85 
     86  // -- Constructor --  
    8187 
    8288  /** Constructs a new main window with the default template. */ 
     89  public Notes() { 
     90    this(null, null); 
     91  } 
     92 
     93  /** Constructs a new main window with the given template. */ 
    8394  public Notes(String template, String newfile) { 
    84     super("OME Notes"); 
     95    super("OME Notes");  
     96 
     97    thumb = new Vector(); 
    8598 
    8699    // set up the main panel 
     
    89102 
    90103    // set up the menu bar 
    91  
     104     
    92105    menubar = new JMenuBar(); 
    93  
     106     
    94107    JMenu file = new JMenu("File"); 
    95  
     108  
    96109    JMenuItem newFile = new JMenuItem("New..."); 
    97110    newFile.setActionCommand("new"); 
     
    127140    // add the status bar 
    128141    progress = new JProgressBar(0, 1); 
    129     progress.setStringPainted(true); 
     142    progress.setStringPainted(true);  
    130143    menubar.add(progress); 
    131144 
    132     setJMenuBar(menubar); 
     145    setJMenuBar(menubar);  
    133146 
    134147    // provide a place to show metadata 
     
    143156    } 
    144157    else { 
    145       templateName = DEFAULT_TEMPLATE; 
     158      templateName = DEFAULT_TEMPLATE;  
    146159      loadTemplate(Notes.class.getResourceAsStream(DEFAULT_TEMPLATE)); 
    147160    } 
    148  
     161   
    149162    try { 
    150163      if (newfile != null) openFile(newfile); 
     
    154167    } 
    155168 
    156     setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
     169    setDefaultCloseOperation(DISPOSE_ON_CLOSE);  
    157170    setVisible(true); 
    158171  } 
     
    162175  /** Load and apply a template from the specified file. */ 
    163176  public void loadTemplate(String filename) { 
    164     // clear out previous template 
     177    // clear out previous template  
    165178 
    166179    progress.setString("Loading template " + filename); 
     
    168181    templateName = filename; 
    169182 
    170     // parse the template file 
    171     try { 
     183    // parse the template file  
     184    try {  
    172185      loadTemplate(new Template(filename)); 
    173186    } 
     
    195208    tabPane = new JTabbedPane(); 
    196209    getContentPane().add(tabPane); 
    197  
     210     
    198211    // retrieve defined GUI parameters 
    199     setPreferredSize(new Dimension(currentTemplate.getDefaultWidth(), 
     212    setPreferredSize(new Dimension(currentTemplate.getDefaultWidth(),  
    200213      currentTemplate.getDefaultHeight())); 
    201214 
    202     font = new Font(currentTemplate.getFontStyle(), Font.PLAIN, 
     215    font = new Font(currentTemplate.getFontStyle(), Font.PLAIN,  
    203216      currentTemplate.getFontSize()); 
    204217 
     
    209222    background = new Color(back[0], back[1], back[2]); 
    210223 
    211     // set up all of the defined tabs and fields 
    212  
     224    // set up all of the defined tabs and fields  
     225     
    213226    TemplateTab[] tabs = currentTemplate.getTabs(); 
    214227 
     
    216229      Vector groups = tabs[i].getAllGroups(); 
    217230      Vector fields = tabs[i].getAllFields(); 
    218  
     231   
    219232      JScrollPane scroll = new JScrollPane(); 
    220233      JPanel panel = new JPanel(); 
    221  
    222       String rowString = ""; 
    223       String colString = "pref:grow,"; 
    224  
    225       int paddingColumns = 1; 
    226  
    227       if (currentTemplate.editTemplateFields()) { 
    228         colString = "30dlu,30dlu,3dlu,pref:grow,"; 
    229         paddingColumns = 4; 
    230       } 
     234      
     235      String rowString = "pref,"; 
     236      String colString = "pref,pref:grow,pref:grow,pref:grow,"; 
    231237 
    232238      int numRows = tabs[i].getRows(); 
    233       if (numRows < 1) numRows = 1; 
    234239      int numColumns = tabs[i].getColumns(); 
    235       if (numColumns < 2) numColumns = 2; 
    236       else numColumns += 2; 
     240 
    237241      for (int j=0; j<numRows; j++) { 
    238         rowString += "pref:grow,"; 
    239       } 
     242        rowString += "pref:grow,pref,"; 
     243      } 
     244 
    240245      for (int j=0; j<numColumns; j++) { 
    241         colString += "pref:grow,"; 
    242       } 
     246        colString += "pref:grow,pref,pref:grow,pref,"; 
     247      }  
     248 
    243249      FormLayout l = new FormLayout(colString, rowString); 
    244250      panel.setLayout(l); 
     
    247253 
    248254      int[] rowNumber = new int[l.getColumnCount()]; 
    249       Arrays.fill(rowNumber, 1); 
    250  
    251       CellConstraints cc = new CellConstraints(); 
     255      Arrays.fill(rowNumber, 2); 
    252256 
    253257      for (int j=0; j<groups.size(); j++) { 
     
    255259        for (int r=0; r<group.getRepetitions(); r++) { 
    256260          FormLayout layout = (FormLayout) panel.getLayout(); 
    257           if (tabs[i].getRows() == 0) { 
    258             for (int n=0; n<group.getNumFields() + 1; n++) { 
    259               layout.appendRow(new RowSpec("pref:grow")); 
    260             } 
    261             panel.setLayout(layout); 
    262           } 
    263  
    264           panel.add(new JLabel(group.getName() + " #" + (r + 1)), 
    265             cc.xyw(paddingColumns, rowNumber[paddingColumns - 1], 2)); 
     261      
     262          int col = 2; 
     263 
    266264          if (currentTemplate.editTemplateFields()) { 
    267265            JButton add = new JButton("+"); 
    268             add.setActionCommand("cloneGroup" + i + "-" + j); 
     266            add.setActionCommand("cloneGroup " + i + "-" + j); 
    269267            add.addActionListener(this); 
    270             panel.add(add, cc.xy(1, rowNumber[0])); 
    271             rowNumber[0]++; 
    272  
     268            panel.add(add, CC.xy(col, rowNumber[col - 1])); 
     269            rowNumber[col - 1]++; 
     270            col++; 
     271           
    273272            JButton remove = new JButton("-"); 
    274273            remove.setActionCommand("removeGroup" + i + "-" + j); 
    275274            remove.addActionListener(this); 
    276             panel.add(remove, cc.xy(2, rowNumber[1])); 
    277             rowNumber[1]++; 
     275            panel.add(remove, CC.xy(col, rowNumber[col - 1])); 
     276            rowNumber[col - 1]++; 
     277            col++; 
    278278          } 
     279        
     280          panel.add(new JLabel(group.getName() + " #" + (r + 1)),  
     281            CC.xy(col, rowNumber[col - 1])); 
     282          rowNumber[col - 1]++; 
     283          col++; 
    279284 
    280285          for (int k=0; k<group.getNumFields(); k++) { 
    281286            TemplateField field = group.getField(r, k); 
    282             if (field.getRow() != -1) { 
    283               panel.add(new JLabel(field.getName()), 
    284                 cc.xy(field.getColumn() + paddingColumns, 
    285                 field.getRow() + 1)); 
    286               panel.add(field.getComponent(), 
    287                 cc.xywh(field.getColumn() + paddingColumns + 1, 
    288                 field.getRow() + 1, field.getWidth(), field.getHeight())); 
    289               rowNumber[field.getColumn() + paddingColumns - 1]++; 
    290               rowNumber[field.getColumn() + paddingColumns]++; 
    291             } 
    292             else { 
    293               panel.add(new JLabel(field.getName()), 
    294                 cc.xy(paddingColumns + 1, rowNumber[paddingColumns])); 
    295               rowNumber[paddingColumns]++; 
    296               panel.add(field.getComponent(), cc.xywh(paddingColumns + 2, 
    297                 rowNumber[paddingColumns + 1], field.getWidth(), 
    298                 field.getHeight())); 
    299               rowNumber[paddingColumns + 1]++; 
    300             } 
    301             rowNumber[paddingColumns - 1]++; 
     287            setupField(field, col, r, rowNumber, panel);  
    302288          } 
    303289        } 
    304290      } 
    305291 
    306       FormLayout layout = (FormLayout) panel.getLayout(); 
    307       for (int j=0; j<fields.size() - 1; j++) { 
    308         layout.appendRow(new RowSpec("pref:grow")); 
    309       } 
    310       panel.setLayout(layout); 
    311  
    312292      for (int j=0; j<fields.size(); j++) { 
    313         TemplateField f = tabs[i].getField(j); 
    314         if (f.getRow() != -1 || f.getColumn() != -1) { 
    315           int column = f.getColumn() == -1 ? 1 : f.getColumn(); 
    316           int row = f.getRow() == -1 ? rowNumber[column - 1] : f.getRow(); 
    317           int width = f.getWidth(); 
    318           int height = f.getHeight(); 
    319  
    320           panel.add(new JLabel(f.getName()), cc.xyw(column, row, 1)); 
    321           panel.add(f.getComponent(), cc.xywh(column + 1, row, width, height)); 
    322           rowNumber[column - 1]++; 
    323         } 
    324         else { 
    325           panel.add(new JLabel(f.getName()), 
    326             cc.xyw(1, rowNumber[0], paddingColumns + 1)); 
    327           rowNumber[0]++; 
    328           panel.add(f.getComponent(), cc.xywh(paddingColumns + 1, 
    329             rowNumber[paddingColumns], f.getWidth(), f.getHeight())); 
    330           rowNumber[paddingColumns]++; 
    331         } 
    332       } 
    333  
    334       tabPane.add(scroll, tabs[i].getName()); 
    335     } 
    336  
     293        TemplateField f = tabs[i].getField(j);  
     294        setupField(f, 2, 0, rowNumber, panel); 
     295      } 
     296 
     297      tabPane.add(scroll, tabs[i].getName());  
     298    } 
     299     
    337300    setFontAndColors(this); 
    338301    changeEditable(currentTemplate.isEditable(), this); 
    339302    progress.setString(""); 
    340303 
    341     pack(); 
     304    pack();  
    342305  } 
    343306 
    344307  /** Recursively set the font and colors for the root and all children. */ 
    345308  public void setFontAndColors(Container root) { 
    346     Component[] components = root instanceof JMenu ? 
     309    Component[] components = root instanceof JMenu ?  
    347310      ((JMenu) root).getMenuComponents() : root.getComponents(); 
    348311    for (int i=0; i<components.length; i++) { 
     
    351314      components[i].setBackground(background); 
    352315 
    353       if (components[i] instanceof JTextArea || 
    354         components[i] instanceof JComboBox || 
    355         components[i] instanceof JCheckBox) 
     316      if (components[i] instanceof JTextArea ||  
     317        components[i] instanceof JComboBox ||  
     318        components[i] instanceof JCheckBox)  
    356319      { 
    357         LineBorder b = new LineBorder(foreground); 
    358         ((JComponent) components[i]).setBorder(b); 
     320        LineBorder b = new LineBorder(foreground);  
     321        ((JComponent) components[i]).setBorder(b);  
    359322      } 
    360323 
     
    369332    Component[] c = root.getComponents(); 
    370333    for (int i=0; i<c.length; i++) { 
    371       if (!(c[i] instanceof JMenuBar) && !(c[i] instanceof JMenu) && 
     334      if (!(c[i] instanceof JMenuBar) && !(c[i] instanceof JMenu) &&  
    372335        !(c[i] instanceof JMenuItem) && !(c[i] instanceof JLabel) && 
    373336        !(c[i] instanceof JScrollBar) && !(c[i] instanceof JTabbedPane)) 
    374       { 
    375         c[i].setEnabled(enable); 
     337      {   
     338        c[i].setEnabled(enable);  
    376339      } 
    377340      if (c[i] instanceof Container) { 
     
    387350 
    388351    if (cmd.equals("new")) { 
    389       // check if the user wants to save the current metadata first 
    390  
    391       int s = JOptionPane.showConfirmDialog(this, "Save current metadata?", "", 
    392         JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); 
    393  
     352      // check if the user wants to save the current metadata first  
     353 
     354      int s = JOptionPane.showConfirmDialog(this, "Save current metadata?", "",  
     355        JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE);  
     356        
    394357      if (s == JOptionPane.YES_OPTION) { 
    395358        actionPerformed(new ActionEvent(this, -1, "save")); 
    396359      } 
    397       loadTemplate(currentTemplate); 
     360      thumb.clear(); 
     361      loadTemplate(currentTemplate);  
    398362    } 
    399363    else if (cmd.equals("open")) { 
    400       progress.setString("Opening file..."); 
     364      progress.setString("Opening file...");  
    401365 
    402366      try { 
     
    408372          currentFile = chooser.getSelectedFile().getAbsolutePath(); 
    409373        } 
    410         if (currentFile == null) return; 
     374        if (currentFile == null) return;  
    411375 
    412376        openFile(currentFile); 
     
    418382    else if (cmd.equals("save")) { 
    419383      progress.setString("Saving metadata to companion file..."); 
    420  
     384      
    421385      if (currentRoot == null) { 
    422386        OMEXMLMetadataStore tmp = new OMEXMLMetadataStore(); 
     
    426390 
    427391      currentTemplate.saveFields(currentRoot); 
    428  
    429       // always save to the current filename + ".ome" 
    430  
     392    
     393      // always save to the current filename + ".ome"  
     394       
    431395      OMEXMLMetadataStore store = new OMEXMLMetadataStore(); 
    432396      store.setRoot(currentRoot); 
     
    434398      try { 
    435399        String name = currentFile; 
    436  
     400         
    437401        if (name == null) { 
    438402          JFileChooser chooser = new JFileChooser(); 
    439  
     403       
    440404          FileFilter filter = new FileFilter() { 
    441405            public boolean accept(File f) { 
    442               return true; 
     406              return true;  
    443407            } 
    444408            public String getDescription() { 
     
    452416          if (status == JFileChooser.APPROVE_OPTION) { 
    453417            name = chooser.getSelectedFile().getAbsolutePath(); 
    454             if (name == null) return; 
     418            if (name == null) return;  
    455419          } 
    456420        } 
    457  
     421        
    458422        if (name == null) return; 
    459423        if (!name.endsWith(".ome")) name += ".ome"; 
     
    461425        File f = new File(name); 
    462426        currentRoot.writeOME(f, false); 
    463         progress.setString("Finished writing companion file (" + name + ")"); 
     427        progress.setString("Finished writing companion file (" + name + ")");  
    464428      } 
    465429      catch (Exception io) { 
     
    471435    } 
    472436    else if (cmd.equals("load")) { 
    473       // prompt for the new template file 
     437      // prompt for the new template file  
    474438      JFileChooser chooser = new JFileChooser(); 
    475  
     439       
    476440      FileFilter filter = new FileFilter() { 
    477441        public boolean accept(File f) { 
     
    489453        loadTemplate(chooser.getSelectedFile().getAbsolutePath()); 
    490454      } 
    491       try { 
    492         if (currentFile != null) openFile(currentFile); 
     455      try {  
     456        if (currentFile != null) openFile(currentFile);  
    493457      } 
    494458      catch (Exception exc) { 
     
    498462    else if (cmd.startsWith("cloneGroup")) { 
    499463      cmd = cmd.substring(10); 
    500       int tabIndex = Integer.parseInt(cmd.substring(0, cmd.indexOf("-"))); 
    501       int groupIndex = Integer.parseInt(cmd.substring(cmd.indexOf("-") + 1)); 
     464      int tabIndex =  
     465        Integer.parseInt(cmd.substring(0, cmd.indexOf("-")).trim()); 
     466      int groupIndex =  
     467        Integer.parseInt(cmd.substring(cmd.indexOf("-") + 1).trim()); 
    502468 
    503469      TemplateTab tab = currentTemplate.getTabs()[tabIndex]; 
    504470      TemplateGroup group = tab.getGroup(groupIndex); 
    505471      group.setRepetitions(group.getRepetitions() + 1); 
    506  
    507       int tabIdx = tabPane.getSelectedIndex(); 
    508  
    509       loadTemplate(currentTemplate); 
    510       try { 
    511         if (currentFile != null) openFile(currentFile); 
     472       
     473      int tabIdx = tabPane.getSelectedIndex();  
     474       
     475      loadTemplate(currentTemplate);  
     476      try {  
     477        if (currentFile != null) openFile(currentFile);  
    512478      } 
    513479      catch (Exception exc) { 
     
    515481      } 
    516482 
    517       tabPane.setSelectedIndex(tabIdx); 
    518     } 
     483      tabPane.setSelectedIndex(tabIdx);  
     484    }  
    519485    else if (cmd.startsWith("removeGroup")) { 
    520486      cmd = cmd.substring(11); 
    521       int tabIndex = Integer.parseInt(cmd.substring(0, cmd.indexOf("-"))); 
    522       int groupIndex = Integer.parseInt(cmd.substring(cmd.indexOf("-") + 1)); 
     487      int tabIndex =  
     488        Integer.parseInt(cmd.substring(0, cmd.indexOf("-")).trim()); 
     489      int groupIndex =  
     490        Integer.parseInt(cmd.substring(cmd.indexOf("-") + 1).trim()); 
    523491 
    524492      TemplateTab tab = currentTemplate.getTabs()[tabIndex]; 
    525493      TemplateGroup group = tab.getGroup(groupIndex); 
    526       group.setRepetitions(group.getRepetitions() - 1); 
    527  
    528       int tabIdx = tabPane.getSelectedIndex(); 
    529  
    530       loadTemplate(currentTemplate); 
    531       try { 
    532         if (currentFile != null) openFile(currentFile); 
     494      group.setRepetitions(group.getRepetitions() - 1);   
     495       
     496      int tabIdx = tabPane.getSelectedIndex();  
     497       
     498      loadTemplate(currentTemplate);  
     499      try {  
     500        if (currentFile != null) openFile(currentFile);  
    533501      } 
    534502      catch (Exception exc) { 
    535503        exc.printStackTrace(); 
    536504      } 
    537  
     505       
    538506      tabPane.setSelectedIndex(tabIdx); 
    539507    } 
     
    544512 
    545513  private void openFile(String file) throws Exception { 
    546     currentFile = file; 
     514    currentFile = file;  
    547515    FileStitcher stitcher = new FileStitcher(); 
    548516    progress.setString("Reading " + currentFile); 
    549  
     517    
    550518    if (currentFile.endsWith(".ome")) { 
    551       File f = new File(currentFile); 
     519      File f = new File(currentFile);  
    552520      currentRoot = new OMENode(f); 
    553521    } 
     
    556524      File companion = new File(currentFile + ".ome"); 
    557525      if (companion.exists()) { 
    558         progress.setString("Reading companion file (" + companion + ")"); 
     526        progress.setString("Reading companion file (" + companion + ")");  
    559527        currentRoot = new OMENode(companion); 
    560528      } 
    561529 
    562530      stitcher.setMetadataStore(new OMEXMLMetadataStore()); 
    563       stitcher.setId(currentFile); 
    564       OMEXMLMetadataStore store = 
     531      stitcher.setId(currentFile);  
     532      OMEXMLMetadataStore store =  
    565533        (OMEXMLMetadataStore) stitcher.getMetadataStore(); 
    566534 
     
    575543        } 
    576544        else { 
    577           currentRoot = merge((OMENode) store.getRoot(), currentRoot); 
     545          currentRoot = merge((OMENode) store.getRoot(), currentRoot);  
    578546        } 
    579547      } 
    580548      else currentRoot = (OMENode) store.getRoot(); 
     549       
     550      // grab thumbnails 
     551 
     552      for (int i=0; i<stitcher.getSeriesCount(); i++) {  
     553        stitcher.setSeries(i);  
     554        thumb.add(stitcher.openThumbImage(0)); 
     555      }  
     556 
    581557      stitcher.close(); 
    582     } 
    583     progress.setString("Populating fields..."); 
    584     currentTemplate.initializeFields(currentRoot); 
    585     currentTemplate.populateFields(currentRoot); 
    586     loadTemplate(currentTemplate); 
    587     progress.setString(""); 
     558    }  
     559    progress.setString("Populating fields...");  
     560    currentTemplate.initializeFields(currentRoot);  
     561    currentTemplate.populateFields(currentRoot);  
     562    loadTemplate(currentTemplate);  
     563    progress.setString("");  
     564  } 
     565 
     566  /** Set up a new field in the current tab. */ 
     567  private void setupField(TemplateField field, int col, int r, int[] rowNumber, 
     568    JPanel panel)  
     569  {  
     570    JComponent c = field.getComponent(); 
     571 
     572    if (field.getType().equals("thumbnail")) { 
     573      BufferedImage thumbnail = null; 
     574      if (field.getValueMap() == null && thumb.size() > 0) { 
     575        thumbnail = (BufferedImage) thumb.get(r); 
     576      } 
     577      else if (field.getValueMap() != null) { 
     578        try { 
     579          ImageReader tempReader = new ImageReader(); 
     580          tempReader.setId(field.getValueMap()); 
     581          if (tempReader.getImageCount() > 0) { 
     582            thumbnail = tempReader.openThumbImage(0); 
     583          } 
     584          tempReader.close();  
     585        } 
     586        catch (Exception e) { 
     587          e.printStackTrace(); 
     588        } 
     589      } 
     590            
     591      if (thumbnail != null) { 
     592        ((JLabel) c).setIcon(new ImageIcon(thumbnail)); 
     593      }  
     594    } 
     595          
     596    int cndx = (field.getColumn() - 1) * 4 + col; 
     597    int rowNdx = field.getRow() == -1 ? rowNumber[cndx - 1] : 2*field.getRow();  
     598    FormLayout layout = (FormLayout) panel.getLayout();  
     599    if (rowNdx > layout.getRowCount() - 1) { 
     600      layout.appendRow(new RowSpec("pref:grow")); 
     601      layout.appendRow(new RowSpec("pref")); 
     602    } 
     603 
     604    panel.add(new JLabel(field.getName()), CC.xy(cndx, rowNdx));  
     605    panel.add(c, CC.xy(cndx + 1, rowNdx));  
     606     
     607    if (field.getRow() == -1) { 
     608      rowNumber[cndx - 1]++;  
     609      rowNumber[cndx]++;  
     610    }  
     611   
     612    if (rowNdx > rowNumber[1]) { 
     613      for (int i=0; i<col - 1; i++) { 
     614        rowNumber[i] = rowNdx + 2; 
     615      } 
     616    } 
    588617  } 
    589618 
    590619  /** 
    591620   * Merge two OME-CA trees. When a conflict arises, use the value in 'over'. 
    592    * This method was adapted from the OME Metadata Editor, 
     621   * This method was adapted from an earlier version of OME Notes, 
    593622   * written by Christopher Peterson. 
    594623   * 
     
    601630    return null; 
    602631  } 
    603  
     632   
    604633  /** 
    605634   * Merge two OME-XML trees. 
    606    * This method was adapted from the OME Metadata Editor, 
     635   * This method was adapted from an earlier version of OME Notes, 
    607636   * written by Christopher Peterson. 
    608637   */ 
     
    630659        else if (!isHighCustom && isLowCustom && !addedCustom) { 
    631660          result.getDOMElement().appendChild(createClone( 
    632             lowNode.getDOMElement(), 
     661            lowNode.getDOMElement(),  
    633662            highNode.getDOMElement().getOwnerDocument())); 
    634663          addedCustom = true; 
     
    640669            if (ids.indexOf(lowID) > -1) { 
    641670              result.getDOMElement().appendChild(createClone( 
    642                 lowNode.getDOMElement(), 
     671                lowNode.getDOMElement(),  
    643672                highNode.getDOMElement().getOwnerDocument())); 
    644               ids.add(lowID); 
     673              ids.add(lowID);  
    645674            } 
    646675          } 
     
    648677      } 
    649678    } 
    650     return result; 
    651   } 
    652  
    653   /** 
    654    * Clones the specified DOM element, preserving the parent structure. 
    655    * This method was adapted from the OME Metadata Editor, 
     679    return result;  
     680  } 
     681 
     682  /**  
     683   * Clones the specified DOM element, preserving the parent structure.  
     684   * This method was adapted from an earlier version of OME Notes, 
    656685   * written by Christopher Peterson. 
    657686   */ 
     
    667696      } 
    668697    } 
    669  
     698   
    670699    if (el.hasChildNodes()) { 
    671700      NodeList nodes = el.getChildNodes(); 
     
    677706      } 
    678707    } 
    679     return clone; 
     708    return clone;  
    680709  } 
    681710 
     
    686715    for (int i=0; i<args.length; i++) { 
    687716      if (args[i].equals("-template")) { 
    688         if (args.length > i + 1) { 
     717        if (args.length > i + 1) {  
    689718          template = args[++i]; 
    690719        } 
    691720        else System.err.println("Please specify a template file"); 
    692721      } 
    693       else data = args[i]; 
    694     } 
    695  
     722      else data = args[i];  
     723    } 
     724    
    696725    new Notes(template, data); 
    697726  } 
  • trunk/loci/ome/notes/Template.java

    r2764 r2780  
    44 
    55/* 
    6 OME Notes library for flexible organization and presentation of OME-XML 
    7 metadata. Copyright (C) 2006-@year@ Melissa Linkert. 
     6OME Metadata Notes application for exploration and editing of OME-XML and 
     7OME-TIFF metadata. Copyright (C) 2006-@year@ Christopher Peterson. 
    88 
    99This program is free software; you can redistribute it and/or modify 
     
    215215              // we're opening 
    216216 
    217               String map = group.getField(0, k).getMap(); 
     217              String map = group.getField(0, k).getValueMap(); 
    218218              map = map.substring(0, map.indexOf(":")); 
    219219 
     
    238238 
    239239        for (int j=0; j<tabs[i].getNumFields(); j++) { 
    240           populateField(root, tabs[i].getField(j)); 
     240          if (!tabs[i].getField(j).getType().equals("thumbnail")) { 
     241            populateField(root, tabs[i].getField(j)); 
     242          }  
    241243        } 
    242244      } 
     
    294296        writer.write("    name \"" + t.getName() + "\"\n"); 
    295297        writer.write("    type \"" + t.getType() + "\"\n"); 
    296         if (t.getMap() != null) { 
    297           writer.write("    map \"" + t.getMap() + "\"\n"); 
     298        if (t.getValueMap() != null) { 
     299          writer.write("    valueMap \"" + t.getValueMap() + "\"\n"); 
     300        } 
     301        if (t.getNameMap() != null) { 
     302          writer.write("    nameMap \"" + t.getNameMap() + "\"\n");  
    298303        } 
    299304        if (t.getDefaultValue() != null) { 
     
    329334          writer.write("      name \"" + t.getName() + "\"\n"); 
    330335          writer.write("      type \"" + t.getType() + "\"\n"); 
    331           if (t.getMap() != null) { 
    332             writer.write("      map \"" + t.getMap() + "\"\n"); 
     336          if (t.getValueMap() != null) { 
     337            writer.write("      valueMap \"" + t.getValueMap() + "\"\n"); 
     338          } 
     339          if (t.getNameMap() != null) { 
     340            writer.write("      nameMap \"" + t.getNameMap() + "\"\n"); 
    333341          } 
    334342          if (t.getDefaultValue() != null) { 
     
    368376      for (int j=0; j<fields; j++) { 
    369377        if (tabs[i].getField(j).isRepeated()) { 
    370           String map = tabs[i].getField(j).getMap(); 
     378          String map = tabs[i].getField(j).getValueMap(); 
    371379          if (map.indexOf("-") != -1) map = map.substring(0, map.indexOf("-")); 
    372380 
    373381          try { 
    374             int nodeCount = getNodeCount(root, map); 
     382            int nodeCount = TemplateTools.getNodeCount(root, map); 
    375383            for (int k=1; k<nodeCount; k++) { 
    376384              TemplateField f = tabs[i].getField(j).copy(); 
    377               f.setMap(map + "-" + k); 
     385              f.setValueMap(map + "-" + k); 
     386              f.setNameMap(f.getNameMap() + "-" + k);  
     387              f.setRow(tabs[i].getField(j).getRow() + k);  
    378388              tabs[i].addField(f); 
    379389            } 
     
    391401          TemplateField f = g.getField(0, k).copy(); 
    392402          if (f.isRepeated()) { 
    393             String map = f.getMap(); 
     403            String map = f.getValueMap(); 
    394404            if (map.indexOf("-") != -1) { 
    395405              map = map.substring(0, map.indexOf("-")); 
     
    397407 
    398408            try { 
    399               for (int m=1; m<getNodeCount(root, map); m++) { 
    400                 f.setMap(map + "-" + k); 
     409              for (int m=1; m<TemplateTools.getNodeCount(root, map); m++) { 
     410                f.setValueMap(map + "-" + k); 
     411                f.setNameMap(f.getNameMap() + "-" + k); 
     412                f.setRow(g.getField(0, k).getRow() + m);  
    401413                g.addField(f); 
    402414              } 
     
    504516  // -- Helper methods -- 
    505517 
     518  /** Populate the given TemplateField's name, if necessary. */ 
     519  private void populateName(OMENode root, TemplateField t) throws Exception { 
     520    if (t.getNameMap() != null) {  
     521      t.setName(TemplateTools.getString(root, t.getNameMap(), false)); 
     522    }  
     523  } 
     524 
    506525  /** Populate the given TemplateField. */ 
    507526  private void populateField(OMENode root, TemplateField t) throws Exception { 
    508     OMEXMLNode node = findNode(root, t.getMap(), false); 
    509  
    510     if (node == null) { 
    511       // unmapped field 
    512  
    513       CustomAttributesNode ca = root.getCustomAttributes(); 
    514  
    515       if (ca != null) { 
    516         Vector elements = DOMUtil.getChildElements("NotesField", 
    517           ca.getDOMElement()); 
    518         for (int i=0; i<elements.size(); i++) { 
    519           Element el = (Element) elements.get(i); 
    520           if (DOMUtil.getAttribute("name", el).equals(t.getName())) { 
    521             String v = DOMUtil.getAttribute("value", el); 
    522             setComponentValue(t, t.getComponent(), v); 
    523           } 
    524         } 
    525       } 
    526  
    527       return; 
    528     } 
    529  
    530     String map = t.getMap(); 
    531     map = map.substring(map.lastIndexOf(":") + 1); 
    532     if (map.indexOf("-") != -1) { 
    533       map = map.substring(0, map.indexOf("-")); 
    534     } 
    535  
    536     if (node instanceof AttributeNode) { 
    537       setComponentValue(t, t.getComponent(), node.getAttribute(map)); 
    538       return; 
    539     } 
    540  
    541     String methodName1 = "get" + map; 
    542     String methodName2 = "is" + map; 
    543  
    544     if (map.equals("CreationDate")) methodName1 = "getCreated"; 
    545  
    546     // retrieve the appropriate value 
    547  
    548     Method[] methods = node.getClass().getMethods(); 
    549     for (int j=0; j<methods.length; j++) { 
    550       String name = methods[j].getName(); 
    551  
    552       if ((name.equals(methodName1) || name.equals(methodName2)) && 
    553         methods[j].getParameterTypes().length == 0) 
    554       { 
    555         Object o = methods[j].invoke(node, new Object[0]); 
    556         String s = o == null ? "" : o.toString(); 
    557         String v = s.toLowerCase(); 
    558  
    559         // populate the corresponding Swing component 
    560  
    561         setComponentValue(t, t.getComponent(), v); 
    562         break; 
    563       } 
    564     } 
     527    setComponentValue(t, t.getComponent(),  
     528      TemplateTools.getString(root, t.getValueMap(), true));  
     529    populateName(root, t); 
    565530  } 
    566531 
    567532  /** Save the given TemplateField. */ 
    568533  private void saveField(OMENode root, TemplateField t) throws Exception { 
    569     OMEXMLNode node = findNode(root, t.getMap(), true); 
     534    OMEXMLNode node = TemplateTools.findNode(root, t.getValueMap(), true); 
    570535 
    571536    JComponent c = t.getComponent(); 
    572     Object value = null; 
    573  
    574     if (c instanceof JCheckBox) { 
    575       value = new Boolean(((JCheckBox) c).isSelected()); 
    576     } 
    577     else if (c instanceof JComboBox) { 
    578       value = ((JComboBox) c).getSelectedItem(); 
    579     } 
    580     else if (c instanceof JScrollPane) { 
    581       JScrollPane scroll = (JScrollPane) c; 
    582       JViewport view = scroll.getViewport(); 
    583       value = ((JTextArea) view.getView()).getText(); 
    584     } 
    585     else if (c instanceof JSpinner) { 
    586       value = ((JSpinner) c).getValue(); 
    587     } 
    588  
    589     String map = t.getMap(); 
     537    Object value = TemplateTools.getComponentValue(c); 
     538    String map = t.getValueMap(); 
    590539 
    591540    if (map == null || map.length() == 0) { 
     
    625574  } 
    626575 
    627   /** Retrieve the number of nodes corresponding to this map. */ 
    628   private int getNodeCount(OMENode root, String map) throws Exception { 
    629     if (map == null || map.length() == 0 || root == null) return 0; 
    630     map = map.substring(0, map.lastIndexOf(":")); 
    631     map = map.substring(map.lastIndexOf(":") + 1); 
    632     if (map.indexOf("-") != -1) map = map.substring(0, map.indexOf("-")); 
    633     return DOMUtil.findElementList(map, root.getOMEDocument(true)).size(); 
    634   } 
    635  
    636   /** 
    637    * Find the OME-XML node corresponding to the given map string. 
    638    * If the 'create' flag is set, a new node will be created if one does not 
    639    * already exist. 
    640    */ 
    641   private OMEXMLNode findNode(OMENode root, String map, boolean create) 
    642     throws Exception 
    643   { 
    644     if (map == null || map.length() == 0) return null; 
    645  
    646     // the 'map' string is a colon-separated list of nodes from the root 
    647     // to the field we want to read 
    648     // 
    649     // example: if we want to read the 'PixelType' value of a Pixels node, 
    650     // the value of 'map' would be 'Image:Pixels:PixelType' 
    651  
    652     String st = map.substring(0, map.indexOf(":")); 
    653     map = map.substring(map.indexOf(":") + 1); 
    654  
    655     int ndx = 0; 
    656     if (map.indexOf("-") != -1 && map.indexOf("OriginalMetadata") == -1) { 
    657       ndx = Integer.parseInt(map.substring(map.indexOf("-") + 1)); 
    658       map = map.substring(0, map.indexOf("-")); 
    659     } 
    660  
    661     Class stClass = null; 
    662  
    663     try { 
    664       stClass = Class.forName("org.openmicroscopy.xml." + st + "Node"); 
    665     } 
    666     catch (ClassNotFoundException c) { 
    667       stClass = Class.forName("org.openmicroscopy.xml.st." + st + "Node"); 
    668     } 
    669  
    670     Vector nodes = OMEXMLNode.createNodes(stClass, 
    671       DOMUtil.getChildElements(st, root.getDOMElement())); 
    672  
    673     if (nodes.size() == 0 && create) { 
    674       Class param = stClass.getName().startsWith("org.openmicroscopy.xml.st.") ? 
    675         CustomAttributesNode.class : root.getClass(); 
    676       Constructor con = stClass.getConstructor(new Class[] {param}); 
    677       nodes.add((OMEXMLNode) con.newInstance(new Object[] {root})); 
    678     } 
    679     else if (nodes.size() == 0) return null; 
    680  
    681     OMEXMLNode node = (OMEXMLNode) nodes.get(ndx < nodes.size() ? ndx : 0); 
    682  
    683     if (map.indexOf("OriginalMetadata") != -1 && map.indexOf("-") != -1) { 
    684       ndx = Integer.parseInt(map.substring(map.indexOf("-") + 1)); 
    685       map = map.substring(0, map.indexOf("-")); 
    686     } 
    687  
    688     while (map.indexOf(":") != -1) { 
    689       String type = map.substring(0, map.indexOf(":")); 
    690       map = map.substring(map.indexOf(":") + 1); 
    691  
    692       String methodName1 = "get" + type; 
    693       String methodName2 = "getDefault" + type; 
    694  
    695       if (node instanceof CustomAttributesNode) { 
    696         methodName2 = "getCAList"; 
    697       } 
    698  
    699       // find the next node in the list 
    700  
    701       Method[] methods = node.getClass().getMethods(); 
    702  
    703       for (int j=0; j<methods.length; j++) { 
    704         String name = methods[j].getName(); 
    705         if (name.equals(methodName1) || name.equals(methodName2)) { 
    706           if (node instanceof CustomAttributesNode) { 
    707             Vector list = (Vector) methods[j].invoke(node, new Object[0]); 
    708  
    709             int count = -1; 
    710             for (int k=0; k<list.size(); k++) { 
    711               String className = list.get(k).getClass().getName(); 
    712               int idx = className.lastIndexOf("."); 
    713               className = className.substring(idx + 1); 
    714  
    715               if (className.equals(type + "Node") || 
    716                 (className.equals("AttributeNode") && 
    717                 type.equals("OriginalMetadata"))) 
    718               { 
    719                 count++; 
    720                 if (count == ndx) { 
    721                   node = (OMEXMLNode) list.get(k); 
    722                   if (type.equals("OriginalMetadata")) return node; 
    723                   break; 
    724                 } 
    725               } 
    726             } 
    727           } 
    728           else node = (OMEXMLNode) methods[j].invoke(node, new Object[0]); 
    729  
    730           // check if we found a matching node; if not, create one 
    731           if (node == null || 
    732             !node.getClass().getName().endsWith(type + "Node")) 
    733           { 
    734             Class target = null; 
    735  
    736             try { 
    737               target = Class.forName("org.openmicroscopy.xml." + type + "Node"); 
    738             } 
    739             catch (ClassNotFoundException e) { 
    740               try { 
    741                 target = 
    742                   Class.forName("org.openmicroscopy.xml.st." + type + "Node"); 
    743               } 
    744               catch (ClassNotFoundException cfe) { 
    745                 cfe.printStackTrace(); 
    746               } 
    747             } 
    748  
    749             Class param = 
    750               target.getName().startsWith("org.openmicroscopy.xml.st.") ? 
    751               CustomAttributesNode.class : node.getClass(); 
    752             Constructor con = target.getConstructor(new Class[] {param}); 
    753  
    754             if (node == null) { 
    755               node = (OMEXMLNode) nodes.get(ndx < nodes.size() ? ndx : 0); 
    756               node = (OMEXMLNode) param.getConstructor(new Class[] 
    757                 {node.getClass()}).newInstance(new Object[] {node}); 
    758             } 
    759  
    760             node = (OMEXMLNode) con.newInstance(new Object[] {node}); 
    761           } 
    762           break; 
    763         } 
    764       } 
    765     } 
    766     return node; 
    767   } 
    768  
    769576  /** Sets the value of the given component, based on the given string. */ 
    770577  private void setComponentValue(TemplateField t, JComponent component, 
  • trunk/loci/ome/notes/TemplateField.java

    r2764 r2780  
    44 
    55/* 
    6 OME Notes library for flexible organization and presentation of OME-XML 
    7 metadata. Copyright (C) 2006-@year@ Melissa Linkert. 
     6OME Metadata Notes application for exploration and editing of OME-XML and 
     7OME-TIFF metadata. Copyright (C) 2006-@year@ Christopher Peterson. 
    88 
    99This program is free software; you can redistribute it and/or modify 
     
    2626import java.util.*; 
    2727import javax.swing.*; 
     28import loci.formats.ImageTools; 
    2829 
    2930/** Stores information about a template field. */ 
     
    4445  private String name; 
    4546 
    46   /** Represents how this field should be mapped into OME-CA. */ 
    47   private String omecaMap; 
     47  /** Represents how this field's name should be mapped into OME-CA. */ 
     48  private String nameMap; 
     49 
     50  /** Represents how this field's value should be mapped into OME-CA. */ 
     51  private String valueMap; 
    4852 
    4953  /** Component used to represent this field. */ 
     
    5155 
    5256  /** Row and column in the layout grid. */ 
    53   private int row = -1, column = -1; 
     57  private int row = -1, column = 1; 
    5458 
    5559  /** Width and height of the component (in terms of grid cells). */ 
     
    7882        value = value.substring(1, value.length() - 1); 
    7983 
    80         if (key.startsWith("name")) name = value; 
     84        if (key.startsWith("nameMap")) nameMap = value; 
     85        else if (key.startsWith("name")) name = value; 
    8186        else if (key.startsWith("type")) type = value; 
    82         else if (key.startsWith("map")) omecaMap = value; 
     87        else if (key.startsWith("valueMap")) valueMap = value; 
    8388        else if (key.startsWith("repeated")) { 
    8489          repeated = new Boolean(value).booleanValue(); 
     
    134139      ((JComboBox) component).setSelectedItem(defaultValue); 
    135140    } 
     141    else if (type.equals("thumbnail")) { 
     142      ImageIcon icon =  
     143        new ImageIcon(ImageTools.makeImage(new byte[1][1], 1, 1));  
     144      component = new JLabel(icon, SwingConstants.LEFT);  
     145    } 
    136146    else if (type.equals("int")) { 
    137147      if (defaultValue == null) defaultValue = new Integer(0); 
     
    150160    rtn.setEnums(getEnums()); 
    151161    rtn.setName(getName()); 
    152     rtn.setMap(getMap()); 
     162    rtn.setNameMap(getNameMap()); 
     163    rtn.setValueMap(getValueMap()); 
    153164    rtn.setColumn(getColumn()); 
    154165    rtn.setWidth(getWidth()); 
     
    174185      ((JComboBox) comp).setSelectedItem(defaultValue); 
    175186    } 
     187    else if (type.equals("thumbnail")) { 
     188      ImageIcon icon =  
     189        new ImageIcon(ImageTools.makeImage(new byte[1][1], 1, 1));  
     190      comp = new JLabel(icon, SwingConstants.LEFT);  
     191    } 
    176192    else if (type.equals("int")) { 
    177193      int v = ((Integer) defaultValue).intValue(); 
     
    199215  public void setName(String name) { this.name = name; } 
    200216 
    201   public String getMap() { return omecaMap; } 
    202  
    203   public void setMap(String map) { omecaMap = map; } 
     217  public String getNameMap() { return nameMap; } 
     218 
     219  public void setNameMap(String map) { nameMap = map; } 
     220 
     221  public String getValueMap() { return valueMap; } 
     222 
     223  public void setValueMap(String map) { valueMap = map; } 
    204224 
    205225  public JComponent getComponent() { return component; } 
  • trunk/loci/ome/notes/TemplateGroup.java

    r2764 r2780  
    44 
    55/* 
    6 OME Notes library for flexible organization and presentation of OME-XML 
    7 metadata. Copyright (C) 2006-@year@ Melissa Linkert. 
     6OME Metadata Notes application for exploration and editing of OME-XML and 
     7OME-TIFF metadata. Copyright (C) 2006-@year@ Christopher Peterson. 
    88 
    99This program is free software; you can redistribute it and/or modify 
     
    114114   */ 
    115115  private void adjustMap(TemplateField t, int repetition) { 
    116     String map = t.getMap(); 
     116    String map = t.getValueMap(); 
    117117    if (map == null) return; 
    118118 
     
    122122 
    123123    map = map + "-" + repetition; 
    124     t.setMap(map); 
     124    t.setValueMap(map); 
    125125  } 
    126126 
  • trunk/loci/ome/notes/TemplateTab.java

    r2764 r2780  
    7474  public void setRows(int rows) { this.rows = rows; } 
    7575 
    76   public int getColumns() { return columns; } 
     76  public int getColumns() {  
     77    if (columns != 0) return columns;  
     78    int max = 1;  
     79     
     80    for (int i=0; i<fields.size(); i++) { 
     81      TemplateField f = (TemplateField) fields.get(i); 
     82      if (f.getColumn() > max) max = f.getColumn(); 
     83    }  
     84    columns = max; 
     85    return columns; 
     86  } 
    7787 
    7888  public void setColumns(int columns) { this.columns = columns; } 
  • trunk/loci/ome/notes/editor/TemplateEditor.java

    r2770 r2780  
    44 
    55/* 
    6 OME Notes library for flexible organization and presentation of OME-XML 
    7 metadata. Copyright (C) 2006-@year@ Melissa Linkert. 
    8  
     6OME Metadata Notes application for exploration and editing of OME-XML and 
     7OME-TIFF metadata. Copyright (C) 2006-@year@ Christopher Peterson. 
     8     
    99This program is free software; you can redistribute it and/or modify 
    1010it under the terms of the GNU Library General Public License as published by 
    1111the Free Software Foundation; either version 2 of the License, or 
    1212(at your option) any later version. 
    13  
     13          
    1414This program is distributed in the hope that it will be useful, 
    1515but WITHOUT ANY WARRANTY; without even the implied warranty of 
    1616MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    1717GNU Library General Public License for more details. 
    18  
     18                   
    1919You should have received a copy of the GNU Library General Public License 
    2020along with this program; if not, write to the Free Software 
     
    2727import java.awt.*; 
    2828import java.awt.event.*; 
    29 import java.io.*; 
     29import java.awt.image.BufferedImage; 
     30import java.io.File; 
     31import java.io.IOException; 
    3032import java.util.*; 
    3133import javax.swing.*; 
    3234import javax.swing.filechooser.FileFilter; 
     35import loci.formats.*; 
    3336import loci.ome.notes.*; 
    3437 
    35 /** Main class for OME Notes template editor. */ 
    36 public class TemplateEditor extends JFrame 
    37   implements ActionListener, MouseListener 
    38 { 
     38/** Main class for template editor. */ 
     39public class TemplateEditor extends JFrame implements ActionListener { 
    3940 
    4041  // -- Constants -- 
    4142 
    4243  /** List of component names. */ 
    43   private static final String[] COMPONENT_NAMES = new String[] {"Text field", 
    44     "Number field", "Choice field", "Checkbox field" 
     44  protected static final String[] COMPONENT_NAMES = new String[] { 
     45    "Text field", "Number field", "Choice box", "Check box", "Image thumbnail" 
    4546  }; 
    4647 
    4748  /** List of component classes. */ 
    48   private static final Class[] COMPONENTS = new Class[] { 
    49     JTextField.class, JSpinner.class, JComboBox.class, JCheckBox.class 
     49  protected static final Class[] COMPONENTS = new Class[] { 
     50    JTextField.class, JSpinner.class, JComboBox.class, JCheckBox.class,  
     51    JLabel.class 
    5052  }; 
    5153 
    5254  /** List of component types. */ 
    53   private static final String[] COMPONENT_TYPES = new String[] { 
    54     "var", "int", "enum", "bool" 
     55  protected static final String[] COMPONENT_TYPES = new String[] { 
     56    "var", "int", "enum", "bool", "thumbnail" 
    5557  }; 
    56  
     58   
    5759  public static final int TAB = 0, GROUP = 1, FIELD = 2; 
    5860 
    5961  // -- Fields -- 
    6062 
    61   /** Menu for choosing which tab to edit. */ 
    62   private JMenu tabMenu; 
    63  
    64   /** Menus for choosing which tab, group, or field to remove. */ 
    65   private JMenu removeTab, removeGroup, removeField; 
    66  
    67   /** Menu for choosing a field to edit. */ 
    68   private JMenu fieldOptions; 
    69  
    70   /** Layout for the template panel. */ 
    71   private FormLayout templateLayout; 
    72  
    73   /** Panel that shows the template. */ 
    74   private JPanel template; 
    75  
    76   /** Panel that contains organization options. */ 
    77   private JPanel organization; 
    78  
    79   /** List of TemplateTabs. */ 
    80   private Vector tabs; 
    81  
    82   /** List of tab panels corresponding to TemplateTabs. */ 
    83   private Vector tabPanels; 
    84  
    85   /** Current tab index. */ 
    86   private int currentTab; 
    87  
    88   /** General template options. */ 
    89   private Hashtable options; 
    90  
    91   /** Popup menu for dynamically adding/removing rows. */ 
    92   private JPopupMenu popup; 
     63  /** Main editing panel. */ 
     64  private JTabbedPane tabPane; 
     65 
     66  /** Panel containing drag-and-drop components. */ 
     67  private JPanel componentPane; 
     68 
     69  /** Current file name. */ 
     70  private String currentFile; 
     71 
     72  private JTextField newTabName; 
     73  
     74  private PictureTransferHandler pictureHandler; 
     75 
     76  private int lastMenuX = 0; 
     77  private int lastMenuY = 0; 
     78  private JComponent lastMenuComponent = null; 
     79 
     80  private Hashtable[] icons; 
     81  private Hashtable[] fields; 
    9382 
    9483  // -- Constructor -- 
    9584 
    96   /** Constructs a new window with a blank template. */ 
    9785  public TemplateEditor() { 
    9886    super("OME Notes Template Editor"); 
    9987 
    100     tabs = new Vector(); 
    101     tabPanels = new Vector(); 
    102  
    103     // set up menu bar 
     88    pictureHandler = new PictureTransferHandler(); 
     89    icons = new Hashtable[0]; 
     90    fields = new Hashtable[0]; 
     91 
     92    // set up the menu bar 
    10493 
    10594    JMenuBar menubar = new JMenuBar(); 
    10695 
    10796    JMenu file = new JMenu("File"); 
    108  
     97     
    10998    JMenuItem newFile = new JMenuItem("New..."); 
    11099    newFile.setActionCommand("new"); 
     
    112101    file.add(newFile); 
    113102 
    114     JMenuItem openFile = new JMenuItem("Open..."); 
     103    JMenuItem openFile = new JMenuItem("Open"); 
    115104    openFile.setActionCommand("open"); 
    116105    openFile.addActionListener(this); 
    117106    file.add(openFile); 
    118107 
    119     JMenuItem saveFile = new JMenuItem("Save..."); 
     108    JMenuItem saveFile = new JMenuItem("Save"); 
    120109    saveFile.setActionCommand("save"); 
    121110    saveFile.addActionListener(this); 
     
    129118    menubar.add(file); 
    130119 
    131     JMenu view = new JMenu("View"); 
    132  
    133     tabMenu = new JMenu("Tab"); 
    134     view.add(tabMenu); 
    135     menubar.add(view); 
    136  
    137     JMenu add = new JMenu("Add"); 
    138  
    139     JMenuItem newTab = new JMenuItem("Tab"); 
    140     newTab.setActionCommand("new tab"); 
    141     newTab.addActionListener(this); 
    142     add.add(newTab); 
    143  
    144     JMenuItem newGroup = new JMenuItem("Group"); 
    145     newGroup.setActionCommand("new group"); 
    146     newGroup.addActionListener(this); 
    147     add.add(newGroup); 
    148  
    149     add.add(new JSeparator()); 
    150  
    151     for (int i=0; i<COMPONENT_NAMES.length; i++) { 
    152       JMenuItem item = new JMenuItem(COMPONENT_NAMES[i]); 
    153       item.setActionCommand(COMPONENT_NAMES[i]); 
    154       item.addActionListener(this); 
    155       add.add(item); 
    156     } 
    157  
    158     menubar.add(add); 
    159  
    160     JMenu remove = new JMenu("Remove"); 
    161  
    162     removeTab = new JMenu("Tab"); 
    163     remove.add(removeTab); 
    164  
    165     removeGroup = new JMenu("Group"); 
    166     remove.add(removeGroup); 
    167  
    168     removeField = new JMenu("Field"); 
    169     remove.add(removeField); 
    170  
    171     menubar.add(remove); 
    172  
    173     JMenu optionsMenu = new JMenu("Options"); 
    174  
    175     JMenuItem general = new JMenuItem("General"); 
    176     general.setActionCommand("general options"); 
    177     general.addActionListener(this); 
    178     optionsMenu.add(general); 
    179  
    180     fieldOptions = new JMenu("Field"); 
    181     optionsMenu.add(fieldOptions); 
    182  
    183     menubar.add(optionsMenu); 
    184  
    185120    setJMenuBar(menubar); 
    186121 
    187     // set up popup menu 
    188  
    189     popup = new JPopupMenu(); 
    190     JMenuItem item = new JMenuItem("Add row"); 
    191     item.setActionCommand("add row"); 
    192     item.addActionListener(this); 
    193     popup.add(item); 
    194  
    195     item = new JMenuItem("Remove row"); 
    196     item.setActionCommand("remove row"); 
    197     item.addActionListener(this); 
    198     popup.add(item); 
    199  
    200     popup.add(new JSeparator()); 
    201  
    202     item = new JMenuItem("Add column"); 
    203     item.setActionCommand("add column"); 
    204     item.addActionListener(this); 
    205     popup.add(item); 
    206  
    207     item = new JMenuItem("Remove column"); 
    208     item.setActionCommand("remove column"); 
    209     item.addActionListener(this); 
    210     popup.add(item); 
    211  
    212     // set up template panel 
     122    // set up the toolbar 
     123 
     124    JToolBar toolbar = new JToolBar(); 
     125    toolbar.setFloatable(false); 
     126 
     127    JButton tab = new JButton("New Tab"); 
     128    tab.addActionListener(this); 
     129    tab.setActionCommand("prompt tab"); 
     130 
     131    JButton row = new JButton("Add Row"); 
     132    row.addActionListener(this); 
     133    row.setActionCommand("add row"); 
     134     
     135    JButton col = new JButton("Add Column");  
     136    col.addActionListener(this); 
     137    col.setActionCommand("add col"); 
     138 
     139    JButton remove = new JButton("Remove this tab"); 
     140    remove.addActionListener(this); 
     141    remove.setActionCommand("removeTab"); 
     142 
     143    toolbar.add(tab); 
     144    toolbar.add(row); 
     145    toolbar.add(col); 
     146    toolbar.add(remove); 
     147 
     148    // set up the rest of the window 
    213149 
    214150    CellConstraints cc = new CellConstraints(); 
    215151 
    216     templateLayout = new FormLayout("pref:grow, pref:grow", "pref:grow"); 
    217     template = new JPanel(templateLayout); 
    218     template.addMouseListener(this); 
    219  
    220     String rowString = "2dlu, pref:grow"; 
    221     for (int i=1; i<COMPONENT_NAMES.length; i++) { 
    222       rowString += ", 2dlu, pref:grow"; 
    223     } 
    224  
    225     setContentPane(template); 
     152    FormLayout layout =  
     153      new FormLayout("pref:grow,pref,pref:grow,pref:grow,pref:grow",  
     154      "pref,5dlu:grow,pref:grow,pref:grow,pref:grow"); 
     155 
     156    JPanel contentPane = new JPanel(layout); 
     157 
     158    contentPane.add(toolbar, cc.xywh(1, 1, 5, 1)); 
     159 
     160    tabPane = new JTabbedPane(); 
     161    contentPane.add(tabPane, cc.xywh(3, 2, 3, 4)); 
     162 
     163    FormLayout componentLayout = new FormLayout("pref:grow,pref:grow",  
     164      "pref:grow,pref:grow,pref:grow,pref:grow,pref:grow,pref:grow"); 
     165    componentPane = new JPanel(componentLayout); 
     166 
     167    componentPane.add(new JLabel("Field Choices"), cc.xywh(1, 1, 2, 1)); 
     168 
     169    try { 
     170      for (int i=0; i<COMPONENTS.length; i++) { 
     171        JLabel label = new JLabel(COMPONENT_NAMES[i]); 
     172        componentPane.add(label, cc.xy(1, i + 2)); 
     173         
     174        JPanel panel = new JPanel();  
     175        JComponent component = (JComponent) COMPONENTS[i].newInstance();  
     176        component.setPreferredSize(new Dimension(64, 25));  
     177        component.setEnabled(false);  
     178        panel.add(component);  
     179 
     180        DraggableIcon img = new DraggableIcon(panel, -1, -1);  
     181        img.setTransferHandler(pictureHandler); 
     182        img.setEditable(false); 
     183 
     184        componentPane.add(img, cc.xy(2, i + 2)); 
     185      } 
     186    } 
     187    catch (Exception e) { 
     188      error("Failed to create field list", e);  
     189    } 
     190 
     191    contentPane.add(componentPane, cc.xywh(1, 2, 1, 4)); 
     192 
     193    setContentPane(contentPane);   
    226194    setPreferredSize(new Dimension(768, 768)); 
    227195    pack(); 
     
    229197    setVisible(true); 
    230198  } 
    231  
     199   
    232200  // -- TemplateEditor API methods -- 
    233201 
    234   /** Add a new tab to this template. */ 
    235   private void addTab(TemplateTab tab) { 
    236     addTab(tab, tab.getNumFields(), 1); 
    237   } 
    238  
    239   /** Add a new tab with the specified number of rows and columns. */ 
    240   private void addTab(TemplateTab tab, int rows, int columns) { 
    241     tabs.add(tab); 
    242  
    243     StringBuffer row = new StringBuffer(); 
    244     StringBuffer col = new StringBuffer(); 
    245  
    246     for (int i=0; i<rows; i++) { 
    247       row.append("pref:grow"); 
    248       if (i < rows - 1) row.append(", "); 
    249     } 
    250  
    251     for (int i=0; i<columns; i++) { 
    252       col.append("pref:grow, pref:grow"); 
    253       if (i < columns - 1) col.append(", "); 
    254     } 
    255  
    256     FormLayout layout = new FormLayout(col.toString(), row.toString()); 
    257     JPanel panel = new JPanel(layout); 
    258  
    259     CellConstraints cc = new CellConstraints(); 
    260  
    261     for (int i=0; i<tab.getNumFields(); i++) { 
    262       TemplateField f = tab.getField(i); 
    263       panel.add(new JLabel(f.getName()), cc.xy(1, i + 1)); 
    264       panel.add(f.getComponent(), cc.xywh(2, i + 1, f.getWidth(), 
    265         f.getHeight())); 
    266     } 
    267     tabPanels.add(panel); 
    268  
    269     // add this tab to the menu bar 
    270     JMenuItem item = new JMenuItem(tab.getName()); 
    271     item.setActionCommand("tab" + (tabs.size() - 1)); 
    272     item.addActionListener(this); 
    273     tabMenu.add(item); 
    274     pack(); 
    275   } 
    276  
    277   private void updateRemoveLists() { 
    278     removeTab.removeAll(); 
    279     removeGroup.removeAll(); 
    280     removeField.removeAll(); 
    281  
    282     for (int i=0; i<tabs.size(); i++) { 
    283       TemplateTab tab = (TemplateTab) tabs.get(i); 
    284  
    285       JMenuItem item = new JMenuItem(tab.getName()); 
    286       item.setActionCommand("removeTab " + i); 
    287       item.addActionListener(this); 
    288       removeTab.add(item); 
    289  
    290       int numFields = 0; 
    291  
    292       for (int j=0; j<tab.getNumGroups(); j++) { 
    293         TemplateGroup g = tab.getGroup(j); 
    294  
    295         JMenuItem group = new JMenuItem(g.getName()); 
    296         group.setActionCommand("removeGroup " + j); 
    297         group.addActionListener(this); 
    298         removeGroup.add(group); 
    299  
    300         for (int k=0; k<g.getNumFields(); k++) { 
    301           JMenuItem f = new JMenuItem(g.getField(0, k).getName()); 
    302           f.setActionCommand("removeField " + j + "-" + (numFields + k)); 
    303           f.addActionListener(this); 
    304           removeField.add(f); 
    305         } 
    306         numFields += g.getNumFields(); 
    307       } 
    308  
    309       for (int j=0; j<tab.getNumFields(); j++) { 
    310         JMenuItem f = new JMenuItem(tab.getField(j).getName()); 
    311         f.setActionCommand("removeField " + (numFields + j)); 
    312         f.addActionListener(this); 
    313         removeField.add(f); 
    314       } 
    315     } 
    316  
    317   } 
    318  
    319   // -- ActionListener API methods -- 
    320  
    321   public void actionPerformed(ActionEvent e) { 
     202  // -- ActionListener API method -- 
     203 
     204  public void actionPerformed(ActionEvent e) {  
    322205    String cmd = e.getActionCommand(); 
    323     if (cmd == null) return; 
    324  
     206   
    325207    if (cmd.equals("new")) { 
     208      icons = new Hashtable[0]; 
     209      fields = new Hashtable[0]; 
     210 
     211      tabPane.removeAll();  
     212      repaint();  
    326213    } 
    327214    else if (cmd.equals("open")) { 
    328       // prompt for template file to open 
    329215      JFileChooser chooser = new JFileChooser(); 
    330216      FileFilter filter = new FileFilter() { 
     
    332218          return f.getAbsolutePath().endsWith(".template") || f.isDirectory(); 
    333219        } 
    334         public String getDescription() { return "OME Notes templates"; } 
     220        public String getDescription() { return "OME Notes Templates"; }  
    335221      }; 
    336  
     222    
    337223      chooser.setFileFilter(filter); 
    338224 
    339       if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { 
    340         try { 
    341           Template t = 
    342             new Template(chooser.getSelectedFile().getAbsolutePath()); 
    343           TemplateTab[] newTabs = t.getTabs(); 
    344           for (int i=0; i<newTabs.length; i++) addTab(newTabs[i]); 
    345         } 
    346         catch (IOException exc) { 
    347           exc.printStackTrace(); 
    348         } 
    349       } 
    350  
    351     } 
    352     else if (cmd.equals("save")) { 
    353       // prompt for path to save to 
    354       try { 
    355         JFileChooser chooser = new JFileChooser(); 
    356         if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { 
    357           Hashtable h = new Hashtable(); 
    358           if (options != null && options.size() > 0) { 
    359             Object[] keys = options.keySet().toArray(); 
    360             for (int i=0; i<keys.length; i++) { 
    361               String value = ((Option) options.get(keys[i])).value; 
    362               if (value != null) h.put(keys[i], value); 
     225      int status = chooser.showOpenDialog(this); 
     226      if (status == JFileChooser.APPROVE_OPTION) { 
     227        String file = chooser.getSelectedFile().getAbsolutePath();  
     228        try {  
     229          Template t = new Template(file);  
     230 
     231          TemplateTab[] tabs = t.getTabs(); 
     232          for (int i=0; i<tabs.length; i++) { 
     233            int rows = tabs[i].getRows();  
     234            int cols = tabs[i].getColumns();  
     235            if (cols == 0) cols = 1; 
     236            if (rows == 0) rows = 1; 
     237 
     238            addTab(tabs[i].getName(), rows, cols); 
     239            tabPane.setSelectedIndex(i); 
     240 
     241            for (int j=0; j<tabs[i].getNumFields(); j++) { 
     242              TemplateField f = tabs[i].getField(j); 
     243               
     244              int x = f.getRow(); 
     245              int y = f.getColumn(); 
     246              if (x == -1) x = 1; 
     247              if (y == -1) y = j + 1; 
     248              
     249              Point p = new Point(x, y); 
     250              DraggableIcon icon = (DraggableIcon) icons[i].get(p); 
     251 
     252              icon.label = new JLabel(f.getName()); 
     253           
     254              JPanel panel = new JPanel(); 
     255              panel.add(f.getComponent()); 
     256 
     257              icon.setPanel(panel);  
    363258            } 
    364259          } 
    365  
    366           Template t = new Template( 
    367             (TemplateTab[]) tabs.toArray(new TemplateTab[0]), h); 
    368           t.save(chooser.getSelectedFile().getAbsolutePath()); 
    369260        } 
    370       } 
    371       catch (IOException exc) { 
    372         exc.printStackTrace(); 
     261        catch (Exception exc) { 
     262          error("Failed to parse template", exc);  
     263        } 
     264 
     265        tabPane.setSelectedIndex(0); 
     266      } 
     267    } 
     268    else if (cmd.equals("save")) { 
     269      // build up the template from the components  
     270       
     271      TemplateTab[] tabs = new TemplateTab[tabPane.getTabCount()];  
     272      
     273      for (int i=0; i<tabs.length; i++) { 
     274        tabs[i] = new TemplateTab(); 
     275        tabs[i].setName(tabPane.getTitleAt(i));  
     276        JComponent c = (JComponent) tabPane.getComponentAt(i); 
     277        FormLayout layout = (FormLayout) c.getLayout(); 
     278 
     279        tabs[i].setRows(layout.getRowCount()); 
     280        tabs[i].setColumns(layout.getColumnCount()); 
     281 
     282        Object[] keys = icons[i].keySet().toArray(); 
     283 
     284        for (int j=0; j<keys.length; j++) { 
     285          Point p = (Point) keys[j]; 
     286          DraggableIcon icon = (DraggableIcon) icons[i].get(p); 
     287          TemplateField f = (TemplateField) fields[i].get(p);  
     288 
     289          if (icon.image != null) { 
     290            Component[] components = icon.image.getComponents(); 
     291            JLabel label = icon.label; 
     292            JComponent component = (JComponent) components[0]; 
     293 
     294            f.setComponent(component); 
     295 
     296            for (int k=0; k<COMPONENTS.length; k++) { 
     297              if (component.getClass().equals(COMPONENTS[k])) { 
     298                f.setType(COMPONENT_TYPES[k]); 
     299                break; 
     300              } 
     301            } 
     302           
     303            f.setRow(p.y); 
     304            f.setColumn(p.x); 
     305            f.setDefaultValue(TemplateTools.getComponentValue(component)); 
     306           
     307            tabs[i].addField(f);  
     308          } 
     309        }  
     310      } 
     311       
     312      Template t = new Template(tabs, null); 
     313 
     314      // prompt for filename to save to  
     315      if (currentFile == null) { 
     316        JFileChooser chooser = new JFileChooser(); 
     317 
     318        FileFilter filter = new FileFilter() { 
     319          public boolean accept(File f) { return true; } 
     320          public String getDescription() { return "All files"; } 
     321        }; 
     322       
     323        chooser.setFileFilter(filter); 
     324 
     325        int status = chooser.showSaveDialog(this); 
     326        if (status == JFileChooser.APPROVE_OPTION) { 
     327          currentFile = chooser.getSelectedFile().getAbsolutePath(); 
     328          if (currentFile == null) return; 
     329        } 
     330      } 
     331       
     332      try { 
     333        t.save(currentFile); 
     334      } 
     335      catch (IOException io) { 
     336        error("Failed to save template", io);  
    373337      } 
    374338    } 
    375339    else if (cmd.equals("quit")) dispose(); 
     340    else if (cmd.equals("add row")) addRow();  
     341    else if (cmd.equals("add col")) addColumn();  
     342    else if (cmd.equals("prompt tab")) { 
     343      // prompt for tab name  
     344      JPopupMenu menu = new JPopupMenu(); 
     345      newTabName = new JTextField(); 
     346      newTabName.setPreferredSize(new Dimension(200, 25));  
     347      menu.add(newTabName); 
     348      JButton b = new JButton("OK"); 
     349      b.addActionListener(this); 
     350      b.setActionCommand("new tab"); 
     351      menu.add(b); 
     352 
     353      JComponent s = (JComponent) e.getSource(); 
     354      menu.show(s, s.getX(), s.getY());  
     355      newTabName.grabFocus(); 
     356    } 
    376357    else if (cmd.equals("new tab")) { 
    377       TemplateTab t = new TemplateTab(); 
    378       Prompter fp = 
    379         new Prompter(this, null, Integer.MAX_VALUE, Integer.MAX_VALUE, TAB); 
    380       if (!fp.wasCanceled()) { 
    381         t.setName(fp.getName()); 
    382         addTab(t, fp.getRow(), fp.getColumn()); 
    383       } 
    384       updateRemoveLists(); 
    385     } 
    386     else if (cmd.equals("new group")) { 
    387       TemplateGroup g = new TemplateGroup(); 
    388  
    389       Prompter fp = new Prompter(this, null, 0, 0, GROUP); 
    390       if (fp.wasCanceled()) return; 
    391  
    392       g.setName(fp.getName()); 
    393       g.setRepetitions(fp.getRepetitions()); 
    394  
    395       ((TemplateTab) tabs.get(currentTab)).addGroup(g); 
    396       updateRemoveLists(); 
    397     } 
    398     else if (cmd.startsWith("removeTab")) { 
    399       int ndx = Integer.parseInt(cmd.substring(cmd.indexOf(" ") + 1)); 
    400       tabs.removeElementAt(ndx); 
    401  
    402       tabMenu.removeAll(); 
    403  
    404       for (int i=0; i<tabs.size(); i++) { 
    405         JMenuItem item = new JMenuItem(((TemplateTab) tabs.get(i)).getName()); 
    406         item.setActionCommand("tab" + i); 
    407         item.addActionListener(this); 
    408         tabMenu.add(item); 
    409       } 
    410  
    411       updateRemoveLists(); 
    412     } 
    413     else if (cmd.startsWith("removeGroup")) { 
    414       int ndx = Integer.parseInt(cmd.substring(cmd.indexOf(" ") + 1)); 
    415       ((TemplateTab) tabs.get(currentTab)).removeGroup(ndx); 
    416       updateRemoveLists(); 
    417     } 
    418     else if (cmd.startsWith("removeField")) { 
    419       String s = cmd.substring(cmd.indexOf(" ") + 1); 
    420       if (s.indexOf("-") != -1) { 
    421         int groupIdx = Integer.parseInt(s.substring(0, s.indexOf("-"))); 
    422         int fieldIdx = Integer.parseInt(s.substring(s.indexOf("-") + 1)); 
    423  
    424         ((TemplateTab) tabs.get(currentTab)).getGroup( 
    425           groupIdx).removeField(fieldIdx); 
     358      newTabName.getParent().setVisible(false);  
     359      addTab(newTabName.getText(), 2, 2);  
     360    } 
     361    else if (cmd.equals("setName")) { 
     362      JPopupMenu menu = (JPopupMenu) ((JComponent) e.getSource()).getParent();  
     363      DraggableIcon icon = (DraggableIcon) menu.getInvoker();  
     364      menu.setVisible(false);  
     365 
     366      String text = ((JTextField) menu.getComponents()[0]).getText(); 
     367 
     368      Point p = new Point(icon.gridx, icon.gridy); 
     369      int ndx = tabPane.getSelectedIndex(); 
     370      TemplateField f = (TemplateField) fields[ndx].get(p); 
     371      f.setName(text); 
     372      f.setNameMap(null); 
     373 
     374      // set the name 
     375      if (icon.label != null) icon.remove(icon.label); 
     376      icon.remove(icon.image);  
     377      icon.label = new JLabel(text); 
     378      icon.add(icon.label); 
     379      icon.add(icon.image); 
     380      icon.getParent().repaint();  
     381    } 
     382    else if (cmd.equals("changeName")) { 
     383      // prompt for new field name 
     384      JPopupMenu menu = new JPopupMenu(); 
     385      JTextField field = new JTextField(); 
     386      field.setPreferredSize(new Dimension(200, 25));  
     387      menu.add(field); 
     388      JButton b = new JButton("OK"); 
     389      b.addActionListener(this); 
     390      b.setActionCommand("setName"); 
     391      menu.add(b); 
     392      menu.show(lastMenuComponent, lastMenuX, lastMenuY);  
     393      field.grabFocus();  
     394    } 
     395    else if (cmd.equals("nameMap")) { 
     396      JPopupMenu menu = (JPopupMenu) ((JComponent) e.getSource()).getParent(); 
     397      DraggableIcon icon = (DraggableIcon) menu.getInvoker(); 
     398      menu.setVisible(false); 
     399 
     400      MappingWindow w = new MappingWindow(this, true); 
     401      w.show(lastMenuComponent, lastMenuX, lastMenuY);  
     402    } 
     403    else if (cmd.equals("map")) { 
     404      JPopupMenu menu = (JPopupMenu) ((JComponent) e.getSource()).getParent();  
     405      DraggableIcon icon = (DraggableIcon) menu.getInvoker();  
     406      menu.setVisible(false);  
     407       
     408      MappingWindow w = new MappingWindow(this, false); 
     409      w.show(lastMenuComponent, lastMenuX, lastMenuY);  
     410    } 
     411    else if (cmd.equals("repeat")) { 
     412      JMenuItem item = (JMenuItem) e.getSource(); 
     413      DraggableIcon icon =  
     414        (DraggableIcon) ((JPopupMenu) item.getParent()).getInvoker();  
     415      TemplateField f = getField(icon); 
     416 
     417      if (item.getText().equals("Repeat this field")) { 
     418        item.setText("Don't repeat this field"); 
     419        f.setRepeated(true);  
    426420      } 
    427421      else { 
    428         int fieldIdx = Integer.parseInt(s); 
    429         ((TemplateTab) tabs.get(currentTab)).removeField(fieldIdx); 
    430       } 
    431       updateRemoveLists(); 
    432     } 
    433     else if (cmd.equals("general options")) { 
    434       // pop up a dialog with general template options 
    435  
    436       if (options == null) { 
    437         options = new Hashtable(); 
    438         //options.put("font-style", new Option("Font", new JTextField(""))); 
    439         //options.put("font-size", new Option("Font size", 
    440         //  new JSpinner(new SpinnerNumberModel(12, 1, Integer.MAX_VALUE, 1)))); 
    441         //options.put("font-color", new Option()); 
    442         //options.put("background-color", new Option()); 
    443         options.put("default-width", new Option("Window width", 
    444           new JSpinner(new SpinnerNumberModel(800, 1, Integer.MAX_VALUE, 1)))); 
    445         options.put("default-height", new Option("Window height", 
    446           new JSpinner(new SpinnerNumberModel(600, 1, Integer.MAX_VALUE, 1)))); 
    447         options.put("editable", new Option("Allow editing", 
    448           new JCheckBox("", true))); 
    449         options.put("prefer-companion", 
    450           new Option("Prefer metadata companion file", 
    451           new JCheckBox("", true))); 
    452         //options.put("edit-template-fields", new Options()); 
    453         //options.put("edit-mapping", new Options()); 
    454         options.put("rows", 
    455           new JSpinner(new SpinnerNumberModel(1, 1, Integer.MAX_VALUE, 1))); 
    456         options.put("columns", 
    457           new JSpinner(new SpinnerNumberModel(1, 1, Integer.MAX_VALUE, 1))); 
    458       } 
    459  
    460       Options window = new Options(this, options); 
    461       options = window.getOptions(); 
    462     } 
    463     else if (cmd.startsWith("tab")) { 
    464       // switch which tab we're editing 
    465  
    466       currentTab = Integer.parseInt(cmd.substring(3)); 
    467       template = (JPanel) tabPanels.get(currentTab); 
    468       template.addMouseListener(this); 
    469       setContentPane(template); 
    470  
    471       fieldOptions.removeAll(); 
    472       TemplateTab tab = (TemplateTab) tabs.get(currentTab); 
    473       for (int i=0; i<tab.getNumFields(); i++) { 
    474         JMenuItem item = new JMenuItem(tab.getField(i).getName()); 
    475         item.setActionCommand("field" + i); 
    476         item.addActionListener(this); 
    477         fieldOptions.add(item); 
    478       } 
    479  
    480       pack(); 
    481       updateRemoveLists(); 
    482     } 
    483     else if (cmd.equals("add row")) { 
    484       FormLayout current = 
    485         (FormLayout) ((JPanel) tabPanels.get(currentTab)).getLayout(); 
    486       current.appendRow(new RowSpec("pref:grow")); 
    487       ((JPanel) tabPanels.get(currentTab)).setLayout(current); 
    488     } 
    489     else if (cmd.equals("remove row")) { 
    490       FormLayout current = 
    491         (FormLayout) ((JPanel) tabPanels.get(currentTab)).getLayout(); 
    492       current.removeRow(current.getRowCount()); 
    493       ((JPanel) tabPanels.get(currentTab)).setLayout(current); 
    494     } 
    495     else if (cmd.equals("add column")) { 
    496       FormLayout current = 
    497         (FormLayout) ((JPanel) tabPanels.get(currentTab)).getLayout(); 
    498       current.appendColumn(new ColumnSpec("pref:grow")); 
    499       current.appendColumn(new ColumnSpec("pref:grow")); 
    500       ((JPanel) tabPanels.get(currentTab)).setLayout(current); 
    501     } 
    502     else if (cmd.equals("remove column")) { 
    503       FormLayout current = 
    504         (FormLayout) ((JPanel) tabPanels.get(currentTab)).getLayout(); 
    505       current.removeColumn(current.getColumnCount()); 
    506       current.removeColumn(current.getColumnCount()); 
    507       ((JPanel) tabPanels.get(currentTab)).setLayout(current); 
    508     } 
    509     else { 
    510       // prompt for name and location 
    511       FormLayout current = 
    512         (FormLayout) ((JPanel) tabPanels.get(currentTab)).getLayout(); 
    513       int maxRow = current.getRowCount(); 
    514       int maxCol = current.getColumnCount() / 2; 
    515  
    516       String[] groupNames = 
    517         new String[((TemplateTab) tabs.get(currentTab)).getNumGroups() + 1]; 
    518       for (int i=1; i<=groupNames.length-1; i++) { 
    519         groupNames[i] = 
    520           ((TemplateTab) tabs.get(currentTab)).getGroup(i - 1).getName(); 
    521       } 
    522  
    523       Prompter fp = new Prompter(this, groupNames, maxRow, maxCol, FIELD); 
    524  
    525       if (fp.wasCanceled()) return; 
    526  
    527       int row = fp.getRow(); 
    528       int col = fp.getColumn(); 
    529       String name = fp.getName(); 
    530  
    531       int ndx = -1; 
    532       for (int i=0; i<COMPONENT_NAMES.length; i++) { 
    533         if (cmd.equals(COMPONENT_NAMES[i])) { 
    534           ndx = i; 
    535           break; 
     422        item.setText("Repeat this field"); 
     423        f.setRepeated(false);  
     424      }  
     425    } 
     426    else if (cmd.equals("removeField")) { 
     427      JPopupMenu menu = (JPopupMenu) ((JComponent) e.getSource()).getParent(); 
     428      DraggableIcon icon = (DraggableIcon) menu.getInvoker(); 
     429      menu.setVisible(false); 
     430       
     431      int idx = tabPane.getSelectedIndex(); 
     432      Object[] keys = icons[idx].keySet().toArray(); 
     433      for (int i=0; i<keys.length; i++) { 
     434        if (icons[idx].get(keys[i]).equals(icon)) { 
     435          icons[idx].remove(keys[i]); 
     436          fields[idx].remove(keys[i]); 
     437          break;  
    536438        } 
    537439      } 
    538  
    539       // now add this component to the panel 
    540  
    541       // TODO : need to handle group layouts 
    542       try { 
    543         CellConstraints cc = new CellConstraints(); 
    544         JPanel pane = (JPanel) tabPanels.get(currentTab); 
    545         pane.add(new JLabel(name), cc.xy(col*2 - 1, row)); 
    546         pane.add((JComponent) COMPONENTS[ndx].newInstance(), 
    547           cc.xywh(col*2, row, fp.getWidth(), fp.getHeight())); 
    548         tabPanels.setElementAt(pane, currentTab); 
    549         pack(); 
    550       } 
    551       catch (Exception exc) { 
    552         exc.printStackTrace(); 
    553       } 
    554  
    555       // add this field to the current tab 
    556       TemplateField field = new TemplateField(); 
    557       field.setName(name); 
    558       field.setRow(row); 
    559       field.setColumn(col); 
    560       field.setWidth(fp.getWidth()); 
    561       field.setHeight(fp.getHeight()); 
    562       field.setType(COMPONENT_TYPES[ndx]); 
    563       field.setMap(fp.getMap()); 
    564  
    565       String group = fp.getGroup(); 
    566       if (group.length() == 0) { 
    567         ((TemplateTab) tabs.get(currentTab)).addField(field); 
    568       } 
    569       else { 
    570         TemplateTab thisTab = (TemplateTab) tabs.get(currentTab); 
    571         for (int i=0; i<thisTab.getNumGroups(); i++) { 
    572           if (thisTab.getGroup(i).getName().equals(group)) { 
    573             thisTab.getGroup(i).addField(field); 
    574             break; 
    575           } 
     440     
     441      icon.remove(icon.label);  
     442      icon.remove(icon.image);  
     443      tabPane.repaint();  
     444    } 
     445    else if (cmd.startsWith("removeRow")) { 
     446      int row = Integer.parseInt(cmd.substring(cmd.indexOf(":") + 1)); 
     447      JPopupMenu menu = (JPopupMenu) ((JComponent) e.getSource()).getParent();  
     448      menu.setVisible(false);  
     449       
     450      JPanel pane = (JPanel) tabPane.getSelectedComponent(); 
     451      FormLayout layout = (FormLayout) pane.getLayout(); 
     452 
     453      int rows = layout.getRowCount(); 
     454      int cols = layout.getColumnCount(); 
     455 
     456      int idx = tabPane.getSelectedIndex(); 
     457 
     458      for (int i=0; i<cols; i++) { 
     459        pane.remove((JComponent) icons[idx].get(new Point(i + 1, row + 1)));  
     460      } 
     461     
     462      rekey(row, -1); 
     463      layout.removeRow(row + 1); 
     464      tabPane.repaint();  
     465    } 
     466    else if (cmd.startsWith("removeColumn")) { 
     467      int col = Integer.parseInt(cmd.substring(cmd.indexOf(":") + 1)); 
     468      JPopupMenu menu = (JPopupMenu) ((JComponent) e.getSource()).getParent();  
     469      menu.setVisible(false);  
     470 
     471      JPanel pane = (JPanel) tabPane.getSelectedComponent(); 
     472      FormLayout layout = (FormLayout) pane.getLayout(); 
     473 
     474      int rows = layout.getRowCount(); 
     475      int cols = layout.getColumnCount(); 
     476      int idx = tabPane.getSelectedIndex(); 
     477      
     478      for (int i=0; i<rows; i++) { 
     479        pane.remove((JComponent) icons[idx].get(new Point(col + 1, i + 1))); 
     480      } 
     481      
     482      rekey(-1, col); 
     483      layout.removeColumn(col + 1); 
     484      tabPane.repaint();  
     485    } 
     486    else if (cmd.equals("removeTab")) { 
     487      int ndx = tabPane.getSelectedIndex(); 
     488      tabPane.remove(ndx); 
     489     
     490      Hashtable[] h = new Hashtable[icons.length - 1]; 
     491      Hashtable[] f = new Hashtable[fields.length - 1]; 
     492    
     493      System.arraycopy(icons, 0, h, 0, ndx); 
     494      System.arraycopy(icons, ndx + 1, h, ndx, h.length - ndx); 
     495      System.arraycopy(fields, 0, f, 0, ndx); 
     496      System.arraycopy(fields, ndx + 1, f, ndx, f.length - ndx); 
     497 
     498      icons = h; 
     499      fields = f; 
     500    } 
     501    else if (cmd.equals("specifyChoices")) { 
     502      JMenuItem item = (JMenuItem) e.getSource(); 
     503      DraggableIcon icon =  
     504        (DraggableIcon) ((JPopupMenu) item.getParent()).getInvoker();  
     505      TemplateField f = getField(icon); 
     506 
     507      EnumWindow w = new EnumWindow(this, f.getEnums()); 
     508      w.show(lastMenuComponent, lastMenuX, lastMenuY); 
     509    } 
     510    else if (cmd.equals("setThumbSource")) { 
     511      JPopupMenu menu = new JPopupMenu(); 
     512      ButtonGroup g = new ButtonGroup(); 
     513 
     514      JRadioButton dataset = new JRadioButton("Use thumbnail from dataset"); 
     515      dataset.setSelected(true);  
     516      g.add(dataset); 
     517 
     518      JRadioButton file = new JRadioButton("Use thumbnail from file:"); 
     519      g.add(file); 
     520 
     521      menu.add(dataset); 
     522      menu.add(file); 
     523 
     524      JTextField field = new JTextField(); 
     525      field.setPreferredSize(new Dimension(200, 25));  
     526      menu.add(field); 
     527      
     528      JButton b = new JButton("OK"); 
     529      b.addActionListener(this); 
     530      b.setActionCommand("applyThumbSource"); 
     531      menu.add(b); 
     532      menu.show(lastMenuComponent, lastMenuX, lastMenuY);  
     533    } 
     534    else if (cmd.equals("applyThumbSource")) { 
     535      JPopupMenu menu = (JPopupMenu) ((JComponent) e.getSource()).getParent();  
     536      DraggableIcon icon = (DraggableIcon) menu.getInvoker();  
     537      
     538      Component[] c = menu.getComponents(); 
     539      JRadioButton dataset = (JRadioButton) c[0]; 
     540 
     541      String text = null; 
     542 
     543      if (!dataset.isSelected()) { 
     544        JTextField t = (JTextField) c[2]; 
     545        text = t.getText();  
     546        getField(icon).setValueMap(text);  
     547      }  
     548       
     549      menu.setVisible(false);  
     550    
     551      if (text != null) { 
     552        try {  
     553          ImageReader reader = new ImageReader(); 
     554          reader.setId(text); 
     555          BufferedImage thumb = reader.openThumbImage(0); 
     556          JLabel label = (JLabel) icon.image.getComponents()[0]; 
     557          label.setIcon(new ImageIcon(thumb)); 
     558          reader.close();  
    576559        } 
    577       } 
    578  
    579       // add this field to the menu 
    580       JMenuItem menuItem = new JMenuItem(name); 
    581       menuItem.setActionCommand("field" + fieldOptions.getItemCount()); 
    582       menuItem.addActionListener(this); 
    583       fieldOptions.add(menuItem); 
    584       pack(); 
    585       updateRemoveLists(); 
    586     } 
    587  
    588   } 
    589  
    590   // -- MouseListener API methods -- 
    591  
    592   public void mouseClicked(MouseEvent e) { } 
    593  
    594   public void mouseEntered(MouseEvent e) { } 
    595  
    596   public void mouseExited(MouseEvent e) { } 
    597  
    598   public void mousePressed(MouseEvent e) { 
    599     int button = e.getButton(); 
    600     if (button == MouseEvent.BUTTON3) { 
     560        catch (FormatException exc) {  
     561          error("Failed to open thumbnail (" + text + ")", exc);  
     562        } 
     563        catch (IOException exc) {  
     564          error("Failed to open thumbnail (" + text + ")", exc);  
     565        } 
     566      }  
     567    }  
     568    else if (cmd.equals("ok")) { 
     569      // this event came from an instance of EnumWindow  
     570      JPanel parent = (JPanel) ((JButton) e.getSource()).getParent();  
     571      EnumWindow menu = (EnumWindow) parent.getParent(); 
     572      DraggableIcon icon = (DraggableIcon) menu.getInvoker();  
     573      TemplateField f = getField(icon); 
     574      menu.setVisible(false);  
     575 
     576      String[] options = menu.getOptions(); 
     577      f.setEnums(options);  
     578      
     579      JComboBox box = (JComboBox) icon.image.getComponents()[0]; 
     580      for (int i=0; i<options.length; i++) box.addItem(options[i]);  
     581      repaint();  
     582    }  
     583    else if (cmd.equals("chooseMapping")) { 
     584      // this event came from an instance of MappingWindow 
     585      JTabbedPane parent = (JTabbedPane) ((JButton) e.getSource()).getParent(); 
     586      MappingWindow menu = (MappingWindow) parent.getParent(); 
     587      DraggableIcon icon = (DraggableIcon) menu.getInvoker(); 
     588      TemplateField f = getField(icon); 
     589 
     590      String omexmlMap = null; 
     591 
     592       
     593       
     594      if (menu.nameMap) f.setNameMap(omexmlMap); 
     595      else f.setValueMap(omexmlMap); 
     596      menu.setVisible(false); 
     597    } 
     598  } 
     599 
     600  // -- Helper methods -- 
     601 
     602  /** Get the TemplateField corresponding to the given DraggableIcon. */ 
     603  private TemplateField getField(DraggableIcon icon) { 
     604    int idx = tabPane.getSelectedIndex(); 
     605    Object[] keys = icons[idx].keySet().toArray(); 
     606    for (int i=0; i<keys.length; i++) { 
     607      if (icons[idx].get(keys[i]).equals(icon)) { 
     608        return (TemplateField) fields[idx].get(keys[i]); 
     609      } 
     610    } 
     611    return null;  
     612  } 
     613 
     614  /** Update the icon and template hashtables. */ 
     615  private void rekey(int row, int col) { 
     616    int idx = tabPane.getSelectedIndex(); 
     617    Object[] keys = icons[idx].keySet().toArray(); 
     618    Hashtable h = new Hashtable(); 
     619    Hashtable f = new Hashtable(); 
     620 
     621    for (int i=0; i<keys.length; i++) { 
     622      Point p = (Point) keys[i]; 
     623         
     624      if ((p.x == col + 1 && col != -1) || (p.y == row + 1 && row != -1)) { 
     625        icons[idx].remove(keys[i]); 
     626        fields[idx].remove(keys[i]); 
     627      }  
     628      else if ((p.x > col + 1 && col != -1) || (p.y > row + 1 && row != -1)) { 
     629        int x = col != -1 ? p.x - 1 : p.x;  
     630        int y = col != -1 ? p.y - 1 : p.y;  
     631        Point k = new Point(x, y); 
     632        h.put(k, icons[idx].get(keys[i])); 
     633        f.put(k, fields[idx].get(keys[i])); 
     634      } 
     635    } 
     636 
     637    icons[idx] = h; 
     638    fields[idx] = f; 
     639  } 
     640 
     641  /** Add a new tab with the given name. */ 
     642  private void addTab(String name, int rows, int cols) { 
     643    String rowString = ""; 
     644    for (int i=0; i<rows; i++) { 
     645      rowString += "pref:grow"; 
     646      if (i < rows - 1) rowString += ","; 
     647    } 
     648 
     649    String colString = ""; 
     650    for (int i=0; i<cols; i++) { 
     651      colString += "pref:grow"; 
     652      if (i < cols - 1) colString += ","; 
     653    } 
     654 
     655    FormLayout layout = new FormLayout(colString, rowString); 
     656 
     657    Hashtable[] tmp = icons; 
     658    icons = new Hashtable[tmp.length + 1]; 
     659    System.arraycopy(tmp, 0, icons, 0, tmp.length); 
     660    icons[icons.length - 1] = new Hashtable(); 
     661 
     662    tmp = fields; 
     663    fields = new Hashtable[tmp.length + 1]; 
     664    System.arraycopy(tmp, 0, fields, 0, tmp.length); 
     665    fields[fields.length - 1] = new Hashtable(); 
     666 
     667    JPanel panel = new JPanel(layout); 
     668 
     669    for (int x=0; x<rows; x++) { 
     670      for (int y=0; y<cols; y++) { 
     671        addIcon(panel, x, y, tabPane.getTabCount()); 
     672      } 
     673    } 
     674   
     675    tabPane.addTab(name, panel);  
     676  } 
     677 
     678  /** Add a new column to the current tab. */ 
     679  private void addRow() { 
     680    JPanel selected = (JPanel) tabPane.getSelectedComponent(); 
     681    FormLayout layout = (FormLayout) selected.getLayout(); 
     682    layout.appendRow(new RowSpec("pref:grow")); 
     683 
     684    int ndx = tabPane.getSelectedIndex(); 
     685 
     686    for (int i=0; i<layout.getColumnCount(); i++) { 
     687      addIcon(selected, layout.getRowCount() - 1, i, ndx); 
     688    } 
     689    tabPane.repaint();  
     690  } 
     691 
     692  /** Add a new row to the current tab. */ 
     693  private void addColumn() { 
     694    JPanel selected = (JPanel) tabPane.getSelectedComponent(); 
     695    FormLayout layout = (FormLayout) selected.getLayout(); 
     696    layout.appendColumn(new ColumnSpec("pref:grow")); 
     697 
     698    int ndx = tabPane.getSelectedIndex(); 
     699 
     700    for (int i=0; i<layout.getRowCount(); i++) { 
     701      addIcon(selected, i, layout.getColumnCount() - 1, ndx);  
     702    } 
     703    tabPane.repaint();  
     704  } 
     705 
     706  /** Add a field icon at the specified grid coordinates. */ 
     707  private void addIcon(JPanel p, int x, int y, int tab) { 
     708    CellConstraints cc = new CellConstraints();  
     709    DraggableIcon dummy = new DraggableIcon(new JPanel(), y + 1, x + 1);  
     710    dummy.setTransferHandler(pictureHandler); 
     711    dummy.setPreferredSize(new Dimension(128, 128));     
     712 
     713    JPopupMenu menu = new JPopupMenu(); 
     714    JMenuItem item = new JMenuItem("Change field name"); 
     715    item.addActionListener(this); 
     716    item.setActionCommand("changeName"); 
     717    menu.add(item);  
     718 
     719    item = new JMenuItem("Change name mapping"); 
     720    item.addActionListener(this); 
     721    item.setActionCommand("nameMap"); 
     722    menu.add(item); 
     723 
     724    item = new JMenuItem("Change OME-XML mapping"); 
     725    item.addActionListener(this); 
     726    item.setActionCommand("map"); 
     727    menu.add(item); 
     728 
     729    item = new JMenuItem("Repeat this field"); 
     730    item.addActionListener(this); 
     731    item.setActionCommand("repeat"); 
     732    menu.add(item); 
     733 
     734    menu.add(new JSeparator()); 
     735 
     736    item = new JMenuItem("Remove this field"); 
     737    item.addActionListener(this); 
     738    item.setActionCommand("removeField"); 
     739    menu.add(item); 
     740 
     741    item = new JMenuItem("Remove this row"); 
     742    item.addActionListener(this); 
     743    item.setActionCommand("removeRow:" + x); 
     744    menu.add(item); 
     745 
     746    item = new JMenuItem("Remove this column"); 
     747    item.addActionListener(this); 
     748    item.setActionCommand("removeColumn:" + y); 
     749    menu.add(item); 
     750 
     751    dummy.menu = menu; 
     752    dummy.listener = this;  
     753    MouseListener popupListener = new PopupListener(menu); 
     754    dummy.addMouseListener(popupListener); 
     755     
     756    p.add(dummy, cc.xy(y + 1, x + 1));  
     757    icons[tab].put(new Point(y + 1, x + 1), dummy);  
     758    fields[tab].put(new Point(y + 1, x + 1), new TemplateField());  
     759  } 
     760 
     761  /** Display an error message. */ 
     762  protected void error(String msg, Exception exc) { 
     763    if (exc != null) { 
     764      StackTraceElement[] n = exc.getStackTrace();  
     765      for (int i=0; i<n.length; i++) { 
     766        msg += "\n" + n[i];  
     767      } 
     768    }  
     769    JOptionPane.showMessageDialog(this, msg, "Error!",  
     770      JOptionPane.ERROR_MESSAGE);  
     771  } 
     772 
     773  // -- Helper classes -- 
     774 
     775  class PopupListener extends MouseAdapter { 
     776    JPopupMenu popup; 
     777 
     778    PopupListener(JPopupMenu popupMenu) { 
     779      popup = popupMenu;  
     780    } 
     781   
     782    public void mousePressed(MouseEvent e) { maybeShowPopup(e); } 
     783 
     784    public void mouseReleased(MouseEvent e) { maybeShowPopup(e); } 
     785 
     786    private void maybeShowPopup(MouseEvent e) { 
    601787      if (e.isPopupTrigger()) { 
     788        lastMenuComponent = (JComponent) e.getComponent();  
     789        lastMenuX = e.getX(); 
     790        lastMenuY = e.getY(); 
    602791        popup.show(e.getComponent(), e.getX(), e.getY()); 
    603792      } 
    604793    } 
    605   } 
    606  
    607   public void mouseReleased(MouseEvent e) { 
    608     int button = e.getButton(); 
    609     if (button == MouseEvent.BUTTON3) { 
    610       if (e.isPopupTrigger()) { 
    611         popup.setVisible(false); 
    612       } 
    613     } 
    614   } 
    615  
    616   // -- Helper classes -- 
    617  
    618   /** Prompts for necessary information about a tab, group or field. */ 
    619   public class Prompter extends JDialog implements ActionListener { 
    620  
    621     // -- Static fields -- 
    622  
    623     private Hashtable omexmlMaps = buildMappings(); 
    624  
    625     Hashtable buildMappings() { 
    626       InputStream stream = 
    627         TemplateEditor.class.getResourceAsStream("mapping.txt"); 
    628       BufferedReader b = new BufferedReader(new InputStreamReader(stream)); 
    629  
    630       Hashtable h = new Hashtable(); 
    631  
    632       try { 
    633         String line = b.readLine().trim(); 
    634         while (line != null) { 
    635           String key = line.substring(1, line.indexOf("\"", 1)); 
    636           line = line.substring(line.indexOf("\"", 1) + 1).trim(); 
    637           String value = line.substring(1, line.indexOf("\"", 1)); 
    638           h.put(key, value); 
    639  
    640           line = b.readLine(); 
    641         } 
    642         b.close(); 
    643       } 
    644       catch (IOException e) { 
    645         e.printStackTrace(); 
    646       } 
    647       return h; 
    648     }; 
    649  
    650     // -- Fields -- 
    651  
    652     private JTextField name; 
    653     private JSpinner row, col; 
    654     private JSpinner width, height; 
    655     private JComboBox omexml; 
    656     private JComboBox group; 
    657     private JSpinner groupSpinner; 
    658     private boolean canceled = false; 
    659  
    660     // -- Constructor -- 
    661  
    662     public Prompter(JFrame owner, String[] groups, int rowMax, int colMax, 
    663       int type) 
    664     { 
    665       super(owner, "New " + (type == TemplateEditor.FIELD ? "field" : 
    666         type == TemplateEditor.TAB ? "tab" : "group") + "...", true); 
    667  
    668       FormLayout layout = 
    669         new FormLayout("2dlu, pref:grow, 2dlu, pref:grow, 2dlu", 
    670         "pref:grow, pref:grow, pref:grow, pref:grow, pref:grow, pref:grow," + 
    671         "pref:grow, pref:grow"); 
    672       JPanel pane = new JPanel(layout); 
    673       CellConstraints cc = new CellConstraints(); 
    674  
    675       name = new JTextField(); 
    676  
    677       String n = type == TemplateEditor.TAB ? "Tab" : 
    678         type == TemplateEditor.GROUP ? "Group" : "Field"; 
    679  
    680       pane.add(new JLabel(n + " name:"), cc.xy(2, 1)); 
    681       pane.add(name, cc.xy(4, 1)); 
    682  
    683       if (type != TemplateEditor.GROUP) { 
    684         boolean field = type == TemplateEditor.FIELD; 
    685  
    686         row = new JSpinner(new SpinnerNumberModel(1, 1, rowMax, 1)); 
    687         col = new JSpinner(new SpinnerNumberModel(1, 1, colMax, 1)); 
    688         pane.add(new JLabel(field ? "Row:" : "Rows:"), cc.xy(2, 2)); 
    689         pane.add(new JLabel(field ? "Column:" : "Columns:"), cc.xy(2, 3)); 
    690         pane.add(row, cc.xy(4, 2)); 
    691         pane.add(col, cc.xy(4, 3)); 
    692       } 
    693  
    694       if (type == TemplateEditor.FIELD) { 
    695         width = new JSpinner(new SpinnerNumberModel(1, 1, rowMax, 1)); 
    696         height = new JSpinner(new SpinnerNumberModel(1, 1, colMax, 1)); 
    697         pane.add(new JLabel("Width:"), cc.xy(2, 4)); 
    698         pane.add(new JLabel("Height:"), cc.xy(2, 5)); 
    699         pane.add(width, cc.xy(4, 4)); 
    700         pane.add(height, cc.xy(4, 5)); 
    701  
    702         pane.add(new JLabel("OME-XML mapping:"), cc.xy(2, 6)); 
    703         pane.add(new JLabel("Group:"), cc.xy(2, 5)); 
    704         group = new JComboBox(groups); 
    705         pane.add(group, cc.xy(4, 5)); 
    706  
    707         omexml = new JComboBox(omexmlMaps.keySet().toArray()); 
    708         pane.add(omexml, cc.xy(4, 6)); 
    709       } 
    710  
    711       if (type == TemplateEditor.GROUP) { 
    712         groupSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 
    713           Integer.MAX_VALUE, 1)); 
    714         pane.add(new JLabel("Repetitions:"), cc.xy(2, 2)); 
    715         pane.add(groupSpinner, cc.xy(4, 2)); 
    716       } 
    717  
    718       JButton ok = new JButton("OK"); 
    719       ok.setActionCommand("ok"); 
    720       ok.addActionListener(this); 
    721       pane.add(ok, cc.xy(2, 7)); 
    722  
    723       JButton cancel = new JButton("Cancel"); 
    724       cancel.setActionCommand("cancel"); 
    725       cancel.addActionListener(this); 
    726       pane.add(cancel, cc.xy(4, 7)); 
    727  
    728       setContentPane(pane); 
    729       setPreferredSize(new Dimension(325, 130)); 
    730       pack(); 
    731       setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
    732       setVisible(true); 
    733     } 
    734  
    735     // -- Prompter API methods -- 
    736  
    737     public int getRow() { return ((Integer) row.getValue()).intValue(); } 
    738  
    739     public int getColumn() { return ((Integer) col.getValue()).intValue(); } 
    740  
    741     public int getWidth() { return ((Integer) width.getValue()).intValue(); } 
    742  
    743     public int getHeight() { return ((Integer) height.getValue()).intValue(); } 
    744  
    745     public String getName() { return name.getText(); } 
    746  
    747     public String getMap() { 
    748       return (String) omexmlMaps.get(omexml.getSelectedItem()); 
    749     } 
    750  
    751     public String getGroup() { return (String) group.getSelectedItem(); } 
    752  
    753     public int getRepetitions() { 
    754       return ((Integer) groupSpinner.getValue()).intValue(); 
    755     } 
    756  
    757     public boolean wasCanceled() { return canceled; } 
    758  
    759     // -- ActionListener API methods -- 
    760  
    761     public void actionPerformed(ActionEvent e) { 
    762       if (e.getActionCommand().equals("ok")) dispose(); 
    763       else if (e.getActionCommand().equals("mapping")) { 
    764       } 
    765       else if (e.getActionCommand().equals("cancel")) { 
    766         canceled = true; 
    767         dispose(); 
    768       } 
    769     } 
    770   } 
    771  
    772   /** Displays a list of general template options. */ 
    773   public class Options extends JDialog implements ActionListener { 
    774  
    775     // -- Fields -- 
    776  
    777     private Hashtable options; 
    778  
    779     // -- Constructor -- 
    780  
    781     public Options(JFrame parent, Hashtable options) { 
    782       super(parent, "General Template Options", true); 
    783       this.options = options; 
    784  
    785       String rowString = "2dlu"; 
    786       for (int i=0; i<=options.size(); i++) { 
    787         rowString += ", pref:grow, 2dlu"; 
    788       } 
    789  
    790       FormLayout layout = 
    791         new FormLayout("2dlu, pref:grow, 2dlu, pref:grow, 2dlu", rowString); 
    792       JPanel panel = new JPanel(layout); 
    793  
    794       CellConstraints cc = new CellConstraints(); 
    795       Object[] keys = options.keySet().toArray(); 
    796       Arrays.sort(keys); 
    797  
    798       for (int i=0; i<keys.length; i++) { 
    799         Option o = (Option) options.get(keys[i]); 
    800         panel.add(new JLabel(o.label), cc.xy(2, 2*(i + 1))); 
    801         panel.add(o.component, cc.xy(4, 2*(i + 1))); 
    802       } 
    803  
    804       JButton ok = new JButton("OK"); 
    805       ok.setActionCommand("ok"); 
    806       ok.addActionListener(this); 
    807       panel.add(ok, cc.xyw(2, 2*(keys.length + 1), 3)); 
    808  
    809       setContentPane(panel); 
    810       setPreferredSize(new Dimension(400, 400)); 
    811       setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
    812       pack(); 
    813       setVisible(true); 
    814     } 
    815  
    816     // -- Options API methods -- 
    817  
    818     public Hashtable getOptions() { return options; } 
    819  
    820     // -- ActionListener API methods -- 
    821  
    822     public void actionPerformed(ActionEvent e) { 
    823       if (e.getActionCommand().equals("ok")) { 
    824         Component[] components = getContentPane().getComponents(); 
    825         for (int i=0; i<components.length; i++) { 
    826           Component src = components[i]; 
    827  
    828           Option o = null; 
    829           String cmd = null; 
    830  
    831           Object[] keys = options.keySet().toArray(); 
    832           for (int j=0; j<keys.length; j++) { 
    833             if (((Option) options.get(keys[j])).component.equals(src)) { 
    834               o = (Option) options.get(keys[j]); 
    835               cmd = (String) keys[j]; 
    836               break; 
    837             } 
    838           } 
    839  
    840           if (src instanceof JTextField) { 
    841             o.value = ((JTextField) src).getText(); 
    842             options.put(cmd, o); 
    843           } 
    844           else if (src instanceof JSpinner) { 
    845             o.value = ((JSpinner) src).getValue().toString(); 
    846             options.put(cmd, o); 
    847           } 
    848           else if (src instanceof JComboBox) { 
    849             o.value = ((JComboBox) src).getSelectedItem().toString(); 
    850             options.put(cmd, o); 
    851           } 
    852           else if (src instanceof JCheckBox) { 
    853             o.value = "" + ((JCheckBox) src).isSelected(); 
    854             options.put(cmd, o); 
    855           } 
    856         } 
    857         dispose(); 
    858       } 
    859     } 
    860  
    861   } 
    862  
    863   public class Option { 
    864     public String label; 
    865     public String value; 
    866     public JComponent component; 
    867  
    868     public Option(String label, JComponent component) { 
    869       this.label = label; 
    870       this.component = component; 
    871     } 
     794   
    872795  } 
    873796 
     
    877800    new TemplateEditor(); 
    878801  } 
     802 
    879803} 
  • trunk/loci/ome/notes/templates/editor.template

    r2764 r2780  
    1 # This is a sample template for OME Notes. 
     1# This is a sample template for the OME Notebook. 
    22 
    33# Define various general options 
     
    4040    name "First name" 
    4141    type "var" 
    42     map "CustomAttributes:Experimenter:FirstName"  
     42    valueMap "CustomAttributes:Experimenter:FirstName"  
    4343  } 
    4444 
     
    4646    name "Last name" 
    4747    type "var" 
    48     map "CustomAttributes:Experimenter:LastName"  
     48    valueMap "CustomAttributes:Experimenter:LastName"  
    4949  } 
    5050 
     
    5252    name "Email" 
    5353    type "var" 
    54     map "CustomAttributes:Experimenter:Email"  
     54    valueMap "CustomAttributes:Experimenter:Email"  
    5555  } 
    5656 
     
    7171      name "Image Name" 
    7272      type "var" 
    73       map "Image:Name"  
     73      valueMap "Image:Name"  
    7474    } 
    7575 
     
    7777      name "Size Z" 
    7878      type "int" 
    79       map "Image:Pixels:SizeZ" 
     79      valueMap "Image:Pixels:SizeZ" 
    8080    } 
    8181 
     
    8484      type "bool" 
    8585      default "false" 
    86       map "Image:Pixels:BigEndian"  
     86      valueMap "Image:Pixels:BigEndian"  
    8787    } 
    8888 
     
    9292      values {"uint8", "uint16", "float"} 
    9393      default "float" 
    94       map "Image:Pixels:PixelType"  
     94      valueMap "Image:Pixels:PixelType"  
    9595    } 
    9696  } 
  • trunk/loci/ome/notes/templates/viewer.template

    r2685 r2780  
    2121      name "Name" 
    2222      type "var" 
    23       map "Image:Name" 
     23      valueMap "Image:Name" 
    2424    } 
    2525 
     
    2727      name "Creation Date" 
    2828      type "var" 
    29       map "Image:CreationDate" 
     29      valueMap "Image:CreationDate" 
    3030    } 
    3131 
     
    3333      name "Description" 
    3434      type "var" 
    35       map "Image:Description" 
     35      valueMap "Image:Description" 
    3636    } 
    3737 
     
    3939      name "Width" 
    4040      type "int" 
    41       map "Image:Pixels:SizeX" 
     41      valueMap "Image:Pixels:SizeX" 
    4242    } 
    4343   
     
    4545      name "Height" 
    4646      type "int" 
    47       map "Image:Pixels:SizeY" 
     47      valueMap "Image:Pixels:SizeY" 
    4848    } 
    4949  
     
    5151      name "Number of slices" 
    5252      type "int" 
    53       map "Image:Pixels:SizeZ" 
     53      valueMap "Image:Pixels:SizeZ" 
    5454    } 
    5555 
     
    5757      name "Number of channels" 
    5858      type "int" 
    59       map "Image:Pixels:SizeC" 
     59      valueMap "Image:Pixels:SizeC" 
    6060    } 
    6161 
     
    6363      name "Number of timepoints" 
    6464      type "int" 
    65       map "Image:Pixels:SizeT" 
     65      valueMap "Image:Pixels:SizeT" 
    6666    } 
    6767   
     
    7070      type "bool" 
    7171      default "false" 
    72       map "Image:Pixels:BigEndian" 
     72      valueMap "Image:Pixels:BigEndian" 
    7373    } 
    7474 
     
    7676      name "Pixel Type" 
    7777      type "var" 
    78       map "Image:Pixels:PixelType" 
     78      valueMap "Image:Pixels:PixelType" 
    7979    } 
     80   
     81    field { 
     82      name "Thumbnail" 
     83      type "thumbnail" 
     84    } 
     85   
    8086  } 
    8187} 
     
    8894    name "First Name" 
    8995    type "var" 
    90     map "CustomAttributes:Experimenter:FirstName" 
     96    valueMap "CustomAttributes:Experimenter:FirstName" 
    9197  } 
    9298 
     
    94100    name "Last Name" 
    95101    type "var" 
    96     map "CustomAttributes:Experimenter:LastName" 
     102    valueMap "CustomAttributes:Experimenter:LastName" 
    97103  } 
    98104 
     
    101107    type "var" 
    102108    span "1,3"  
    103     map "CustomAttributes:Experimenter:Email" 
     109    valueMap "CustomAttributes:Experimenter:Email" 
    104110  } 
    105111} 
    106112 
    107113tab { 
    108   name "Metadata hashtable" 
     114  name "Other metadata" 
    109115 
    110116  grid "1,2" 
    111117 
    112118  field { 
    113     name "Field name" 
    114     map "Image:CustomAttributes:OriginalMetadata:name" 
     119    nameMap "Image:CustomAttributes:OriginalMetadata:name" 
     120    valueMap "Image:CustomAttributes:OriginalMetadata:value" 
    115121    repeated "true"  
    116122    type "var"  
     
    118124  } 
    119125 
    120   field { 
    121     name "Field value" 
    122     map "Image:CustomAttributes:OriginalMetadata:value" 
    123     repeated "true" 
    124     type "var" 
    125     grid "1,3"  
    126   } 
    127  
    128126} 
Note: See TracChangeset for help on using the changeset viewer.