// // WiscScanPane.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.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.Arrays; import java.util.Vector; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.Scrollable; import javax.swing.border.Border; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; import javax.swing.border.TitledBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import ome.xml.DOMUtil; import ome.xml.OMEXMLNode; import org.openmicroscopy.xml.OMENode; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; /** * A class that emulates the login and experiment setup screen * found in the program WiscScan, which acquires laser data and * records various things in OMEXML. Many things in WiscScan * itself seem completely broken at the present time and so * many of the fields which are disabled fall into the category * of "broken in WiscScan, not my fault." This view was designed * to make our biologists at UW feel less overwhelmed with the * multiple scary fields found in the normal view. Also it is * not at all clear in many cases how the OMEXML was generated * in the first place. * * <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/WiscScanPane.java">Trac</a>, * <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/legacy/ome-editor/src/loci/ome/editor/WiscScanPane.java;hb=HEAD">Gitweb</a></dd></dl> * * @author Christopher Peterson crpeterson2 at wisc.edu */ public class WiscScanPane extends JTabbedPane implements ActionListener, ItemListener, DocumentListener { /** Holds types of experiments available. */ public static final Object [] EX_CHOICES = {"Time-lapse","4-D+", "PGI/Documentation", "Photoablation","Fluorescense-Lifetime","Spectral-Imaging", "FP","FRET","Screen","Immunocytochemistry Immunofluorescence", "FISH","Electrophysiology","Ion-Imaging","Colocalization", "FRAP","Photoactivation","Uncaging","Optical-Trapping", "Other"}; /** Holds types of filter wheels. */ public static final Object [] WHEE_CHOICES = {"None","1 TFI 650SP"}; /** Holds types of filter holders. */ public static final Object [] HO_CHOICES = {"None","1 TFI 650SP"}; /** The various GUI input components for this program. */ protected JComboBox groupBox, exB, wheeB, hoB; /** The various GUI input components for this program. */ protected JCheckBox tiC, phC, pmtC; /** The various GUI input components for this program. */ protected JTextField firstField,lastField,omeField,passField, emailField,prT, tempT, pocT, tapT, tiT,pmtT; /** The various GUI input components for this program. */ protected JTextArea desA; /** The XML elements associated with the GUI input components. */ protected Element exrEle,exEle,prEle,desEle,tiEle,pmtEle,phEle; /** * A toggle that turns off the action listening for the GUI * components when we are initializing them so that we don't * needlessly change XML to what it already is. */ protected boolean setup; /** The OMENode for the document being edited. */ protected OMENode ome; /** Construct a new WiscScanPane. */ public WiscScanPane() { setup = false; ome = null; exrEle = null; exEle = null; prEle = null; desEle = null; tiEle = null; pmtEle = null; phEle = null; setPreferredSize(new Dimension(700, 500)); JPanel loginPanel = new JPanel(); JPanel experimentPanel = new ScrollablePanel(); JScrollPane jScroll = new JScrollPane(experimentPanel); addTab("WiscScan Login", (Icon) null, loginPanel, "Emulates the login screen of WiscScan."); addTab("Experiment Setup Information", (Icon) null, jScroll, "Emulates the Experiment Setup Information" + " screen of WiscScan."); //gui setup for login screen int w = 300, h = 20; JLabel firstLabel = new JLabel("First Name"); firstLabel.setPreferredSize(new Dimension(w,h)); firstField = new JTextField(); firstField.setPreferredSize(new Dimension(w,h)); firstField.getDocument().addDocumentListener(this); JLabel lastLabel = new JLabel("Last Name"); lastLabel.setPreferredSize(new Dimension(w,h)); lastField = new JTextField(); lastField.setPreferredSize(new Dimension(w,h)); lastField.getDocument().addDocumentListener(this); JLabel omeLabel = new JLabel("OME Name (not supported)"); omeLabel.setPreferredSize(new Dimension(w,h)); omeField = new JTextField(); omeField.setEnabled(false); omeField.setPreferredSize(new Dimension(w,h)); omeField.getDocument().addDocumentListener(this); JLabel passLabel = new JLabel("Password (not supported)"); passLabel.setPreferredSize(new Dimension(w,h)); passField = new JTextField(); passField.setEnabled(false); passField.setPreferredSize(new Dimension(w,h)); passField.getDocument().addDocumentListener(this); JLabel emailLabel = new JLabel("Email"); emailLabel.setPreferredSize(new Dimension(w,h)); emailField = new JTextField(); emailField.setPreferredSize(new Dimension(w,h)); emailField.getDocument().addDocumentListener(this); JLabel groupLabel = new JLabel("Group (not supported)"); groupLabel.setPreferredSize(new Dimension(w,h)); groupBox = new JComboBox(); groupBox.setPreferredSize(new Dimension(w,h)); groupBox.addActionListener(this); groupBox.setEnabled(false); JPanel subPanel = null; FormLayout layout = new FormLayout( "5dlu,center:pref,5dlu", "5dlu,pref,5dlu,pref,5dlu,pref,5dlu,pref,5dlu,pref,5dlu,pref," + "5dlu,pref,5dlu,pref,5dlu,pref,5dlu,pref,5dlu,pref,5dlu,pref,5dlu"); PanelBuilder build = new PanelBuilder(layout); CellConstraints cc = new CellConstraints(); build.add(firstLabel,cc.xy(2,2)); build.add(firstField,cc.xy(2,4)); build.add(lastLabel,cc.xy(2,6)); build.add(lastField,cc.xy(2,8)); build.add(omeLabel,cc.xy(2,10)); build.add(omeField,cc.xy(2,12)); build.add(passLabel,cc.xy(2,14)); build.add(passField,cc.xy(2,16)); build.add(emailLabel,cc.xy(2,18)); build.add(emailField,cc.xy(2,20)); build.add(groupLabel,cc.xy(2,22)); build.add(groupBox,cc.xy(2,24)); subPanel = build.getPanel(); Border lineB = BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK); EmptyBorder emptyB = new EmptyBorder(5,5,5,5); EmptyBorder empB = new EmptyBorder(5,5,5,5); CompoundBorder tempB = new CompoundBorder(lineB,emptyB); CompoundBorder finalB = new CompoundBorder(empB,lineB); subPanel.setBorder(finalB); JPanel holderP = new JPanel(); holderP.add(subPanel); JLabel welcomeLabel = new JLabel("Welcome To WiscScan", JLabel.CENTER); // Font thisFont = welcomeLabel.getFont(); Font thisFont = new Font("Serif", Font.PLAIN,64); welcomeLabel.setFont(thisFont); loginPanel.setLayout(new BorderLayout()); loginPanel.add(welcomeLabel, BorderLayout.NORTH); loginPanel.add(holderP, BorderLayout.CENTER); //gui setup for experiment setup screen Border etchB = BorderFactory.createEtchedBorder( EtchedBorder.LOWERED); TitledBorder infoB = BorderFactory.createTitledBorder( etchB, "Experiment Information"); TitledBorder filterB = BorderFactory.createTitledBorder( etchB, "Filter"); TitledBorder laserB = BorderFactory.createTitledBorder( etchB, "Laser"); TitledBorder detB = BorderFactory.createTitledBorder( etchB, "Detector"); JPanel infoP, filterP, laserP, detP; w = 250; JLabel exL = new JLabel("Experiment Type"); JLabel prL = new JLabel("Project Name"); JLabel desL = new JLabel("Description"); JLabel tempL = new JLabel("Temperature"); JLabel pocL = new JLabel("Pockel Cell"); JLabel tapL = new JLabel("Tap Settings"); JLabel wheeL = new JLabel("Wheel"); JLabel hoL = new JLabel("Holder"); prT = new JTextField(); prT.setPreferredSize(new Dimension(w,h)); prT.getDocument().addDocumentListener(this); tempT = new JTextField(); tempT.setPreferredSize(new Dimension(w,h)); tempT.setEnabled(false); pocT = new JTextField(); pocT.setPreferredSize(new Dimension(w,h)); pocT.setEnabled(false); tapT = new JTextField(); tapT.setPreferredSize(new Dimension(w,h)); tapT.setEnabled(false); tiT = new JTextField(); tiT.setPreferredSize(new Dimension(80,h)); tiT.setEnabled(false); pmtT = new JTextField(); pmtT.setPreferredSize(new Dimension(80,h)); pmtT.getDocument().addDocumentListener(this); desA = new JTextArea("",4,1); desA.setLineWrap(true); desA.setWrapStyleWord(true); desA.getDocument().addDocumentListener(this); JScrollPane desS = new JScrollPane(desA); desS.setPreferredSize(new Dimension(w,h*4)); desS.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); exB = new JComboBox(EX_CHOICES); exB.setPreferredSize(new Dimension(w,h)); exB.addActionListener(this); wheeB = new JComboBox(WHEE_CHOICES); wheeB.setEnabled(false); hoB = new JComboBox(HO_CHOICES); hoB.setEnabled(false); tiC = new JCheckBox("Ti-Sapphire"); tiC.addItemListener(this); phC = new JCheckBox("Photodiode Bio-Rad 1024TLD"); phC.addItemListener(this); pmtC = new JCheckBox("PMT Hamamatsu H7422"); pmtC.addItemListener(this); FormLayout layoutF = new FormLayout( "5dlu,pref,5dlu,pref:grow,5dlu", "5dlu,pref,5dlu,pref,5dlu"); PanelBuilder buildF = new PanelBuilder(layoutF); CellConstraints ccF = new CellConstraints(); buildF.add(wheeL, ccF.xy(2,2)); buildF.add(wheeB, ccF.xy(4,2)); buildF.add(hoL, ccF.xy(2,4)); buildF.add(hoB, ccF.xy(4,4)); filterP = buildF.getPanel(); filterP.setBorder(filterB); FormLayout layoutL = new FormLayout( "5dlu,pref,5dlu,pref,pref:grow, 5dlu", "5dlu,pref,25dlu"); PanelBuilder buildL = new PanelBuilder(layoutL); CellConstraints ccL = new CellConstraints(); buildL.add(tiC, cc.xy(2,2)); buildL.add(tiT, cc.xy(4,2)); laserP = buildL.getPanel(); laserP.setBorder(laserB); FormLayout layoutD = new FormLayout( "5dlu,pref,5dlu,pref,pref:grow, 5dlu", "5dlu,pref,5dlu,pref,20dlu"); PanelBuilder buildD = new PanelBuilder(layoutD); CellConstraints ccD = new CellConstraints(); buildD.add(phC, cc.xy(2,2)); buildD.add(pmtC, cc.xy(2,4)); buildD.add(pmtT, cc.xy(4,4)); detP = buildD.getPanel(); detP.setBorder(detB); FormLayout layoutE = new FormLayout( "5dlu,pref,5dlu,pref,5dlu,", "5dlu,pref,5dlu,pref,5dlu,top:pref,5dlu,pref,5dlu,pref," + "5dlu,pref,5dlu,pref,5dlu,pref,5dlu,pref,5dlu"); PanelBuilder buildE = new PanelBuilder(layoutE); CellConstraints ccE = new CellConstraints(); buildE.add(exL, cc.xy(2,2)); buildE.add(exB, cc.xy(4,2)); buildE.add(prL, cc.xy(2,4)); buildE.add(prT, cc.xy(4,4)); buildE.add(desL, cc.xy(2,6)); buildE.add(desS, cc.xy(4,6)); buildE.add(tempL, cc.xy(2,8)); buildE.add(tempT, cc.xy(4,8)); buildE.add(pocL, cc.xy(2,10)); buildE.add(pocT, cc.xy(4,10)); buildE.add(tapL, cc.xy(2,12)); buildE.add(tapT, cc.xy(4,12)); buildE.add(filterP, cc.xyw(2,14,3)); buildE.add(laserP, cc.xyw(2,16,3)); buildE.add(detP, cc.xyw(2,18,3)); infoP = buildE.getPanel(); infoP.setBorder(infoB); experimentPanel.add(infoP); } /** * Set whether or not the user should be able to edit the * OMEXML in any document. */ public void setEditable(boolean editable) { // groupBox.setEditable(editable); exB.setEnabled(editable); // wheeB.setEnabled(editable); // hoB.setEnabled(editable); tiC.setEnabled(editable); phC.setEnabled(editable); pmtC.setEnabled(editable); firstField.setEditable(editable); lastField.setEditable(editable); // omeField.setEditable(editable); // passField.setEditable(editable); emailField.setEditable(editable); prT.setEditable(editable); // tempT.setEditable(editable); // pocT.setEditable(editable); // tapT.setEditable(editable); // tiT.setEditable(editable); pmtT.setEditable(editable); desA.setEditable(editable); } /** * Update the OMEXML that this document is displaying/editing. * @param omeNode The OMENode of the current OMEXML document. */ public void setOMEXML(OMENode omeNode) { ome = omeNode; setup = true; exrEle = null; exEle = null; prEle = null; desEle = null; tiEle = null; pmtEle = null; phEle = null; Document omeDoc = null; try { omeDoc = ome.getOMEDocument(true); } catch (Exception exc) {} Vector exrVector = DOMUtil.findElementList("Experimenter",omeDoc); String firstName = "",lastName = "",emailName = ""; for (int i = 0;i<exrVector.size();i++) { Element ele = (Element) exrVector.get(i); if (ele.hasAttribute("FirstName")) { if (exrEle==null || exrEle == ele) { firstName = ele.getAttribute("FirstName"); exrEle = ele; } } if (ele.hasAttribute("LastName")) { if (exrEle==null || exrEle == ele) { lastName = ele.getAttribute("LastName"); exrEle = ele; } } if (ele.hasAttribute("Email")) { if (exrEle==null || exrEle == ele) { emailName = ele.getAttribute("Email"); exrEle = ele; } } } firstField.setText(firstName); lastField.setText(lastName); emailField.setText(emailName); if (exrEle == null && exrVector.size() != 0) { exrEle = (Element) exrVector.get(0); } Vector exVector = DOMUtil.findElementList("Experiment",omeDoc); String exType = "Other"; for (int i = 0;i<exVector.size();i++) { Element ele = (Element) exVector.get(i); if (ele.hasAttribute("Type")) { if (exEle==null || exEle == ele) { exType = ele.getAttribute("Type"); exEle = ele; } } } Arrays.sort(EX_CHOICES); if (Arrays.binarySearch(EX_CHOICES, exType) >= 0) exB.setSelectedItem(exType); else exB.setSelectedItem("Other"); if (exEle == null && exVector.size() != 0) { exEle = (Element) exVector.get(0); } Vector prVector = DOMUtil.findElementList("Project",omeDoc); String prName = null; for (int i = 0;i<prVector.size();i++) { Element ele = (Element) prVector.get(i); if (ele.hasAttribute("Name")) { if (prEle==null || prEle == ele) { prName = ele.getAttribute("Name"); prEle = ele; } } } prT.setText(prName); if (prEle == null && prVector.size() != 0) { prEle = (Element) prVector.get(0); } Vector desVector = exVector; String desText = null; for (int i = 0;i<desVector.size();i++) { Element ele = (Element) desVector.get(i); if (ele.hasAttribute("Description")) { if (desEle==null || desEle == ele) { desText = ele.getAttribute("Description"); desEle = ele; } } } desA.setText(desText); if (desEle == null && desVector.size() != 0) { desEle = (Element) desVector.get(0); } Vector tiVector = DOMUtil.findElementList("Laser",omeDoc); boolean tiToggle = false; for (int i = 0;i<tiVector.size();i++) { Element ele = (Element) tiVector.get(i); if (ele.hasAttribute("Medium")) { String attr = ele.getAttribute("Medium"); if (attr.equals("Ti-Sapphire")) { if (tiEle==null || tiEle == ele) { tiToggle = true; tiEle = ele; } } } } tiC.setSelected(tiToggle); Vector phVector = DOMUtil.findElementList("Detector",omeDoc); boolean phToggle = false; for (int i = 0;i<phVector.size();i++) { Element ele = (Element) phVector.get(i); if (ele.hasAttribute("Type")) { String attr = ele.getAttribute("Type"); if (attr.equals("Photodiode")) { if (phEle==null || phEle==ele) { phEle = ele; phToggle = true; } } } } phC.setSelected(phToggle); Vector pmtVector = phVector; boolean pmtToggle = false; for (int i = 0;i<pmtVector.size();i++) { Element ele = (Element) pmtVector.get(i); if (ele.hasAttribute("Type")) { String attr = ele.getAttribute("Type"); if (attr.equals("PMT")) { if (pmtEle==null || pmtEle==ele) { pmtToggle = true; pmtEle = ele; } } } } pmtC.setSelected(pmtToggle); pmtT.setEnabled(pmtToggle); if (pmtEle != null && pmtEle.hasAttribute("Gain")) { pmtT.setText(pmtEle.getAttribute("Gain")); } setup = false; } // -- ActionListener API methods -- /** Handle selections in the JComboBoxes. */ public void actionPerformed(ActionEvent e) { if (setup) return; if (e.getSource() instanceof JComboBox) { JComboBox src = (JComboBox) e.getSource(); if (src==exB) { if (exEle==null) { exEle = MetadataPane.makeNode("Experiment", ome).getDOMElement(); } exEle.setAttribute("Type",(String) exB.getSelectedItem()); setOMEXML(ome); } } } // -- ItemListener API methods -- /** Handle changes with selection in the JCheckBoxes. */ public void itemStateChanged(ItemEvent e) { if (setup) return; JCheckBox src = (JCheckBox) e.getItem(); if (src==tiC) { if (e.getStateChange() == ItemEvent.SELECTED) { OMEXMLNode newNode = MetadataPane.makeNode("Laser",ome); newNode.setAttribute("Medium", "Ti-Sapphire"); newNode.setAttribute("Type", "Solid State"); tiEle = newNode.getDOMElement(); } else { if (ome.getChildNode("CustomAttributes") != null) { Node thisNode = (Node) ome.getChildNode( "CustomAttributes").getDOMElement(); thisNode.removeChild((Node)tiEle); tiEle = null; } } } else if (src==phC) { if (e.getStateChange() == ItemEvent.SELECTED) { OMEXMLNode newNode = MetadataPane.makeNode("Detector",ome); newNode.setAttribute("Manufacturer", "Bio-Rad"); newNode.setAttribute("Model", "1024LD"); newNode.setAttribute("Type", "Photodiode"); phEle = newNode.getDOMElement(); } else { if (ome.getChildNode("CustomAttributes") != null) { Node thisNode = (Node) ome.getChildNode( "CustomAttributes").getDOMElement(); thisNode.removeChild((Node)phEle); phEle = null; } } } else if (src==pmtC) { if (e.getStateChange() == ItemEvent.SELECTED) { OMEXMLNode newNode = MetadataPane.makeNode("Detector",ome); newNode.setAttribute("Manufacturer", "Hamamatsu"); newNode.setAttribute("Model", "H7422"); newNode.setAttribute("Type", "PMT"); pmtEle = newNode.getDOMElement(); pmtT.setEnabled(true); } else { if (ome.getChildNode("CustomAttributes") != null) { Node thisNode = (Node) ome.getChildNode( "CustomAttributes").getDOMElement(); thisNode.removeChild((Node)pmtEle); pmtEle = null; pmtT.setEnabled(false); pmtT.setText(""); } } } } // -- DocumentListener API methods -- /** Calls changeNode(e). */ public void insertUpdate(DocumentEvent e) {changeNode(e);} /** Calls changeNode(e). */ public void removeUpdate(DocumentEvent e) {changeNode(e);} /** Calls changeNode(e). */ public void changedUpdate(DocumentEvent e) {changeNode(e);} /** Change the OMEXMLNode tree appropriately for a given DocumentEvent. */ private void changeNode(DocumentEvent e) { if (setup) return; setup = true; try { if (e.getDocument() == desA.getDocument()) { if (desEle==null) { desEle = MetadataPane.makeNode("Experiment", ome).getDOMElement(); } desEle.setAttribute("Description", e.getDocument().getText(0, e.getDocument().getLength())); setOMEXML(ome); } else if (e.getDocument() == prT.getDocument()) { if (prEle==null) { prEle = MetadataPane.makeNode("Project", ome).getDOMElement(); } prEle.setAttribute("Name", e.getDocument().getText(0, e.getDocument().getLength())); setOMEXML(ome); } else if (e.getDocument() == pmtT.getDocument()) { if (pmtC != null) pmtEle.setAttribute("Gain", e.getDocument().getText(0, e.getDocument().getLength())); else pmtT.setText(""); } else if (e.getDocument() == firstField.getDocument()) { if (exrEle==null) { exrEle = MetadataPane.makeNode("Experimenter" ,ome).getDOMElement(); } exrEle.setAttribute("FirstName", e.getDocument().getText(0, e.getDocument().getLength())); setOMEXML(ome); } else if (e.getDocument() == lastField.getDocument()) { if (exrEle==null) { exrEle = MetadataPane.makeNode("Experimenter" ,ome).getDOMElement(); } exrEle.setAttribute("LastName", e.getDocument().getText(0, e.getDocument().getLength())); setOMEXML(ome); } else if (e.getDocument() == emailField.getDocument()) { if (exrEle==null) { exrEle = MetadataPane.makeNode("Experimenter", ome).getDOMElement(); } exrEle.setAttribute("Email", e.getDocument().getText(0, e.getDocument().getLength())); setOMEXML(ome); } } catch (Exception exc) {} setup = false; } // -- Helper classes -- /** * Fixes the annoyingness that happens with JPanel expansion * within a JScrollPane. Resizing should work appropriately now. */ public class ScrollablePanel extends JPanel implements Scrollable { public ScrollablePanel() { super(); } public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {return 5;} public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {return visibleRect.height;} public boolean getScrollableTracksViewportWidth() {return true;} public boolean getScrollableTracksViewportHeight() {return false;} } }