/*
* #%L
* gitools-ui-app
* %%
* Copyright (C) 2013 Universitat Pompeu Fabra - Biomedical Genomics group
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package org.gitools.ui.core.pages.common;
import org.gitools.api.ApplicationContext;
import org.gitools.api.resource.ResourceReference;
import org.gitools.heatmap.HeatmapDimension;
import org.gitools.heatmap.header.HeatmapHeader;
import org.gitools.heatmap.header.HeatmapTextLabelsHeader;
import org.gitools.matrix.format.AnnotationMatrixFormat;
import org.gitools.matrix.model.matrix.AnnotationMatrix;
import org.gitools.persistence.locators.UrlResourceLocator;
import org.gitools.ui.core.utils.DocumentChangeListener;
import org.gitools.ui.core.utils.FileChooserUtils;
import org.gitools.ui.core.utils.LogUtils;
import org.gitools.ui.platform.IconUtils;
import org.gitools.ui.platform.icons.IconNames;
import org.gitools.ui.platform.settings.Settings;
import org.gitools.ui.platform.wizard.AbstractWizardPage;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class PatternSourcePage extends AbstractWizardPage {
private HeatmapDimension hdim;
private boolean idOptVisible;
private boolean viewOnlyMode;
private List<AnnotationOption> annotationOptions;
public PatternSourcePage(boolean idOptVisible) {
this(null, idOptVisible, false);
}
public PatternSourcePage(HeatmapDimension hdim) {
this(hdim, true, false);
}
public PatternSourcePage(HeatmapDimension hdim, boolean idAsOption) {
this(hdim, idAsOption, false);
}
public PatternSourcePage(HeatmapDimension hdim, boolean idAsOption, boolean viewOnlyMode) {
this.hdim = hdim;
this.idOptVisible = idAsOption;
this.viewOnlyMode = viewOnlyMode;
setLogo(IconUtils.getImageIconResourceScaledByHeight(IconNames.annotation512, 96));
initComponents();
ChangeListener optListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
sourceChanged();
}
};
if (!viewOnlyMode) {
idOpt.addChangeListener(optListener);
annOpt.addChangeListener(optListener);
patOpt.addChangeListener(optListener);
} else {
idOpt.setVisible(false);
idOpt.setEnabled(false);
patOpt.setVisible(false);
patOpt.setEnabled(false);
}
annSepCb.setModel(new DefaultComboBoxModel(new String[]{",", "-", " | ", " / ", " > ", "::"}));
annSepCb.setSelectedIndex(0);
annList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
annListChanged();
}
});
patText.getDocument().addDocumentListener(new DocumentChangeListener() {
@Override
protected void update(DocumentEvent e) {
updateComplete();
}
});
setTitle("Annotations selection");
setComplete(true);
}
class FilterCellRenderer extends DefaultListCellRenderer {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
AnnotationOption annOpt = (AnnotationOption) value;
String needle = annotationSearchField.getText().toLowerCase();
boolean match;
match = annotationSearchField.getText().isEmpty();
if (!match) {
match = annOpt.getKey().toLowerCase().contains(needle) |
annOpt.getDescription().toLowerCase().contains(needle);
}
if (match) {// <= put your logic here
c.setFont(c.getFont().deriveFont(Font.ITALIC, 14.0f));
c.setForeground(Color.BLACK);
} else {
c.setFont(c.getFont().deriveFont(Font.ITALIC, 9.0f));
c.setForeground(Color.LIGHT_GRAY);
}
return c;
}
}
@Override
public void updateControls() {
super.updateControls();
if (hdim != null && hdim.getAnnotations() != null && !hdim.getAnnotations().getLabels().isEmpty()) {
annOpt.setSelected(true);
annOpt.setEnabled(true);
DefaultListModel<AnnotationOption> model = new DefaultListModel<>();
FilterCellRenderer cellRenderer = new FilterCellRenderer();
if (idOptVisible) {
model.addElement(new AnnotationOption("id"));
}
annotationOptions = new ArrayList<>(hdim.getAnnotations().getLabels().size());
for (String key : hdim.getAnnotations().getLabels()) {
String description = hdim.getAnnotations().getAnnotationMetadata("description", key);
annotationOptions.add(new AnnotationOption(key, description));
}
Collections.sort(annotationOptions, new Comparator<AnnotationOption>() {
@Override
public int compare(AnnotationOption o1, AnnotationOption o2) {
return o1.toString().toUpperCase().compareTo(o2.toString().toUpperCase());
}
});
for (AnnotationOption annotationOption : annotationOptions) {
model.addElement(annotationOption);
}
annList.setModel(model);
annList.setSelectedIndex(0);
annList.setCellRenderer(cellRenderer);
} else {
if (idOptVisible) {
idOpt.setSelected(true);
} else {
patOpt.setSelected(true);
}
annOpt.setEnabled(false);
}
}
private void removeSelecedAnnotations() {
String inUse = "id";
for (HeatmapHeader hh : hdim.getHeaders()) {
inUse = inUse + ", " + hh.getAnnotationPattern();
}
for (Object option : annList.getSelectedValuesList()) {
String label = ((AnnotationOption) option).getKey();
if (!inUse.contains(label)) {
hdim.getAnnotations().removeAnnotations(label);
}
}
updateControls();
annList.setSelectedIndices(new int[0]);
}
public void setAnnSeparationModel(String[] strings) {
annSepCb.setModel(new DefaultComboBoxModel(strings));
annSepCb.setSelectedIndex(0);
}
private void updateComplete() {
setComplete(annOpt.isSelected() && annList.getSelectedIndices().length > 0 || patOpt.isSelected() && patText.getDocument().getLength() > 0);
}
private void sourceChanged() {
boolean annSel = annOpt.isSelected();
annList.setEnabled(annSel);
annSepLabel.setEnabled(annSel);
annSepCb.setEnabled(annSel);
patText.setEnabled(patOpt.isSelected());
}
private void annListChanged() {
patText.setText(getPattern());
updateComplete();
}
public String getPattern() {
if (idOpt.isSelected()) {
return "${id}";
} else if (patOpt.isSelected()) {
return patText.getText();
}
StringBuilder sb = new StringBuilder();
String[] values = getSelectedValues();
if (values.length == 0) {
return "";
}
sb.append("${");
sb.append(values[0]);
sb.append("}");
for (int i = 1; i < values.length; i++) {
sb.append(annSepCb.getSelectedItem());
sb.append("${");
sb.append(values[i]);
sb.append("}");
}
return sb.toString();
}
public String getPatternTitle() {
if (idOpt.isSelected()) {
return "id";
} else if (patOpt.isSelected()) {
return patText.getText();
}
StringBuilder sb = new StringBuilder();
String[] values = getSelectedValues();
sb.append(values[0]);
for (int i = 1; i < values.length; i++) {
sb.append(annSepCb.getSelectedItem());
sb.append(values[i]);
}
return sb.toString();
}
public String[] getSelectedValues() {
int[] indices = annList.getSelectedIndices();
String[] values = new String[indices.length];
for (int i = 0; i < indices.length; i++) {
int index = indices[i];
if (index == 0) {
values[i] = "id";
} else {
values[i] = annotationOptions.get(index - 1).getKey();
}
}
return values;
}
public void setHeatmapDimension(HeatmapDimension heatmapDimension) {
this.hdim = heatmapDimension;
updateControls();
}
public boolean isIdOptVisible() {
return idOptVisible;
}
public void setIdOptVisible(boolean idOptVisible) {
this.idOptVisible = idOptVisible;
idOpt.setVisible(idOptVisible);
invalidate();
}
private void filterAnnotationsBox(KeyEvent evt) {
annList.repaint();
}
public HeatmapTextLabelsHeader.LabelSource getLabelSource() {
if (idOpt.isSelected()) {
return HeatmapTextLabelsHeader.LabelSource.ID;
} else if (annOpt.isSelected()) {
if (annList.getSelectedIndex() == 0) {
return HeatmapTextLabelsHeader.LabelSource.ID;
} else {
return HeatmapTextLabelsHeader.LabelSource.PATTERN;
}
} else if (patOpt.isSelected()) {
return HeatmapTextLabelsHeader.LabelSource.PATTERN;
}
return HeatmapTextLabelsHeader.LabelSource.ID;
}
public String getAnnotationName() {
if (annList.getSelectedIndex() > 0) {
return annotationOptions.get(annList.getSelectedIndex() - 1).getKey();
} else {
return "";
}
}
/**
* This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
optGroup = new javax.swing.ButtonGroup();
annOpt = new javax.swing.JRadioButton();
jScrollPane1 = new javax.swing.JScrollPane();
annList = new javax.swing.JList();
patOpt = new javax.swing.JRadioButton();
patText = new javax.swing.JTextField();
jLabel1 = new javax.swing.JLabel();
annSepLabel = new javax.swing.JLabel();
annSepCb = new javax.swing.JComboBox();
idOpt = new javax.swing.JRadioButton();
loadAnnotations = new javax.swing.JButton();
annotationSearchField = new javax.swing.JTextField();
jLabel2 = new javax.swing.JLabel();
removeSelected = new javax.swing.JButton();
optGroup.add(annOpt);
annOpt.setText("Annotations");
jScrollPane1.setViewportView(annList);
optGroup.add(patOpt);
patOpt.setText("Pattern");
patText.setText("${id}");
jLabel1.setFont(jLabel1.getFont().deriveFont(jLabel1.getFont().getSize() - 2f));
jLabel1.setText("Press Ctrl key to select for multiple annotations");
annSepLabel.setText("Separator");
annSepCb.setEditable(true);
optGroup.add(idOpt);
idOpt.setText("Identifiers");
loadAnnotations.setText("Load from file");
loadAnnotations.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
loadAnnotationsActionPerformed(evt);
}
});
annotationSearchField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
annotationSearchFieldKeyReleased(evt);
}
});
jLabel2.setText("Filter:");
removeSelected.setText("remove Selected");
removeSelected.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
removeSelectedActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(24, 24, 24)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(annotationSearchField))
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 564, Short.MAX_VALUE)
.addComponent(patText, javax.swing.GroupLayout.DEFAULT_SIZE, 564, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(idOpt)
.addGroup(layout.createSequentialGroup()
.addComponent(annOpt)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(loadAnnotations)
.addGap(18, 18, 18)
.addComponent(removeSelected))))
.addGroup(layout.createSequentialGroup()
.addGap(24, 24, 24)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1)
.addGroup(layout.createSequentialGroup()
.addComponent(annSepLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(annSepCb, javax.swing.GroupLayout.PREFERRED_SIZE, 125, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(patOpt)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(idOpt)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(annOpt)
.addComponent(loadAnnotations)
.addComponent(removeSelected))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(annotationSearchField, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel2))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 128, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(annSepLabel)
.addComponent(annSepCb, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addComponent(patOpt)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(patText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
private void loadAnnotationsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadAnnotationsActionPerformed
try {
File file = FileChooserUtils.selectFile("Open annotations file", Settings.get().getLastAnnotationPath(), FileChooserUtils.MODE_OPEN).getFile();
if (file != null) {
hdim.addAnnotations(new ResourceReference<>(new UrlResourceLocator(file), ApplicationContext.getPersistenceManager().getFormat(AnnotationMatrixFormat.EXTENSION, AnnotationMatrix.class)).get());
Settings.get().setLastAnnotationPath(file.getParent());
updateControls();
//annFile.setText(file.getName());
}
} catch (Exception ex) {
LogUtils.logException(ex, LoggerFactory.getLogger(getClass()));
}
}//GEN-LAST:event_loadAnnotationsActionPerformed
private void annotationSearchFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_annotationSearchFieldKeyReleased
filterAnnotationsBox(evt);
}//GEN-LAST:event_annotationSearchFieldKeyReleased
private void removeSelectedActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeSelectedActionPerformed
removeSelecedAnnotations();
}//GEN-LAST:event_removeSelectedActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JList annList;
private javax.swing.JRadioButton annOpt;
private javax.swing.JComboBox annSepCb;
private javax.swing.JLabel annSepLabel;
private javax.swing.JTextField annotationSearchField;
private javax.swing.JRadioButton idOpt;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JButton loadAnnotations;
private javax.swing.ButtonGroup optGroup;
private javax.swing.JRadioButton patOpt;
private javax.swing.JTextField patText;
private javax.swing.JButton removeSelected;
// End of variables declaration//GEN-END:variables
}