/*****************************************************************************
* Copyright (c) 2008 Bioclipse Project
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*****************************************************************************/
package net.bioclipse.spectrum.editor;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Logger;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.RTFTransfer;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xmlcml.cml.base.CMLElement;
import org.xmlcml.cml.element.CMLPeak;
import org.xmlcml.cml.element.CMLPeakList;
import org.xmlcml.cml.element.CMLSpectrum;
import spok.utils.SpectrumUtils;
/**
* @author Stefan Kuhn
*/
public class PeakTableViewer {
private static final Logger logger = Logger.getLogger(PeakTableViewer.class);
HashMap<String,Node> spectypemap = new HashMap<String,Node>();
Table table;
TableViewer tableViewer;
String[] cmlPeakFields = { "", "", "", "" };
private final String X_AXIS = "xaxis";
private final String Y_AXIS = "yaxis";
private String[] columnNames = new String[6];
CMLSpectrum spectrumItem = null;
public static final String INVALID_COLUMN = "---";
int highestColumn = 1;
PeakTablePage peakTablePage;
public int[] hashesofpeaks;
public CMLSpectrum getSpectrumItem() {
return spectrumItem;
}
public void setSpectrumItem(CMLSpectrum spectrumItem) {
this.spectrumItem = spectrumItem;
}
public PeakTableViewer(Composite parent, CMLSpectrum spectrumItem, PeakTablePage peakTablePage) {
try {
columnNames[0] = X_AXIS;
columnNames[1] = Y_AXIS;
columnNames[2] = INVALID_COLUMN;
;
columnNames[3] = INVALID_COLUMN;
columnNames[4] = INVALID_COLUMN;
columnNames[5] = INVALID_COLUMN;
this.addChildControls(parent);
this.setSpectrumItem(spectrumItem);
this.peakTablePage=peakTablePage;
} catch (Exception ex) {
StringWriter strWr = new StringWriter();
PrintWriter prWr = new PrintWriter(strWr);
ex.printStackTrace(prWr);
logger.debug("problems creating PeakTableViewer "
+ strWr.toString());
}
}
public TableViewer getTableViewer() {
return tableViewer;
}
public String[] getCmlPeakFields() {
return cmlPeakFields;
}
public Table getTable() {
return table;
}
public void dispose() {
// Tell the label provider to release its ressources
tableViewer.getLabelProvider().dispose();
}
private void addChildControls(Composite composite) throws Exception {
// Create a composite to hold the children
GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL
| GridData.FILL_BOTH);
composite.setLayoutData(gridData);
// Set numColumns to 3 for the buttons
GridLayout layout = new GridLayout(3, false);
layout.marginWidth = 4;
composite.setLayout(layout);
// Create the table
createTable(composite);
// Create and setup the TableViewer
createTableViewer();
tableViewer.setContentProvider(new PeakContentProvider());
tableViewer.setLabelProvider(new PeakLabelProvider(this));
// Set the cell modifier for the viewer
tableViewer.setCellModifier(new PeakCellModifier(this));
// Set the default sorter for the viewer
// tableViewer.setSorter(new PeakSorter(X_AXIS,this,false));
CMLSpectrum spectrum = new CMLSpectrum();
tableViewer.setInput(spectrum);
// Add the buttons
createButtons(composite);
}
private void createTable(Composite parent) {
int style = SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL
| SWT.FULL_SELECTION | SWT.HIDE_SELECTION | SWT.RESIZE;
table = new Table(parent, style);
GridData gridData = new GridData(GridData.FILL_BOTH);
gridData.grabExcessVerticalSpace = true;
gridData.horizontalSpan = 3;
table.setLayoutData(gridData);
table.setLinesVisible(true);
table.setHeaderVisible(true);
TableColumn[] column = new TableColumn[columnNames.length];
for (int i = 0; i < columnNames.length; i++) {
column[i] = new TableColumn(table, SWT.CENTER, i);
column[i].setText(columnNames[i]);
column[i].setWidth(100);
column[i].addSelectionListener(new MySelectionAdapter(i, this));
}
}
private void createTableViewer() {
tableViewer = new TableViewer(table);
tableViewer.setUseHashlookup(true);
tableViewer.setColumnProperties(columnNames);
// Create the cell editors
CellEditor[] editors = new CellEditor[columnNames.length + 4];
// Column 2 : X_AXIS (Free text)
TextCellEditor xEditor = new TextCellEditor(table);
((Text) xEditor.getControl()).setTextLimit(60);
((Text) xEditor.getControl()).addListener(SWT.Traverse, new Listener() {
public void handleEvent(Event event) {
if (event.detail == SWT.TRAVERSE_TAB_PREVIOUS
|| event.detail == SWT.TRAVERSE_ARROW_PREVIOUS) {
if (table.getSelectionIndex() > 0)
tableViewer.editElement(tableViewer.getElementAt(table
.getSelectionIndex() - 1), highestColumn);
}
if (event.detail == SWT.TRAVERSE_TAB_NEXT
|| event.detail == SWT.TRAVERSE_ARROW_NEXT) {
tableViewer.editElement(tableViewer.getElementAt(table
.getSelectionIndex()), 1);
}
}
});
editors[0] = xEditor;
// Column 3 : Y_AXIS ;
TextCellEditor yEditor = new TextCellEditor(table);
((Text) yEditor.getControl()).setTextLimit(60);
((Text) yEditor.getControl()).addListener(SWT.Traverse, new Listener() {
public void handleEvent(Event event) {
if (event.detail == SWT.TRAVERSE_TAB_PREVIOUS
|| event.detail == SWT.TRAVERSE_ARROW_PREVIOUS) {
tableViewer.editElement(tableViewer.getElementAt(table
.getSelectionIndex()), 0);
// logger.debug(table.getSelectionIndex());
}
if (event.detail == SWT.TRAVERSE_TAB_NEXT
|| event.detail == SWT.TRAVERSE_ARROW_NEXT) {
if (highestColumn == 1
&& table.getSelectionIndex() < ((CMLSpectrum) tableViewer
.getInput()).getPeakListElements().get(0).getChildCount() - 1)
tableViewer.editElement(tableViewer.getElementAt(table
.getSelectionIndex() + 1), 0);
if (highestColumn > 1)
tableViewer.editElement(tableViewer.getElementAt(table
.getSelectionIndex()), 2);
}
}
});
editors[1] = yEditor;
for (int i = 0; i < 4; i++) {
TextCellEditor cellEditor = new TextCellEditor(table);
((Text) cellEditor.getControl()).setTextLimit(60);
((Text) cellEditor.getControl()).addListener(SWT.Traverse,
new MyListener(2 + i));
editors[2 + i] = cellEditor;
}
// Assign the cell editors to the viewer
tableViewer.setCellEditors(editors);
}
public class MyListener implements Listener {
private int myColumn = 0;
public MyListener(int myColumn) {
this.myColumn = myColumn;
}
public void handleEvent(Event event) {
if (event.detail == SWT.TRAVERSE_TAB_PREVIOUS
|| event.detail == SWT.TRAVERSE_ARROW_PREVIOUS) {
// if(table.getSelectionIndex()> n)
tableViewer.editElement(tableViewer.getElementAt(table
.getSelectionIndex()), myColumn - 1);
}
if (event.detail == SWT.TRAVERSE_TAB_NEXT
|| event.detail == SWT.TRAVERSE_ARROW_NEXT) {
if (highestColumn == myColumn
&& table.getSelectionIndex() < ((CMLSpectrum) tableViewer
.getInput()).getPeakListElements().get(0).getChildCount() - 1)
tableViewer.editElement(tableViewer.getElementAt(table
.getSelectionIndex() + 1), 0);
if (highestColumn > myColumn)
tableViewer.editElement(tableViewer.getElementAt(table
.getSelectionIndex()), myColumn + 1);
}
}
}
public class MySelectionAdapter extends SelectionAdapter {
private int columnNumber;
private boolean reverseSort = false;
private PeakTableViewer peakTableViewer;
public MySelectionAdapter(int columnNumber,
PeakTableViewer peakTableViewer) {
this.columnNumber = columnNumber;
this.peakTableViewer = peakTableViewer;
}
public void widgetSelected(SelectionEvent e) {
try {
tableViewer.setSorter(new PeakSorter(columnNames[columnNumber],
peakTableViewer, reverseSort));
// reverseSort = reverseSort?false:true;
if (reverseSort) {
reverseSort = false;
} else {
reverseSort = true;
}
} catch (Exception ex) {
StringWriter strWr = new StringWriter();
PrintWriter prWr = new PrintWriter(strWr);
ex.printStackTrace(prWr);
logger.error(strWr.toString());
}
}
}
public class PeakContentProvider implements IStructuredContentProvider {
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
}
public void dispose() {
}
// Return the peaks as an array of Objects
public Object[] getElements(Object parent) {
CMLSpectrum cpl = (CMLSpectrum) tableViewer.getInput();
List<CMLElement> peaks = SpectrumUtils.getPeakElements(cpl);
return peaks.toArray();
}
}
public void configureFromXMLFile()
throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
//TODO do parsing only once, code duplication with MetadataModifyListener
Document document = builder
.parse(this
.getClass()
.getClassLoader()
.getResourceAsStream(
"net/bioclipse/spectrum/editor/spec.xml"));
NodeList nl = document.getElementsByTagName("spectrumtypes");
Node spectrumtypes = nl.item(nl.getLength() - 1);
NodeList spectrumtypelist = spectrumtypes.getChildNodes();
Node unknownnode=null;
for (int i = 0; i < spectrumtypelist.getLength(); i++) {
Node spectrumtype = spectrumtypelist.item(i);
if (spectrumtype.getNodeType() != Node.TEXT_NODE) {
spectypemap.put(spectrumtype.getAttributes().getNamedItem(
"cmltype").getNodeValue(), spectrumtype);
if(spectrumtype.getAttributes().getNamedItem("name").getNodeValue().equals("unknown"))
unknownnode=spectrumtype;
}
}
Node myNode = (Node) spectypemap.get(spectrumItem.getType());
if(myNode==null){
myNode=unknownnode;
}
NodeList mySiblings = myNode.getChildNodes();
for (int k = 0; k < mySiblings.getLength(); k++) {
Node currentSibling = mySiblings.item(k);
if (currentSibling.getNodeName().equals("xaxis")) {
table.getColumn(0).setText(
currentSibling.getAttributes()
.getNamedItem("name")
.getNodeValue());
columnNames[0] = table.getColumn(0).getText();
} else if (currentSibling.getNodeName().equals(
"yaxis")) {
table.getColumn(1).setText(
currentSibling.getAttributes()
.getNamedItem("name")
.getNodeValue());
columnNames[1] = table.getColumn(1).getText();
} else if (currentSibling.getNodeName().equals(
"additionalFields")) {
NodeList fields = currentSibling
.getChildNodes();
int m = 0;
for (int l = 0; l < fields.getLength(); l++) {
if (fields.item(l).getNodeType() != Node.TEXT_NODE) {
Node field = fields.item(l);
table.getColumn(2 + m).setText(
field.getAttributes()
.getNamedItem("name")
.getNodeValue());
table.getColumn(2 + m).setWidth(100);
cmlPeakFields[m] = field
.getAttributes().getNamedItem(
"cmlpeakfield")
.getNodeValue();
columnNames[2 + m] = field
.getAttributes().getNamedItem(
"name").getNodeValue();
m++;
}
}
highestColumn = 1 + m;
for (int l = m; l < 4; l++) {
table.getColumn(2 + l).setText(
INVALID_COLUMN);
table.getColumn(2 + l).setWidth(100);
cmlPeakFields[l] = "";
columnNames[2 + l] = INVALID_COLUMN;
}
}
}
for (int i = 0; i < table.getColumnCount(); i++) {
table.getColumn(i).pack();
}
tableViewer.setInput(spectrumItem);
hashesofpeaks=new int[spectrumItem.getPeakListElements().get(0).getChildCount()];
CMLPeak[] array = new CMLPeak[spectrumItem.getPeakListElements().get(0).getChildCount()];
for (int i = 0; i < hashesofpeaks.length; i++) {
array[i] = (CMLPeak) spectrumItem.getPeakListElements().get(0).getPeakElements().get(i);
if(array[i]!=null)
hashesofpeaks[i]=array[i].hashCode();
}
}
// Add the "Add", "Delete", "Copy to clipboard" buttons
private void createButtons(final Composite parent) throws Exception {
// Create and configure the "Add" button
Button add = new Button(parent, SWT.PUSH | SWT.CENTER);
add.setText("Add");
GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gridData.widthHint = 80;
add.setLayoutData(gridData);
add.addSelectionListener(new SelectionAdapter() {
// Add a peakvalue to the PeakTable and refresh the view
public void widgetSelected(SelectionEvent e) {
CMLPeak peak = new CMLPeak();
peak.setXValue(0);
peak.setYValue(0);
if(((CMLSpectrum) tableViewer.getInput()).getPeakListElements().size()==0)
((CMLSpectrum) tableViewer.getInput()).addPeakList(new CMLPeakList());
((CMLSpectrum) tableViewer.getInput()).getPeakListElements().get(0).addPeak(peak);
tableViewer.add(peak);
CMLPeak[] array = new CMLPeak[spectrumItem.getPeakListElements().get(0).getChildCount()];
hashesofpeaks=new int[spectrumItem.getPeakListElements().get(0).getChildCount()];
for (int i = 0; i < array.length; i++) {
array[i] = (CMLPeak) spectrumItem.getPeakListElements().get(0).getPeakElements().get(i);
hashesofpeaks[i]=array[i].hashCode();
}
tableViewer.setSelection(new StructuredSelection(peak));
peakTablePage.setDirty(true);
}
});
// Create and configure the "Delete" button
Button delete = new Button(parent, SWT.PUSH | SWT.CENTER);
delete.setText("Delete");
gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gridData.widthHint = 80;
delete.setLayoutData(gridData);
delete.addSelectionListener(new SelectionAdapter() {
// Remove the selection and refresh the view
public void widgetSelected(SelectionEvent e) {
CMLPeak task = (CMLPeak) ((IStructuredSelection) tableViewer
.getSelection()).getFirstElement();
if (task != null) {
tableViewer.remove(task);
CMLSpectrum spectrum = ((CMLSpectrum) tableViewer.getInput());
spectrum.getPeakListElements().get( 0 ).removeChild(task);
peakTablePage.setDirty(true);
}
}
});
// Create and configure the "export" button
Button export = new Button(parent, SWT.PUSH | SWT.CENTER);
export.setText("Copy to clipboard");
gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gridData.widthHint = 180;
export.setLayoutData(gridData);
export.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
List<CMLElement> peaks = SpectrumUtils.getPeakElements( spectrumItem );
StringBuffer sb=new StringBuffer();
for(int i=0;i<peaks.size();i++){
sb.append( ((CMLPeak)peaks.get( i )).getXValue()+" "+((CMLPeak)peaks.get( i )).getYValue()+"\r\n" );
}
Clipboard clipboard = new Clipboard(PeakTableViewer.this.getControl().getDisplay());
TextTransfer textTransfer = TextTransfer.getInstance();
clipboard.setContents(new String[]{sb.toString()}, new Transfer[]{textTransfer});
clipboard.dispose();
}
});
}
public java.util.List<String> getColumnNames() {
return Arrays.asList(columnNames);
}
public ISelection getSelection() {
return tableViewer.getSelection();
}
/**
* Return the parent composite
*/
public Control getControl() {
return table.getParent();
}
}