package org.phenoscape.view; import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.border.TitledBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.obo.annotation.base.OBOUtil; import org.obo.annotation.base.OBOUtil.Differentium; import org.obo.datamodel.LinkedObject; import org.obo.datamodel.OBOClass; import org.obo.datamodel.OBOProperty; import org.obo.util.TermUtil; import org.oboedit.controller.SelectionManager; import org.phenoscape.controller.PhenexController; import org.phenoscape.model.Phenotype; import org.phenoscape.model.PhenotypeProposal; import org.phenoscape.model.PhenotypeProposal.ResolvedStatus; import org.phenoscape.model.State; import ca.odell.glazedlists.EventList; public class PhenotypeProposalComponent extends PhenoscapeGUIComponent { private TermPanel entityPanel = new TermPanel(); private TermPanel entityLocatorPanel = new TermPanel(); private TermPanel qualityPanel = new TermPanel(); private TermPanel relatedEntityPanel = new TermPanel(); private JPanel phenotypePanel; public PhenotypeProposalComponent(String id, PhenexController controller) { super(id, controller); } @Override public void init() { super.init(); this.initializeInterface(); } private void initializeInterface() { this.getController().getCurrentStatesSelectionModel().addListSelectionListener(new StateSelectionListener()); this.setLayout(new GridBagLayout()); final GridBagConstraints constraints = new GridBagConstraints(); constraints.fill = GridBagConstraints.BOTH; constraints.weightx = 1; constraints.weighty = 1; constraints.gridy = 0; constraints.gridx = 0; constraints.gridwidth = 3; this.phenotypePanel = new JPanel(new GridBagLayout()); phenotypePanel.setBorder(BorderFactory.createTitledBorder("Proposed Phenotype")); this.updatePanelColorAndTitle(); this.add(phenotypePanel, constraints); final JButton rejectButton = new JButton(new AbstractAction("Reject Phenotype") { @Override public void actionPerformed(ActionEvent event) { rejectProposal(); } }); constraints.anchor = GridBagConstraints.EAST; constraints.gridwidth = 1; constraints.weightx = 0; constraints.weighty = 0; constraints.gridy = 1; constraints.gridx = 1; constraints.fill = GridBagConstraints.NONE; this.add(rejectButton, constraints); final JButton acceptButton = new JButton(new AbstractAction("Accept and Edit Phenotype") { @Override public void actionPerformed(ActionEvent event) { createAndAddPhenotype(); acceptProposal(); } }); constraints.gridx = 2; this.add(acceptButton, constraints); final GridBagConstraints phenotypeConstraints = new GridBagConstraints(); phenotypeConstraints.gridx = 0; phenotypeConstraints.gridy = 0; phenotypeConstraints.anchor = GridBagConstraints.EAST; phenotypePanel.add(new JLabel("Entity:"), phenotypeConstraints); phenotypeConstraints.gridy += 1; phenotypePanel.add(new JLabel("Entity Locator:"), phenotypeConstraints); phenotypeConstraints.gridy += 1; phenotypePanel.add(new JLabel("Quality:"), phenotypeConstraints); phenotypeConstraints.gridy += 1; phenotypePanel.add(new JLabel("Related Entity:"), phenotypeConstraints); phenotypeConstraints.anchor = GridBagConstraints.CENTER; phenotypeConstraints.fill = GridBagConstraints.HORIZONTAL; phenotypeConstraints.weightx = 1; phenotypeConstraints.gridy = 0; phenotypeConstraints.gridx = 1; phenotypeConstraints.gridy = 0; phenotypePanel.add(entityPanel, phenotypeConstraints); phenotypeConstraints.gridy += 1; phenotypePanel.add(entityLocatorPanel, phenotypeConstraints); phenotypeConstraints.gridy += 1; phenotypePanel.add(qualityPanel, phenotypeConstraints); phenotypeConstraints.gridy += 1; phenotypePanel.add(relatedEntityPanel, phenotypeConstraints); } private State getSelectedState() { final EventList<State> selected = this.getController().getCurrentStatesSelectionModel().getSelected(); if (selected.size() == 1) { return selected.get(0); } else { return null; } } private void stateSelectionDidChange() { this.updatePanelColorAndTitle(); final String unselectedTitle = "Phenotypes"; final String selectedPrefix = "Phenotype Proposal for State: "; final State state = this.getSelectedState(); if (state == null) { this.updatePanelTitle(unselectedTitle); } else { this.updatePanelTitle(selectedPrefix + state); this.clearFields(); final PhenotypeProposal proposal = state.getProposal(); if (proposal != null) { this.entityPanel.setTerms(proposal.getEntities()); this.entityLocatorPanel.setTerms(proposal.getEntityLocators()); this.qualityPanel.setTerms(proposal.getProcessedQualities(this.getController().getOntologyController().getOBOSession())); this.relatedEntityPanel.setTerms(proposal.getQualityModifiers()); SelectionManager.selectTerms(this, this.collectTerms(proposal)); } } } private Set<LinkedObject> collectTerms(PhenotypeProposal proposal) { final Set<LinkedObject> terms = new HashSet<LinkedObject>(); terms.addAll(proposal.getEntities()); terms.addAll(proposal.getEntityLocators()); terms.addAll(proposal.getQualities()); terms.addAll(proposal.getQualityModifiers()); if (proposal.getNegatedQualityParent() != null) { terms.add(proposal.getNegatedQualityParent()); } final Set<LinkedObject> parents = new HashSet<LinkedObject>(); for (LinkedObject term : terms) { parents.addAll(TermUtil.getParents(term, false, null)); } terms.addAll(parents); return terms; } private void createAndAddPhenotype() { final State state = this.getSelectedState(); if (state != null) { final Phenotype phenotype = new Phenotype(); final OBOClass entity = this.entityPanel.getSelectedTerm(); final OBOClass entityLocator = this.entityLocatorPanel.getSelectedTerm(); if (entity != null && entityLocator != null) { final Differentium diff = new Differentium(); diff.setRelation((OBOProperty)(this.getController().getOntologyController().getOBOSession().getObject("OBO_REL:part_of"))); diff.setTerm(entityLocator); final OBOClass composition = OBOUtil.createPostComposition(entity, Collections.singletonList(diff)); phenotype.setEntity(composition); } else if (entity != null) { phenotype.setEntity(entity); } else{ phenotype.setEntity(entityLocator); } phenotype.setQuality(this.qualityPanel.getSelectedTerm()); phenotype.setRelatedEntity(this.relatedEntityPanel.getSelectedTerm()); if (phenotype.getEntity() != null || phenotype.getQuality() != null || phenotype.getRelatedEntity() != null) { state.addPhenotype(phenotype); } } } private void updatePanelColorAndTitle() { if (this.phenotypePanel != null) { final TitledBorder border = (TitledBorder)(this.phenotypePanel.getBorder()); final State state = this.getSelectedState(); if (state != null && state.getProposal() != null) { final PhenotypeProposal proposal = state.getProposal(); log().debug("Setting title color"); switch (proposal.getStatus()) { case PROPOSED: border.setTitleColor(Color.BLUE); border.setTitle("Proposed Phenotype"); break; case ACCEPTED: border.setTitleColor(Color.GREEN); border.setTitle("Proposed Phenotype - accepted"); break; case REJECTED: border.setTitleColor(Color.RED); border.setTitle("Proposed Phenotype - rejected"); break; } } else { border.setTitle("No Proposed Phenotype"); border.setTitleColor(Color.BLACK); } this.phenotypePanel.repaint(); } } private void acceptProposal() { this.getSelectedState().getProposal().setStatus(ResolvedStatus.ACCEPTED); this.updatePanelColorAndTitle(); } private void rejectProposal() { this.getSelectedState().getProposal().setStatus(ResolvedStatus.REJECTED); this.updatePanelColorAndTitle(); } private void clearFields() { this.entityPanel.setTerms(Collections.<OBOClass>emptyList()); this.entityLocatorPanel.setTerms(Collections.<OBOClass>emptyList()); this.qualityPanel.setTerms(Collections.<OBOClass>emptyList()); this.relatedEntityPanel.setTerms(Collections.<OBOClass>emptyList()); } private class StateSelectionListener implements ListSelectionListener { public StateSelectionListener() { stateSelectionDidChange(); } @Override public void valueChanged(ListSelectionEvent e) { stateSelectionDidChange(); } } private static class TermPanel extends JPanel { private JComponent termComponent; private List<OBOClass> terms; public TermPanel() { this.setLayout(new BorderLayout()); this.setTerms(Collections.<OBOClass>emptyList()); } public void setTerms(List<OBOClass> terms) { this.terms = terms; this.removeAll(); this.termComponent = null; if (this.terms.size() > 1) { this.termComponent = new JComboBox(this.terms.toArray()); } else if (terms.size() == 1) { final JTextField field = new JTextField(terms.get(0).getName()); this.termComponent = field; field.setEditable(false); } else { final JTextField field = new JTextField(); this.termComponent = field; field.setEditable(false); field.setEnabled(false); } this.add(termComponent, BorderLayout.CENTER); } public OBOClass getSelectedTerm() { if (this.terms.size() > 1) { return (OBOClass)(((JComboBox)this.termComponent).getSelectedItem()); } else if (this.terms.size() == 1) { return this.terms.get(0); } else { return null; } } } }