package org.obo.annotation.view;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.TransferHandler;
import javax.swing.border.Border;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.Document;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import org.apache.log4j.Logger;
import org.bbop.framework.AbstractGUIComponent;
import org.bbop.framework.ComponentConfiguration;
import org.bbop.framework.ComponentManager;
import org.bbop.framework.ConfigurationPanel;
import org.bbop.swing.HyperlinkLabel;
import org.bbop.swing.StringLinkListener;
import org.obo.annotation.datamodel.Annotation;
import org.obo.app.swing.SpringUtilities;
import org.obo.app.swing.StackedBox;
import org.obo.datamodel.DanglingObject;
import org.obo.datamodel.Dbxref;
import org.obo.datamodel.IdentifiedObject;
import org.obo.datamodel.Link;
import org.obo.datamodel.LinkDatabase;
import org.obo.datamodel.LinkedObject;
import org.obo.datamodel.OBOClass;
import org.obo.datamodel.OBOObject;
import org.obo.datamodel.OBOProperty;
import org.obo.datamodel.OBORestriction;
import org.obo.datamodel.OBOSession;
import org.obo.datamodel.ObsoletableObject;
import org.obo.datamodel.PathCapable;
import org.obo.datamodel.PropertyValue;
import org.obo.datamodel.RootAlgorithm;
import org.obo.datamodel.Synonym;
import org.obo.datamodel.impl.OBOSessionImpl;
import org.obo.util.TermUtil;
import org.oboedit.gui.ObjectSelector;
import org.oboedit.gui.Selection;
import org.oboedit.gui.event.ExpandCollapseListener;
import org.oboedit.gui.event.SelectionListener;
import edu.stanford.ejalbert.BrowserLauncher;
import edu.stanford.ejalbert.exception.BrowserLaunchingInitializingException;
import edu.stanford.ejalbert.exception.UnsupportedOperatingSystemException;
/**
* This is the second implementation of the Term Info window to provide
* read-only information about ontology terms for the user.
* <p>
* This constructs the toolbar as well as the information panels.
* <p>
* This uses the {@link StackedBox} and {@link JXCollapsablePane} classes.
* <p>
*
* Things to fix:
* <p>
* <ul>
* <li>make more generic...so that components can be moved around, right now
* they are in a set order</li>
* <li>make sure text doesn't go off the panel to the right. esp important for
* the term name and definition, as they seem to be having problems</li>
* <li>fancy things might include remembering state between sessions</li>
* <li>should be able to close a panel, and never display if not interested
* perhaps regain it again through a right-click menu or something. could be
* something for the 'configure this panel' when we move to john's gui stuff</li>
* <li>The whole termInfo panel should probably be an array of panels, or at least
* they should be kept track of that way. that will reduce the size of the code a bit
* and will make it easier when it comes time for customization to be able to swap
* panels around, so that particular panels won't be married to a particular position.</li>
* </ul>
*
* @author Nicole Washington
*
*/
public class TermInfoComponent extends AbstractGUIComponent {
private static final Logger LOG = Logger.getLogger(TermInfoComponent.class);
protected Map<OBOObject,Float> cachedAnnotationInformationContentByClass = new HashMap<OBOObject,Float>();
protected Map<OBOObject,Integer> cachedAnnotationCountByClass = new HashMap<OBOObject,Integer>();
protected boolean includeImplicitAnnotations = false;
protected boolean includeExternalDatabaseAnnotations = false;
// constants
private static final int TERM_INFO_DEFAULT_WIDTH = 350;
private static final int TERM_INFO_DEFAULT_HEIGHT = 400;
private static final int BUTTON_HEIGHT = 30;
private static Border contentBorder = BorderFactory.createEmptyBorder(3, 3,
6, 3); //top, left, bottom, right...orig 6,8,6,8
//these are used for the spring layout.
private static final int XPAD = 5; //between elements horizontally
private static final int YPAD = 3; //between elements vertically
private static final int INITX = 3;
private static final int INITY = 3;
private static final int PREFERREDX = 75;
private static final String PHENOTE_LINK_PREFIX = "Phenote?id=";
// content variables
private OBOObject currentOboClass = null;
private UseTermListener useTermListener;
private TermHyperlinkListener termHyperlinkListener;
private static List<String> termInfoNaviHistory = new ArrayList<String>();
// private List termInfoNaviHistory = new List();
private static int naviIndex = -1;
private SelectionManager selectionManager;
// gui components
private TermInfoToolbar termInfoToolbar;
private JScrollPane termInfoScroll;
/** StackedBox is a class in the phenote.gui package, that nicole got from
web & modified */
private StackedBox termInfoPanel;
private JPanel basicInfoPanel;
//private JLabel termName; // no selection
//private JTextField termName; // doesnt do html
private JEditorPane termName;
//private JLabel termID;
private JTextField termID;
private JLabel ontologyName;
private JLabel annotationSummaryLabel;
private JEditorPane definitionTextArea;
private HyperlinkLabel annotationSummaryTextArea;
private JPanel considerReplacePanel;
private JTextArea considerTerms;
private JTextArea replacementTerms;
private JPanel synonymPanel;
private JPanel annotationPanel;
// private JTextArea synonyms;
private JPanel dbxrefPanel;
private JTextArea dbxrefText;
private JPanel xpDefPanel;
private JTextArea xpDefList;
private JPanel propertyValuesPanel;
// private JTextArea propValsList;
private JPanel ontologyLinksPanel;
private JPanel parentsPanel;
private JTextArea parentsText;
private JPanel childrenPanel;
private JTextArea childrenText;
private JPanel commentsPanel;
private JTextArea commentsText;
private JPanel emptyPanel;
private boolean showEmptyPanelsFlag = false;
private static final String basicInfoPanelName = "BASIC"; //0
private static final String considerReplacePanelName = "CONSIDERS"; //2
private static final String synonymPanelName = "SYNONYMS"; //4
private static final String xpdefsPanelName = "XPDEFS"; //6
private static final String linksPanelName = "LINKS"; //8
private static final String dbxrefPanelName = "DBXREFS"; //10
private static final String propvalsPanelName = "PROPVALS"; //12
private static final String commentsPanelName = "COMMENTS"; //14
private static final String annotationPanelName = "ANNOTATIONS"; //16
private OBOSession oboSession = new OBOSessionImpl();
public TermInfoComponent(String id, OntologyCoordinator coordinator) {
super(id);
this.oboSession = coordinator.getOBOSession();
this.selectionManager = coordinator.getSelectionManager();
this.selectionManager.addTermSelectionListener(new InfoTermSelectionListener());
this.initTermInfo();
}
public OBOSession getOBOSession() {
return this.oboSession;
}
public void setOBOSession(OBOSession newSession) {
this.oboSession = newSession;
}
public boolean isIncludeImplicitAnnotations() {
return includeImplicitAnnotations;
}
public void setIncludeImplicitAnnotations(boolean includeImplicitAnnotations) {
this.includeImplicitAnnotations = includeImplicitAnnotations;
}
public boolean isIncludeExternalDatabaseAnnotations() {
return includeExternalDatabaseAnnotations;
}
public void setIncludeExternalDatabaseAnnotations(
boolean includeExternalDatabaseAnnotations) {
this.includeExternalDatabaseAnnotations = includeExternalDatabaseAnnotations;
}
@Override
public ConfigurationPanel getConfigurationPanel() {
ConfigurationPanel p = new ConfigurationPanel() {
protected JCheckBox includeImplicitAnnotationsBox = new JCheckBox(
"Include implicit annotations",
false);
protected JCheckBox includeExternalDatabaseAnnotationsBox = new JCheckBox(
"Include external database annotations",
false);
{
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(includeImplicitAnnotationsBox);
add(includeExternalDatabaseAnnotationsBox);
}
@Override
public void commit() {
TermInfo2Config config = (TermInfo2Config) getComponent()
.getConfiguration();
config.setIncludeImplicitAnnotations(includeImplicitAnnotationsBox.isSelected());
config.setIncludeExternalDatabaseAnnotations(includeExternalDatabaseAnnotationsBox.isSelected());
getComponent().setConfiguration(config);
// getComponent().getComponent().updateUI(); TODO: update UI
}
@Override
public void init() {
TermInfo2Config config = (TermInfo2Config) getComponent()
.getConfiguration();
includeImplicitAnnotationsBox.setSelected(config.isIncludeImplicitAnnotations());
includeExternalDatabaseAnnotationsBox.setSelected(config.isIncludeExternalDatabaseAnnotations());
}
};
return p;
}
@Override
public ComponentConfiguration getConfiguration() {
return new TermInfo2Config(isIncludeImplicitAnnotations(),
isIncludeExternalDatabaseAnnotations());
}
@Override
public void setConfiguration(ComponentConfiguration config) {
if (config instanceof TermInfo2Config) {
setIncludeImplicitAnnotations(((TermInfo2Config) config)
.isIncludeImplicitAnnotations());
setIncludeExternalDatabaseAnnotations(((TermInfo2Config) config)
.isIncludeExternalDatabaseAnnotations());
}
}
public static class TermInfo2Config implements ComponentConfiguration {
protected boolean includeImplicitAnnotations = false;
protected boolean includeExternalDatabaseAnnotations = false;
public TermInfo2Config(boolean includeImplicitAnnotations, boolean includeExternalDatabaseAnnotations) {
super();
this.includeImplicitAnnotations = includeImplicitAnnotations;
this.includeExternalDatabaseAnnotations = includeExternalDatabaseAnnotations;
}
public TermInfo2Config() {
}
public boolean isIncludeImplicitAnnotations() {
return includeImplicitAnnotations;
}
public void setIncludeImplicitAnnotations(boolean includeImplicitAnnotations) {
this.includeImplicitAnnotations = includeImplicitAnnotations;
}
public boolean isIncludeExternalDatabaseAnnotations() {
return includeExternalDatabaseAnnotations;
}
public void setIncludeExternalDatabaseAnnotations(
boolean includeExternalDatabaseAnnotations) {
this.includeExternalDatabaseAnnotations = includeExternalDatabaseAnnotations;
}
}
private void initTermInfo() {
// create the panel the whole thing will live in (including toolbars,
// etc.)
//this.setLayout(new BorderLayout(0,0));
getComponent().setLayout(new BoxLayout(getComponent(),BoxLayout.Y_AXIS));
this.setPreferredSize(new Dimension(TERM_INFO_DEFAULT_WIDTH,TERM_INFO_DEFAULT_HEIGHT));
// create the toolbar
termInfoToolbar = new TermInfoToolbar();
termInfoToolbar.setPreferredSize(new Dimension(TERM_INFO_DEFAULT_WIDTH, BUTTON_HEIGHT+5));
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
termInfoToolbar.setMaximumSize(new Dimension(screenSize.width, BUTTON_HEIGHT+5));
this.add(termInfoToolbar); //, BorderLayout.NORTH);
// create the stackedbox that the term info will live in
termInfoPanel = new StackedBox();
// put it in a scrollpane
termInfoScroll = new JScrollPane(termInfoPanel);
termInfoScroll.setBorder(null);
// put the scrollpane into the whole bucket
this.add(termInfoScroll); //, BorderLayout.CENTER);
// The first part, which includes all the basic information,
// ontology, id, def
basicInfoPanel = new JPanel();
basicInfoPanel.setOpaque(false);
basicInfoPanel.setBackground(Color.WHITE);
basicInfoPanel.setLayout(new SpringLayout());
basicInfoPanel.setBorder(contentBorder);
basicInfoPanel.setName(basicInfoPanelName);
// Create and populate the panel.
JLabel nameLabel = new JLabel("Term: ", JLabel.TRAILING);
basicInfoPanel.add(nameLabel);
termName = new JEditorPane(); // handles html & text select/copy
termName.setEditable(false);
termName.setBorder(null);
termName.setBackground(Color.WHITE);
termName.setContentType("text/html");
termName.setText("(No Selection)");
nameLabel.setLabelFor(termName);
nameLabel.setVerticalAlignment(JLabel.TOP);
basicInfoPanel.add(termName);
// make nameLabel draggable to drag term to fields
//nameLabel.setTransferHandler(new InfoTransferHandler());
JLabel idLabel = new JLabel("ID: ", JLabel.TRAILING);
basicInfoPanel.add(idLabel);
termID = new JTextField(); //Label(); -> selectable text!
termID.setEditable(false);
termID.setBorder(null); // ?
termID.setBackground(Color.WHITE);
idLabel.setLabelFor(termID);
basicInfoPanel.add(termID);
ontologyName = new JLabel();
JLabel ontologyLabel = new JLabel("Ontology: ", JLabel.TRAILING);
basicInfoPanel.add(ontologyLabel);
ontologyLabel.setLabelFor(ontologyName);
basicInfoPanel.add(ontologyName);
JLabel definitionLabel = new JLabel("Definition: ", JLabel.TRAILING);
definitionLabel.setVerticalAlignment(JLabel.TOP);
basicInfoPanel.add(definitionLabel);
definitionTextArea = new JEditorPane();
definitionTextArea.setText(" ");
definitionTextArea.setEditable(false);
definitionTextArea.setBorder(null);
definitionTextArea.setBackground(Color.WHITE);
definitionTextArea.setContentType("text/html");
termHyperlinkListener = new TermHyperlinkListener();
definitionLabel.setLabelFor(definitionTextArea);
basicInfoPanel.add(definitionTextArea);
//removing for 1.5 release
// if (this.isIncludeExternalDatabaseAnnotations()) {
annotationSummaryLabel = new JLabel("<html><p align=right>External Annotations:</p></html>", JLabel.TRAILING);
annotationSummaryLabel.setVerticalAlignment(JLabel.TOP);
basicInfoPanel.add(annotationSummaryLabel);
annotationSummaryTextArea = new HyperlinkLabel(" ");
annotationSummaryLabel.setLabelFor(annotationSummaryTextArea);
basicInfoPanel.add(annotationSummaryTextArea);
annotationSummaryLabel.setVisible(this.isIncludeExternalDatabaseAnnotations());
annotationSummaryTextArea.setVisible(this.isIncludeExternalDatabaseAnnotations());
// }
// Lay out the panel.
int[] maxX = {PREFERREDX,-1};
int[] maxY = null;
SpringLayout layout = new SpringLayout();
basicInfoPanel.setLayout(layout);
SpringUtilities.makeCompactGrid(basicInfoPanel, 5, 2, // rows, cols
INITX, INITY, // initX, initY
XPAD, YPAD); // xPad, yPad
SpringUtilities.fixCellWidth(basicInfoPanel, 5, 2, // rows,
// cols
INITX, INITY, // initX, initY
XPAD, YPAD, // xPad, yPad
maxX, maxY);
termInfoPanel.addBox("Basic Info", basicInfoPanel);
//consider & replacement terms - for obo1.2+ format
considerReplacePanel = new JPanel();
considerReplacePanel.setOpaque(false);
considerReplacePanel.setLayout(new SpringLayout());
considerReplacePanel.setBorder(contentBorder);
considerReplacePanel.setBackground(Color.WHITE);
considerTerms = new JTextArea();
considerReplacePanel.add(considerTerms);
replacementTerms = new JTextArea();
considerReplacePanel.add(replacementTerms);
considerReplacePanel.setName(considerReplacePanelName);
considerReplacePanel.setVisible(false);
termInfoPanel.addBox("Consider & Replacement Terms", considerReplacePanel);
// synonyms
synonymPanel = new JPanel();
synonymPanel.setOpaque(false);
synonymPanel.setLayout(new SpringLayout());
synonymPanel.setBorder(contentBorder);
synonymPanel.setName(synonymPanelName);
synonymPanel.setVisible(false);
termInfoPanel.addBox("Synonyms", synonymPanel);
// xp definitions
xpDefPanel = new JPanel();
xpDefPanel.setBackground(Color.WHITE);
xpDefPanel.setLayout(new BoxLayout(xpDefPanel, BoxLayout.PAGE_AXIS));
xpDefList = new JTextArea();
xpDefList.setLineWrap(true);
xpDefList.setText(" ");
xpDefPanel.add(xpDefList);
xpDefPanel.setName(xpdefsPanelName);
xpDefPanel.setVisible(false);
termInfoPanel.addBox("Cross Product Definitions", xpDefPanel);
//Links - parents and children
ontologyLinksPanel = new JPanel();
ontologyLinksPanel.setBackground(Color.WHITE);
ontologyLinksPanel.setName(linksPanelName);
ontologyLinksPanel.setLayout(new SpringLayout());
termInfoPanel.addBox("Parents & Children", ontologyLinksPanel);
parentsPanel = new JPanel(new SpringLayout());
parentsText = new JTextArea();
parentsPanel.add(parentsText);
parentsPanel.setBackground(Color.WHITE);
ontologyLinksPanel.add(parentsPanel);
childrenPanel = new JPanel(new SpringLayout());
childrenText = new JTextArea();
childrenPanel.add(childrenText);
childrenPanel.setBackground(Color.WHITE);
ontologyLinksPanel.add(childrenPanel);
ontologyLinksPanel.setVisible(false);
//the two panels are placed in a spring grid within the larger panel
SpringUtilities.makeCompactGrid(ontologyLinksPanel, 2, 1,
0, 0, // initX, initY
0, 0); // xPad, yPad
// dbxrefs
dbxrefPanel = new JPanel();
dbxrefPanel.setBackground(Color.WHITE);
dbxrefPanel.setLayout(new SpringLayout());
dbxrefText = new JTextArea();
dbxrefPanel.add(dbxrefText);
dbxrefPanel.setName(dbxrefPanelName);
dbxrefPanel.setVisible(false);
termInfoPanel.addBox("DBxrefs", dbxrefPanel);
// propertyValues (often used for OWL ontologies)
propertyValuesPanel = new JPanel();
propertyValuesPanel.setOpaque(false);
propertyValuesPanel.setLayout(new SpringLayout());
propertyValuesPanel.setBorder(contentBorder);
propertyValuesPanel.setName(propvalsPanelName);
propertyValuesPanel.setVisible(false);
termInfoPanel.addBox("Other Properties", propertyValuesPanel);
commentsPanel = new JPanel();
commentsPanel.setOpaque(false);
commentsPanel.setBackground(Color.WHITE);
commentsPanel.setLayout(new BoxLayout(commentsPanel, BoxLayout.PAGE_AXIS));
commentsText = new JTextArea();
commentsText.setLineWrap(true);
commentsText.setWrapStyleWord(true);
commentsPanel.add(commentsText);
commentsPanel.setBorder(contentBorder);
commentsPanel.setName(commentsPanelName);
commentsPanel.setVisible(false);
termInfoPanel.addBox("Comments", commentsPanel);
// Annotations
// Do we want a single panel here?
annotationPanel = new JPanel();
annotationPanel.setOpaque(false);
annotationPanel.setLayout(new SpringLayout());
annotationPanel.setBorder(contentBorder);
annotationPanel.setName(annotationPanelName);
annotationPanel.setVisible(false);
termInfoPanel.addBox("Annotations", annotationPanel);
//okay, this is a hack to make the refresh work properly... one extra panel
//does it
emptyPanel = new JPanel();
termInfoPanel.add(emptyPanel);
// refresh
validate();
repaint();
setVisible(true);
}
// public static JComponent getComponent() {
// return entirePanel;
// }
private void setTextFromOboClass(OBOObject oboClass) {
TermInfoComponent.this.currentOboClass = oboClass;
// basicInfoPanel
if (!oboClass.isObsolete()) {
termInfoPanel.setBoxTitleBackgroundColor(0, Color.LIGHT_GRAY);
termInfoPanel.setBoxTitle("Basic Info", 0);
// hide the consider/replace panel
termInfoPanel.getComponent(2).setVisible(false);
considerReplacePanel.setVisible(false);
} else {
termInfoPanel.setBoxTitleBackgroundColor(0, Color.RED);
termInfoPanel.setBoxTitle("Basic Info [OBSOLETE]", 0);
// show the consider/replacements
termInfoPanel.getComponent(2).setVisible(true);
considerReplacePanel.setVisible(true);
}
termInfoToolbar.setTermFieldText(oboClass); //is the toolbar now out of date b/c of the component title?
//always show the basics, even if empty...shouldn't be empty.
termID.setText(oboClass.getID());
if (oboClass.getNamespace()!=null) {
ontologyName.setText(oboClass.getNamespace().toString());
}
else {
ontologyName.setText("No namespace/ontology specified");
LOG.error("No namespace for term "+oboClass);
}
if (oboClass.getDefinition().length()>0) {
String def = oboClass.getDefinition();
// definitions can have refs in brackets after def
Set<Dbxref> defRefs = oboClass.getDefDbxrefs();
if (defRefs!=null && !defRefs.isEmpty()) {
int i=1;
for (Dbxref x : defRefs) {
def += "<br>Definition ref "+ i++ +": " +x;
}
}
definitionTextArea.setText("<html>"+def+"</html>");
} else {
definitionTextArea.setText("<html> (no definition provided) </html>");
}
if ((!showEmptyPanelsFlag) && ((oboClass.getConsiderReplacements().size()+oboClass.getReplacedBy().size()) == 0)) {
termInfoPanel.getComponent(2).setVisible(false);
considerReplacePanel.setVisible(false);
} else {
termInfoPanel.getComponent(2).setVisible(true);
// Consider/replace panel
makeObsPanel(oboClass);
termInfoPanel.setBoxTitle("Consider ("
+ oboClass.getConsiderReplacements().size() + ") & Replacement ("
+ oboClass.getReplacedBy().size() + ") Terms", 2);
considerReplacePanel.validate();
considerReplacePanel.repaint();
considerReplacePanel.setVisible(true);
}
if (isIncludeExternalDatabaseAnnotations()) {
// annotationSummaryTextArea.setText("<html>annotation count: <b>"+ this.getAnnotationCountByClass(oboClass) + " "+
// "</b><br>information content: <b>"+this.getAnnotationInformationContentByClass(oboClass) +
// "</b></html>");
} else {
annotationSummaryTextArea.setText("");
}
annotationSummaryLabel.setVisible(this.isIncludeExternalDatabaseAnnotations());
annotationSummaryTextArea.setVisible(this.isIncludeExternalDatabaseAnnotations());
if ((!showEmptyPanelsFlag) && (oboClass.getSynonyms().size() == 0)) {
termInfoPanel.getComponent(4).setVisible(false);
synonymPanel.setVisible(false);
} else {
// SynonymPanel
termInfoPanel.getComponent(4).setVisible(true);
makeSynPanel(oboClass.getSynonyms());
termInfoPanel.setBoxTitle("Synonyms (" + oboClass.getSynonyms().size()
+ ")", 4);
synonymPanel.validate();
synonymPanel.repaint();
synonymPanel.setVisible(true);
}
// xpDefPanel
int linkCount = 0;
linkCount = makeLinksPanel(oboClass.getParents(), true, false, xpDefPanel);
termInfoPanel.setBoxTitle("Cross-product Definitions (" + linkCount + ")",
6);
if ((!showEmptyPanelsFlag) && (linkCount == 0)) {
termInfoPanel.getComponent(6).setVisible(false);
xpDefPanel.setVisible(false);
} else {
termInfoPanel.getComponent(6).setVisible(true);
xpDefPanel.setVisible(true);
}
// parentsPanel
linkCount = 0;
linkCount = makeLinksPanel(oboClass.getParents(), false, false,
parentsPanel);
parentsPanel.validate();
parentsPanel.repaint();
// childrenPanel
linkCount += makeLinksPanel(oboClass.getChildren(), false, true,
childrenPanel);
childrenPanel.validate();
childrenPanel.repaint();
termInfoPanel.setBoxTitle("Links (" + linkCount + ")", 8);
if ((!showEmptyPanelsFlag) && (linkCount == 0)) {
termInfoPanel.getComponent(8).setVisible(false);
ontologyLinksPanel.setVisible(false);
} else {
ontologyLinksPanel.validate();
ontologyLinksPanel.repaint();
ontologyLinksPanel.setVisible(true);
termInfoPanel.getComponent(8).setVisible(true);
}
// dbxrefsPanel
if ((!showEmptyPanelsFlag) && (oboClass.getDbxrefs().size() == 0)) {
termInfoPanel.getComponent(10).setVisible(false);
dbxrefPanel.setVisible(false);
} else {
makeDbxrefPanel(oboClass.getDbxrefs());
termInfoPanel.setBoxTitle("DBxrefs (" + oboClass.getDbxrefs().size() + ")",
10);
dbxrefPanel.validate();
dbxrefPanel.repaint();
dbxrefPanel.setVisible(true);
termInfoPanel.getComponent(10).setVisible(true);
}
// propValues
// propertyValuesList.setText(oboClass.getPropertyValues().toString());
linkCount = makePropValsPanel(oboClass.getPropertyValues());
termInfoPanel.setBoxTitle("Other Properties (" + linkCount + ")", 12);
if (!showEmptyPanelsFlag && (linkCount == 0)) {
termInfoPanel.getComponent(12).setVisible(false);
propertyValuesPanel.setVisible(false);
} else {
propertyValuesPanel.validate();
propertyValuesPanel.repaint();
propertyValuesPanel.setVisible(true);
termInfoPanel.getComponent(12).setVisible(true);
}
// commentsPanel
if (oboClass.getComment().length() == 0) {
termInfoPanel.setBoxTitle("Comments (none)", 14);
if (!showEmptyPanelsFlag) {
termInfoPanel.getComponent(14).setVisible(false);
commentsPanel.setVisible(false);
}
} else {
termInfoPanel.setBoxTitle("Comments*", 14);
commentsText.setText(oboClass.getComment().toString());
termInfoPanel.getComponent(14).setVisible(true);
commentsPanel.setVisible(true);
commentsPanel.validate();
commentsPanel.repaint();
}
// Annotations
//moving annotations to only show if the button is clicked.
//want to hide the annotation panel until the person clicks the button
// termInfoPanel.getComponent(16).setVisible(false);
// annotationPanel.setVisible(false);
// this refreshes the main panel
//this seems a little out of order, but its to get the scrollbar movement right
termName.setText("<html><b>"+oboClass.getName()+"</b></html>");
termName.validate();
termName.repaint(); //really trying to make sure the scroll works properly.
basicInfoPanel.validate();
basicInfoPanel.repaint();
basicInfoPanel.setVisible(true);
termInfoScroll.getVerticalScrollBar().setValue(0);
termInfoScroll.getViewport().setViewPosition(new Point(0, 0));
termInfoPanel.validate();
termInfoPanel.repaint();
emptyPanel.repaint();
validate();
repaint();
}
/**
* Puts the currently browsed term name into the component title <p>
* @param oboClass the term being browsed
*/
public void setComponentTitleFromOBOObject (OBOObject oboClass) {
String title = "Term Info: "+ oboClass.getName();
// this only works and only makes sense in phenote2 with docking framework
// where each gui item has a border around it with a title - otherwise throws
// null pointer - just catch null pointer and do nothing
try { ComponentManager.getManager().setLabel(this,title); }
catch (NullPointerException x) {}
}
/** Listen for selection from phenote (mouse over completion list) */
private class InfoTermSelectionListener implements TermSelectionListener {
@Override
public void termSelected(TermSelectionEvent e) {
clearAnnotations(); // ???
//navi selection is a mouseover event
if (!e.isMouseOverEvent()) {
// add the item to the navi history if selected from list only
String id = e.getOboClass().getID();
addTermToNaviHistory(id); //only add the item if its not from navigation
}
setTextFromOboClass(e.getOboClass());
// This sets who now listens to use term button clicks (only 1
// listener)
//setUseTermListener(e.getUseTermListener());
termInfoToolbar.setUseTermListener(e.getUseTermListener());
//change the name of the item being browsed in the term info header
setComponentTitleFromOBOObject(e.getOboClass());
}
}
/** just gets useTermListener from terminfotoolbar, which back & forward
action use, which actually probably isnt right as back & forward
might be hitting terms with different use term listeners
but good enough for now */
public UseTermListener getUseTermListener() {
return termInfoToolbar.getUseTermListener();
}
private void addTermToNaviHistory(String link) {
int tot = termInfoNaviHistory.size();
// int tot = termInfoNaviHistory.getItemCount();
if ((tot - 1) > naviIndex) { // we're in the middle of the navi
if (naviIndex >= 0) { // we're not at the beginning
// remove all the items between end and here
for (int i = (tot - 1); i > naviIndex; i--) {
termInfoNaviHistory.remove(i);
}
}
}
termInfoNaviHistory.add(link);
// termComboBox.insertItemAt(link,0);
// termComboBox.setSelectedIndex(0);
naviIndex++; // we should be at the end of the history
// System.out.println("tot="+tot+"; naviIndex="+naviIndex);
}
public static String getTermFromNaviHistory(int position) {
if (termInfoNaviHistory.size() >= 1)
// if (termInfoNaviHistory.getItemCount() >= 1)
return termInfoNaviHistory.get(position).toString();
// return termInfoNaviHistory.getItem(position);
else
return "";
}
/**
* inner class TermHyperlink Listener, listens for clicks on term & external
* hyper links and brings up the term or brings up the external web page
*/
private class TermHyperlinkListener implements StringLinkListener,
HyperlinkListener {
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
if (!(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)) return;
URL url = e.getURL();
LOG.debug("got url "+url+" desc "+e.getDescription());
// internal link to term...
if (isPhenoteLink(e)) {
bringUpTermInTermInfo(e);
return;
}
if (url == null) { // relative urls are null
LOG.error("invalid url " + url);
return;
}
bringUpInBrowser(url);
}
private void bringUpInBrowser(URL url) {
if (url == null) return;
try {
BrowserLauncher bl = new BrowserLauncher(null); // no logger
bl.openURLinBrowser(url.toString());
} catch (BrowserLaunchingInitializingException be) {
LOG.error("cant launch browser ", be);
} catch (UnsupportedOperatingSystemException ue) {
LOG.error("cant launch browser ", ue);
}
}
private void bringUpTermInTermInfo(HyperlinkEvent e) {
// or do through obo session?
String id = getIdFromHyperlink(e);
if (id == null) return;
bringUpTermInTermInfo(id);
}
private void bringUpTermInTermInfo(String id) {
// or do through obo session?
if (id == null) return;
// try {
IdentifiedObject io = getOBOSession().getObject(id);
if (io instanceof OBOObject) {
OBOObject c = (OBOObject) io;
setTextFromOboClass(c);
setComponentTitleFromOBOObject(c);
addTermToNaviHistory(id);
// send out term selection (non mouse over) for DAG view
// im guessing this is a work in progress as currently true for isHyperLink
// causes SelMan to not fireTermSelect and thus this does nothing
// whats the idea here?? - MG
if (c instanceof OBOClass)
selectionManager.selectTerm(TermInfoComponent.this, (OBOClass)c, true);
}
}
@Override
public void link(String href) {
bringUpTermInTermInfo(href);
// TODO Auto-generated method stub
}
} // end of inner class TermHyperlinkListener
private void makeSynPanel(Set<Synonym> someSet) {
// private JList makeSynList (Set someSet) {
String[] synTypes = { "BROAD", "NARROW", "EXACT", "RELATED", "OTHER" };
String[] syns = { "", "", "", "", "" };
int numSynTypes = 5;
int rowCount = 0;
Synonym syn;
for (Iterator<Synonym> it = someSet.iterator(); it.hasNext();) {
syn = it.next();
if (syn.getScope() == Synonym.BROAD_SYNONYM) {
syns[0] += syn + "<br>";
} else if (syn.getScope() == Synonym.NARROW_SYNONYM) {
syns[1] += syn + "<br>";
} else if (syn.getScope() == Synonym.EXACT_SYNONYM) {
syns[2] += syn + "<br>";
} else if (syn.getScope() == Synonym.RELATED_SYNONYM) {
syns[3] += syn + "<br>";
} else if (syn.getScope() == Synonym.UNKNOWN_SCOPE) {
syns[4] += syn + "<br>";
} else {
syns[4] += syn + "<br>";
}
}
synonymPanel.removeAll(); // clear out the old ones
synonymPanel.setBorder(contentBorder);
synonymPanel.setOpaque(false);
synonymPanel.setBackground(Color.WHITE);
// create the synonym items
for (int i = 0; i < numSynTypes; i++) {
if (syns[i].length() > 0) { // only add the item if there's this
// category
JLabel synTypeLabel = new JLabel(synTypes[i], JLabel.TRAILING);
synTypeLabel.setVerticalAlignment(JLabel.TOP);
synonymPanel.add(synTypeLabel);
JLabel synList = new JLabel();
synList.setText("<html>"+syns[i]+"</html>");
synTypeLabel.setLabelFor(synList);
synonymPanel.add(synList);
rowCount++;
// SpringLayout layout = new SpringLayout();
// // line up the rel type with the items
// layout.putConstraint(SpringLayout.NORTH, synTypeLabel, 5,
// SpringLayout.NORTH, synonymPanel);
// layout.putConstraint(SpringLayout.NORTH, synList, 5,
// SpringLayout.NORTH, synonymPanel);
// synonymPanel.setLayout(layout);
}
}
// Lay out the panel.
SpringUtilities.makeCompactGrid(synonymPanel, rowCount, 2, // rows,
// cols
INITX, INITY, // initX, initY
XPAD, YPAD); // xPad, yPad
int[] maxX = {PREFERREDX,-1};
int[] maxY = null;
SpringUtilities.fixCellWidth(synonymPanel, rowCount, 2, // rows,
// cols
INITX, INITY, // initX, initY
XPAD, YPAD, // xPad, yPad
maxX, maxY);
synonymPanel.setVisible(true);
}
private void clearAnnotations() {
annotationPanel.removeAll();
termInfoPanel.getComponent(16).setVisible(false);
annotationPanel.validate();
annotationPanel.repaint();
}
private void makeAnnotationPanel(Collection<Annotation> annots) {
int rowCount = 0;
annotationPanel.removeAll(); // clear out the old ones
annotationPanel.setBorder(contentBorder);
annotationPanel.setOpaque(false);
annotationPanel.setBackground(Color.WHITE);
for (Annotation annot : annots) {
LinkedObject ae = annot.getSubject();
if (ae == null) {
LOG.error("no subject for "+annot);
continue;
}
LinkedObject annotatedTo = annot.getObject();
if (annotatedTo == null) {
LOG.error("no object for "+annot);
continue;
}
JLabel aeLabel = new JLabel(ae.getID());
// aeLabel.setToolTipText("Name: "+ae.getName()+"\n"+"Annotated to: "+annotatedTo);
// annotationPanel.add(getObjHrefLabel(annotatedTo));
annotationPanel.add(new JLabel("")); // TODO: show blank until we prettify the subj
annotationPanel.add(aeLabel);
rowCount++;
SpringLayout layout = new SpringLayout();
// layout.putConstraint(SpringLayout.NORTH, aeLabel, 5,
// SpringLayout.NORTH, annotationPanel);
annotationPanel.setLayout(layout);
}
// Lay out the panel.
SpringUtilities.makeCompactGrid(annotationPanel, rowCount, 2, // rows,
// cols
INITX, INITY, // initX, initY
XPAD, YPAD); // xPad, yPad
int[] maxX = {PREFERREDX,-1};
int[] maxY = null;
SpringUtilities.fixCellWidth(annotationPanel, rowCount, 2, // rows,
// cols
INITX, INITY, // initX, initY
XPAD, YPAD, // xPad, yPad
maxX, maxY);
// annotationPanel.setVisible(true);
annotationPanel.validate();
annotationPanel.repaint();
}
private void makeDbxrefPanel(Set<Dbxref> someSet) {
int rowCount = 0;
String tempID;
OBOObject tempOboClass = null;
String panelText = "<html>";
Dbxref dbxrefObj;
dbxrefPanel.removeAll(); // clear out the old ones
for (Iterator<Dbxref> it = someSet.iterator(); it.hasNext();) {
dbxrefObj = it.next();
if (dbxrefObj != null) {
// will make this linkable - internal & external
// eventually, get smart and enable adding ontology!
tempID = dbxrefObj.getDatabase() + ":" + dbxrefObj.getDatabaseID();
// check if the term is in the current obosession
final IdentifiedObject obj = this.getOBOSession().getObject(tempID);
if (obj instanceof OBOClass) { tempOboClass = (OBOClass)obj; }
if (tempOboClass != null) {
panelText+= "<a href='" + tempOboClass.getID() + "'>" + tempOboClass.getName();
} else {
panelText += tempID; // just use the ID for external refs
}
// dbxrefPanel.add(dbxrefItem);
rowCount++;
}
if (it.hasNext()) {
panelText += "<br>";
}
}
HyperlinkLabel textArea = new HyperlinkLabel();
termHyperlinkListener = new TermHyperlinkListener();
textArea.addStringLinkListener(termHyperlinkListener);
panelText += "</html>";
textArea.setText(panelText);
dbxrefPanel.add(textArea);
// Lay out the panel.
if (rowCount > 0) {
SpringUtilities.makeCompactGrid(dbxrefPanel, 1, 1, // rows, cols
INITX+10, INITY, // initX, initY
XPAD, YPAD); // xPad, yPad
}
dbxrefPanel.validate();
dbxrefPanel.repaint();
dbxrefPanel.setVisible(true);
}
/**
* Given a collection of links, a {@link JPanel} is return to the implementing
* class that contains a set of hyperlinks that will trigger refresh to that
* new term.
* <p>
*
* @param links
* a collection of oboclass links to display in a panel
* @param isXP
* flag to indicate if panel is to display cross-products or regular
* links
* @param isChild
* flag indicating if a panel displays parent or child links. This
* may be important in the future for display purposes.
* @param panel
* The panel into which the links will be placed.
* @return the number of links created
*/
private int makeLinksPanel(Collection<Link> links, boolean isXP,
boolean isChild, JPanel panel) {
// would be best to sort these into alpha order
IdentifiedObject temp;
panel.removeAll();
List<List<Link>> allLinks = linksList(links, isXP, isChild);
JLabel linkLabel;
JLabel typeLabel;
panel.setBorder(contentBorder);
panel.setOpaque(false);
panel.setBackground(Color.WHITE);
int rowCount = 0;
int itemCount = 0;
int totalItems = 0;
String panelText = "";
if (isChild) {
linkLabel = new JLabel("<html><b>Children</b></html>");
} else {
linkLabel = new JLabel("<html><b>Parents</b></html>");
}
if (!isXP) { //only add the parent/child heading if not cross-products
panel.add(new JLabel("")); //blank column for spring layout
panel.add(linkLabel);
rowCount+=1;
}
for (ListIterator<List<Link>> lit = allLinks.listIterator(); lit
.hasNext();) {
// group by each relationship type
List<Link> listOfLinks = lit.next();
// the elements should be sorted in alpha order
panelText = "<html>"; // reset the text
itemCount = 0;
for (Iterator<Link> it = listOfLinks.iterator(); it.hasNext();) {
// create all the clickable links first
Link link = (Link) it.next();
if (isChild) {
temp = (IdentifiedObject) link.getChild();
} else {
temp = (IdentifiedObject) link.getParent();
}
if (TermUtil.isClass(temp)) { // only show actual classes...not danglers
// only put in items that are not xps
if (TermUtil.isIntersection((OBOObject) temp)) // {
panelText += "<i>";
panelText += "<a href='" + temp.getID() + "'>" + temp.getName()
+ "</a>";
if (TermUtil.isIntersection((OBOObject) temp)) // {
panelText += "</i>";
if (it.hasNext()) {
panelText += ", ";
}
itemCount++;
// }
} else if (TermUtil.isDangling(temp)) {
if (!TermUtil.isIntersection((DanglingObject) temp)) {
panelText += temp.getName(); // dangling objects don't have links
// eventually want to be smart and allow user to import the
// necessary ontology to resolve danglers!
if (it.hasNext()) {
panelText += ", ";
}
itemCount++;
}
}
}
if (itemCount > 0) {
// if there's at least one item, add the section to the pane
panelText += "</html>";
final String linkName = listOfLinks.isEmpty() ? "" : listOfLinks.get(0).getType().getName();
String tempType = "<html><p align=right>"+linkName+"</p></html>";
typeLabel = new JLabel(tempType, JLabel.TRAILING);
typeLabel.setVerticalAlignment(JLabel.TOP);
panel.add(typeLabel);
HyperlinkLabel textArea = new HyperlinkLabel(panelText);
termHyperlinkListener = new TermHyperlinkListener();
textArea.addStringLinkListener(termHyperlinkListener);
typeLabel.setLabelFor(textArea);
panel.add(textArea);
rowCount++;
}
totalItems += itemCount;
}
if (rowCount > 0) { //first row is the header
SpringUtilities.makeCompactGrid(panel, rowCount, 2, // rows, cols
INITX, INITY, // initX, initY
XPAD, YPAD); // xPad, yPad
int[] maxX = {PREFERREDX,-1};
int[] maxY = null;
SpringUtilities.fixCellWidth(panel, rowCount, 2, // rows,
// cols
INITX, INITY, // initX, initY
XPAD, YPAD, // xPad, yPad
maxX, maxY);
panel.setVisible(true);
} else {
panel.setVisible(false); //hide the parents/children panel if empty
}
panel.validate();
panel.repaint();
return totalItems;
}
/**
* Given a collection of oboclass links, this processes the collection to
* separate out the links and group by relationship type+parent/child xp state
* It will always put the is_a links in the list first.
*
* @param links
* a collection of oboclass links
* @param xp
* specifies if the request is for cross-product-specific list
* @param isChild
* specifies if the links are parents or children of the implementing
* class
* @return a list of links sorted by relationship type.
*
*/
private static List<List<Link>> linksList(Collection<Link> links, boolean xp, boolean isChild) {
HashSet<OBOProperty> relSet = new HashSet<OBOProperty>();
List<List<Link>> allLinks = new ArrayList<List<Link>>();
for (Iterator<Link> it = links.iterator(); it.hasNext();) {
Link link = (Link) it.next();
if (((OBORestriction) link).getCompletes() == xp) {
// only add to links list those that match the desired xp state
OBOProperty type = link.getType();
if (!relSet.contains(type)) {
relSet.add(type);
List<Link> linkSet = new ArrayList<Link>();
linkSet.add(link);
if (type.equals(OBOProperty.IS_A))
allLinks.add(0, linkSet);
else
allLinks.add(linkSet);
} else {
for (ListIterator<List<Link>> lit = allLinks.listIterator(); lit.hasNext();) {
List<Link> temp = lit.next();
if (temp.get(0).getType() == type) {
temp.add(link);
allLinks.set(lit.nextIndex() - 1, temp);
}
}
}
}
}
return allLinks;
}
/**
* Given a set of "Consider" and "Replaced-by" links, navigable links are
* created in a panel.
*
* @param oboClass
* the item that is obsoleted
* @param panel
* the panel to populate with this information
*/
private void makeObsPanel(OBOObject oboClass) {
// to display the replaced-bys and consider term links for obsoleted
// terms
// need to make this its own panel so i can hide/show it as well as
// make it easier to create the hyperlinks. will do this similar to
// synonyms.
// if this is its own stacked box, maybe ought to make the bar a
// different
// color, like red or something
// really should compact this whole thing into a for-loop
considerReplacePanel.removeAll();
String panelText = "";
Set<ObsoletableObject> obsItems;
int rowCount = 0;
JLabel typeLabel;
boolean replaceFlag = false;
boolean considerFlag = false;
ObsoletableObject obsObj;
for (int i = 0; i < 2; i++) { // do this 2x, once for each Obs type
if (i == 0) {
obsItems = oboClass.getReplacedBy();
replaceFlag = !obsItems.isEmpty();
typeLabel = new JLabel("Replaced by: ");
} else {
obsItems = oboClass.getConsiderReplacements();
considerFlag = !obsItems.isEmpty();
typeLabel = new JLabel("Consider using: ");
}
// JEditorPane.registerEditorKitForContentType
// ("text/html", "HTMLEditorKit2");
// JEditorPane textArea = new JEditorPane();
// textArea.setEditorKitForContentType
// ("text/html", new HTMLEditorKit2());
//
// textArea.setContentType("text/html");
HyperlinkLabel textArea = new HyperlinkLabel();
termHyperlinkListener = new TermHyperlinkListener();
textArea.addStringLinkListener(termHyperlinkListener);
// textArea.setEditable(false);
for (Iterator<ObsoletableObject> it = obsItems.iterator(); it.hasNext();) {
obsObj = it.next();
if (obsObj != null) {
panelText += "<a href='" + obsObj.getID() + "'>" + obsObj.getName();
}
if (it.hasNext()) {
panelText += ", ";
}
}
if (!obsItems.isEmpty()) {
rowCount++;
typeLabel.setLabelFor(textArea);
textArea.setText(panelText);
textArea.validate();
considerReplacePanel.add(typeLabel);
considerReplacePanel.add(textArea);
}
}
if (rowCount < 1) // no items, hide
{
considerReplacePanel.setVisible(false);
} else {
SpringUtilities.makeCompactGrid(considerReplacePanel, rowCount, 2, // rows,
// cols
INITX, INITY, // initX, initY
XPAD, YPAD); // xPad, yPad
int[] maxX = {PREFERREDX,-1};
int[] maxY = null;
SpringUtilities.fixCellWidth(considerReplacePanel, rowCount, 2, // rows,
// cols
INITX, INITY, // initX, initY
XPAD, YPAD, // xPad, yPad
maxX, maxY);
considerReplacePanel.validate();
considerReplacePanel.setVisible(true);
}
}
private int makePropValsPanel(Set<PropertyValue> propertyValues) {
int rowCount = 0;
JLabel propLabel;
JLabel valLabel;
PropertyValue propVal;
String name="";
String value="";
propertyValuesPanel.removeAll();
//right now property values on terms are stored as tag value where the tag
//is property_value, and the value is the tag+value. these need to be
//split
for (Iterator<PropertyValue> it = propertyValues.iterator(); it.hasNext();) {
propVal = it.next();
LOG.trace("prop val "+propVal+" prop "+propVal.getProperty());
if (propVal != null) {
if (propVal.getProperty().equals("property_value")) {
LOG.trace("prop val ok");
/*
* property_value: married_to heather
* property_value: shoe_size "8" xsd:positiveInteger
*
* these go into propertyValSet
*/
// int quoteIndex = findUnescaped(propVal.getValue(), '"', 0, propVal.getValue().length());
int quoteIndex = -1;
if (quoteIndex == -1) {
/* no quotes:
* this means we have a pv of the following form:
* property_value: eats id:1234
*
* ie linking two instanes
*/
StringTokenizer tokenizer = new StringTokenizer(propVal.getValue());
List<String> tokens = new ArrayList<String>();
while (tokenizer.hasMoreTokens()) {
tokens.add(tokenizer.nextToken());
}
name = (String)tokens.get(0);
value = (String)tokens.get(1);
} else {
// /* quotes:
// * this means we have a pv of the following form:
// * property_value: shoe_size "8" xsd:positiveInteger
// *
// * ie linking an instance with a property value
// */
// SOPair p = unescape(value, '"', quoteIndex + 1, value
// .length(), true);
// String propID = value.substring(0, quoteIndex).trim();
// String optional = value.substring(p.index + 1,
// value.length()).trim();
//testing to see if in someproperty: value
}
} else {
name = propVal.getProperty();
value = propVal.getValue();
}
propLabel = new JLabel("<html>"+name+"</html>");
propLabel.validate();
valLabel = new JLabel("<html>"+value+"</html>");
valLabel.validate();
propLabel.setLabelFor(valLabel);
propLabel.setVerticalAlignment(JLabel.TOP);
propertyValuesPanel.add(propLabel);
propertyValuesPanel.add(valLabel);
rowCount++;
}
}
if (rowCount > 0) {
SpringUtilities.makeCompactGrid(propertyValuesPanel, rowCount, 2, // rows,
// cols
INITX, INITY, // initX, initY
XPAD, YPAD); // xPad, yPad
int[] maxX = {PREFERREDX,-1};
int[] maxY = null;
SpringUtilities.fixCellWidth(propertyValuesPanel, rowCount, 2, // rows,
// cols
INITX, INITY, // initX, initY
XPAD, YPAD, // xPad, yPad
maxX, maxY);
propertyValuesPanel.validate();
propertyValuesPanel.repaint();
propertyValuesPanel.setVisible(true);
} else {
propertyValuesPanel.removeAll();
propertyValuesPanel.setVisible(false);
}
LOG.trace("rows= "+ rowCount);
return rowCount;
}
public void naviRefresh(String action) {
int tot = termInfoNaviHistory.size();
if (action.equals("back")) {
if (naviIndex > 0) {
naviIndex--;
}
} else if (action.equals("forward")) {
if (naviIndex < (tot - 1)) {
naviIndex++;
}
}
String id = getTermFromNaviHistory(naviIndex);
final IdentifiedObject obj = this.getOBOSession().getObject(id);
OBOObject term = (obj instanceof OBOObject) ? (OBOObject)obj : null;
setTextFromOboClass(term);
// send out term selection (non mouse over) for DAG view
// this.selectionManager.selectTerm(this, term, true);
// Since items are added in reverse order, "back" is actually
// forward
// termComboBox.setSelectedIndex(termComboBox.getSelectedIndex()+1);
}
// for testing
String getTermNameText() {
return termName == null ? null : termName.getText();
}
public String getObjHref(LinkedObject obj) {
return
"<html><a href='" + obj.getID() + "'>" + obj.getName() + "</a></html>";
}
public HyperlinkLabel getObjHrefLabel(LinkedObject obj) {
HyperlinkLabel textArea = new HyperlinkLabel();
termHyperlinkListener = new TermHyperlinkListener();
textArea.addStringLinkListener(termHyperlinkListener);
textArea.setText(getObjHref(obj));
return textArea;
}
/** for testing */
void simulateHyperlinkEvent(HyperlinkEvent e) {
termHyperlinkListener.hyperlinkUpdate(e);
}
public List<String> getTermInfoNaviHistory() {
return termInfoNaviHistory;
}
public int getNaviIndex() {
return naviIndex;
}
public void setNaviIndex(int index) {
naviIndex = index;
}
class HTMLEditorKit2 extends HTMLEditorKit {
@Override
public Document createDefaultDocument() {
HTMLDocument doc = (HTMLDocument) (super.createDefaultDocument());
doc.setAsynchronousLoadPriority(-1); // load synchronously
return doc;
}
}
public void setShowEmptyPanelsFlag (boolean flag) {
showEmptyPanelsFlag = flag;
}
public boolean getShowEmptyPanelsFlag () {
return showEmptyPanelsFlag;
}
private boolean isPhenoteLink(HyperlinkEvent e) {
return e.getURL() == null && e.getDescription().startsWith(PHENOTE_LINK_PREFIX);
}
/** extracts id from link, returns null if fails */
private String getIdFromHyperlink(HyperlinkEvent e) {
String desc = e.getDescription();
if (desc == null || desc.equals("")) return null;
String id = getIdFromHyperlinkDesc(desc);
return id;
}
/** extract id from hyperlink description string */
private String getIdFromHyperlinkDesc(String desc) {
return desc.substring(PHENOTE_LINK_PREFIX.length());
}
/** To drag main term (not yet parents/kids) from term info to fields
subcalss SelectionTransferHandler, or just use straight up? */
private class InfoTransferHandler extends TransferHandler {
/** does a copy operation */
@Override
public int getSourceActions(JComponent c) {
return COPY;
}
}
/** attempting to model oboedit selection to use for drag & drop of terms from term
info to fields to mimic whats already done between graph and fields */
private class InfoSelector implements ObjectSelector {
@Override
public void select(Selection selection) {}
/**
* Most object selectors will just use this method as a delegate to
* {@link #getSelection()}. This method should be overridden if a special
* selection should be used for right-clicks, drags, etc based on mouse position
*/
@Override
public Selection getSelection(MouseEvent e) { return null; }
@Override
public Selection getSelection() { return null; }
@Override
public LinkDatabase getLinkDatabase() { return null; }
@Override
public RootAlgorithm getRootAlgorithm() { return null; }
@Override
public void setLive(boolean isLive) {}
@Override
public boolean isLive() { return false; }
@Override
public void addSelectionListener(SelectionListener listener) {}
@Override
public void removeSelectionListener(SelectionListener listener) {}
@Override
public boolean hasCombinedTermsAndLinks() { return false; }
@Override
public void addExpansionListener(ExpandCollapseListener listener) {}
@Override
public void removeExpansionListener(ExpandCollapseListener listener) {}
@Override
public Collection<PathCapable> getVisibleObjects() { return null; }
}
}
// /** use term listener comes from selection events, and it listens for useTerm
// events, this is how UseTerm button sets terms in char field guis.
// I think this should ignore setting to null, which right now is what
// happens from normal select events (as opposed to mouse over events)
// actually i think this isnt used anymore and should be taken out
// replaced by term info toolbar.setUseTermListener */
// private void setUseTermListener(UseTermListener utl) {
// // ignore null useTermListeners??, this means keep using one set previous
// LOG.debug("setting use term "+utl);
// if (utl == null) return;
// useTermListener = utl;
// }