//
// VariableComboEditor.java
//
/*
OME Metadata Editor application for exploration and editing of OME-XML and
OME-TIFF metadata. Copyright (C) 2006-@year@ Christopher Peterson.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package loci.ome.editor;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Hashtable;
import java.util.Vector;
import javax.swing.AbstractCellEditor;
import javax.swing.JComboBox;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableModel;
import ome.xml.OMEXMLNode;
/**
* A class to handle a combobox editor that chooses its items
* intelligently based on the template. This class looks at the
* files in the TypeDef folder to see what kind of tag this
* reference should be pointing to and then lists all reference
* IDs found in the file that meet this criterion.
*
* <dl><dt><b>Source code:</b></dt>
* <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/legacy/ome-editor/src/loci/ome/editor/VariableComboEditor.java">Trac</a>,
* <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/legacy/ome-editor/src/loci/ome/editor/VariableComboEditor.java;hb=HEAD">Gitweb</a></dd></dl>
*
* @author Christopher Peterson crpeterson2 at wisc.edu
*/
public class VariableComboEditor extends AbstractCellEditor
implements TableCellEditor, ActionListener, FocusListener, MouseListener
{
// -- Fields --
/**
* Vectors that hold Panels that have ID (idPanels)
* and also all external references in the file (addPanels)
*/
private Vector idPanels, addPanels;
/**
* refers to the node associated with the TablePanel that
* holds the table which uses this cell editor
*/
private OMEXMLNode oNode;
/** refers to the TablePanel using this editor */
private MetadataPane.TablePanel tableP;
/** holds the current combobox needed when the cell is clicked */
private JRowBox box;
/** holds the table of references this cell editor is for */
protected JTable refTable;
/**
* holds internal reference data found in the ome-xml file
* that is currently opened by MetadataPane
*/
private Hashtable iDefs;
private String result;
// -- Constants --
/**
* get the hashtable describing which attributes refer to what
* type of nodes
*/
private static final Hashtable REF_HASH = TemplateParser.getRefHash();
// -- Constructor --
/**
* Construct a new VariableComboEditor.
* @param IDP vector of TablePanels that have been found to have ID
* attributes.
* @param AddP vector of Strings that hold all external LSIDs found in this
* file.
* @param tp the TablePanel this editor edits.
* @param internalDefs a hashtable representing semantic type defs found in
* the current open file itself.
*/
public VariableComboEditor(Vector IDP, Vector AddP,
MetadataPane.TablePanel tp, Hashtable internalDefs)
{
//initialize all fields
result = null;
idPanels = IDP;
addPanels = AddP;
tableP = tp;
refTable = tp.table;
oNode = tp.oNode;
box = new JRowBox(-1);
iDefs = internalDefs;
}
// -- VariableComboEditor API --
/**Reset the necessary lists for this editor.*/
public void setDefs(Vector IDP, Vector AddP) {
idPanels = IDP;
addPanels = AddP;
}
/**
* If we give up on tailoring the combobox to the appropriate types,
* this method simply adds all possible references of all types to
* the combobox.
*/
public void addAll(JRowBox jrb) {
//add internal references
for (int i = 0;i<idPanels.size();i++) {
MetadataPane.TablePanel tp = (MetadataPane.TablePanel) idPanels.get(i);
if (tp.refDetails != null && !tp.refDetails.equals(""))
jrb.addItem(tp.name + " - " + tp.refDetails);
else jrb.addItem(tp.name);
}
//add external references
for (int i = 0;i<addPanels.size();i++) {
jrb.addItem( (String) addPanels.get(i) );
}
}
// -- AbstractCellEditor Implementation --
/** Implement the one CellEditor method that AbstractCellEditor doesn't. */
public Object getCellEditorValue() {
return result;
}
/** Implement the one method defined by TableCellEditor. */
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column)
{
TableModel tModel = table.getModel();
//use parameters to get information about the cell being edited
JRowBox thisBox = new JRowBox(row);
thisBox.addFocusListener(this);
//tagname of the node associated with this table
String eleName = oNode.getDOMElement().getTagName();
//name of the attribute being edited
String attrName = (String) tModel.getValueAt(row, 0);
//get the sub-hashtable for the key associated with this tablepanel's
//OMEXMLNode... check internal defs first, then external defs
Hashtable subHash = (Hashtable) iDefs.get(eleName);
if (subHash == null) subHash = (Hashtable) REF_HASH.get(eleName);
if (subHash != null) {
//get the string representation of the type this attribute should
//refer to
String type = (String) subHash.get(attrName);
if (type != null) {
//check the list of internal references for nodes of the
//type that we just found
for (int i = 0;i<idPanels.size();i++) {
MetadataPane.TablePanel tp =
(MetadataPane.TablePanel) idPanels.get(i);
String tpClass = tp.oNode.getClass().getName();
boolean isCorrectType =
tpClass.equals("org.openmicroscopy.xml.st." + type + "Node");
//if the node is of the right type, add it to the combobox
if (isCorrectType && !tp.refDetails.equals("")) {
thisBox.addItem(tp.name + " - " + tp.refDetails);
}
else if (isCorrectType && tp.refDetails.equals("")) {
thisBox.addItem(tp.name);
}
}
//check the list of external references for references of
//the appropriate type
for (int i = 0;i<addPanels.size();i++) {
String thisExID = (String) addPanels.get(i);
if (thisExID.indexOf(":" + type + ":") >= 0) {
//add this external reference to the combobox
thisBox.addItem(thisExID);
}
}
}
//if no type is found for this attribute, add all internal/external
//reference options to the combobox
else addAll(thisBox);
}
//if no attributes are found for this element, add all references
else addAll(thisBox);
//listen to changes in this combobox
thisBox.addActionListener(this);
//set the initial item in the combobox based on the parameter "value"
thisBox.setSelectedItem(value);
return thisBox;
}
// -- EventListener API --
/**Handle whenever the user has selected an item from this combobox.*/
public void actionPerformed(ActionEvent e) {
if ( e.getSource() instanceof JRowBox) {
box = (JRowBox) e.getSource();
//get the row this JRowBox is made to edit
int row = box.row;
TableModel model = (TableModel) refTable.getModel();
//get the new value of the attribute selected in the combobox
String data = (String) box.getSelectedItem();
//get the attribute of this row from the table
String attr = (String) model.getValueAt(row,0);
//set default of thisID as null
String thisID = null;
if (data == null || data.equals("")) {
if (oNode.getDOMElement().hasAttribute(attr))
oNode.getDOMElement().removeAttribute(attr);
}
else {
//check if the selected item corresponds to an internal id
//if it does, set thisID to the internal id in question
for (int i = 0;i<idPanels.size();i++) {
MetadataPane.TablePanel tp =
(MetadataPane.TablePanel) idPanels.get(i);
if (data.startsWith(tp.name)) thisID = tp.id;
}
//if an internal reference was found, set the node tree
//to reflect the changes made by the new selection of
//the attribute's value
if (thisID != null) {
oNode.setAttribute(attr, thisID);
}
//if no internal reference was found, look for an external
//reference and clip the "(External) " marker from it
//before setting the attribute to the new value
else {
for (int i = 0;i<addPanels.size();i++) {
String s = (String) addPanels.get(i);
if (data.equals(s)) {
oNode.setAttribute(attr, s.substring(11));
}
}
}
}
result = (String) box.getSelectedItem();
tableP.callStateChanged(true);
//let the table know that our editor is done with its
//eeeeeevil deeds
fireEditingStopped();
}
}
/**
* Needs this in order to handle when the user presses tab
* while the editor combobox is still open.
*/
public void focusGained(FocusEvent e) {
if (e.getSource() instanceof JRowBox) {
JRowBox thisBox = (JRowBox) e.getSource();
result = (String) thisBox.getSelectedItem();
}
}
public void focusLost(FocusEvent e) {}
/** Handle whenever the user clicks on this editor.*/
public void mousePressed(MouseEvent e) {
if (e.getSource() instanceof JRowBox &&
e.getButton() == MouseEvent.BUTTON1)
{
JRowBox thisBox = (JRowBox) e.getSource();
result = (String) thisBox.getSelectedItem();
}
}
public void mouseReleased(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
// -- Helper Classes --
/**
* Very simple extension of JComboBox that simply adds an int
* field to designate which row this combobox edits.
*/
public class JRowBox extends JComboBox {
public int row;
public JRowBox (int r) {
super();
row = r;
}
}
}