Java tutorial
/* * Copyright (c) 2003-2012 Fred Hutchinson Cancer Research Center * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fhcrc.cpl.viewer.gui; import org.fhcrc.cpl.viewer.align.Aligner; import org.fhcrc.cpl.viewer.align.BucketedPeptideArray; import org.fhcrc.cpl.viewer.align.SplineAligner; import org.fhcrc.cpl.toolbox.proteomics.MSRun; import org.fhcrc.cpl.viewer.Localizer; import org.fhcrc.cpl.viewer.util.SharedProperties; import org.fhcrc.cpl.toolbox.gui.ListenerHelper; import org.fhcrc.cpl.toolbox.ApplicationContext; import org.fhcrc.cpl.toolbox.TextProvider; import org.fhcrc.cpl.toolbox.proteomics.feature.*; import org.jfree.data.xy.XYSeriesCollection; import org.jfree.data.xy.XYSeries; import org.jfree.chart.ChartPanel; import org.apache.log4j.Logger; import javax.swing.*; import javax.swing.border.Border; import javax.swing.table.*; import javax.swing.event.ListSelectionEvent; import java.awt.*; import java.awt.event.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.FileOutputStream; import java.io.PrintWriter; import java.util.*; import java.util.List; import java.text.SimpleDateFormat; import java.text.NumberFormat; import java.text.DecimalFormat; public class FeatureSelectionFrame extends AbstractAction implements PropertyChangeListener { protected static Logger _log = Logger.getLogger(FeatureSelectionFrame.class); public FeatureSelectionDialog dialog = null; public void propertyChange(PropertyChangeEvent event) { // setEnabled(null != ApplicationContext.getProperty(SharedProperties.MS_RUN)); } public void actionPerformed(ActionEvent event) { dialog = new FeatureSelectionDialog(); dialog.setVisible(true); } public static class FeatureSelectionDialog extends JDialog { public static final int ACTION_CANCEL = 0; public static final int ACTION_OK = 1; public int action = ACTION_CANCEL; public JTable tblFeatureSets; public JButton buttonAddFiles; public JButton buttonRemoveFiles; public JTabbedPane tabbedPane; public JTextField textMinMz; public JTextField textMaxMz; public JTextField textMinCharge; public JTextField textMaxCharge; public JTextField textMinScans; public JTextField textMaxKL; public JTextField textMinIntensity; public JTextField textMinPeaks; public JTextField textOutputFile; public JButton buttonBrowseOutputDir; public JTextField textPepArrayMzBucket; public JTextField textPepArrayScanBucket; public JCheckBox checkBoxNormalize; public JButton buttonOptimize; public JLabel lblNumBuckets; public JLabel lblExactMatches; public JButton buttonCreatePeptideArray; public JButton buttonCancel; public JButton buttonApply; public JButton buttonOK; public FileListTableModel model; //supporting components public static JFileChooser chooser = new WorkbenchFileChooser(); public static JFileChooser saveChooser = new WorkbenchFileChooser(); private static FeatureSelectionDialog _instance; private static Color[] featureSetColors = new Color[] { Color.BLUE, Color.GREEN, Color.CYAN, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED, Color.YELLOW }; synchronized public static FeatureSelectionDialog getInstance() { if (null == _instance) _instance = new FeatureSelectionDialog(); return _instance; } static { chooser.setMultiSelectionEnabled(true); } public FeatureSelectionDialog() { super(ApplicationContext.getFrame(), TextProvider.getText("DISPLAY_FEATURES")); //graphical stuff Container contentPanel = null; try { contentPanel = Localizer.renderSwixml("org/fhcrc/cpl/viewer/gui/FeatureSelectionFrame.xml", this); setContentPane(contentPanel); pack(); } catch (Exception x) { ApplicationContext.errorMessage(TextProvider.getText("ERROR_CREATING_DIALOG"), x); throw new RuntimeException(x); } Dimension d = contentPanel.getPreferredSize(); setBounds(600, 100, 6 + (int) d.getWidth(), 50 + (int) d.getHeight()); ListenerHelper helper = new ListenerHelper(this); buttonApply.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { FeatureSet.FeatureSelector selector = createFeatureSelector(); updateFeatureSelector(selector); } }); buttonCancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { FeatureSelectionDialog.this.dispose(); } }); buttonOK.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { FeatureSet.FeatureSelector selector = createFeatureSelector(); updateFeatureSelector(selector); FeatureSelectionDialog.this.dispose(); } }); helper.addListener(buttonAddFiles, "buttonAddFile_actionPerformed"); helper.addListener(buttonRemoveFiles, "buttonRemoveFiles_actionPerformed"); //end graphical stuff FeatureSet.FeatureSelector selector = (FeatureSet.FeatureSelector) ApplicationContext .getProperty("featureSelector"); if (null == selector) { selector = new FeatureSet.FeatureSelector(); updateFeatureSelector(selector); } textMaxKL.setText(String.valueOf(selector.getMaxKL())); textMinCharge.setText(String.valueOf(selector.getMinCharge())); textMaxCharge.setText(String.valueOf(selector.getMaxCharge())); textMaxMz.setText(String.valueOf(selector.getMaxMz())); textMinMz.setText(String.valueOf(selector.getMinMz())); textMinIntensity.setText(String.valueOf(selector.getMinIntensity())); textMinScans.setText(String.valueOf(selector.getMinScans())); File dir = null; MSRun run = (MSRun) ApplicationContext.getProperty(SharedProperties.MS_RUN); if (null != run && null != run.getFile()) dir = run.getFile().getParentFile(); if (null == dir) dir = saveChooser.getCurrentDirectory(); if (null != dir) textOutputFile.setText(dir.getAbsolutePath() + File.separatorChar + "pepArray.tsv"); else textOutputFile.setText("pepArray.tsv"); model = new FileListTableModel(); tblFeatureSets.setModel(model); TableColumn displayColumn = tblFeatureSets.getColumnModel().getColumn(0); displayColumn.setPreferredWidth(50); displayColumn.setMaxWidth(50); TableColumn colorColumn = tblFeatureSets.getColumnModel().getColumn(2); colorColumn.setPreferredWidth(50); colorColumn.setMaxWidth(50); colorColumn.setCellRenderer(new ColorRenderer(false)); colorColumn.setCellEditor(new ColorEditor()); TableColumn browseColumn = tblFeatureSets.getColumnModel().getColumn(3); browseColumn.setPreferredWidth(30); browseColumn.setMaxWidth(30); final JButton button = new JButton("..."); final TableCellRenderer browseButtonRenderer = new TableCellRenderer() { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { return button; } }; browseColumn.setCellRenderer(browseButtonRenderer); browseColumn.setCellEditor(new BrowseEditor()); List<FeatureSet> featureSets = (List<FeatureSet>) ApplicationContext .getProperty(SharedProperties.FEATURE_SETS); if (null != featureSets) { for (FeatureSet fs : featureSets) { model.addFeatureSet(fs); } } buttonAddFiles.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { int chooserStatus = chooser.showOpenDialog(FeatureSelectionDialog.this); //if user didn't hit OK, ignore if (chooserStatus != JFileChooser.APPROVE_OPTION) return; File[] files = chooser.getSelectedFiles(); for (File file : files) { //String path = files[i].getAbsolutePath().toLowerCase(); FeatureSet featureSet = new FeatureSet(file, nextColor()); //int numWithoutComp = 0; //for (Feature feature : featureSet.getFeatures()) if (feature.comprised == null) numWithoutComp++; //System.err.println(numWithoutComp + " of " + featureSet.getFeatures().length + " features no comp"); _log.debug("Loaded " + featureSet.getFeatures().length + " features from file " + file.getAbsolutePath() + ". Status: " + featureSet.getLoadStatus()); //check to see if features loaded correctly if (featureSet.getLoadStatus() == FeatureSet.FEATURESET_LOAD_SUCCESS) { featureSet.setDisplayed(tabbedPane.getSelectedIndex() != 3); addFeatureSet(featureSet); } else { ApplicationContext.infoMessage(featureSet.getLoadStatusMessage()); } } } }); buttonRemoveFiles.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { int[] rows = tblFeatureSets.getSelectedRows(); Arrays.sort(rows); FileListTableModel model = (FileListTableModel) tblFeatureSets.getModel(); for (int i = rows.length - 1; i >= 0; i--) model.removeFeatureSet(rows[i]); } }); buttonBrowseOutputDir.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { File file = new File(textOutputFile.getText()); File dir = file.getParentFile(); if (dir.exists()) { saveChooser.setCurrentDirectory(dir.getParentFile()); saveChooser.setSelectedFile(file); } int chooserStatus = saveChooser.showOpenDialog(FeatureSelectionDialog.this); //if user didn't hit OK, ignore if (chooserStatus != JFileChooser.APPROVE_OPTION) return; file = saveChooser.getSelectedFile(); if (null != file) textOutputFile.setText(file.getAbsolutePath()); } }); buttonOptimize.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { double[] mzVal = new double[1]; mzVal[0] = Double.parseDouble(textPepArrayMzBucket.getText()); final Optimizer optimizer = new Optimizer(mzVal, new int[] { 10, 25, 50, 75, 100, 150, 200, 300, 400 }, getFeatureRanges()); optimizer.runLater = new OptimizeGrapher(optimizer); Thread t = new Thread(optimizer); t.start(); } }); buttonCreatePeptideArray.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { List featureSets = getFeatureSets(); if (null == featureSets || featureSets.size() < 2) { ApplicationContext.errorMessage(TextProvider.getText("TWO_FILES_TO_CREATE_PEPTIDE_ARRAY"), null); return; } BucketedPeptideArray arr = new BucketedPeptideArray(featureSets, createFeatureSelector()); float mzBucketSize = Float.parseFloat(textPepArrayMzBucket.getText()); int scanBucketSize = Integer.parseInt(textPepArrayScanBucket.getText()); boolean normalize = checkBoxNormalize.isSelected(); arr.setElutionMode(FeatureClusterer.ELUTION_MODE_SCAN); arr.setElutionBucket(scanBucketSize); arr.setMassBucket(mzBucketSize); arr.setNormalize(normalize); File file = new File(textOutputFile.getText()); if (!file.getParentFile().exists()) { ApplicationContext.errorMessage(TextProvider.getText("DIR_NOT_LEGAL_DIR_NAME", file.getParentFile().getAbsolutePath()), null); return; } arr.setOutFileName(file.getAbsolutePath()); Thread t = new Thread(arr); t.setPriority(Thread.MIN_PRIORITY); t.start(); // //Create because user may have failed to hit apply button // FeatureSet.FeatureSelector sel = createFeatureSelector(); // List ranges = generateMergedSets(featureSets, sel, false); // PeptideArray array = new PeptideArray(ranges); // array.setOutputDir(dir); // //TODO: Error checking } }); } private static int nextColor; public static synchronized Color nextColor() { Color color = featureSetColors[nextColor]; nextColor = ++nextColor % featureSetColors.length; return color; } public List getFeatureSets() { return (List) ApplicationContext.getProperty(SharedProperties.FEATURE_SETS); } public List getFeatureRanges() { return (List) ApplicationContext.getProperty(SharedProperties.FEATURE_RANGES); } public FeatureSet.FeatureSelector getFeatureSelector() { FeatureSet.FeatureSelector sel = (FeatureSet.FeatureSelector) ApplicationContext .getProperty("featureSelector"); if (null == sel) //Should never happen... { sel = createFeatureSelector(); ApplicationContext.setProperty("featureSelector", sel); } return sel; } private FeatureSet.FeatureSelector createFeatureSelector() { FeatureSet.FeatureSelector selector = new FeatureSet.FeatureSelector(); //TODO: Error handling... selector.setMaxKL(Float.parseFloat(textMaxKL.getText())); selector.setMinCharge(Integer.parseInt(textMinCharge.getText())); selector.setMaxCharge(Integer.parseInt(textMaxCharge.getText())); selector.setMaxMz(Float.parseFloat(textMaxMz.getText())); selector.setMinMz(Float.parseFloat(textMinMz.getText())); selector.setMinIntensity(Float.parseFloat(textMinIntensity.getText())); selector.setMinPeaks(Integer.parseInt(textMinPeaks.getText())); selector.setMinScans(Integer.parseInt(textMinScans.getText())); return selector; } public void addFeatureSet(File file) { FeatureSet featureSet; try { featureSet = new FeatureSet(file); } catch (Exception x) { //JOptionPane.showMessageDialog(null, x.getMessage()); ApplicationContext.errorMessage(null, x); return; } addFeatureSet(featureSet); } public void addFeatureSet(Feature[] features) { addFeatureSet(new FeatureSet(features)); } public void addFeatureSet(FeatureSet featureSet) { featureSet.setColor(nextColor()); _log.debug("Adding new featureset with " + featureSet.getFeatures().length + " features to list of displayed featuresets"); ((FileListTableModel) tblFeatureSets.getModel()).addFeatureSet(featureSet); ApplicationContext.setProperty(SharedProperties.SELECTED, featureSet); } /** * Updates the featureselector based on the currently loaded features * * @param sel */ public void updateFeatureSelector(FeatureSet.FeatureSelector sel) { List featureSets = (List) ApplicationContext.getProperty(SharedProperties.FEATURE_SETS); if (null != featureSets) { List mergedFeatureSets = generateMergedSets(featureSets, sel); ApplicationContext.setProperty(SharedProperties.FEATURE_RANGES, mergedFeatureSets); } ApplicationContext.setProperty("featureSelector", sel); } /** * Generates a new merged feature list * * @param featureSets * @param sel * @return */ protected List<FeatureSet> generateMergedSets(List<? extends FeatureSet> featureSets, FeatureSet.FeatureSelector sel) { List<FeatureSet> mergedFeatureSets = new ArrayList<FeatureSet>(featureSets.size()); for (FeatureSet fs : featureSets) { FeatureSet fsMerged = fs.filter(sel); fsMerged.setDisplayed(fs.isDisplayed()); fsMerged.setSourceFile(fs.getSourceFile()); mergedFeatureSets.add(fsMerged); } return mergedFeatureSets; } public void updateFeatureSets(List<? extends FeatureSet> featureSets, boolean displayOnly) { FeatureSet.FeatureSelector sel = (FeatureSet.FeatureSelector) ApplicationContext .getProperty("featureSelector"); if (null != sel) { List<FeatureSet> mergedFeatureSets = null; if (displayOnly) { mergedFeatureSets = new ArrayList<FeatureSet>(); List<? extends FeatureSet> oldFeatureSets = (List<? extends FeatureSet>) ApplicationContext .getProperty(SharedProperties.FEATURE_RANGES); for (int i = 0; i < oldFeatureSets.size(); i++) { //Need to clone them or else property change support says nothing changed. FeatureSet merged = (FeatureSet) oldFeatureSets.get(i).clone(); FeatureSet unmerged = featureSets.get(i); merged.setColor(unmerged.getColor()); merged.setDisplayed(unmerged.isDisplayed()); mergedFeatureSets.add(merged); } } else { mergedFeatureSets = generateMergedSets(featureSets, sel); } ApplicationContext.setProperty(SharedProperties.FEATURE_RANGES, mergedFeatureSets); } ApplicationContext.setProperty(SharedProperties.FEATURE_SETS, featureSets); } /* * UI event handlers */ public void buttonAddFile_actionPerformed(ActionEvent event) { } public void buttonRemoveFiles_actionPerformed(ActionEvent event) { } /* * Inner classes */ public static class Optimizer implements Runnable { //private static final int OPTIMIZE_STEPS = 15; //private static final int OPTIMIZE_INCREMENT = 20; double[] mzValues; int[] scanValues; int bestScanWindow = 50; double bestMzWindow = .3; int bestMatchMzIndex = 0; int bestMatchScanIndex = 0; //2D Arrays one subarray for each mzValue int[][] numBuckets = null; int[][] perfectMatches = null; private int topN = 0; XYSeries[] series; List<FeatureSet> featureSets = null; public boolean align = true; Runnable runLater = null; File outFile = null; PrintWriter out = new PrintWriter(System.out); public Optimizer(double[] mzValues, int[] scanValues, List<FeatureSet> featureSets) { this.mzValues = mzValues; this.scanValues = scanValues; this.featureSets = featureSets; series = new XYSeries[mzValues.length]; for (int i = 0; i < series.length; i++) series[i] = new XYSeries("-Points (" + mzValues[i] + ")"); numBuckets = new int[mzValues.length][scanValues.length]; perfectMatches = new int[mzValues.length][scanValues.length]; } public Optimizer(double[] mzValues, int[] scanValues, List<FeatureSet> featureSets, File outFile) { this(mzValues, scanValues, featureSets); if (null == outFile) return; this.outFile = outFile; try { this.out = new PrintWriter(new FileOutputStream(outFile)); } catch (Exception x) { ApplicationContext.errorMessage( TextProvider.getText("COULD_NOT_OPEN_FILE_FILENAME", outFile.getPath()), x); } } public void run() { //use getFeatureRanges so that we have a filtered set. //Alignment was much too slow. if (null == featureSets || featureSets.size() < 2) { //JOptionPane.showMessageDialog(FeatureSelectionFrame.this, "At least 2 files must be selected to create a peptide array"); ApplicationContext.errorMessage(TextProvider.getText("TWO_FILES_TO_CREATE_PEPTIDE_ARRAY"), null); return; } FeatureSet[] alignedSets = null; if (align) { List<FeatureSet> alignedList; try { ApplicationContext.setMessage(TextProvider.getText("ALIGNING_DOTDOTDOT")); Aligner aligner = new SplineAligner(); aligner.setBuildCharts(true); Aligner.MzFeaturePairSelector pairSelector = new Aligner.MzFeaturePairSelector(); pairSelector.setTopN(topN); aligner.setFeaturePairSelector(Aligner.DEFAULT_FEATURE_PAIR_SELECTOR); alignedList = aligner.alignFeatureSets(featureSets, true); } catch (Exception x) { ApplicationContext.errorMessage(TextProvider.getText("COULD_NOT_ALIGN_FEATURE_SETS"), x); return; } alignedSets = alignedList.toArray(new FeatureSet[featureSets.size()]); } else alignedSets = featureSets.toArray(new FeatureSet[featureSets.size()]); FeatureGrouper grouper = new FeatureGrouper(); for (int i = 0; i < alignedSets.length; i++) grouper.addSet(alignedSets[i]); out.println("mzBucketSize\tscanCount\tnumBuckets\tperfectMatches"); for (int iMz = 0; iMz < mzValues.length; iMz++) { for (int iScan = 0; iScan < scanValues.length; iScan++) { int scanCount = scanValues[iScan]; double mzBucketSize = mzValues[iMz]; ApplicationContext .setMessage(TextProvider.getText("CALCULATING_ARRAY_SCAN_MZ", "SCAN_COUNT", Integer.toString(scanCount), "MZ_WINDOW", Double.toString(mzBucketSize))); grouper.split2D(mzBucketSize, scanCount); numBuckets[iMz][iScan] = grouper.numBuckets(); perfectMatches[iMz][iScan] = grouper.rowsWithOneFromEach(); if (perfectMatches[iMz][iScan] > perfectMatches[bestMatchMzIndex][bestMatchScanIndex]) { bestMatchMzIndex = iMz; bestMatchScanIndex = iScan; bestScanWindow = scanCount; bestMzWindow = mzBucketSize; } series[iMz].add(scanCount, (double) perfectMatches[iMz][iScan]); out.println(mzBucketSize + "\t" + scanCount + "\t" + numBuckets[iMz][iScan] + "\t" + perfectMatches[iMz][iScan]); } } out.flush(); if (null != this.outFile) out.close(); if (null != runLater) EventQueue.invokeLater(runLater); } public int getTopN() { return topN; } public void setTopN(int topN) { this.topN = topN; } } private class FileListTableModel extends AbstractTableModel { ArrayList _featureSets = new ArrayList(); synchronized public void addFeatureSet(FeatureSet fs) { _featureSets.add(fs); ArrayList changedFeatureSets = new ArrayList(); changedFeatureSets.addAll(_featureSets); updateFeatureSets(changedFeatureSets, false); super.fireTableRowsInserted(_featureSets.size() - 1, _featureSets.size() - 1); } synchronized public void removeFeatureSet(int i) { _featureSets.remove(i); ArrayList changedFeatureSets = new ArrayList(); changedFeatureSets.addAll(_featureSets); updateFeatureSets(changedFeatureSets, false); super.fireTableRowsDeleted(i, i); } public int getRowCount() { return _featureSets.size(); } public int getColumnCount() { return 4; } public Class getColumnClass(int c) { switch (c) { case 0: return Boolean.class; case 2: return Color.class; default: return Object.class; } } public boolean isCellEditable(int row, int col) { return col == 0 || col == 2 || col == 3; } public Object getValueAt(int row, int col) { if (row >= _featureSets.size()) return null; FeatureSet fs = (FeatureSet) _featureSets.get(row); switch (col) { case 0: return new Boolean(fs.isDisplayed()); case 1: return fs.getSourceFile() != null ? fs.getSourceFile().getAbsolutePath() : "(no file)"; case 2: return fs.getColor(); default: return fs; } } private String[] columnNames = new String[] { TextProvider.getText("DISPLAY"), TextProvider.getText("FILE"), TextProvider.getText("COLOR") }; public String getColumnName(int i) { return i >= 0 && i < columnNames.length ? columnNames[i] : ""; } public void setValueAt(Object o, int row, int col) { if (row >= _featureSets.size()) return; FeatureSet fs = (FeatureSet) _featureSets.get(row); switch (col) { case 0: fs.setDisplayed(((Boolean) o).booleanValue()); break; case 1: throw new IllegalArgumentException(TextProvider.getText("CANT_EDIT_FILE_NAME")); case 2: fs.setColor((Color) o); break; default: return; } ArrayList changedFeatureSets = new ArrayList(); changedFeatureSets.addAll(_featureSets); updateFeatureSets(changedFeatureSets, true); super.fireTableCellUpdated(row, col); } } private class OptimizeGrapher implements Runnable { FeatureSelectionFrame.FeatureSelectionDialog.Optimizer optimizer; private OptimizeGrapher(Optimizer optimizer) { this.optimizer = optimizer; } public void run() { textPepArrayScanBucket.setText(String.valueOf(optimizer.bestScanWindow)); textPepArrayMzBucket.setText(String.valueOf(optimizer.bestMzWindow)); lblNumBuckets.setText(String .valueOf(optimizer.numBuckets[optimizer.bestMatchMzIndex][optimizer.bestMatchScanIndex])); lblExactMatches.setText(String.valueOf( optimizer.perfectMatches[optimizer.bestMatchMzIndex][optimizer.bestMatchScanIndex])); XYSeriesCollection seriesColl = new XYSeriesCollection(); for (int i = 0; i < optimizer.mzValues.length; i++) seriesColl.addSeries(optimizer.series[i]); StringBuffer mzBucketSizeStr = new StringBuffer(); String sep = ""; for (int i = 0; i < optimizer.mzValues.length; i++) { mzBucketSizeStr.append(sep); mzBucketSizeStr.append(optimizer.mzValues[i]); sep = ", "; } JFrame newFrame = new JFrame( TextProvider.getText("BUCKETS_FOR_MZ_OF_SIZE", new String(mzBucketSizeStr))); ChartPanel chart = SpectrumChartFactory.CreateChartPanel(seriesColl); chart.getChart().getXYPlot().getDomainAxis().setLabel(TextProvider.getText("SCAN_WINDOW")); chart.getChart().getXYPlot().getRangeAxis().setLabel(TextProvider.getText("QUOTE_PERFECT_BUCKETS")); newFrame.setContentPane(chart); newFrame.setSize(400, 500); newFrame.setVisible(true); } } public static class ColorRenderer extends JLabel implements TableCellRenderer { Border unselectedBorder = null; Border selectedBorder = null; boolean isBordered = true; public ColorRenderer(boolean isBordered) { this.isBordered = isBordered; setOpaque(true); //MUST do this for background to show up. } public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { Color newColor = (Color) color; setBackground(newColor); if (isBordered) { if (isSelected) { if (selectedBorder == null) { selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5, table.getSelectionBackground()); } setBorder(selectedBorder); } else { if (unselectedBorder == null) { unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5, table.getBackground()); } setBorder(unselectedBorder); } } setToolTipText(TextProvider.getText("RGB_VALUE_RED_GREEN_BLUE", "RED", Integer.toString(newColor.getRed()), "GREEN", Integer.toString(newColor.getGreen()), "BLUE", Integer.toString(newColor.getBlue()))); return this; } } public static class ColorEditor extends AbstractCellEditor implements TableCellEditor, ActionListener { Color currentColor; JButton button; JColorChooser colorChooser; JDialog dialog; protected static final String EDIT = "edit"; public ColorEditor() { //Set up the editor (from the table's point of view), //which is a button. //This button brings up the color chooser dialog, //which is the editor from the user's point of view. button = new JButton(); button.setActionCommand(EDIT); button.addActionListener(this); button.setBorderPainted(false); //Set up the dialog that the button brings up. colorChooser = new JColorChooser(); dialog = JColorChooser.createDialog(button, "Pick a Color", true, //modal colorChooser, this, //OK button handler null); //no CANCEL button handler } /** * Handles events from the editor button and from * the dialog's OK button. */ public void actionPerformed(ActionEvent e) { if (EDIT.equals(e.getActionCommand())) { //The user has clicked the cell, so //bring up the dialog. button.setBackground(currentColor); colorChooser.setColor(currentColor); dialog.setVisible(true); //Make the renderer reappear. fireEditingStopped(); } else { //User pressed dialog's "OK" button. currentColor = colorChooser.getColor(); } } //Implement the one CellEditor method that AbstractCellEditor doesn't. public Object getCellEditorValue() { return currentColor; } //Implement the one method defined by TableCellEditor. public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { currentColor = (Color) value; return button; } } public static class BrowseEditor extends AbstractCellEditor implements TableCellEditor, ActionListener { FeatureSet fs; JButton button; public BrowseEditor() { button = new JButton("..."); button.addActionListener(this); } public void actionPerformed(ActionEvent e) { if (null == fs) return; FeatureFrame frame = new FeatureFrame(fs); frame.setVisible(true); } //Implement the one CellEditor method that AbstractCellEditor doesn't. public Object getCellEditorValue() { return fs; } //Implement the one method defined by TableCellEditor. public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { fs = (FeatureSet) value; return button; } } public static class FeatureFrame extends JFrame { FeatureSet _fs; FeatureTable _table; JDialog _popup = null; public FeatureFrame(FeatureSet fs) { super((fs.getSourceFile() != null ? fs.getSourceFile().getName() : "(no file)") + " -- " + fs.getFeatures().length); setSize(640, 400); setIconImage(ApplicationContext.getFrame().getIconImage()); JPanel editPanel = new JPanel(); JButton propertiesButton = new JButton(TextProvider.getText("PROPERTIES")); JButton deleteButton = new JButton(TextProvider.getText("DELETE")); JButton saveButton = new JButton(TextProvider.getText("SAVE")); JButton addButton = new JButton(TextProvider.getText("ADD")); JButton closeButton = new JButton(TextProvider.getText("CLOSE")); ListenerHelper helper = new ListenerHelper(this); helper.addListener(propertiesButton, "properties_actionPerformed"); helper.addListener(deleteButton, "delete_actionPerformed"); helper.addListener(addButton, "add_actionPerformed"); helper.addListener(saveButton, "save_actionPerformed"); helper.addListener(closeButton, "close_actionPerformed"); editPanel.add(propertiesButton); editPanel.add(addButton); editPanel.add(deleteButton); editPanel.add(saveButton); editPanel.add(closeButton); _table = new FeatureTable(fs); JScrollPane pane = new JScrollPane(_table); getContentPane().add(pane); getContentPane().add(editPanel, BorderLayout.PAGE_END); } public void properties_actionPerformed(ActionEvent e) { if (true) { if (ApplicationContext.getFrame() instanceof WorkbenchFrame) ((WorkbenchFrame) ApplicationContext.getFrame()).showPropertiesPane(); ApplicationContext.setProperty(SharedProperties.SELECTED, _fs); } else { PropertiesPane.popup(_fs.getProperties()); } /* Map map = _fs.getProperties(); if (null == map) map = new HashMap(); TableModel m = new DefaultTableModel(map.size(), 2); int row = 0; for (Iterator it = map.entrySet().iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry)it.next(); m.setValueAt(entry.getKey(), row, 0); m.setValueAt(entry.getValue(), row, 1); row++; } JTable table = new JTable(m); table.getColumnModel().getColumn(0).setHeaderValue("property"); table.getColumnModel().getColumn(1).setHeaderValue("value"); String title = "" + _fs.getSourceFile() + " properties"; JDialog dialog = new JDialog(ApplicationContext.getFrame(), title, true); ListenerHelper h = new ListenerHelper(this); h.addListener(dialog.getContentPane(), "popup_keyPressed"); h.addListener(table, "popup_keyPressed"); dialog.getContentPane().add(new JScrollPane(table)); dialog.setSize(400, 300); _popup = dialog; dialog.setVisible(true); } */ } /* public void popup_keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE && null != _popup) { _popup.dispose(); _popup = null; e.consume(); return; } } */ public void delete_actionPerformed(ActionEvent e) { int row; int sortRow = _table.getSelectedRow(); if (sortRow < 0 || sortRow >= _fs.getFeatures().length) return; row = _table.convertRowIndexToModel(sortRow); Feature[] features = _fs.getFeatures(); Feature[] newFeatures = new Feature[features.length - 1]; for (int i = 0; i < row; i++) newFeatures[i] = features[i]; for (int i = row + 1; i < features.length; i++) newFeatures[i - 1] = features[i]; //TODO: Move fs into tablemodel so don't have to hack around like this... _fs.setFeatures(newFeatures); _table._model._features = newFeatures; _table._model.fireTableRowsDeleted(row, row); _table.getSelectionModel().setSelectionInterval(sortRow, sortRow); _table.requestFocus(); FeatureSelectionDialog.getInstance() .updateFeatureSets(FeatureSelectionDialog.getInstance().getFeatureSets(), false); } public void add_actionPerformed(ActionEvent e) { Spectrum.Peak p = (Spectrum.Peak) ApplicationContext.getProperty(SharedProperties.SELECTED_POINT); Feature f; if (null == p) f = new Feature(); else f = new Feature(p); int row; int sortRow = _table.getSelectedRow(); sortRow = Math.min(sortRow, _fs.getFeatures().length - 1); row = _table.convertRowIndexToModel(sortRow); Feature[] features = _fs.getFeatures(); Feature[] newFeatures = new Feature[features.length + 1]; for (int i = 0; i <= row; i++) newFeatures[i] = features[i]; newFeatures[row + 1] = f; for (int i = row + 1; i < features.length; i++) newFeatures[i + 1] = features[i]; String userName = System.getProperty("user.name"); //not translating, since this will be stored at the feature level f.setDescription("Added=" + userName + ", " + new SimpleDateFormat().format(new Date())); //TODO: Move fs into tablemodel so don't have to hack around like this... _fs.setFeatures(newFeatures); _table._model._features = newFeatures; _table._model.fireTableRowsInserted(row + 1, row + 1); _table.getSelectionModel().setSelectionInterval(sortRow + 1, sortRow + 1); _table.requestFocus(); FeatureSelectionDialog.getInstance() .updateFeatureSets(FeatureSelectionDialog.getInstance().getFeatureSets(), false); } public void close_actionPerformed(ActionEvent e) { this.dispose(); } public void save_actionPerformed(ActionEvent e) { try { if (_fs.getSourceFile() == null) { WorkbenchFileChooser wfc = new WorkbenchFileChooser(); wfc.showSaveDialog(this); File file = wfc.getSelectedFile(); _fs.setSourceFile(file); } _fs.save(); } catch (Exception x) { //JOptionPane.showMessageDialog(null, "Exception saving: " + x.getMessage()); ApplicationContext.errorMessage(null, x); } } private void selectRow() { if (null == _fs) return; if (null == _table) return; int row = _table.getSelectedRow(); if (row < 0 || row >= _fs.getFeatures().length) return; row = _table.convertRowIndexToModel(row); Feature f = _fs.getFeatures()[row]; //System.err.println(f); float mz = f.getMz(); if (mz <= 0) return; // UNDONE: float time = f.getCPUTime(); int scanNum = f.getScan(); if (scanNum <= 0) return; MSRun run = (MSRun) ApplicationContext.getProperty(SharedProperties.MS_RUN); MSRun.MSScan selectedScan = null; if (run != null) { if (scanNum >= run.getScanCount()) scanNum = run.getScanCount() - 1; selectedScan = run.getScan(scanNum); } ApplicationContext.setProperty(SharedProperties.MS_SCAN, selectedScan); Feature c = (Feature) f.clone(); ApplicationContext.setProperty(SharedProperties.SELECTED_POINT, c); ApplicationContext.setProperty(SharedProperties.SELECTED, c); } public void table_keyPressed(KeyEvent e) { ApplicationContext.setMessage("" + e.getKeyCode()); if (e.getKeyCode() != 10) return; e.consume(); selectRow(); } public void table_mouseClicked(MouseEvent e) { if (e.getClickCount() != 2) return; e.consume(); selectRow(); } public class FeatureTable extends JTable { FeatureTableModel _model; JTextField _textEditor; public FeatureTable(FeatureSet fs) { _fs = fs; _model = new FeatureTableModel(_fs.getFeatures()); setModel(_model); //dhmay replacing the old usage of our custom TableSorter class with the standard 1.6 syntax TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(_model); setRowSorter(sorter); int count = _model.getColumnCount(); for (int i = 0; i < count - 1; i++) getColumnModel().getColumn(i).setCellRenderer(new FeatureSelectionDialog.NumberRenderer()); getColumnModel().getColumn(count - 1).setPreferredWidth(200); ListenerHelper helper = new ListenerHelper(FeatureFrame.this); helper.addListener(this, "table_mouseClicked"); helper.addListener(this, "table_keyPressed"); } public Component prepareEditor(TableCellEditor editor, int row, int column) { Component c = super.prepareEditor(editor, row, column); if (c instanceof JTextField) ((JTextField) c).selectAll(); return c; } public void valueChanged(ListSelectionEvent e) { super.valueChanged(e); selectRow(); } } } public static class NumberRenderer extends DefaultTableCellRenderer { NumberFormat format; int decimal = 2; public NumberRenderer() { super(); setHorizontalAlignment(RIGHT); format = new DecimalFormat(); format.setMaximumFractionDigits(decimal); format.setMinimumFractionDigits(decimal); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Object formatted = value; if (value instanceof Float || value instanceof Double) formatted = format.format(value); return super.getTableCellRendererComponent(table, formatted, isSelected, hasFocus, row, column); } } } }