/*
* Copyright (c) 2014. Matthew Campbell <matthew.campbell@mq.edu.au>, David R. Damerell <david@nixbioinf.org>.
*
* This file is part of GlycanBuilder Vaadin Release and its affliated projects EUROCarbDB, UniCarb-DB and UniCarbKB.
*
* This program is free software 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.
*
* GlycanBuilder Vaadin Release 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 (LICENSE.txt) for more details.
*
* You should have received a copy of the GNU General Public License
* along with GlycanBuilder Vaadin Release. If not, see <http ://www.gnu.org/licenses/>.
*/
package ac.uk.icl.dell.vaadin.glycanbuilder;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import org.eurocarbdb.application.glycanbuilder.AbstractGlycanRenderer;
import org.eurocarbdb.application.glycanbuilder.BuilderWorkspace;
import org.eurocarbdb.application.glycanbuilder.CoreDictionary;
import org.eurocarbdb.application.glycanbuilder.CoreType;
import org.eurocarbdb.application.glycanbuilder.Glycan;
import org.eurocarbdb.application.glycanbuilder.GlycanDocument;
import org.eurocarbdb.application.glycanbuilder.GlycanRendererAWT;
import org.eurocarbdb.application.glycanbuilder.GlycanRendererMode;
import org.eurocarbdb.application.glycanbuilder.GraphicOptions;
import org.eurocarbdb.application.glycanbuilder.Linkage;
import org.eurocarbdb.application.glycanbuilder.LogUtils;
import org.eurocarbdb.application.glycanbuilder.MassOptions;
import org.eurocarbdb.application.glycanbuilder.RepetitionPropertiesDialog;
import org.eurocarbdb.application.glycanbuilder.Residue;
import org.eurocarbdb.application.glycanbuilder.ResidueDictionary;
import org.eurocarbdb.application.glycanbuilder.ResiduePropertiesDialog;
import org.eurocarbdb.application.glycanbuilder.ResidueType;
import org.eurocarbdb.application.glycanbuilder.SVGUtils;
import org.eurocarbdb.application.glycanbuilder.TerminalDictionary;
import org.eurocarbdb.application.glycanbuilder.TerminalType;
import ac.uk.icl.dell.vaadin.LocalResourceWatcher;
import ac.uk.icl.dell.vaadin.MessageDialogBox;
import ac.uk.icl.dell.vaadin.ProducesLocalResources;
import ac.uk.icl.dell.vaadin.canvas.basiccanvas.BasicCanvas;
import ac.uk.icl.dell.vaadin.canvas.basiccanvas.font.Font;
import ac.uk.icl.dell.vaadin.canvas.basiccanvas.font.Font.FONT;
import ac.uk.icl.dell.vaadin.glycanbuilder.MassOptionsDialog.MassOptionListener;
import ac.uk.icl.dell.vaadin.navigator7.pages.buildingblocks.NavigatorFileUpload;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.server.DownloadStream;
import com.vaadin.server.FileResource;
import com.vaadin.server.Page;
import com.vaadin.server.ThemeResource;
import com.vaadin.ui.AbstractSelect;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.ListSelect;
import com.vaadin.ui.MenuBar.Command;
import com.vaadin.ui.MenuBar.MenuItem;
import com.vaadin.ui.NativeButton;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.Panel;
import com.vaadin.ui.PopupView;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.Upload.FailedEvent;
import com.vaadin.ui.Upload.SucceededEvent;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
public class VaadinGlycanCanvas extends BasicCanvas implements BasicCanvas.SelectionListener, GlycanCanvas.GlycanCanvasUpdateListener, GlycanCanvas.SelectionChangeListener, ProducesLocalResources, MassOptionListener{
private static final long serialVersionUID=-4055030966241059255L;
private List<Component> componentsWithResidueSelectionDependency;
public List<MenuItem> menuItemsWithResidueSelectionDependency;
private List<LocalResourceWatcher> localResourceWatchers=new ArrayList<LocalResourceWatcher>();
protected GlycanCanvas theCanvas;
protected boolean automaticallyAdjustHeight=true;
private OptionGroup field_anomeric_state;
private OptionGroup field_anomeric_carbon;
private OptionGroup field_linkage_position;
private OptionGroup field_chirality;
private OptionGroup field_ring_size;
private CheckBox field_second_bond;
private OptionGroup field_second_child_position;
private OptionGroup field_second_parent_position;
private PopupView linkage_one_panel;
private PopupView linkage_two_panel;
float realWidth;
float realHeight;
public VaadinGlycanCanvas() {
theCanvas=new GlycanCanvas(new GlycanRendererCanvas(),new CanvasPaintable(this));
theCanvas.addGlycanCanvasUpdateListener(this);
this.addListener((CanvasMouseUpListener)this);
this.addListener((CanvasMouseDownListener)this);
this.setFont(Font.getFont(FONT.STANDARD));
componentsWithResidueSelectionDependency=new ArrayList<Component>();
menuItemsWithResidueSelectionDependency=new ArrayList<MenuItem>();
addSelectionListener(this);
theCanvas.addSelectionChangeListener(this);
theCanvas.theWorkspace.getGraphicOptions().SHOW_REDEND_CANVAS=false;
theCanvas.theWorkspace.getGraphicOptions().SHOW_MASSES_CANVAS=false;
setImmediate(true);
}
public void setDocument(GlycanDocument doc){
theCanvas.setDocument(doc);
updateActions();
}
public void appendStructureMenu(MenuItem parent){
MenuItem structureMenu=parent.addItem("Add structure", null);
for(String superclass:CoreDictionary.getSuperclasses()){
MenuItem superClassMenu=structureMenu.addItem(superclass,null);
for(final CoreType t:CoreDictionary.getCores(superclass)){
superClassMenu.addItem(t.getName(), new Command(){
private static final long serialVersionUID=-148395291969656325L;
@Override
public void menuSelected(MenuItem selectedItem) {
theCanvas.addSequenceByName(t.getName());
}
});
}
}
createAddResidueMenu(parent);
createInsertResidueMenu(parent);
createChangeResidueMenu(parent);
createTerminalMenu(parent);
}
private void createTerminalMenu(MenuItem parent){
MenuItem structureMenu=parent.addItem("Add terminal", null);
for(String superclass : TerminalDictionary.getSuperclasses()){
MenuItem superClassMenu=structureMenu.addItem(superclass,null);
for (TerminalType t : TerminalDictionary.getTerminals(superclass)) {
MenuItem terminalType=superClassMenu.addItem(t.getDescription(),null);
final String type=t.getName();
Command addTerminal=new Command(){
private static final long serialVersionUID=6872577027235164629L;
@Override
public void menuSelected(MenuItem selectedItem) {
String longForm=selectedItem.getText();
if(longForm.equals("Unknown linkage")){
theCanvas.addTerminal(type);
}else{
theCanvas.addTerminal(longForm.charAt(0)+"-"+type);
}
}
};
terminalType.addItem("Unknown linkage", addTerminal);
for (int l = 1; l < 9; l++) {
terminalType.addItem(l+"-linked", addTerminal);
}
}
}
}
public void appendImportMenu(MenuItem parent, MenuItem beforeItem){
final Window importWindow=new Window(){
private static final long serialVersionUID=-397373017493034496L;
@Override
public void close(){
setVisible(false);
}
};
importWindow.setCaption("Import from sequence");
importWindow.setResizable(false);
final CanvasImport canvasImport=new CanvasImport();
VerticalLayout canvasImportLayout = new VerticalLayout();
canvasImportLayout.setMargin(true);
canvasImportLayout.addComponent(canvasImport);
importWindow.setContent(canvasImportLayout);
importWindow.center();
importWindow.setVisible(false);
@SuppressWarnings("unused")
MenuItem importMenu=parent.addItemBefore("Import",null, new Command(){
private static final long serialVersionUID=-6735134306275926140L;
@Override
public void menuSelected(MenuItem selectedItem) {
if(!importWindow.isVisible()){
if(UI.getCurrent().getWindows().contains(importWindow)==false){
UI.getCurrent().addWindow(importWindow);
}
importWindow.setVisible(true);
}
}
},beforeItem);
importWindow.setSizeUndefined();
importWindow.getContent().setSizeUndefined();
final Window importFromStringWindow=new Window(){
private static final long serialVersionUID=7035248961169308096L;
@Override
public void close(){
setVisible(false);
}
};
importFromStringWindow.setCaption("Import sequence from string");
importFromStringWindow.setWidth("50%");
importFromStringWindow.setHeight("50%");
final ImportStructureFromStringDialog importStructureStringDialog=new ImportStructureFromStringDialog(theCanvas);
importStructureStringDialog.addListener(new UserInputEndedListener() {
@Override
public void done(boolean cancelled) {
if(!cancelled){
if(!theCanvas.theDoc.importFromString(importStructureStringDialog.getSequenceString(),theCanvas.getImportFormatShortFormat(importStructureStringDialog.getSequenceFormat()))){
reportMessage(LogUtils.getLastError());
LogUtils.clearLastError();
}
}
}
});
VerticalLayout layout=new VerticalLayout();
layout.setSizeFull();
importFromStringWindow.setContent(layout);
layout.addComponent(importStructureStringDialog);
layout.setComponentAlignment(importStructureStringDialog, Alignment.MIDDLE_CENTER);
importFromStringWindow.center();
importFromStringWindow.setVisible(false);
@SuppressWarnings("unused")
MenuItem importFromStringMenu=parent.addItemBefore("Import from string",null, new Command(){
private static final long serialVersionUID=1586089744665899803L;
@Override
public void menuSelected(MenuItem selectedItem) {
if(!importFromStringWindow.isVisible()){
if(UI.getCurrent().getWindows().contains(importFromStringWindow)==false){
UI.getCurrent().addWindow(importFromStringWindow);
}
importFromStringWindow.setVisible(true);
}
}
},beforeItem);
}
public class CanvasImport extends Panel {
private static final long serialVersionUID=8487960720141044728L;
NavigatorFileUpload uploader;
ListSelect importTypes;
public CanvasImport(){
VerticalLayout canvasImportLayout = new VerticalLayout();
canvasImportLayout.setMargin(true);
setContent(canvasImportLayout);
uploader=new NavigatorFileUpload("Upload"){
@Override
public void uploadFailed(FailedEvent failedEvent){
reportMessage("Upload failed");
}
@Override
public void uploadSucceeded(SucceededEvent succeededEvent){
File file=getUploadedFile();
String format=theCanvas.getImportFormatShortFormat((String)importTypes.getValue());
try{
theCanvas.theDoc.importFrom(file.getPath(), format);
}catch(Exception ex){
reportMessage("Wrong format or invalid content");
}
if(LogUtils.hasLastError()){
reportMessage("Wrong format or invalid content");
}
LogUtils.clearLastError();
if(file.delete()==false){
reportException(new Exception("Unable to delete file: "+file.getPath()));
}
removeLocalResource(file);
}
@Override
public void uploadFailed(Message msg){
reportMessage(msg.getMessage());
}
};
uploader.setLocalResourceWatchers(localResourceWatchers);
List<String> importTypeList=theCanvas.getImportFormats();
importTypes=new ListSelect("Format", importTypeList);
importTypes.setNullSelectionAllowed(false);
importTypes.setValue(importTypeList.get(0));
canvasImportLayout.addComponent(importTypes);
canvasImportLayout.addComponent(uploader.getUploadComponent());
}
}
public void showMessage(String message,String width, String height){
showMessage(message,width,height,"");
}
public void showMessage(String message,String width, String height,String caption){
Label messageLabel=new Label(message);
Window window = new Window(caption);
VerticalLayout windowContent = new VerticalLayout();
windowContent.addComponent(messageLabel);
windowContent.setMargin(true);
windowContent.setComponentAlignment(messageLabel, Alignment.MIDDLE_CENTER);
window.setContent(windowContent);
window.setWidth(width);
window.setHeight(height);
window.center();
UI.getCurrent().addWindow(window);
}
public void addLocalResource(File file){
for(LocalResourceWatcher watcher:localResourceWatchers){
watcher.addLocalResource(file);
}
}
public void removeLocalResource(File file){
for(LocalResourceWatcher watcher:localResourceWatchers){
watcher.removeLocalResource(file);
}
}
public void appendExportMenu(MenuItem parent, MenuItem beforeItem){
Command command=new Command(){
/**
*
*/
private static final long serialVersionUID=-3300979660830126504L;
@Override
public void menuSelected(MenuItem selectedItem) {
if(theCanvas.theDoc.getStructures().size()==0){
return;
}
String format=theCanvas.getInternalFormat(selectedItem.getText());
try {
File file = File.createTempFile("seq", "."+format);
addLocalResource(file);
theCanvas.theDoc.exportTo(file.getPath(), format);
String mimeType="text/plain";
if(format.equals("glycoct_xml") || format.equals("glyde")){
mimeType="text/xml";
}
final String finalMimeType=mimeType;
Page.getCurrent().open(new FileResource(file){
private static final long serialVersionUID=6816460214678812683L;
@Override
public DownloadStream getStream(){
try{
final DownloadStream ds=new DownloadStream(new FileInputStream(getSourceFile()),finalMimeType,getFilename());
ds.setParameter("Content-Disposition", "attachment; filename=\"" +getFilename() + "\"");
ds.setCacheTime(getCacheTime());
return ds;
}catch(Exception ex){
reportMessage("An error has occured attempting to export the glycan canvas", ex);
}
return null;
}
}, "_blank", true);
} catch (IOException e) {
reportMessage("An error has occured attempting to export the glycan canvas", e);
}
}
};
MenuItem exportMenu=parent.addItemBefore("Export", null, null, beforeItem);
for(String format:theCanvas.getSequenceExportFormats()){
exportMenu.addItem(format, command);
}
Command onImageExport=new Command(){
private static final long serialVersionUID=-3304865968113708422L;
@Override
public void menuSelected(MenuItem selectedItem) {
if(theCanvas.theDoc.getStructures().size()==0){
return;
}
String format=theCanvas.getImageExportShortFormat(selectedItem.getText());
try {
File file = File.createTempFile("seq", "."+format);
for(LocalResourceWatcher watcher:localResourceWatchers){
watcher.addLocalResource(file);
}
GlycanRendererAWT renderer=new GlycanRendererAWT((AbstractGlycanRenderer)theCanvas.getWorkspace().getGlycanRenderer());
SVGUtils.export(renderer,file.getPath(),theCanvas.theDoc.getStructures(),theCanvas.theWorkspace.getGraphicOptions().SHOW_MASSES_CANVAS,theCanvas.theWorkspace.getGraphicOptions().SHOW_REDEND_CANVAS,format);
String mimeType="image/"+format;
if(format.equals("pdf")){
mimeType="application/pdf";
}else if(format.equals("ps")){
mimeType="application/postscript";
}else if(format.equals("svg")){
mimeType=mimeType.concat("+xml");
}
final String finalMimeType=mimeType;
Page.getCurrent().open(new FileResource(file){
private static final long serialVersionUID=7843576185418877104L;
@Override
public DownloadStream getStream(){
try{
final DownloadStream ds=new DownloadStream(new FileInputStream(getSourceFile()),finalMimeType,getFilename());
ds.setParameter("Content-Disposition", "attachment; filename=\"" +getFilename() + "\"");
ds.setCacheTime(getCacheTime());
return ds;
}catch(Exception ex){
reportMessage("An error has occured attempting to export the glycan canvas", ex);
}
return null;
}
}, "_blank", true);
} catch (IOException e) {
reportMessage("An error has occured attempting to export the glycan canvas", e);
}
}
};
MenuItem exportToImageMenu=parent.addItemBefore("Image export", null,null,beforeItem);
for(String format:theCanvas.getImageExportFormats()){
exportToImageMenu.addItem(format, onImageExport);
}
}
public void createAddResidueMenu(MenuItem parent) {
String notation=theCanvas.getWorkspace().getGlycanRenderer().getGraphicOptions().NOTATION;
MenuItem structureMenu=parent.addItem("Add residue", null);
for (String superclass : ResidueDictionary.getSuperclasses()) {
MenuItem superClassMenu=structureMenu.addItem(superclass,null);
for (ResidueType t : ResidueDictionary.getResidues(superclass)) {
if (t.canHaveParent()){
superClassMenu.addItem(t.getName(), new Command(){
private static final long serialVersionUID=4750928193466060500L;
@Override
public void menuSelected(MenuItem selectedItem) {
theCanvas.addResidueByNameToSelected(selectedItem.getText());
}
}).setIcon(new ThemeResource("icons"+File.separator+"residues"+File.separator+notation+File.separator+t.getName()+".png"));
}
}
if(superClassMenu.getChildren()==null){
structureMenu.removeChild(superClassMenu);
}
}
}
public void createInsertResidueMenu(MenuItem parent){
MenuItem structureMenu=parent.addItem("Insert residue", null);
String notation=theCanvas.getWorkspace().getGlycanRenderer().getGraphicOptions().NOTATION;
for (String superclass : ResidueDictionary.getSuperclasses()) {
MenuItem superClassMenu=structureMenu.addItem(superclass,null);
for (ResidueType t : ResidueDictionary.getResidues(superclass)) {
if (t.canHaveParent() && t.canHaveChildren()
&& t.getMaxLinkages() >= 2){
superClassMenu.addItem(t.getName(), new Command(){
private static final long serialVersionUID=2685831199169131556L;
@Override
public void menuSelected(MenuItem selectedItem) {
theCanvas.insertResidueByNameBeforeSelected(selectedItem.getText());
}
}).setIcon(new ThemeResource("icons"+File.separator+"residues"+File.separator+notation+File.separator+t.getName()+".png"));
}
}
if(superClassMenu.getChildren()==null){
structureMenu.removeChild(superClassMenu);
}
}
structureMenu.setEnabled(false);
menuItemsWithResidueSelectionDependency.add(structureMenu);
}
private void createChangeResidueMenu(MenuItem parent) {
MenuItem structureMenu=parent.addItem("Change residue", null);
String notation=theCanvas.getWorkspace().getGlycanRenderer().getGraphicOptions().NOTATION;
for (String superclass : ResidueDictionary.getSuperclasses()) {
MenuItem superClassMenu=structureMenu.addItem(superclass,null);
for (ResidueType t : ResidueDictionary.getResidues(superclass)){
superClassMenu.addItem(t.getName(), new Command(){
private static final long serialVersionUID=-7886271503255704127L;
@Override
public void menuSelected(MenuItem selectedItem) {
theCanvas.changeSelectedToResidueByName(selectedItem.getText());
}
}).setIcon(new ThemeResource("icons"+File.separator+"residues"+File.separator+notation+File.separator+t.getName()+".png"));
}
if(superClassMenu.getChildren()==null){
structureMenu.removeChild(superClassMenu);
}
}
structureMenu.setEnabled(false);
menuItemsWithResidueSelectionDependency.add(structureMenu);
}
public void appendNotationMenu(MenuItem parent) {
final HashMap<String,String> notationIndex=new HashMap<String,String>();
Command notationChangeCommand=new Command(){
private static final long serialVersionUID=5081687058270283137L;
@Override
public void menuSelected(MenuItem selectedItem) {
String notation=notationIndex.get(selectedItem.getText());
theCanvas.setNotation(notation);
}
};
parent.addItem("CFG notation", notationChangeCommand);
notationIndex.put("CFG notation", GraphicOptions.NOTATION_CFG);
parent.addItem("CFG black and white notation", notationChangeCommand);
notationIndex.put("CFG black and white notation", GraphicOptions.NOTATION_CFGBW);
parent.addItem("CFG with linkage placement notation", notationChangeCommand);
notationIndex.put("CFG with linkage placement notation", GraphicOptions.NOTATION_CFGLINK);
parent.addItem("UOXF notation", notationChangeCommand);
notationIndex.put("UOXF notation", GraphicOptions.NOTATION_UOXF);
parent.addItem("UOXFCOL notation", notationChangeCommand);
notationIndex.put("UOXFCOL notation", GraphicOptions.NOTATION_UOXFCOL);
parent.addItem("Text only notation", notationChangeCommand);
notationIndex.put("Text only notation", GraphicOptions.NOTATION_TEXT);
parent.addItem("Show Masses", new ThemeResource("icons/uncheckedbox.png"),new Command(){
private static final long serialVersionUID=6140157670134115820L;
@Override
public void menuSelected(MenuItem selectedItem) {
//selectedItem.setIcon(arg0);
boolean showMasses=theCanvas.theWorkspace.getGraphicOptions().SHOW_MASSES_CANVAS;
if(showMasses){
theCanvas.theWorkspace.getGraphicOptions().SHOW_MASSES_CANVAS=false;
selectedItem.setIcon(new ThemeResource("icons/uncheckedbox.png"));
}else{
theCanvas.theWorkspace.getGraphicOptions().SHOW_MASSES_CANVAS=true;
selectedItem.setIcon(new ThemeResource("icons/checkbox.png"));
}
theCanvas.documentUpdated();
}
});
parent.addItem("Show reducing end symbol",new ThemeResource("icons/uncheckedbox.png"), new Command(){
private static final long serialVersionUID=-5209359926737326181L;
@Override
public void menuSelected(MenuItem selectedItem) {
boolean showRedEnd=theCanvas.theWorkspace.getGraphicOptions().SHOW_REDEND_CANVAS;
if(showRedEnd){
theCanvas.theWorkspace.getGraphicOptions().SHOW_REDEND_CANVAS=false;
selectedItem.setIcon(new ThemeResource("icons/uncheckedbox.png"));
}else{
theCanvas.theWorkspace.getGraphicOptions().SHOW_REDEND_CANVAS=true;
selectedItem.setIcon(new ThemeResource("icons/checkbox.png"));
}
theCanvas.documentUpdated();
}
});
final Window massOptionsDialog=new Window(){
private static final long serialVersionUID=-5094399884130705221L;
@Override
public void close(){
setVisible(false);
}
};
massOptionsDialog.setResizable(false);
//massOptionsDialog.setIcon(new ThemeResource("icons/massoptions.png"));
massOptionsDialog.setCaption("Mass options");
MassOptionsDialog dialog=new MassOptionsDialog(theCanvas.theDoc.getStructures(), theCanvas.theWorkspace.getDefaultMassOptions());
dialog.addMassOptionListener(this);
VerticalLayout massOptionsDialogLayout = new VerticalLayout(dialog);
massOptionsDialogLayout.setMargin(true);
massOptionsDialogLayout.setComponentAlignment(dialog, Alignment.MIDDLE_CENTER);
massOptionsDialog.setContent(massOptionsDialogLayout);
massOptionsDialog.setVisible(false);
massOptionsDialog.center();
parent.addItem("Mass options",new Command(){
private static final long serialVersionUID=-589321392382766804L;
@Override
public void menuSelected(MenuItem selectedItem) {
if(massOptionsDialog.getParent()==null){
UI.getCurrent().addWindow(massOptionsDialog);
}
massOptionsDialog.setVisible(true);
}
});
massOptionsDialog.setSizeUndefined();
massOptionsDialog.getContent().setSizeUndefined();
}
public void enableResidueToolBarMode(){
theCanvas.getWorkspace().getGlycanRenderer().setRenderMode(GlycanRendererMode.TOOLBAR);
appendResidueToolBar();
}
public void clearAll(){
clear(); //clear remote canvas
theCanvas.clear(); //clear residue/linkage selection state and the glycan document of all structures
}
public void appendResidueToolBar(){
theCanvas.setDocumentChangedEventFiring(false);
HashSet<String> selectedResiduesByName=new HashSet<String>();
for(Residue res:theCanvas.selectedResidues){
selectedResiduesByName.add(res.getTypeName());
}
clearAll();
HashSet<String> drawn=new HashSet<String>();
for(Iterator<ResidueType> i=ResidueDictionary.directResidues().iterator();i.hasNext();) {
ResidueType t = i.next();
if(t.canHaveParent()){
theCanvas.addResidueByNameToSelected(t.getName());
drawn.add(t.getName());
}
}
int numberOfResiduesInHistory=theCanvas.residueTypeHistoryList.size();
if(theCanvas.residueTypeHistoryList.size()>0){
for(int i=0;i<numberOfResiduesInHistory;i++){
String name=theCanvas.residueTypeHistoryList.get(i);
if(!drawn.contains(name)){
theCanvas.addResidueByNameToSelected(name);
}
}
}
theCanvas.selectAllResiduesByName(selectedResiduesByName);
theCanvas.documentUpdated();
theCanvas.setDocumentChangedEventFiring(true);
}
public void setResidueHistoryList(Vector<String> residueHistoryList){
theCanvas.residueTypeHistoryList=residueHistoryList;
}
/**
* Set the properties of the residue with the focus using the values in the
* properties toolbar
*
* @see #getToolBarProperties
*/
public void onSetProperties() {
Residue current = theCanvas.getCurrentResidue();
if (current != null) {
current.setAnomericState(getSelectedValueChar(field_anomeric_state));
current.setAnomericCarbon(getSelectedValueChar(field_anomeric_carbon));
current.setChirality(getSelectedValueChar(field_chirality));
current.setRingSize(getSelectedValueChar(field_ring_size));
Linkage parent_linkage = current.getParentLinkage();
if (parent_linkage != null) {
char[] sel_linkage_positions = getSelectedPositions(field_linkage_position);
if((Boolean)field_second_bond.getValue()){
char[] sel_second_parent_positions = getSelectedPositions(field_second_parent_position);
char sel_second_child_position = getSelectedValueChar(field_second_child_position);
parent_linkage.setLinkagePositions(sel_linkage_positions,
sel_second_parent_positions,
sel_second_child_position);
}else{
parent_linkage.setLinkagePositions(sel_linkage_positions);
}
}
theCanvas.documentUpdated();
}
}
/**
* Change the properties of the residue with the focus. Display a
* {@link ResiduePropertiesDialog} or a {@link RepetitionPropertiesDialog}
* depending of the type of the residue.
*/
public void onProperties() {
Residue current = theCanvas.getCurrentResidue();
if (current == null)
return;
if (current.getParent() != null
&& (!current.isSpecial() || current.isCleavage())) {
theCanvas.setSelection(current);
theCanvas.documentUpdated();
} else if (current.isStartRepetition()) {
theCanvas.setSelection(current);
theCanvas.documentUpdated();
} else if (current.isEndRepetition()) {
theCanvas.setSelection(current);
theCanvas.documentUpdated();
}
}
private char[] getSelectedPositions(AbstractSelect field) {
@SuppressWarnings("rawtypes")
Set sel = (Set) field.getValue();
if(sel.size() == 0){
return new char[] { '?' };
}else{
char[] ret = new char[sel.size()];
int i=0;
for(Object obj:sel){
ret[i] = ((String) obj).charAt(0);
i++;
}
return ret;
}
}
private char getSelectedValueChar(AbstractSelect field) {
if (field.getValue() == null)
return '?';
return ((String) field.getValue()).charAt(0);
}
private void updateLinkageToolBar() {
if(linkagePanel==null){
return;
}else{
final Residue current = theCanvas.getCurrentResidue();
if(field_anomeric_state!=null){
field_anomeric_state.removeValueChangeListener(defaultListener);
field_anomeric_state.removeValueChangeListener(defaultListener);
field_anomeric_carbon.removeValueChangeListener(defaultListener);
field_linkage_position.removeValueChangeListener(defaultListener);
field_chirality.removeValueChangeListener(defaultListener);
field_ring_size.removeValueChangeListener(defaultListener);
field_second_child_position.removeValueChangeListener(defaultListener);
field_second_parent_position.removeValueChangeListener(defaultListener);
}
//linkagePanel.removeAllComponents();
popupLayout2 = new HorizontalLayout();
linkage_two_panel = new PopupView("2nd Linkage", popupLayout2);
popupLayout2.addStyleName("2nd_linkage_panel");
linkage_two_panel.setEnabled(false);
field_anomeric_state = new OptionGroup("Anomeric state",Arrays.asList(new String[] { "?","a", "b" }));
field_anomeric_state.setStyleName("linkage_component_select");
field_anomeric_state.setEnabled(false);
field_anomeric_carbon = new OptionGroup("Anomeric carbon",Arrays.asList(new String[] { "?","1", "2", "3" }));
field_anomeric_carbon.setEnabled(false);
field_linkage_position = new OptionGroup("Linkage position",Arrays.asList(new String[] { "?", "1", "2", "3", "4", "5", "6", "7", "8", "9" }));
field_linkage_position.setMultiSelect(true);
field_linkage_position.setEnabled(false);
field_chirality = new OptionGroup("Chirality",Arrays.asList(new String[] { "?","D","L" }));
field_chirality.setMultiSelect(false);
field_chirality.setEnabled(false);
field_ring_size = new OptionGroup("Ring",Arrays.asList(new String[] { "?", "p","f", "o" }));
field_ring_size.setMultiSelect(false);
field_ring_size.setEnabled(false);
field_second_bond=new CheckBox("");
field_second_bond.setEnabled(false);
field_second_bond.addStyleName("glycanbuilder-2nd-cov-checkbox");
field_second_bond.setValue(false);
field_second_bond.setImmediate(true); //forces a value change event to be fired immediately
field_second_child_position = new OptionGroup("Linkage Position",Arrays.asList(new String[] { "?", "1", "2", "3" }));
field_second_child_position.setMultiSelect(false);
field_second_child_position.setEnabled(false);
field_second_parent_position = new OptionGroup("Linkage Position",Arrays.asList(new String[] { "?", "1", "2", "3", "4", "5", "6", "7","8", "9" }));
field_second_parent_position.setMultiSelect(true);
field_second_parent_position.setEnabled(false);
if(current != null && (!current.isSpecial() || current.isCleavage() || current.isStartRepetition())){
//linkagePanel.setVisible(true);
Linkage parent_link = current.getParentLinkage();
if(parent_link != null){
field_linkage_position.removeAllItems();
List<String> positions=theCanvas.createPositions(parent_link.getParentResidue());
for(String position:positions){
field_linkage_position.addItem(position);
}
field_second_parent_position.removeAllItems();
for(String position:positions){
field_second_parent_position.addItem(position);
}
}
boolean can_have_parent_linkage = (parent_link != null && parent_link.getParentResidue() != null &&
(parent_link.getParentResidue().isSaccharide() || parent_link.getParentResidue().isBracket() ||
parent_link.getParentResidue().isRepetition() || parent_link.getParentResidue().isRingFragment()));
field_linkage_position.setEnabled(can_have_parent_linkage);
field_anomeric_state.setEnabled(current.isSaccharide());
field_anomeric_carbon.setEnabled(current.isSaccharide());
field_chirality.setEnabled(current.isSaccharide());
field_ring_size.setEnabled(current.isSaccharide());
field_second_bond.setEnabled(can_have_parent_linkage);
linkage_two_panel.setEnabled(can_have_parent_linkage && parent_link.hasMultipleBonds());
field_second_parent_position.setEnabled(can_have_parent_linkage && parent_link.hasMultipleBonds());
field_second_child_position.setEnabled(can_have_parent_linkage && parent_link.hasMultipleBonds());
if (parent_link != null){
field_linkage_position.setValue(Arrays.asList(theCanvas.toStrings(parent_link.glycosidicBond().getParentPositions())));
}else{
field_linkage_position.setValue(null);
}
field_anomeric_state.setValue(""
+ current.getAnomericState());
field_anomeric_carbon.setValue(""
+ current.getAnomericCarbon());
field_chirality.setValue("" + current.getChirality());
field_ring_size.setValue("" + current.getRingSize());
if (parent_link != null) {
field_second_bond.setValue(parent_link.hasMultipleBonds());
field_second_parent_position.setValue(Arrays.asList(theCanvas.toStrings(parent_link.getBonds()
.get(0).getParentPositions())));
field_second_child_position.setValue(""+ parent_link.getBonds().get(0).getChildPosition());
}else{
field_second_parent_position.setValue(null);
field_second_child_position.setValue("?");
}
forceLinkagePopRepaint();
}else{
//linkagePanel.setVisible(false);
field_linkage_position.setEnabled(false);
field_anomeric_state.setEnabled(false);
field_anomeric_carbon.setEnabled(false);
field_chirality.setEnabled(false);
field_ring_size.setEnabled(false);
field_second_bond.setEnabled(false);
field_second_parent_position.setEnabled(false);
field_second_child_position.setEnabled(false);
field_linkage_position.setValue(null);
field_anomeric_state.setValue("?");
field_anomeric_carbon.setValue("");
field_chirality.setValue("?");
field_ring_size.setValue("?");
field_second_parent_position.setValue(null);
field_second_child_position.setValue("?");
forceLinkagePopRepaint();
}
}
}
public void registerLinkageListeners(){
defaultListener = new Property.ValueChangeListener() {
private static final long serialVersionUID=375264676842546361L;
@Override
public void valueChange(ValueChangeEvent event) {
onSetProperties();
System.err.println("Value change listener");
}
};
field_anomeric_state.addValueChangeListener(defaultListener);
field_anomeric_carbon.addValueChangeListener(defaultListener);
field_linkage_position.addValueChangeListener(defaultListener);
field_chirality.addValueChangeListener(defaultListener);
field_ring_size.addValueChangeListener(defaultListener);
field_second_child_position.addValueChangeListener(defaultListener);
field_second_parent_position.addValueChangeListener(defaultListener);
field_second_bond.addValueChangeListener(new Property.ValueChangeListener() {
private static final long serialVersionUID=1577488601988220206L;
@Override
public void valueChange(ValueChangeEvent event) {
boolean checked=(Boolean) event.getProperty().getValue();
onSetProperties();
Residue current=theCanvas.getCurrentResidue();
if(checked){
Linkage parent_link=current.getParentLinkage();
boolean can_have_parent_linkage = (parent_link != null && parent_link.getParentResidue() != null &&
(parent_link.getParentResidue().isSaccharide() || parent_link.getParentResidue().isBracket() ||
parent_link.getParentResidue().isRepetition() || parent_link.getParentResidue().isRingFragment()));
field_second_parent_position.setEnabled(can_have_parent_linkage && parent_link.hasMultipleBonds());
field_second_child_position.setEnabled(can_have_parent_linkage && parent_link.hasMultipleBonds());
linkage_two_panel.setEnabled(true);
}else{
linkage_two_panel.setEnabled(false);
}
}
});
}
public void forceLinkagePopRepaint(){
registerLinkageListeners();
HorizontalLayout toolBar=new HorizontalLayout();
toolBar.setWidth("100%");
HorizontalLayout popupLayout = new HorizontalLayout();
linkage_one_panel = new PopupView("1st Linkage",popupLayout);
if(field_linkage_position.isEnabled() || field_anomeric_carbon.isEnabled() ||
field_anomeric_state.isEnabled() || field_chirality.isEnabled() || field_ring_size.isEnabled()){
linkage_one_panel.setEnabled(true);
}else{
linkage_one_panel.setEnabled(false);
}
popupLayout.addStyleName("1st_linkage_panel");
popupLayout.addComponent(field_anomeric_state);
popupLayout.addComponent(field_anomeric_carbon);
popupLayout.addComponent(field_linkage_position);
popupLayout.addComponent(field_chirality);
popupLayout.addComponent(field_ring_size);
// boolean enabled=linkage_two_panel.isEnabled();
// linkage_two_panel = new PopupButton("2nd Linkage");
// linkage_two_panel.setEnabled(enabled);
// linkage_two_panel.setComponent(popupLayout2);
// linkage_one_panel.addStyleName(BaseTheme.BUTTON_LINK);
// linkage_two_panel.addStyleName("link");
linkage_two_panel.addStyleName("igg-glycan-builder-linkage-toolbar-panel-item");
linkage_one_panel.addStyleName("igg-glycan-builder-linkage-toolbar-panel-item");
field_second_bond.addStyleName("igg-glycan-builder-linkage-toolbar-panel-item");
toolBar.addComponent(linkage_one_panel);
popupLayout2.addComponent(field_second_child_position);
popupLayout2.addComponent(field_second_parent_position);
toolBar.addComponent(field_second_bond);
toolBar.addComponent(linkage_two_panel);
HorizontalLayout filler = new HorizontalLayout();
toolBar.addComponent(filler);
toolBar.setExpandRatio(filler, 1f);
//linkagePanel.removeAllComponents();
linkagePanel.setContent(toolBar);
}
Panel linkagePanel;
private HorizontalLayout popupLayout2;
private Property.ValueChangeListener defaultListener;
public void appendLinkageToolBar(Panel theLinkageToolBarPanel){
linkagePanel=theLinkageToolBarPanel;
updateLinkageToolBar();
}
public void appendGeneralToolBar(Panel theToolBarPanel){
HorizontalLayout toolBar=new HorizontalLayout();
toolBar.setStyleName("toolbar");
NativeButton deleteButton=new NativeButton("Delete");
deleteButton.setIcon(new ThemeResource("icons/deleteNew.png"));
deleteButton.addClickListener(new ClickListener(){
private static final long serialVersionUID=1289257412952359727L;
@Override
public void buttonClick(ClickEvent event) {
theCanvas.delete();
}
});
deleteButton.setEnabled(false);
NativeButton copyButton=new NativeButton("Copy");
final NativeButton pasteButton=new NativeButton("Paste");
copyButton.setIcon(new ThemeResource("icons/editcopy.png"));
copyButton.addClickListener(new ClickListener(){
private static final long serialVersionUID=-1740735587078805580L;
@Override
public void buttonClick(ClickEvent event) {
theCanvas.copy();
pasteButton.setEnabled(true);
}
});
copyButton.setEnabled(false);
pasteButton.setIcon(new ThemeResource("icons/editpaste.png"));
pasteButton.addClickListener(new ClickListener(){
private static final long serialVersionUID=-8732259244009686729L;
@Override
public void buttonClick(ClickEvent event) {
theCanvas.paste();
pasteButton.setEnabled(false);
}
});
pasteButton.setEnabled(false);
final NativeButton bracketButton=new NativeButton("Bracket");
bracketButton.setIcon(new ThemeResource("icons/bracket.png"));
bracketButton.addClickListener(new ClickListener(){
private static final long serialVersionUID=5201094306113759901L;
@Override
public void buttonClick(ClickEvent event) {
theCanvas.addBracket();
}
});
bracketButton.setEnabled(false);
final NativeButton repeatButton=new NativeButton("Repeat");
repeatButton.setIcon(new ThemeResource("icons/repeat.png"));
repeatButton.addClickListener(new ClickListener(){
private static final long serialVersionUID=-23302591439643695L;
@Override
public void buttonClick(ClickEvent event) {
try {
theCanvas.addRepeat();
} catch (Exception ex) {
showMessage(ex.getMessage(), "400px","100px","Error creating repeat");
}
}
});
repeatButton.setEnabled(false);
componentsWithResidueSelectionDependency.add(repeatButton);
componentsWithResidueSelectionDependency.add(bracketButton);
componentsWithResidueSelectionDependency.add(deleteButton);
componentsWithResidueSelectionDependency.add(copyButton);
final NativeButton orientationButton=new NativeButton("Orientation");
orientationButton.setIcon(new ThemeResource("icons/"+theCanvas.getOrientationIcon()));
orientationButton.addClickListener(new ClickListener(){
private static final long serialVersionUID=6621021858668446143L;
@Override
public void buttonClick(ClickEvent event) {
theCanvas.changeOrientation();
orientationButton.setIcon(new ThemeResource("icons/"+theCanvas.getOrientationIcon()));
}
});
final NativeButton selectAllButton=new NativeButton("Select all");
selectAllButton.setIcon(new ThemeResource("icons/selectall.png"));
selectAllButton.addClickListener(new ClickListener(){
private static final long serialVersionUID=-5848923636575805154L;
@Override
public void buttonClick(ClickEvent event) {
theCanvas.selectAll();
theCanvas.documentUpdated();
}
});
final NativeButton deSelectAllButton=new NativeButton("Select none");
deSelectAllButton.setIcon(new ThemeResource("icons/deselect.png"));
deSelectAllButton.addClickListener(new ClickListener(){
private static final long serialVersionUID=8339468775345706027L;
@Override
public void buttonClick(ClickEvent event) {
theCanvas.resetSelection();
theCanvas.documentUpdated();
}
});
final NativeButton moveCWButton=new NativeButton("Move CW");
moveCWButton.setIcon(new ThemeResource("icons/rotatecw.png"));
moveCWButton.addClickListener(new ClickListener(){
private static final long serialVersionUID = -6061975045440741204L;
@Override
public void buttonClick(ClickEvent event) {
theCanvas.onMoveCW();
}
});
componentsWithResidueSelectionDependency.add(moveCWButton);
final NativeButton moveCCWButton=new NativeButton("Move CCW");
moveCCWButton.setIcon(new ThemeResource("icons/rotateccw.png"));
moveCCWButton.addClickListener(new ClickListener(){
private static final long serialVersionUID = 3555726070782377309L;
@Override
public void buttonClick(ClickEvent event) {
theCanvas.onMoveCCW();
}
});
componentsWithResidueSelectionDependency.add(moveCCWButton);
toolBar.addComponent(deleteButton);
toolBar.addComponent(copyButton);
toolBar.addComponent(pasteButton);
toolBar.addComponent(orientationButton);
toolBar.addComponent(selectAllButton);
toolBar.addComponent(deSelectAllButton);
toolBar.addComponent(bracketButton);
toolBar.addComponent(repeatButton);
toolBar.addComponent(moveCWButton);
toolBar.addComponent(moveCCWButton);
HorizontalLayout layout=new HorizontalLayout();
layout.setSizeFull();
toolBar.addComponent(layout);
toolBar.setExpandRatio(layout, 1);
theToolBarPanel.setContent(toolBar);
}
public void updateActions(){
if(theCanvas.hasSelectedResidues()){
for(Component component:componentsWithResidueSelectionDependency){
component.setEnabled(true);
}
for(MenuItem menuItem:menuItemsWithResidueSelectionDependency){
menuItem.setEnabled(true);
}
}else{
for(MenuItem menuItem:menuItemsWithResidueSelectionDependency){
menuItem.setEnabled(false);
}
for(Component component:componentsWithResidueSelectionDependency){
component.setEnabled(false);
}
}
}
public void automaticHeightAdjust(boolean automaticallyAdjustHeight){
this.automaticallyAdjustHeight=automaticallyAdjustHeight;
}
private void updateCanvasHeight(){
if(automaticallyAdjustHeight){
int proposedHeight=theCanvas.getHeight();
if(theCanvas.getWorkspace().getGlycanRenderer().getRenderMode()==GlycanRendererMode.TOOLBAR){
proposedHeight+=2;
}else{
proposedHeight+=100;
}
int proposedWidth=theCanvas.getWidth();
setMinimumSize(proposedWidth, proposedHeight);
}
}
@Override
public void recieveSelectionUpdate(double x, double y, double width,double height,boolean mouseMoved) {
final Residue selectedResidue=theCanvas.getCurrentResidue();
theCanvas.selectIntersectingRectangles(x, y, width, height, mouseMoved);
if(theCanvas.getCurrentResidue()!=null && selectedResidue==theCanvas.getCurrentResidue() && selectedResidue.isRepetition()){
final Window window=new Window("Repeatition options");
VerticalLayout layout=new VerticalLayout();
final TextField minRep=new TextField("Minimum");
final TextField maxRep=new TextField("Maximum");
NativeButton okBut=new NativeButton("Ok");
NativeButton cancelBut=new NativeButton("Cancel");
minRep.setImmediate(true);
maxRep.setImmediate(true);
minRep.setValue(String.valueOf(selectedResidue.getMinRepetitions()));
maxRep.setValue(String.valueOf(selectedResidue.getMaxRepetitions()));
okBut.addClickListener(new ClickListener(){
private static final long serialVersionUID = -408364885359729326L;
@Override
public void buttonClick(ClickEvent event) {
String minRepNum=(String) minRep.getValue();
String maxRepNum=(String) maxRep.getValue();
boolean valid=true;
try{
Integer.parseInt(minRepNum);
Integer.parseInt(maxRepNum);
}catch(NumberFormatException ex){
valid=false;
}
if(valid){
selectedResidue.setMinRepetitions((String) minRep.getValue());
selectedResidue.setMaxRepetitions((String) maxRep.getValue());
theCanvas.documentUpdated();
}
UI.getCurrent().removeWindow(window);
}
});
cancelBut.addClickListener(new ClickListener(){
private static final long serialVersionUID = -657746118918366530L;
@Override
public void buttonClick(ClickEvent event) {
UI.getCurrent().removeWindow(window);
}
});
layout.addComponent(minRep);
layout.addComponent(maxRep);
HorizontalLayout buttonLayout=new HorizontalLayout();
buttonLayout.addComponent(okBut);
buttonLayout.addComponent(cancelBut);
layout.addComponent(buttonLayout);
window.center();
window.setContent(layout);
window.getContent().setSizeUndefined();
window.setSizeUndefined();
UI.getCurrent().addWindow(window);
}
}
@Override
public synchronized void glycanCanvasUpdated() {
updateActions();
updateCanvasHeight();
}
@Override
public void selectionChanged() {
System.err.println("Updating linkage toolbar");
updateLinkageToolBar();
}
@Override
public void setLocalResourceWatcher(LocalResourceWatcher watcher) {
localResourceWatchers.add(watcher);
}
@Override
public void removeLocalResourceWatcher(LocalResourceWatcher watcher) {
localResourceWatchers.remove(watcher);
}
@Override
public void massOptions(MassOptions massOptions,Collection<Glycan> structures) {
Collection<Glycan> glycans=theCanvas.getSelectedStructures();
if(glycans.size()==0){
glycans=theCanvas.theDoc.getStructures();
}
theCanvas.theDoc.setMassOptions(glycans, massOptions);
theCanvas.theWorkspace.getDefaultMassOptions().setValues(massOptions);
theCanvas.documentUpdated();
}
public synchronized void resizeCanvas() {
}
// @Override
// public void paintContent(PaintTarget target) throws PaintException {
// super.paintContent(target);
//
// /**
// * - When a page is refreshed we currently don't have a method of reinstalling the client side resize repeat command
// * - So this is just a hack to get around this limitation
// */
// updateCanvasHeight();
// }
public void setWorkspace(BuilderWorkspace workspace) {
theCanvas.setWorkspace(workspace);
}
public void setNotation(String notation){
theCanvas.setNotation(notation);
}
public BuilderWorkspace getWorkspace() {
return theCanvas.getWorkspace();
}
private void reportMessage(String message,Exception ex){
reportMessage(message);
reportException(ex);
}
private void reportException(Exception ex){
ex.printStackTrace();
}
private void reportMessage(String message){
MessageDialogBox box=new MessageDialogBox("Notification", message);
box.setVisible(true);
box.center();
}
}