/*
* EuroCarbDB, a framework for carbohydrate bioinformatics
*
* Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
* A copy of this license accompanies this distribution in the file LICENSE.txt.
*
* 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 Lesser General Public License
* for more details.
*
* Last commit: $Rev: 1930 $ by $Author: david@nixbioinf.org $ on $Date:: 2010-07-29 #$
*/
/**
@author Alessio Ceroni (a.ceroni@imperial.ac.uk)
*/
package org.eurocarbdb.application.glycoworkbench.plugin;
import org.eurocarbdb.application.glycoworkbench.plugin.reporting.*;
import org.eurocarbdb.application.glycoworkbench.*;
import org.eurocarbdb.application.glycoworkbench.Annotation;
import org.eurocarbdb.application.glycanbuilder.*;
import java.io.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
import java.util.*;
import java.text.*;
import java.awt.print.*;
public class WorkspacePanel extends JPanel implements TreeModel,
ActionListener, TreeSelectionListener,
BaseDocument.DocumentChangeListener, GlycanWorkspace.Listener,
MouseListener {
class WorkspaceTreeCellRenderer extends DefaultTreeCellRenderer {
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
super.getTreeCellRendererComponent(tree, "", sel, expanded, leaf,
row, hasFocus);
setFont(getFont().deriveFont(Font.PLAIN));
if (value instanceof BaseDocument) {
JLabel master;
BaseDocument doc = (BaseDocument) value;
if(doc.getRegisteredComponent("treeView")!=null){
master=(JLabel)doc.getRegisteredComponent("treeView");
master.setBackground(this.getBackground());
master.setForeground(this.getForeground());
}else{
master=new JLabel();
// set icon
if (leaf)
master.setIcon(doc.getIcon());
}
// set text
String text = doc.getName();
if (doc.wasSaved())
text += " - "
+ FileHistory.getAbbreviatedName(doc.getFileName());
if (doc.hasChanged())
text += "*";
master.setText(text);
doc.registerComponent("treeView",master);
return master;
} else if (value instanceof Scan) {
Scan scan = (Scan) value;
String text = (scan.getName() != null && scan.getName()
.length() > 0) ? scan.getName() : "Scan";
if (scan.getPrecursorMZ() != null)
text += " [precursor m/z= "
+ new DecimalFormat("0.0000").format(scan
.getPrecursorMZ().doubleValue()) + " Da]";
setText(text);
if (theWorkspace.isCurrent(scan))
setFont(getFont().deriveFont(Font.BOLD));
}
return this;
}
}
private static final long serialVersionUID = 0L;
// components
protected GlycoWorkbench theApplication;
protected JTree theTree;
protected JScrollPane theScrollPane;
protected JToolBar theToolBarDocument;
protected JToolBar theToolBarEdit;
// data
protected GlycanWorkspace theWorkspace;
// actions
protected ActionManager theActionManager;
protected Vector<TreeModelListener> tm_listeners;
Double edit_mz = null;
Double edit_int = null;
//
public WorkspacePanel(GlycoWorkbench application) {
super(new BorderLayout());
this.theApplication=application;
// init data
//theApplication = null;
theWorkspace = new GlycanWorkspace();
// init actions
theActionManager = new ActionManager();
createActions();
tm_listeners = new Vector<TreeModelListener>();
// create workspace viewer
theTree = new JTree();
theTree.setEditable(false);
theTree.setDragEnabled(false);
theTree.setRootVisible(true);
theTree.setToggleClickCount(3);
theTree.setCellRenderer(new WorkspaceTreeCellRenderer());
theTree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
theTree.setModel(this);
theScrollPane = new JScrollPane(theTree);
add(theScrollPane, BorderLayout.CENTER);
// create toolbar
JPanel theToolBarPanel = new JPanel(new BorderLayout());
theToolBarDocument = createToolBarDocument();
theToolBarEdit = createToolBarEdit();
theToolBarPanel.add(theToolBarDocument, BorderLayout.NORTH);
theToolBarPanel.add(theToolBarEdit, BorderLayout.CENTER);
add(theToolBarPanel, BorderLayout.SOUTH);
// final settings
theWorkspace.addDocumentChangeListener(this);
theWorkspace.addWorkspaceListener(this);
theTree.addTreeSelectionListener(this);
theTree.addMouseListener(this);
expandAll();
setMinimumSize(new Dimension(0, 0));
setBackground(Color.white);
this.setOpaque(true);
}
public void setApplication(GlycoWorkbench application) {
theApplication = application;
updateActions();
updateView();
}
public void setWorkspace(GlycanWorkspace workspace) {
theWorkspace = workspace;
theWorkspace.addWorkspaceListener(this);
theWorkspace.addDocumentChangeListener(this);
updateActions();
updateView();
}
private void createActions() {
// file
theActionManager.add("new", this.theApplication.getThemeManager().getResizableIcon(STOCK_ICON.DOCUMENT_NEW,ICON_SIZE.SMALL),
"Clear selected document", KeyEvent.VK_N, "", this);
theActionManager.add("open",this.theApplication.getThemeManager().getResizableIcon(STOCK_ICON.DOCUMENT_OPEN,ICON_SIZE.SMALL),
"Open selected document", KeyEvent.VK_O, "", this);
theActionManager.add("save",this.theApplication.getThemeManager().getResizableIcon(STOCK_ICON.DOCUMENT_SAVE,ICON_SIZE.SMALL),
"Save selected document", KeyEvent.VK_S, "", this);
theActionManager.add("saveas", this.theApplication.getThemeManager().getResizableIcon(STOCK_ICON.DOCUMENT_SAVE_AS,ICON_SIZE.SMALL),
"Save selected document as...", KeyEvent.VK_A, "", this);
theActionManager.add("newall", this.theApplication.getThemeManager().getResizableIcon("newall",ICON_SIZE.SMALL),
"Clear the workspace", -1, "", this);
theActionManager.add("openall", this.theApplication.getThemeManager().getResizableIcon("openall",ICON_SIZE.SMALL),
"Open a workspace", -1, "", this);
theActionManager.add("saveall", this.theApplication.getThemeManager().getResizableIcon("saveall",ICON_SIZE.SMALL),
"Save the workspace", -1, "", this);
theActionManager.add("saveallas", this.theApplication.getThemeManager().getResizableIcon("saveallas",ICON_SIZE.SMALL),
"Save the workspace as...", -1, "", this);
theActionManager.add("add", this.theApplication.getThemeManager().getResizableIcon("add",ICON_SIZE.SMALL),
"Attach new scan", KeyEvent.VK_D, "", this);
theActionManager.add("delete", this.theApplication.getThemeManager().getResizableIcon("delete",ICON_SIZE.SMALL), "Delete",
KeyEvent.VK_E, "", this);
theActionManager.add("select", this.theApplication.getThemeManager().getResizableIcon("select",ICON_SIZE.SMALL), "Activate",
KeyEvent.VK_L, "", this);
theActionManager.add("sync",ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),"Sync",-1, "",this);
theActionManager.add("properties",this.theApplication.getThemeManager().getResizableIcon("properties",ICON_SIZE.SMALL),
"Properties", KeyEvent.VK_P, "", this);
}
private void updateActions() {
theActionManager.get("new").setEnabled(
hasSelectedDocument() && !hasSelectedAnnotationReport());
theActionManager.get("open").setEnabled(hasSelectedDocument());
theActionManager.get("save").setEnabled(
hasSelectedDocument() && !hasSelectedSpectra());
theActionManager.get("saveas").setEnabled(
hasSelectedDocument() && !hasSelectedSpectra());
// theActionManager.get("undo").setEnabled(theWorkspace.getUndoManager().canUndo());
// theActionManager.get("redo").setEnabled(theWorkspace.getUndoManager().canRedo());
theActionManager.get("delete").setEnabled(
hasSelectedScan() || hasSelectedAnnotationReport());
theActionManager.get("select").setEnabled(hasSelection());
theActionManager.get("properties").setEnabled(hasSelectedScan());
theActionManager.get("sync").setEnabled(hasSelectedScan());
}
private JToolBar createToolBarDocument() {
JToolBar toolbar = new JToolBar();
toolbar.setFloatable(false);
toolbar.add(theActionManager.get("newall"));
toolbar.add(theActionManager.get("openall"));
toolbar.add(theActionManager.get("saveall"));
toolbar.add(theActionManager.get("saveallas"));
toolbar.addSeparator();
toolbar.add(theActionManager.get("new"));
toolbar.add(theActionManager.get("open"));
toolbar.add(theActionManager.get("save"));
toolbar.add(theActionManager.get("saveas"));
// toolbar.addSeparator();
// toolbar.add(theActionManager.get("undo"));
// toolbar.add(theActionManager.get("redo"));
return toolbar;
}
private JToolBar createToolBarEdit() {
JToolBar toolbar = new JToolBar();
toolbar.setFloatable(false);
toolbar.add(theActionManager.get("add"));
toolbar.add(theActionManager.get("delete"));
toolbar.add(theActionManager.get("select"));
toolbar.addSeparator();
toolbar.add(theActionManager.get("properties"));
return toolbar;
}
private JPopupMenu createPopupMenu() {
JPopupMenu menu = new JPopupMenu();
menu.add(theActionManager.get("open"));
menu.add(theActionManager.get("save"));
menu.add(theActionManager.get("saveas"));
menu.addSeparator();
menu.add(theActionManager.get("add"));
menu.add(theActionManager.get("delete"));
menu.add(theActionManager.get("select"));
menu.addSeparator();
menu.add(theActionManager.get("sync"));
menu.add(theActionManager.get("properties"));
return menu;
}
private void showPopup(MouseEvent e) {
theTree.setSelectionPath(theTree.getClosestPathForLocation(e.getX(), e
.getY()));
createPopupMenu().show(this, e.getX(), e.getY());
}
// -------------
// selection
public boolean hasSelection() {
return theTree.getSelectionPath() != null;
}
public boolean hasSelectedWorkspace() {
return (getSelectedObject() instanceof GlycanWorkspace);
}
public boolean hasSelectedSpectra() {
return (getSelectedObject() instanceof SpectraDocument);
}
public boolean hasSelectedScan() {
return (getSelectedObject() instanceof Scan);
}
public boolean hasSelectedAnnotationReport() {
return (getSelectedObject() instanceof AnnotationReportDocument);
}
public boolean hasSelectedDocument() {
return (getSelectedObject() instanceof BaseDocument);
}
public Object getSelectedObject() {
TreePath sel = theTree.getSelectionPath();
if (sel != null)
return sel.getLastPathComponent();
return null;
}
public Scan getSelectedScan() {
Object node = getSelectedObject();
if (node != null && (node instanceof Scan))
return (Scan) node;
return null;
}
public AnnotationReportDocument getSelectedAnnotationReport() {
Object node = getSelectedObject();
if (node != null && (node instanceof AnnotationReportDocument))
return (AnnotationReportDocument) node;
return null;
}
public BaseDocument getSelectedDocument() {
Object node = getSelectedObject();
if (node != null && (node instanceof BaseDocument))
return (BaseDocument) node;
return null;
}
public Scan getSelectedObjectOrParentScan() {
TreePath sel = theTree.getSelectionPath();
if (sel != null) {
Object node = sel.getLastPathComponent();
if (node instanceof Scan)
return (Scan) node;
if ((node instanceof GlycanDocument)
|| (node instanceof FragmentDocument)
|| (node instanceof SpectraDocument)
|| (node instanceof PeakList)
|| (node instanceof AnnotatedPeakList)
|| (node instanceof NotesDocument)
|| (node instanceof AnnotationReportDocument))
return (Scan) sel.getParentPath().getLastPathComponent();
}
return null;
}
// ---------------
// table model
public void expandAll() {
for (Scan s : theWorkspace.getScanList())
expandSubTree(s);
}
public void expandSubTree(Scan s) {
expand(s);
for (Scan c : s.getChildren())
expandSubTree(c);
}
public void expand(Object node) {
theTree.expandPath(getTreePath(node));
}
public Object getRoot() {
return theWorkspace;
}
public Object getChild(Object parent, int index) {
if (parent == theWorkspace)
return theWorkspace.scanAt(index);
else if (parent instanceof Scan) {
if (index == 0)
return ((Scan) parent).getStructures();
if (index == 1)
return ((Scan) parent).getFragments();
if (index == 2)
return ((Scan) parent).getSpectra();
if (index == 3)
return ((Scan) parent).getPeakList();
if (index == 4)
return ((Scan) parent).getAnnotatedPeakList();
if (index == 5)
return ((Scan) parent).getNotes();
if (index >= 6
&& index <= 5 + ((Scan) parent).getAnnotationReports()
.size())
return ((Scan) parent).getAnnotationReports().get(index - 6);
else
return ((Scan) parent).childAt(index
- ((Scan) parent).getAnnotationReports().size() - 6);
}
return null;
}
public int getIndexOfChild(Object parent, Object child) {
if (parent == theWorkspace)
return theWorkspace.indexOf((Scan) child);
else if (parent instanceof Scan) {
if (child == ((Scan) parent).getStructures())
return 0;
if (child == ((Scan) parent).getFragments())
return 1;
if (child == ((Scan) parent).getSpectra())
return 2;
if (child == ((Scan) parent).getPeakList())
return 3;
if (child == ((Scan) parent).getAnnotatedPeakList())
return 4;
if (child == ((Scan) parent).getNotes())
return 5;
if (((Scan) parent).getAnnotationReports().contains(child))
return 6 + ((Scan) parent).getAnnotationReports()
.indexOf(child);
if (child instanceof Scan)
return 6 + ((Scan) parent).getAnnotationReports().size()
+ ((Scan) parent).indexOf((Scan) child);
}
return -1;
}
public TreePath getTreePath(Object node) {
if (node == theWorkspace)
return new TreePath(theWorkspace);
for (Scan s : theWorkspace.getScanList()) {
TreePath ret = getTreePath(new Union(theWorkspace), s, node);
if (ret != null)
return ret;
}
return null;
}
private TreePath getTreePath(Union<Object> path, Scan cur_node, Object node) {
if (cur_node == node)
return new TreePath(path.and(cur_node).toArray());
if (node == cur_node.getStructures())
return new TreePath(path.and(cur_node).and(node).toArray());
if (node == cur_node.getFragments())
return new TreePath(path.and(cur_node).and(node).toArray());
if (node == cur_node.getSpectra())
return new TreePath(path.and(cur_node).and(node).toArray());
if (node == cur_node.getPeakList())
return new TreePath(path.and(cur_node).and(node).toArray());
if (node == cur_node.getAnnotatedPeakList())
return new TreePath(path.and(cur_node).and(node).toArray());
if (node == cur_node.getNotes())
return new TreePath(path.and(cur_node).and(node).toArray());
if (cur_node.getAnnotationReports().contains(node))
return new TreePath(path.and(cur_node).and(node).toArray());
for (Scan s : cur_node.getChildren()) {
TreePath ret = getTreePath(path.and(cur_node), s, node);
if (ret != null)
return ret;
}
return null;
}
public int getChildCount(Object parent) {
if (parent == theWorkspace)
return theWorkspace.getNoScans();
else if (parent instanceof Scan)
return 6 + ((Scan) parent).getAnnotationReports().size()
+ ((Scan) parent).getNoChildren();
return 0;
}
public boolean isLeaf(Object node) {
return (node != theWorkspace && !(node instanceof Scan));
}
public void valueForPathChanged(TreePath path, Object newValue) {
}
public void addTreeModelListener(TreeModelListener l) {
if (l != null)
tm_listeners.add(l);
}
public void removeTreeModelListener(TreeModelListener l) {
tm_listeners.remove(l);
}
// -----------------
// data
public boolean checkDocumentChanges() {
/*
* if( theWorkspace.hasChanged() && !theWorkspace.isEmpty() ) { int ret
* = JOptionPane.showConfirmDialog(this,"Save changes to peak list?",
* null, JOptionPane.YES_NO_CANCEL_OPTION,
* JOptionPane.QUESTION_MESSAGE); if( ret == JOptionPane.CANCEL_OPTION )
* return false; if( ret == JOptionPane.YES_OPTION ) { if(
* !theApplication.onSaveAs(theWorkspace) ) return false; } } return
* true;
*/
return true;
}
// -----------
// Visualization
public void updateView() {
fireTreeStructureChanged(theWorkspace);
expandAll();
}
// -----------------
// actions
public void onPrint() {
}
/*
* public void onUndo() { try { theWorkspace.getUndoManager().undo(); }
* catch(Exception e) { LogUtils.report(e); } }
*
* public void onRedo() { try { theWorkspace.getUndoManager().redo(); }
* catch(Exception e) { LogUtils.report(e); } }
*/
public void cut() {
copy();
delete();
}
public void copy() {
}
public void paste() {
}
public boolean sync(){
System.err.println("Sync has been called");
if(hasSelectedScan()){
Scan scan=getSelectedScan();
if(scan!=null){
return theWorkspace.syncScan(scan);
}
}
return false;
}
public void delete() {
if (hasSelectedScan()) {
Scan s = getSelectedScan();
if (s != null
&& JOptionPane
.showConfirmDialog(
this,
"Are you sure to remove the selected scan, its children, and all the data associated?") == JOptionPane.YES_OPTION)
theWorkspace.removeScan(s.getParent(), s);
} else {
AnnotationReportDocument ard = getSelectedAnnotationReport();
if (ard != null
&& JOptionPane
.showConfirmDialog(this,
"Are you sure to remove the selected annotation report?") == JOptionPane.YES_OPTION)
theWorkspace.removeAnnotationReport(ard);
}
}
public void onAdd() {
Scan s = getSelectedObjectOrParentScan();
theWorkspace.addScan(s, new Scan(theWorkspace));
}
public void onSelect() {
try {
Object sel = getSelectedObject();
if (sel instanceof Scan)
select((Scan) sel);
else if (sel instanceof GlycanDocument) {
select(getSelectedObjectOrParentScan());
// theApplication.getPluginManager().show("Structures","Structures");
} else if (sel instanceof FragmentDocument) {
select(getSelectedObjectOrParentScan());
theApplication.getPluginManager().show("Fragments", "Summary");
} else if (sel instanceof SpectraDocument) {
select(getSelectedObjectOrParentScan());
theApplication.getPluginManager().show("Spectra", "Spectra");
} else if (sel instanceof PeakList) {
select(getSelectedObjectOrParentScan());
theApplication.getPluginManager().show("PeakList", "PeakList");
} else if (sel instanceof AnnotatedPeakList) {
select(getSelectedObjectOrParentScan());
theApplication.getPluginManager().show("Annotation", "Summary");
} else if (sel instanceof NotesDocument) {
select(getSelectedObjectOrParentScan());
theApplication.getPluginManager().show("Notes", "Notes");
} else if (sel instanceof AnnotationReportDocument) {
select(getSelectedObjectOrParentScan());
((ReportingPlugin) theApplication.getPluginManager().get(
"Reporting")).showAnnotationsReport(
(AnnotationReportDocument) sel, false);
}
} catch (Exception ex) {
LogUtils.report(ex);
}
}
public void select(Scan s) {
if (s != null)
theWorkspace.setCurrentScan(s);
}
public void onProperties() {
Scan s = getSelectedScan();
if (s != null) {
/*
* String m_z = JOptionPane.showInputDialog(this,
* "Insert m/z value of the precursor ion", s.getPrecursorMZ()); if(
* m_z!=null ) theWorkspace.setPrecursorMZ(s,Double.valueOf(m_z));
*/
new ScanPropertiesDialog(theApplication, s, theWorkspace)
.setVisible(true);
}
}
// -----------
// listeners
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
if (action.equals("newall"))
theApplication.onNew(theWorkspace);
else if (action.equals("openall"))
theApplication.onOpen(null, theWorkspace, false);
else if (action.equals("saveall"))
theApplication.onSave(theWorkspace);
else if (action.equals("saveallas"))
theApplication.onSaveAs(theWorkspace);
else if (action.equals("new"))
theApplication.onNew(getSelectedDocument());
else if (action.equals("open")) {
if (theApplication.onOpen(null, getSelectedDocument(), false))
onSelect();
} else if (action.equals("save"))
theApplication.onSave(getSelectedDocument());
else if (action.equals("saveas"))
theApplication.onSaveAs(getSelectedDocument());
/*
* else if( action.equals("undo") ) onUndo(); else if(
* action.equals("redo") ) onRedo();
*/
/*
* else if( action.equals("cut") ) cut(); else if( action.equals("copy")
* ) copy(); else if( action.equals("paste") ) paste();
*/
if (action.equals("add"))
onAdd();
else if (action.equals("delete"))
delete();
else if (action.equals("select"))
onSelect();
else if (action.equals("properties"))
onProperties();
else if (action.equals("sync"))
sync();
updateActions();
}
public void valueChanged(TreeSelectionEvent e) {
updateActions();
}
public void currentScanChanged(GlycanWorkspace.Event e) {
fireTreeNodesChanged(e.getChildScan());
fireTreeNodesChanged(e.getCurrentScan());
updateActions();
}
public void scanAdded(GlycanWorkspace.Event e) {
fireTreeNodesInserted(e.getParentScan(), e.getChildScan(), e.getIndex());
expand(e.getChildScan());
updateActions();
}
public void scanRemoved(GlycanWorkspace.Event e) {
fireTreeNodesRemoved(e.getParentScan(), e.getChildScan(), e.getIndex());
updateActions();
}
public void internalDocumentChanged(GlycanWorkspace.Event e) {
fireTreeNodesChanged(e.getSource());
updateActions();
}
public void documentInit(BaseDocument.DocumentChangeEvent e) {
fireTreeStructureChanged(e.getSource());
updateActions();
}
public void documentChanged(BaseDocument.DocumentChangeEvent e) {
if (e.getSource() == theWorkspace)
fireTreeStructureChanged(e.getSource());
else
fireTreeNodesChanged(e.getSource());
updateActions();
}
public void mousePressed(MouseEvent e) {
if (MouseUtils.isPopupTrigger(e))
showPopup(e);
}
public void mouseReleased(MouseEvent e) {
if (MouseUtils.isPopupTrigger(e))
showPopup(e);
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
if (MouseUtils.isSelectTrigger(e))
onSelect();
}
public void fireTreeNodesChanged(Object node) {
for (TreeModelListener tml : tm_listeners)
tml.treeNodesChanged(new TreeModelEvent(this, getTreePath(node)));
}
public void fireTreeNodesInserted(Object parent, Object child, int index) {
TreePath par_path = (parent == null) ? getTreePath(theWorkspace)
: getTreePath(parent);
for (TreeModelListener tml : tm_listeners)
tml.treeNodesInserted(new TreeModelEvent(this, par_path,
new int[] { index }, new Object[] { child }));
}
public void fireTreeNodesRemoved(Object parent, Object child, int index) {
TreePath par_path = (parent == null) ? getTreePath(theWorkspace)
: getTreePath(parent);
for (TreeModelListener tml : tm_listeners)
tml.treeNodesRemoved(new TreeModelEvent(this, par_path,
new int[] { index }, new Object[] { child }));
}
public void fireTreeStructureChanged(Object node) {
TreePath path = (node == null) ? getTreePath(theWorkspace)
: getTreePath(node);
for (TreeModelListener tml : tm_listeners)
tml.treeStructureChanged(new TreeModelEvent(this, path));
expandAll();
}
}