/*
* 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: 1937 $ by $Author: david@nixbioinf.org $ on $Date:: 2010-08-06 #$
*/
package org.eurocarbdb.application.glycanbuilder;
import static org.eurocarbdb.application.glycanbuilder.Geometry.bottom;
import static org.eurocarbdb.application.glycanbuilder.Geometry.center;
import static org.eurocarbdb.application.glycanbuilder.Geometry.distance;
import static org.eurocarbdb.application.glycanbuilder.Geometry.expand;
import static org.eurocarbdb.application.glycanbuilder.Geometry.left;
import static org.eurocarbdb.application.glycanbuilder.Geometry.makeRectangle;
import static org.eurocarbdb.application.glycanbuilder.Geometry.right;
import static org.eurocarbdb.application.glycanbuilder.Geometry.top;
import static org.eurocarbdb.application.glycanbuilder.Geometry.union;
import org.pushingpixels.substance.api.SubstanceLookAndFeel;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import javax.swing.Action;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.JViewport;
import javax.swing.ListModel;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import org.pushingpixels.flamingo.api.common.CommandButtonDisplayState;
import org.pushingpixels.flamingo.api.common.JCommandButton;
import org.pushingpixels.flamingo.api.common.JCommandButtonPanel;
import org.pushingpixels.flamingo.api.common.JCommandToggleButton;
import org.pushingpixels.flamingo.api.common.RichTooltip;
import org.pushingpixels.flamingo.api.common.StringValuePair;
import org.pushingpixels.flamingo.api.common.icon.ImageWrapperResizableIcon;
import org.pushingpixels.flamingo.api.common.icon.ResizableIcon;
import org.pushingpixels.flamingo.api.common.popup.JCommandPopupMenu;
import org.pushingpixels.flamingo.api.ribbon.JFlowRibbonBand;
import org.pushingpixels.flamingo.api.ribbon.JRibbonBand;
import org.pushingpixels.flamingo.api.ribbon.JRibbonFrame;
import org.pushingpixels.flamingo.api.ribbon.RibbonContextualTaskGroup;
import org.pushingpixels.flamingo.api.ribbon.RibbonElementPriority;
import org.pushingpixels.flamingo.api.ribbon.RibbonTask;
import org.pushingpixels.flamingo.api.ribbon.JRibbonBand.RibbonGalleryPopupCallback;
import org.pushingpixels.flamingo.api.ribbon.resize.CoreRibbonResizePolicies;
import org.pushingpixels.flamingo.api.ribbon.resize.IconRibbonBandResizePolicy;
import org.pushingpixels.flamingo.api.ribbon.resize.RibbonBandResizePolicy;
import org.pushingpixels.substance.api.skin.SubstanceOfficeBlue2007LookAndFeel;
import org.pushingpixels.substance.internal.utils.SubstanceSizeUtils;
/**
* A component that implement a visual editor of glycan structures. Multiple
* structures can be created in the same editor. The structures are displayed
* using the settings specified by the current {@link GraphicOptions}. The
* actions to create and modify the structures can be accessed by toolbars menus
* that should be added to the application frame. The default toolbars and menus
* can be retrieved using: {@link #getToolBarDocument},
* {@link #getToolBarStructure}, {@link #getToolBarProperties},
* {@link #getEditMenu}, {@link #getStructureMenu} and {@link #getViewMenu}.
* Listeners can be registered to react to changes in the structures (through
* the underlying {@link GlycanDocument}) and in the selections.
*
* @see GlycanDocument
* @see GlycanRenderer
* @author Alessio Ceroni (a.ceroni@imperial.ac.uk)
*/
public class GlycanCanvas extends JComponent implements ActionListener,
BaseDocument.DocumentChangeListener, ResidueHistory.Listener,
Printable, MouseListener, MouseMotionListener {
private static ICON_SIZE defaultMenuIconSize = ICON_SIZE.L3;
// Classes
/**
* Interface that should be implemented by all objects that want to be
* notified when the selection is changed
*/
public interface SelectionChangeListener {
/**
* Called by the component when the selection is changed
*/
public void selectionChanged(SelectionChangeEvent e);
}
/**
* Contains the information about a selection change event
*/
public static class SelectionChangeEvent {
private GlycanCanvas src;
/**
* Default constructor
*
* @param _src
* the source of the event
*/
public SelectionChangeEvent(GlycanCanvas _src) {
src = _src;
}
/**
* Return the source of the event
*/
public GlycanCanvas getSource() {
return src;
}
}
// -----------
protected ImageIcon last;
protected static final long serialVersionUID = 0L;
protected GlycanCanvas this_object = null;
// singletons
protected JFrame theParent = null;
protected BuilderWorkspace theWorkspace = null;
protected GlycanDocument theDoc = null;
// protected ActionManager theActionManager;
protected ActionManager theActionManager;
// graphic objects
protected JScrollPane theScrollPane = null;
protected JToolBar theToolBarDocument;
protected JToolBar theToolBarStructure;
protected JToolBar theToolBarProperties;
protected JComboBox field_anomeric_state;
protected JComboBox field_anomeric_carbon;
protected DropDownList field_linkage_position;
protected JComboBox field_chirality;
protected JComboBox field_ring_size;
protected JCheckBox field_second_bond;
protected JComboBox field_second_child_position;
protected DropDownList field_second_parent_position;
// menus
protected JMenu theEditMenu = null;
protected JMenu theStructureMenu = null;
protected JMenu theViewMenu = null;
protected JCheckBoxMenuItem show_redend_canvas_button = null;
protected int recent_residues_index = -1;
protected int no_recent_residues_buttons = 0;
protected ButtonGroup display_button_group = null;
protected HashMap<String, ButtonModel> display_models = null;
// selection
protected Residue current_residue;
protected Linkage current_linkage;
protected HashSet<Residue> selected_residues;
protected HashSet<Linkage> selected_linkages;
// painting
protected GlycanRenderer theGlycanRenderer;
protected Rectangle all_structures_bbox;
protected BBoxManager theBBoxManager;
protected PositionManager thePosManager;
protected boolean is_printing;
protected JLabel sel_label = new JLabel();
// events
private boolean ignore_actions = false;
protected Point mouse_start_point = null;
protected Point mouse_end_point = null;
// DnD
protected boolean is_dragndrop = false;
protected boolean was_dragged = false;
protected Cursor dndcopy_cursor = null;
protected Cursor dndmove_cursor = null;
protected Cursor dndnocopy_cursor = null;
protected Cursor dndnomove_cursor = null;
//
protected Vector<SelectionChangeListener> listeners;
protected ThemeManager themeManager;
private RibbonTask theEditRibbon;
private RibbonTask theStructureRibbon;
private RibbonTask theViewRibbon;
private JRibbonBand structureSelectionBand;
private JRibbonBand structureRibbonBandCFG;
private JRibbonBand structureRibbonBandCFGGRY;
private String STRUCTURE_GALLERY_NAME = "Add structure";
private String RESIDUE_GALLERY_NAME = "Add residue";
private String TERMINAL_GAL_NAME = "Add terminal";
private JRibbonBand insertResidueJRibbonBand;
private JCommandButton orientationButton;
private JRibbonBand terminalRibbonBand;
private RibbonContextualTaskGroup theLinkageRibbon;
protected Set<ContextAwareContainer> contextAwareContainers;
protected Set<NotationChangeListener> notationChangeListeners;
public void nullAll() {
listeners = null;
themeManager = null;
theEditRibbon = null;
theStructureRibbon = null;
theViewRibbon = null;
structureSelectionBand = null;
structureRibbonBandCFG = null;
structureRibbonBandCFGGRY = null;
insertResidueJRibbonBand = null;
orientationButton = null;
terminalRibbonBand = null;
theLinkageRibbon = null;
contextAwareContainers = null;
notationChangeListeners = null;
}
private HashMap<RESIDUE_INSERT_MODES, List<ResidueGalleryIndex>> residueGalleries;
public enum RESIDUE_INSERT_MODES {
INSERT, REPLACE, ADD, TERMINAL
}
public class ResidueGalleryIndex {
public JRibbonBand band;
public String galleryName;
public ResidueGalleryIndex(JRibbonBand _band, String _galleryName) {
this.band = _band;
this.galleryName = _galleryName;
}
}
// ---------
// construction
public RibbonTask getTheViewRibbon() {
return theViewRibbon;
}
public RibbonTask getTheStructureRibbon() {
return theStructureRibbon;
}
/**
* Default constructor
*
* @param parent
* the parent frame
* @param _workspace
* the workspace containing all documents and options
* @throws MalformedURLException
*/
public GlycanCanvas(JFrame parent, BuilderWorkspace _workspace,
ThemeManager _themeManager) {
initCanvas(parent, _workspace, _themeManager, true);
}
public GlycanCanvas(JFrame parent, BuilderWorkspace _workspace,
ThemeManager _themeManager, boolean enableRibbons)
throws MalformedURLException {
initCanvas(parent, _workspace, _themeManager, enableRibbons);
}
public void initCanvas(JFrame parent, BuilderWorkspace _workspace,
ThemeManager _themeManager, boolean enableRibbons) {
// init
this.themeManager = _themeManager;
FileUtils.themeManager=_themeManager;
try {
themeManager.addIconPath("/icons/glycan_builder", this.getClass());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
themeManager.addIconPath("/icons/crystal_project", this.getClass());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this_object = this;
theParent = parent;
theWorkspace = _workspace;
theDoc = theWorkspace.getStructures();
theDoc.addDocumentChangeListener(this);
// theActionManager = new ActionManager();
theActionManager = new ActionManager();
current_residue = null;
current_linkage = null;
selected_residues = new HashSet<Residue>();
selected_linkages = new HashSet<Linkage>();
theGlycanRenderer = theWorkspace.getGlycanRenderer();
thePosManager = new PositionManager();
theBBoxManager = new BBoxManager();
all_structures_bbox = null;
is_printing = false;
residueGalleries = new HashMap<RESIDUE_INSERT_MODES, List<ResidueGalleryIndex>>();
for (RESIDUE_INSERT_MODES mode : RESIDUE_INSERT_MODES.values()) {
residueGalleries.put(mode, new ArrayList<ResidueGalleryIndex>());
}
// initialize the action set
createActions();
// create toolbars
theToolBarDocument = createToolBarDocument();
theToolBarStructure = createToolBarStructure();
theToolBarProperties = createToolBarProperties();
// create menus
theEditMenu = createEditMenu();
theStructureMenu = createStructureMenu();
theViewMenu = createViewMenu();
if (enableRibbons) {
theEditRibbon = createEditRibbonBand();
theStructureRibbon = createStructureRibbonTask();
theViewRibbon = createViewRibbonTask();
theLinkageRibbon = createLinkageRibbon();
}
// set the canvas
this.setOpaque(true);
this.setBackground(Color.white);
// load DnD cursors
dndcopy_cursor = FileUtils.createCursor("dnd-copy");
dndnocopy_cursor = FileUtils.createCursor("dnd-nocopy");
dndmove_cursor = FileUtils.createCursor("dnd-move");
dndnomove_cursor = FileUtils.createCursor("dnd-nomove");
// init events
theWorkspace.getResidueHistory().addHistoryChangedListener(this);
theDoc.addDocumentChangeListener(this);
addMouseMotionListener(this);
addMouseListener(this);
listeners = new Vector<SelectionChangeListener>();
contextAwareContainers = new HashSet<ContextAwareContainer>();
notationChangeListeners = new HashSet<NotationChangeListener>();
}
public void addContextAwareContainer(ContextAwareContainer container) {
contextAwareContainers.add(container);
}
public void addNotationChangeListener(
NotationChangeListener notationChangeListener) {
notationChangeListeners.add(notationChangeListener);
}
public RibbonContextualTaskGroup getTheLinkageRibbon() {
return theLinkageRibbon;
}
public RibbonTask getTheEditRibbon() {
return theEditRibbon;
}
/**
* Set the underlying document containing the glycan structures that are
* being created and modified
*/
public void setDocument(GlycanDocument doc) {
if (theDoc != null)
theDoc.removeDocumentChangeListener(this);
theDoc = doc;
if (theDoc != null)
theDoc.addDocumentChangeListener(this);
resetSelection();
this.respondToDocumentChange = true;
repaint();
}
/**
* Return the underlying document containing the glycan structures that are
* being created and modified
*/
public GlycanDocument getDocument() {
return theDoc;
}
/**
* Return the action manager
*/
public ActionManager getActionManager() {
return theActionManager;
}
/**
* Return the object that is used to render the structures
*/
public GlycanRenderer getGlycanRenderer() {
return theGlycanRenderer;
}
/**
* Set the object that is used to render the structures
*/
public void setGlycanRenderer(GlycanRenderer r) {
theGlycanRenderer = r;
}
/**
* Add a scroll pane to the component
*/
public void setScrollPane(JScrollPane sp) {
theScrollPane = sp;
theScrollPane.getVerticalScrollBar().setUnitIncrement(20);
theScrollPane.getVerticalScrollBar().setBlockIncrement(20);
theScrollPane.getHorizontalScrollBar().setUnitIncrement(10);
theScrollPane.getHorizontalScrollBar().setBlockIncrement(10);
}
/**
* Return the toolbar containing the default actions to create and modify
* the underlying document
*/
public JToolBar getToolBarDocument() {
return theToolBarDocument;
}
/**
* Return the toolbar containing the default actions to create and modify
* the glycan structures
*/
public JToolBar getToolBarStructure() {
return theToolBarStructure;
}
/**
* Return the toolbar containing the default actions to change the residue
* properties
*/
public JToolBar getToolBarProperties() {
return theToolBarProperties;
}
/**
* Return the menu containing the default actions to create and modify the
* underlying document
*/
public JMenu getEditMenu() {
return theEditMenu;
}
/**
* Return the menu containing the default actions to create and modify the
* glycan structures
*/
public JMenu getStructureMenu() {
return theStructureMenu;
}
/**
* Return the menu containing the default actions to change the graphic
* options
*/
public JMenu getViewMenu() {
return theViewMenu;
}
private String getCurrentOrientation() {
int orientation = theWorkspace.getGraphicOptions().ORIENTATION;
String iconId;
if (orientation == GraphicOptions.LR) {
iconId = "lr";
} else if (orientation == GraphicOptions.RL) {
iconId = "rl";
} else if (orientation == GraphicOptions.TB) {
iconId = "tb";
} else if (orientation == GraphicOptions.BT) {
iconId = "bt";
} else {
return null;
}
return iconId;
}
private EurocarbResizableIcon getOrientationIcon() {
return themeManager.getResizableIcon(getCurrentOrientation(),
ICON_SIZE.L3);
}
private void createActions() {
theActionManager.add("undo", themeManager.getResizableIcon(
STOCK_ICON.UNDO, defaultMenuIconSize), "Undo", KeyEvent.VK_U,
"ctrl Z", this);
theActionManager.add("redo", themeManager.getResizableIcon(
STOCK_ICON.REDO, defaultMenuIconSize), "Redo", KeyEvent.VK_R,
"ctrl Y", this);
theActionManager.add("cut", themeManager.getResizableIcon(
STOCK_ICON.CUT, defaultMenuIconSize), "Cut", KeyEvent.VK_T,
"ctrl X", this);
theActionManager.add("copy", themeManager.getResizableIcon(
STOCK_ICON.COPY, defaultMenuIconSize), "Copy", KeyEvent.VK_C,
"ctrl C", this);
theActionManager.add("paste", themeManager.getResizableIcon(
STOCK_ICON.PASTE, defaultMenuIconSize), "Paste", KeyEvent.VK_P,
"ctrl V", this);
theActionManager.add("delete", themeManager.getResizableIcon(
STOCK_ICON.DELETE, defaultMenuIconSize), "Delete",
KeyEvent.VK_L, "DELETE", this);
theActionManager.add("orderstructuresasc", themeManager
.getResizableIcon("sort_ascending", defaultMenuIconSize),
"Sort structures by m/z in ascending order", KeyEvent.VK_A, "",
this);
theActionManager.add("orderstructuresdesc", themeManager
.getResizableIcon("sort_descending", defaultMenuIconSize),
"Sort structures by m/z in descending order", KeyEvent.VK_D,
"", this);
theActionManager.add("selectstructure", themeManager.getResizableIcon(
"selectstructure", defaultMenuIconSize),
"Select current structure", KeyEvent.VK_S, "ctrl W", this);
theActionManager.add("selectall", themeManager.getResizableIcon(
"selectall", defaultMenuIconSize), "Select all", KeyEvent.VK_A,
"ctrl A", this);
theActionManager.add("selectnone", themeManager.getResizableIcon(
"deselect", defaultMenuIconSize), "Select none", KeyEvent.VK_N,
"ESCAPE", this);
theActionManager.add("gotostart", themeManager.getResizableIcon(
"go-first", defaultMenuIconSize),
"Show beginning of the canvas", KeyEvent.VK_B, "ctrl HOME",
this);
theActionManager.add("gotoend", themeManager.getResizableIcon(
"go-last", defaultMenuIconSize), "Show end of the canvas",
KeyEvent.VK_E, "ctrl END", this);
// navigation
// theActionManager.add("navup", FileUtils.getIcon("navup"),
// "Navigate up", KeyEvent.VK_U, "ctrl UP", this);
// theActionManager.add("navdown", FileUtils.getIcon("navdown"),
// "Navigate down", KeyEvent.VK_W, "ctrl DOWN", this);
// theActionManager.add("navleft", FileUtils.getIcon("navleft"),
// "Navigate left", KeyEvent.VK_F, "ctrl LEFT", this);
// theActionManager.add("navright", FileUtils.getIcon("navright"),
// "Navigate right", KeyEvent.VK_R, "ctrl RIGHT", this);
// structure
for (CoreType t : CoreDictionary.getCores()) {
theActionManager.add("addstructure=" + t.getName(), ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3), t.getDescription(),
-1, "", this);
}
theActionManager.add("addstructurestr", themeManager.getResizableIcon(
"write", defaultMenuIconSize), "Add structure from string",
KeyEvent.VK_S, "", this);
theActionManager.add("addcomposition", themeManager.getResizableIcon(
"piechart", defaultMenuIconSize), "Add composition",
KeyEvent.VK_C, "", this);
theActionManager.add("bracket", themeManager.getResizableIcon(
"bracket", defaultMenuIconSize), "Add bracket", KeyEvent.VK_B,
"ctrl B", this);
theActionManager.add("repeat", themeManager.getResizableIcon("repeat",
defaultMenuIconSize), "Add repeating unit", KeyEvent.VK_U,
"ctrl R", this);
theActionManager.add("properties", themeManager.getResizableIcon(
"properties", defaultMenuIconSize), "Residue properties",
KeyEvent.VK_P, "ctrl ENTER", this);
theActionManager.add("moveccw", themeManager.getResizableIcon(
"moveccw", defaultMenuIconSize),
"Move residue counter-clockwise", KeyEvent.VK_K,
"ctrl shift LEFT", this);
theActionManager.add("movecw", themeManager.getResizableIcon("movecw",
defaultMenuIconSize), "Move residue clockwise", KeyEvent.VK_W,
"ctrl shift RIGHT", this);
theActionManager.add("changeredend", themeManager.getResizableIcon(
"changeredend", defaultMenuIconSize),
"Change reducing end type", KeyEvent.VK_Y, "", this);
theActionManager.add("massoptstruct", themeManager.getResizableIcon(
"massoptstruct", defaultMenuIconSize),
"Mass options of selected structures", KeyEvent.VK_M, "", this);
// view
theActionManager
.add("notation=" + GraphicOptions.NOTATION_CFG, themeManager
.getResizableIcon("CFG_color", defaultMenuIconSize),
"CFG notation", KeyEvent.VK_C, "", this);
theActionManager.add("notation=" + GraphicOptions.NOTATION_CFGBW,
themeManager.getResizableIcon("CFG_greyscale",
defaultMenuIconSize), "CFG black and white notation",
KeyEvent.VK_B, "", this);
theActionManager.add("notation=" + GraphicOptions.NOTATION_CFGLINK,
themeManager.getResizableIcon("CFG_linkage",
defaultMenuIconSize),
"CFG with linkage placement notation", KeyEvent.VK_L, "", this);
theActionManager.add("notation=" + GraphicOptions.NOTATION_UOXF,
themeManager.getResizableIcon("uoxf", defaultMenuIconSize),
"UOXF notation", KeyEvent.VK_O, "", this);
theActionManager.add("notation=" + GraphicOptions.NOTATION_UOXFCOL,
themeManager.getResizableIcon("uoxfcol", defaultMenuIconSize),
"UOXFCOL notation", KeyEvent.VK_O, "", this);
theActionManager.add("notation=" + GraphicOptions.NOTATION_TEXT,
themeManager.getResizableIcon("text", defaultMenuIconSize),
"Text only notation", KeyEvent.VK_T, "", this);
theActionManager.add("display=" + GraphicOptions.DISPLAY_COMPACT,
ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),
"compact view", KeyEvent.VK_O, "", this);
theActionManager.add("display=" + GraphicOptions.DISPLAY_NORMAL,
ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),
"normal view", KeyEvent.VK_N, "", this);
theActionManager.add("display=" + GraphicOptions.DISPLAY_NORMALINFO,
ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),
"normal view with linkage info", KeyEvent.VK_I, "", this);
theActionManager.add("display=" + GraphicOptions.DISPLAY_CUSTOM,
ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),
"custom view with user settings", KeyEvent.VK_U, "", this);
theActionManager.add("scale=400", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3), "400%", -1, "", this);
theActionManager.add("scale=300", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3), "300%", -1, "", this);
theActionManager.add("scale=200", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3), "200%", -1, "", this);
theActionManager.add("scale=150", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3), "150%", -1, "", this);
theActionManager.add("scale=100", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3), "100%", -1, "", this);
theActionManager.add("scale=67", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3), "67%", -1, "", this);
theActionManager.add("scale=50", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3), "50%", -1, "", this);
theActionManager.add("scale=33", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3), "33%", -1, "", this);
theActionManager.add("scale=25", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3), "25%", -1, "", this);
theActionManager.add("collapsemultipleantennae", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3),
"Collapse multiple antennae", KeyEvent.VK_A, "", this);
theActionManager.add("showmassescanvas", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3),
"Show masses in the drawing canvas", KeyEvent.VK_V, "", this);
theActionManager.add("showmasses", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3),
"Show masses when exporting", KeyEvent.VK_M, "", this);
theActionManager.add("showredendcanvas", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3),
"Show reducing end indicator in the drawing canvas",
KeyEvent.VK_R, "", this);
theActionManager.add("showredend", ThemeManager
.getResizableEmptyIcon(ICON_SIZE.L3),
"Show reducing end indicator when exporting", KeyEvent.VK_E,
"", this);
theActionManager.add("orientation", getOrientationIcon(),
"Change orientation", KeyEvent.VK_O, "", this);
theActionManager.add("displaysettings", themeManager.getResizableIcon(
"display", ICON_SIZE.L4), "Change display settings",
KeyEvent.VK_D, "", this);
// help
theActionManager.add("about", themeManager.getResizableIcon("about",
ICON_SIZE.L4), "About", KeyEvent.VK_B, "", this);
ICON_SIZE iconSize = ICON_SIZE.L4;
ResidueRenderer rr = theGlycanRenderer.getResidueRenderer();
for (ResidueType t : ResidueDictionary.allResidues()) {
ImageWrapperResizableIcon icon = ImageWrapperResizableIcon.getIcon(
rr.getImage(t, iconSize.getSize()), new Dimension(iconSize
.getSize(), iconSize.getSize()));
EurocarbResizableIcon eu_icon = new EurocarbResizableIcon(
this.themeManager, null, icon);
eu_icon.setResizableIcon(icon);
theActionManager.add("change=" + t.getName(), eu_icon, t
.getDescription(), -1, "", this);
if (t.canHaveParent()) {
theActionManager.add("add=" + t.getName(), eu_icon, t
.getDescription(), -1,
(t.getToolbarOrder() != 0) ? ("ctrl " + t
.getToolbarOrder()) : "", this);
last = new ImageIcon(rr.getImage(t, iconSize.getSize()));
theActionManager.get("add=" + t.getName()).putValue(
Action.SMALL_ICON,
new ImageIcon(rr.getImage(t, ICON_SIZE.L3.getSize())));
}
if (t.canHaveParent() && t.canHaveChildren())
theActionManager.add("insert=" + t.getName(), eu_icon, t
.getDescription(), -1, "", this);
if (t.canBeReducingEnd())
theActionManager.add("redend=" + t.getName(), eu_icon, t
.getDescription(), -1, "", this);
}
}
private void updateActions() {
theActionManager.get("undo").setEnabled(
theDoc.getUndoManager().canUndo());
theActionManager.get("redo").setEnabled(
theDoc.getUndoManager().canRedo());
theActionManager.get("cut").setEnabled(hasSelectedResidues());
theActionManager.get("copy").setEnabled(hasSelectedResidues());
theActionManager.get("delete").setEnabled(hasSelectedResidues());
theActionManager.get("bracket").setEnabled(hasCurrentResidue());
theActionManager.get("repeat").setEnabled(hasCurrentResidue());
theActionManager.get("properties").setEnabled(hasCurrentResidue());
// theActionManager.get("orientation").putValue(Action.SMALL_ICON,
// getOrientationIcon().);
theActionManager.get("massoptstruct").setEnabled(hasSelection());
theActionManager.get("moveccw").setEnabled(hasCurrentSelection());
// theActionManager.get("resetplace").setEnabled(hasCurrentSelection());
theActionManager.get("movecw").setEnabled(hasCurrentSelection());
}
private void updateResidueActions() {
// structure
ResidueRenderer rr = theGlycanRenderer.getResidueRenderer();
ICON_SIZE iconSize = ICON_SIZE.L4;
for (ResidueType t : ResidueDictionary.allResidues()) {
ImageWrapperResizableIcon icon = ImageWrapperResizableIcon.getIcon(
rr.getImage(t, iconSize.getSize()), new Dimension(iconSize
.getSize(), iconSize.getSize()));
EurocarbResizableIcon eu_icon = new EurocarbResizableIcon(
this.themeManager, null, icon);
eu_icon.setResizableIcon(icon);
theActionManager.update("change=" + t.getName(), eu_icon, t
.getDescription(), -1, "");
if (t.canHaveParent()) {
theActionManager.update("add=" + t.getName(), eu_icon, t
.getDescription(), -1,
(t.getToolbarOrder() != 0) ? ("ctrl " + t
.getToolbarOrder()) : "");
theActionManager.get("add=" + t.getName()).putValue(
Action.SMALL_ICON,
new ImageIcon(rr.getImage(t, ICON_SIZE.L3.getSize())));
}
if (t.canHaveParent() && t.canHaveChildren())
theActionManager.update("insert=" + t.getName(), eu_icon, t
.getDescription(), -1, "");
if (t.canBeReducingEnd())
theActionManager.update("redend=" + t.getName(), eu_icon, t
.getDescription(), -1, "");
}
updateStructureRibbonGallery(STRUCTURE_GALLERY_NAME,
structureSelectionBand);
for (ResidueGalleryIndex gal : this.residueGalleries
.get(RESIDUE_INSERT_MODES.ADD)) {
this.updateAddResidueRibbonGallery(gal.galleryName, gal.band);
}
for (ResidueGalleryIndex gal : this.residueGalleries
.get(RESIDUE_INSERT_MODES.REPLACE)) {
this.updateChangeResidueRibbonGallery(gal.galleryName, gal.band);
}
for (ResidueGalleryIndex gal : this.residueGalleries
.get(RESIDUE_INSERT_MODES.INSERT)) {
this.updateInsertResidueRibbonGallery(gal.galleryName, gal.band);
}
for (ResidueGalleryIndex gal : this.residueGalleries
.get(RESIDUE_INSERT_MODES.TERMINAL)) {
updateTerminalRibbonGallery(gal.galleryName, gal.band);
}
}
private String[] toStrings(char[] pos) {
String[] ret = new String[pos.length];
for (int i = 0; i < pos.length; i++)
ret[i] = "" + pos[i];
return ret;
}
private ListModel createPositions(Residue parent) {
DefaultListModel ret = new DefaultListModel();
// collect available positions
char[] par_pos = null;
if (parent == null
|| parent.getType().getLinkagePositions().length == 0)
par_pos = new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9',
'N' };
else
par_pos = parent.getType().getLinkagePositions();
// add elements
ret.addElement("?");
for (int i = 0; i < par_pos.length; i++)
ret.addElement("" + par_pos[i]);
return ret;
}
private void fireContextChanged(Context context, boolean switchToDefault) {
for (ContextAwareContainer container : contextAwareContainers) {
container.fireContextChanged(context, switchToDefault);
}
}
private void fireUndoContextChanged(Context context) {
for (ContextAwareContainer container : contextAwareContainers) {
container.fireUndoContextChanged(context);
}
}
private void updateToolbarProperties(boolean showControls) {
ignore_actions = true;
Residue current = getCurrentResidue();
if (theParent instanceof JRibbonFrame && showControls
&& current != null) {
boolean switchToDefault = true;
if (lastMouseButton != null
&& lastMouseButton == MouseEvent.BUTTON3) {
switchToDefault = false;
}
fireContextChanged(Context.GLYCAN_CANVAS_ITEM, switchToDefault);
}
if (current != null && (!current.isSpecial() || current.isCleavage())) {
Linkage parent_link = current.getParentLinkage();
if (parent_link != null) {
field_linkage_position.setListModel(createPositions(parent_link
.getParentResidue()));
field_second_parent_position
.setListModel(createPositions(parent_link
.getParentResidue()));
}
// enable items
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);
field_second_parent_position.setEnabled(can_have_parent_linkage
&& parent_link.hasMultipleBonds());
field_second_child_position.setEnabled(can_have_parent_linkage
&& parent_link.hasMultipleBonds());
// fill items
if (parent_link != null)
field_linkage_position.setSelectedValues(toStrings(parent_link
.glycosidicBond().getParentPositions()));
else
field_linkage_position.clearSelection();
field_anomeric_state.setSelectedItem(""
+ current.getAnomericState());
field_anomeric_carbon.setSelectedItem(""
+ current.getAnomericCarbon());
field_chirality.setSelectedItem("" + current.getChirality());
field_ring_size.setSelectedItem("" + current.getRingSize());
if (parent_link != null) {
field_second_bond.setSelected(parent_link.hasMultipleBonds());
field_second_parent_position
.setSelectedValues(toStrings(parent_link.getBonds()
.get(0).getParentPositions()));
field_second_child_position.setSelectedItem(""
+ parent_link.getBonds().get(0).getChildPosition());
} else {
field_second_bond.setSelected(false);
field_second_parent_position.clearSelection();
field_second_child_position.setSelectedItem("?");
}
} else {
if (theParent instanceof JRibbonFrame && !showControls) {
fireUndoContextChanged(Context.GLYCAN_CANVAS_ITEM);
// ((JRibbonFrame) theParent).getRibbon().setVisible(
// this.theLinkageRibbon, false);
}
// reset all
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);
// fill items
field_linkage_position.clearSelection();
field_anomeric_state.setSelectedItem("?");
field_anomeric_carbon.setSelectedItem("");
field_chirality.setSelectedItem("?");
field_ring_size.setSelectedItem("?");
field_second_bond.setSelected(false);
field_second_parent_position.clearSelection();
field_second_child_position.setSelectedItem("?");
}
ignore_actions = false;
}
private JMenu createAddStructureMenu() {
JMenu add_menu = new JMenu("Add structure");
add_menu.setMnemonic(KeyEvent.VK_A);
add_menu.setIcon(ThemeManager.getEmptyIcon(null));
for (String superclass : CoreDictionary.getSuperclasses()) {
JMenu class_menu = new JMenu(superclass);
for (CoreType t : CoreDictionary.getCores(superclass))
class_menu.add(theActionManager.get("addstructure="
+ t.getName()));
if (class_menu.getItemCount() > 0)
add_menu.add(class_menu);
}
return add_menu;
}
private JMenu createAddResidueMenu() {
JMenu add_menu = new JMenu("Add residue");
add_menu.setMnemonic(KeyEvent.VK_R);
add_menu.setIcon(ThemeManager.getEmptyIcon(null));
for (String superclass : ResidueDictionary.getSuperclasses()) {
JMenu class_menu = new JMenu(superclass);
for (ResidueType t : ResidueDictionary.getResidues(superclass)) {
if (t.canHaveParent())
class_menu.add(theActionManager.get("add=" + t.getName()));
}
if (class_menu.getItemCount() > 0)
add_menu.add(class_menu);
}
return add_menu;
}
private JMenu createAddTerminalMenu() {
JMenu add_menu = new JMenu("Add terminal");
add_menu.setMnemonic(KeyEvent.VK_T);
add_menu.setIcon(ThemeManager.getEmptyIcon(null));
for (String superclass : TerminalDictionary.getSuperclasses()) {
JMenu class_menu = new JMenu(superclass);
for (TerminalType t : TerminalDictionary.getTerminals(superclass)) {
JMenu terminal_menu = new JMenu(t.getDescription());
JMenuItem nlinked_terminal = new JMenuItem("Unknown linkage");
nlinked_terminal.setActionCommand("addterminal=" + t.getName());
nlinked_terminal.addActionListener(this);
terminal_menu.add(nlinked_terminal);
for (int l = 1; l < 9; l++) {
nlinked_terminal = new JMenuItem(l + "-linked");
nlinked_terminal.setActionCommand("addterminal=" + l + "-"
+ t.getName());
nlinked_terminal.addActionListener(this);
terminal_menu.add(nlinked_terminal);
}
class_menu.add(terminal_menu);
}
if (class_menu.getItemCount() > 0)
add_menu.add(class_menu);
}
return add_menu;
}
private JMenu createInsertResidueMenu() {
JMenu insert_menu = new JMenu("Insert residue before");
insert_menu.setMnemonic(KeyEvent.VK_I);
insert_menu.setIcon(ThemeManager.getEmptyIcon(null));
for (String superclass : ResidueDictionary.getSuperclasses()) {
JMenu class_menu = new JMenu(superclass);
for (ResidueType t : ResidueDictionary.getResidues(superclass)) {
if (t.canHaveParent() && t.canHaveChildren()
&& t.getMaxLinkages() >= 2)
class_menu.add(theActionManager
.get("insert=" + t.getName()));
}
if (class_menu.getItemCount() > 0)
insert_menu.add(class_menu);
}
return insert_menu;
}
private JMenu createChangeResidueTypeMenu() {
JMenu change_menu = new JMenu("Change residue type");
change_menu.setMnemonic(KeyEvent.VK_H);
change_menu.setIcon(ThemeManager.getEmptyIcon(null));
for (String superclass : ResidueDictionary.getSuperclasses()) {
JMenu class_menu = new JMenu(superclass);
for (ResidueType t : ResidueDictionary.getResidues(superclass))
class_menu.add(theActionManager.get("change=" + t.getName()));
if (class_menu.getItemCount() > 0)
change_menu.add(class_menu);
}
return change_menu;
}
private void updateRecentResiduesToolbar(JToolBar tb) {
for (int i = 0; i < no_recent_residues_buttons; i++)
tb.remove(recent_residues_index);
no_recent_residues_buttons = 0;
for (String typename : theWorkspace.getResidueHistory()
.getRecentResidues()) {
JButton b = new JButton(theActionManager.get("add=" + typename));
b.setText(null);
tb.add(b, recent_residues_index + no_recent_residues_buttons++);
}
}
private JMenu createZoomMenu() {
GraphicOptions view_opt = theWorkspace.getGraphicOptions();
JMenu zoom_menu = new JMenu("Zoom");
zoom_menu.setMnemonic(KeyEvent.VK_Z);
JRadioButtonMenuItem last = null;
ButtonGroup group = new ButtonGroup();
zoom_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("scale=400")));
last.setSelected(view_opt.SCALE_CANVAS == 4.);
group.add(last);
zoom_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("scale=300")));
last.setSelected(view_opt.SCALE_CANVAS == 3.);
group.add(last);
zoom_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("scale=200")));
last.setSelected(view_opt.SCALE_CANVAS == 2.);
group.add(last);
zoom_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("scale=150")));
last.setSelected(view_opt.SCALE_CANVAS == 1.5);
group.add(last);
zoom_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("scale=100")));
last.setSelected(view_opt.SCALE_CANVAS == 1.);
group.add(last);
zoom_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("scale=67")));
last.setSelected(view_opt.SCALE_CANVAS == 0.67);
group.add(last);
zoom_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("scale=50")));
last.setSelected(view_opt.SCALE_CANVAS == 0.5);
group.add(last);
zoom_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("scale=33")));
last.setSelected(view_opt.SCALE_CANVAS == 0.33);
group.add(last);
zoom_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("scale=25")));
last.setSelected(view_opt.SCALE_CANVAS == 0.25);
group.add(last);
return zoom_menu;
}
private JMenu createViewMenu() {
GraphicOptions view_opt = theWorkspace.getGraphicOptions();
JMenu view_menu = new JMenu("View");
view_menu.setMnemonic(KeyEvent.VK_V);
view_menu.add(createZoomMenu());
view_menu.addSeparator();
// notation
JRadioButtonMenuItem last = null;
ButtonGroup groupn = new ButtonGroup();
view_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("notation=" + GraphicOptions.NOTATION_CFG)));
last.setSelected(view_opt.NOTATION.equals(GraphicOptions.NOTATION_CFG));
groupn.add(last);
view_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("notation=" + GraphicOptions.NOTATION_CFGBW)));
last.setSelected(view_opt.NOTATION
.equals(GraphicOptions.NOTATION_CFGBW));
groupn.add(last);
view_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("notation=" + GraphicOptions.NOTATION_CFGLINK)));
last.setSelected(view_opt.NOTATION
.equals(GraphicOptions.NOTATION_CFGLINK));
groupn.add(last);
view_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("notation=" + GraphicOptions.NOTATION_UOXF)));
last
.setSelected(view_opt.NOTATION
.equals(GraphicOptions.NOTATION_UOXF));
view_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("notation=" + GraphicOptions.NOTATION_UOXFCOL)));
last
.setSelected(view_opt.NOTATION
.equals(GraphicOptions.NOTATION_UOXFCOL));
groupn.add(last);
view_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("notation=" + GraphicOptions.NOTATION_TEXT)));
last
.setSelected(view_opt.NOTATION
.equals(GraphicOptions.NOTATION_TEXT));
groupn.add(last);
view_menu.addSeparator();
// display
display_button_group = new ButtonGroup();
display_models = new HashMap<String, ButtonModel>();
view_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("display=" + GraphicOptions.DISPLAY_COMPACT)));
last.setSelected(view_opt.DISPLAY
.equals(GraphicOptions.DISPLAY_COMPACT));
display_models.put(GraphicOptions.DISPLAY_COMPACT, last.getModel());
display_button_group.add(last);
view_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("display=" + GraphicOptions.DISPLAY_NORMAL)));
last
.setSelected(view_opt.DISPLAY
.equals(GraphicOptions.DISPLAY_NORMAL));
display_models.put(GraphicOptions.DISPLAY_NORMAL, last.getModel());
display_button_group.add(last);
view_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("display=" + GraphicOptions.DISPLAY_NORMALINFO)));
last.setSelected(view_opt.DISPLAY
.equals(GraphicOptions.DISPLAY_NORMALINFO));
display_models.put(GraphicOptions.DISPLAY_NORMALINFO, last.getModel());
display_button_group.add(last);
view_menu.add(last = new JRadioButtonMenuItem(theActionManager
.get("display=" + GraphicOptions.DISPLAY_CUSTOM)));
last
.setSelected(view_opt.DISPLAY
.equals(GraphicOptions.DISPLAY_CUSTOM));
display_models.put(GraphicOptions.DISPLAY_CUSTOM, last.getModel());
display_button_group.add(last);
// view_menu.add( lastcb = new
// JCheckBoxMenuItem(theActionManager.get("showinfo")) );
// lastcb.setState(view_opt.SHOW_INFO);
view_menu.addSeparator();
// export
JCheckBoxMenuItem lastcb = null;
view_menu.add(lastcb = new JCheckBoxMenuItem(theActionManager
.get("collapsemultipleantennae")));
lastcb.setState(view_opt.COLLAPSE_MULTIPLE_ANTENNAE);
view_menu.add(lastcb = new JCheckBoxMenuItem(theActionManager
.get("showmassescanvas")));
lastcb.setState(view_opt.SHOW_MASSES_CANVAS);
view_menu.add(lastcb = new JCheckBoxMenuItem(theActionManager
.get("showmasses")));
lastcb.setState(view_opt.SHOW_MASSES);
view_menu.add(lastcb = new JCheckBoxMenuItem(theActionManager
.get("showredendcanvas")));
show_redend_canvas_button = lastcb;
lastcb.setState(view_opt.SHOW_REDEND_CANVAS);
view_menu.add(lastcb = new JCheckBoxMenuItem(theActionManager
.get("showredend")));
lastcb.setState(view_opt.SHOW_REDEND);
view_menu.addSeparator();
// orientation
view_menu.add(theActionManager.get("orientation"));
view_menu.addSeparator();
view_menu.add(theActionManager.get("displaysettings"));
return view_menu;
}
private RibbonTask createViewRibbonTask() {
JFlowRibbonBand band1 = new JFlowRibbonBand(
"Notation format",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
ArrayList<RibbonBandResizePolicy> resizePolicies1 = new ArrayList<RibbonBandResizePolicy>();
resizePolicies1.add(new CoreRibbonResizePolicies.FlowTwoRows(band1
.getControlPanel()));
resizePolicies1.add(new IconRibbonBandResizePolicy(band1
.getControlPanel()));
band1.setResizePolicies(resizePolicies1);
final GraphicOptions view_opt = theWorkspace.getGraphicOptions();
JCommandButtonPanel panel = new JCommandButtonPanel(
CommandButtonDisplayState.TILE);
panel.addButtonGroup("Active notation");
panel.addButtonToLastGroup(theActionManager.get(
"notation=" + GraphicOptions.NOTATION_CFG)
.getJCommandToggleButton("", this,
view_opt.NOTATION.equals(GraphicOptions.NOTATION_CFG),
ICON_SIZE.L6));
panel
.addButtonToLastGroup(theActionManager.get(
"notation=" + GraphicOptions.NOTATION_CFGBW)
.getJCommandToggleButton(
"",
this,
view_opt.NOTATION
.equals(GraphicOptions.NOTATION_CFGBW),
ICON_SIZE.L6));
panel.addButtonToLastGroup(theActionManager.get(
"notation=" + GraphicOptions.NOTATION_CFGLINK)
.getJCommandToggleButton(
"",
this,
view_opt.NOTATION
.equals(GraphicOptions.NOTATION_CFGLINK),
ICON_SIZE.L6));
panel.addButtonToLastGroup(theActionManager.get(
"notation=" + GraphicOptions.NOTATION_UOXF)
.getJCommandToggleButton("", this,
view_opt.NOTATION.equals(GraphicOptions.NOTATION_UOXF),
ICON_SIZE.L6));
panel.addButtonToLastGroup(theActionManager.get(
"notation=" + GraphicOptions.NOTATION_UOXFCOL)
.getJCommandToggleButton("", this,
view_opt.NOTATION.equals(GraphicOptions.NOTATION_UOXFCOL),
ICON_SIZE.L6));
panel.addButtonToLastGroup(theActionManager.get(
"notation=" + GraphicOptions.NOTATION_TEXT)
.getJCommandToggleButton("", this,
view_opt.NOTATION.equals(GraphicOptions.NOTATION_TEXT),
ICON_SIZE.L6));
panel.setToShowGroupLabels(false);
panel.setSingleSelectionMode(true);
panel.setMaxButtonColumns(6);
panel.setMaxButtonRows(1);
band1.addFlowComponent(panel);
JFlowRibbonBand band3 = new JFlowRibbonBand(
"Display settings",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
band3.addFlowComponent(theActionManager.get("displaysettings")
.getJCommandButton(ICON_SIZE.L4, " ", this,
new RichTooltip("Change display settings", " "), true));
JComboBox zoomList = new JComboBox();
zoomList.addItem(theActionManager.get("scale=300").getName());
zoomList.addItem(theActionManager.get("scale=400").getName());
zoomList.addItem(theActionManager.get("scale=200").getName());
zoomList.addItem(theActionManager.get("scale=150").getName());
zoomList.addItem(theActionManager.get("scale=100").getName());
zoomList.addItem(theActionManager.get("scale=67").getName());
zoomList.addItem(theActionManager.get("scale=50").getName());
zoomList.addItem(theActionManager.get("scale=33").getName());
zoomList.addItem(theActionManager.get("scale=25").getName());
int zoom = (int) (theWorkspace.getGraphicOptions().SCALE_CANVAS * 100);
if (zoom == 145)
zoom = 150;
zoomList.setSelectedItem(theActionManager.get("scale=" + zoom)
.getName());
zoomList.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JComboBox cb = (JComboBox) e.getSource();
String zoomLevel = (String) cb.getSelectedItem();
theWorkspace.getGraphicOptions().SCALE_CANVAS = Double
.parseDouble(zoomLevel.substring(0,
zoomLevel.length() - 1)) / 100.;
respondToDocumentChange = true;
repaint();
}
});
updateOrientationButton();
band3.addFlowComponent(orientationButton);
band3.addFlowComponent(new JLabel("Zoom"));
band3.addFlowComponent(zoomList);
ArrayList<RibbonBandResizePolicy> resizePolicies3 = new ArrayList<RibbonBandResizePolicy>();
resizePolicies3.add(new CoreRibbonResizePolicies.FlowTwoRows(band3
.getControlPanel()));
// //resizePolicies3.add(new
// CoreRibbonResizePolicies.FlowThreeRows(band3.getControlPanel()));
resizePolicies3.add(new IconRibbonBandResizePolicy(band3
.getControlPanel()));
band3.setResizePolicies(resizePolicies3);
JFlowRibbonBand band2 = new JFlowRibbonBand(
"Notation style",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
ArrayList<RibbonBandResizePolicy> resizePolicies2 = new ArrayList<RibbonBandResizePolicy>();
resizePolicies2.add(new CoreRibbonResizePolicies.FlowTwoRows(band2
.getControlPanel()));
resizePolicies2.add(new IconRibbonBandResizePolicy(band2
.getControlPanel()));
band2.setResizePolicies(resizePolicies2);
ButtonGroup group = new ButtonGroup();
JCheckBox box;
band2.addFlowComponent(box = theActionManager.get(
"display=" + GraphicOptions.DISPLAY_COMPACT).getJCheckBox(
"Compact",
view_opt.DISPLAY.equals(GraphicOptions.DISPLAY_COMPACT), this));
group.add(box);
band2.addFlowComponent(box = theActionManager.get(
"display=" + GraphicOptions.DISPLAY_NORMAL).getJCheckBox(
"Normal",
view_opt.DISPLAY.equals(GraphicOptions.DISPLAY_NORMAL), this));
group.add(box);
band2.addFlowComponent(box = theActionManager.get(
"display=" + GraphicOptions.DISPLAY_NORMALINFO).getJCheckBox(
"Extended",
view_opt.DISPLAY.equals(GraphicOptions.DISPLAY_NORMALINFO),
this));
group.add(box);
band2.addFlowComponent(box = theActionManager.get(
"display=" + GraphicOptions.DISPLAY_CUSTOM).getJCheckBox(
"Custom",
view_opt.DISPLAY.equals(GraphicOptions.DISPLAY_CUSTOM), this));
group.add(box);
JFlowRibbonBand band4 = new JFlowRibbonBand(
"Show features",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
ArrayList<RibbonBandResizePolicy> resizePolicies4 = new ArrayList<RibbonBandResizePolicy>();
resizePolicies4.add(new CoreRibbonResizePolicies.FlowThreeRows(band4
.getControlPanel()));
resizePolicies4.add(new IconRibbonBandResizePolicy(band4
.getControlPanel()));
band4.setResizePolicies(resizePolicies4);
band4.addFlowComponent(theActionManager.get("collapsemultipleantennae")
.getJCheckBox("Collapse multiple antennae", this));
band4.addFlowComponent(theActionManager.get("showmassescanvas")
.getJCheckBox("Masses [canvas]", this));
band4.addFlowComponent(theActionManager.get("showmasses").getJCheckBox(
"Masses [export]", this));
band4.addFlowComponent(theActionManager.get("showredendcanvas")
.getJCheckBox("Reducing end indicator [canvas]", this));
band4.addFlowComponent(theActionManager.get("showredend").getJCheckBox(
"Reducing end indicator [export]", this));
theActionManager.get("showmassescanvas").setSelected(
theGlycanRenderer.getGraphicOptions().SHOW_MASSES_CANVAS);
theActionManager.get("showmasses").setSelected(
theGlycanRenderer.getGraphicOptions().SHOW_MASSES);
theActionManager.get("showredend").setSelected(
theGlycanRenderer.getGraphicOptions().SHOW_REDEND);
theActionManager.get("showredendcanvas").setSelected(
theGlycanRenderer.getGraphicOptions().SHOW_REDEND_CANVAS);
JFlowRibbonBand band5 = new JFlowRibbonBand(
"Switch themes",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
ArrayList<RibbonBandResizePolicy> resizePolicies5 = new ArrayList<RibbonBandResizePolicy>();
resizePolicies5.add(new CoreRibbonResizePolicies.FlowTwoRows(band5
.getControlPanel()));
resizePolicies5.add(new IconRibbonBandResizePolicy(band5
.getControlPanel()));
band5.setResizePolicies(resizePolicies5);
JComboBox themes = new JComboBox(new String[] {
"org.pushingpixels.substance.api.skin.OfficeBlue2007Skin",
"org.pushingpixels.substance.api.skin.AutumnSkin",
"org.pushingpixels.substance.api.skin.TwilightSkin",
"org.pushingpixels.substance.api.skin.GraphiteGlassSkin",
"org.pushingpixels.substance.api.skin.GraphiteAquaSkin",
"org.pushingpixels.substance.api.skin.EmeraldDuskSkin",
"org.pushingpixels.substance.api.skin.OfficeSilver2007Skin" });
themes.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane
.showMessageDialog(
null,
"You may need to restart GlycoWorkbench, for the new theme to take full affect!");
// TODO Auto-generated method stub
JComboBox cb = (JComboBox) e.getSource();
String themeString = (String) cb.getSelectedItem();
try {
SubstanceLookAndFeel.setSkin(themeString);
} catch (Exception exc) {
exc.printStackTrace();
}
theWorkspace.getGraphicOptions().THEME = themeString;
}
});
band5.addFlowComponent(themes);
return new RibbonTask("View", band1, band2, band4, band3, band5);
}
private void updateOrientationButton() {
if (orientationButton == null) {
orientationButton = theActionManager.get("orientation")
.getJCommandButton(ICON_SIZE.L4, this, " ");
}
EurocarbResizableIcon iconR = getOrientationIcon();
if(iconR==null){
System.err.println("Icon R is null1");
}else if(iconR.getIconProperties()==null){
System.err.println("Icon R is null2");
}else if(iconR.getIconProperties().id==null){
System.err.println("Icon R is null3");
}
orientationButton.setIcon(iconR.getThemeManager().getResizableIcon(
iconR.getIconProperties().id, ICON_SIZE.L4).getResizableIcon());
try {
theActionManager.get("orientation").putValue(
Action.SMALL_ICON,
iconR.getThemeManager().getImageIcon(
iconR.getIconProperties().id, ICON_SIZE.L3));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private RibbonTask createEditRibbonBand() {
JRibbonBand band2 = new JRibbonBand(
"Actions",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
ArrayList<RibbonBandResizePolicy> resizePolicies = new ArrayList<RibbonBandResizePolicy>();
resizePolicies.add(new CoreRibbonResizePolicies.Mirror(band2
.getControlPanel()));
resizePolicies.add(new CoreRibbonResizePolicies.Mid2Low(band2
.getControlPanel()));
resizePolicies.add(new IconRibbonBandResizePolicy(band2
.getControlPanel()));
band2.setResizePolicies(resizePolicies);
band2.addCommandButton(theActionManager.get("undo").getJCommandButton(
ICON_SIZE.L3, "Undo", this, null), RibbonElementPriority.TOP);
band2.addCommandButton(theActionManager.get("redo").getJCommandButton(
ICON_SIZE.L3, "Redo", this, null), RibbonElementPriority.TOP);
band2.addCommandButton(theActionManager.get("cut").getJCommandButton(
ICON_SIZE.L3, "Cut", this, null), RibbonElementPriority.TOP);
band2.addCommandButton(theActionManager.get("copy").getJCommandButton(
ICON_SIZE.L3, "Copy", this, null), RibbonElementPriority.TOP);
band2.addCommandButton(theActionManager.get("paste").getJCommandButton(
ICON_SIZE.L3, "Paste", this, null), RibbonElementPriority.TOP);
band2.addCommandButton(theActionManager.get("delete")
.getJCommandButton(ICON_SIZE.L3, "Delete", this, null),
RibbonElementPriority.TOP);
JRibbonBand band3 = new JRibbonBand(
"Structures",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
resizePolicies = new ArrayList<RibbonBandResizePolicy>();
resizePolicies.add(new CoreRibbonResizePolicies.Mirror(band3
.getControlPanel()));
resizePolicies.add(new CoreRibbonResizePolicies.Mid2Low(band3
.getControlPanel()));
resizePolicies.add(new IconRibbonBandResizePolicy(band3
.getControlPanel()));
band3.setResizePolicies(resizePolicies);
band3.addCommandButton(theActionManager.get("orderstructuresasc")
.getJCommandButton(ICON_SIZE.L3, "Order ASC", this, null),
RibbonElementPriority.TOP);
band3.addCommandButton(theActionManager.get("orderstructuresdesc")
.getJCommandButton(ICON_SIZE.L3, "Order DSC", this, null),
RibbonElementPriority.TOP);
band3.addCommandButton(theActionManager.get("selectstructure")
.getJCommandButton(ICON_SIZE.L3, "Select", this, null),
RibbonElementPriority.TOP);
band3.addCommandButton(theActionManager.get("selectall")
.getJCommandButton(ICON_SIZE.L3, "Select All", this, null),
RibbonElementPriority.TOP);
band3.addCommandButton(theActionManager.get("selectnone")
.getJCommandButton(ICON_SIZE.L3, "deselect", this, null),
RibbonElementPriority.TOP);
band3.addCommandButton(theActionManager.get("gotostart")
.getJCommandButton(ICON_SIZE.L3, "Start", this, null),
RibbonElementPriority.TOP);
band3.addCommandButton(theActionManager.get("gotoend")
.getJCommandButton(ICON_SIZE.L3, "End", this, null),
RibbonElementPriority.TOP);
return new RibbonTask("Edit", band2, band3,
createStructureRibbonControls());
}
/**
* Update the structure ribbon gallery. a)First checks if a gallery with the
* given name already exists on the ribbon band and removes it if it does
* b)Adds a new gallery with the given name
*
* @param galleryName
* @param band
*/
private void updateStructureRibbonGallery(String galleryName,
JRibbonBand band) {
final GlycanCanvas self = this;
if (band != null && band.getControlPanel() != null) {
if (band.getControlPanel().getRibbonGallery(galleryName) != null) {
band.getControlPanel().removeRibbonGallery(galleryName);
}
ICON_SIZE iconSize = ICON_SIZE.L6;
List<StringValuePair<List<JCommandToggleButton>>> galleryButtons = new ArrayList<StringValuePair<List<JCommandToggleButton>>>();
for (String superclass : CoreDictionary.getSuperclasses()) {
Collection<CoreType> core_types = CoreDictionary
.getCores(superclass);
if (core_types.size() > 0) {
List<JCommandToggleButton> galleryButtonsList = new ArrayList<JCommandToggleButton>();
for (CoreType coreType : core_types) {
JCommandToggleButtonAction button = new JCommandToggleButtonAction(
coreType.getName(), ImageWrapperResizableIcon
.getIcon(theGlycanRenderer.getImage(
Glycan.fromString(coreType
.getStructure()),
false, false, false),
new Dimension(iconSize
.getSize(), iconSize
.getSize()))
);
button.addActionListener(self);
button
.setDisplayState(CommandButtonDisplayState.FIT_TO_ICON);
button.setActionCommand("addstructure="
+ coreType.getName());
galleryButtonsList.add(button);
}
galleryButtons
.add(new StringValuePair<List<JCommandToggleButton>>(
superclass, galleryButtonsList));
}
}
Map<RibbonElementPriority, Integer> visibleButtonCounts = new HashMap<RibbonElementPriority, Integer>();
visibleButtonCounts.put(RibbonElementPriority.LOW, 4);
visibleButtonCounts.put(RibbonElementPriority.MEDIUM, 4);
visibleButtonCounts.put(RibbonElementPriority.TOP, 4);
band.addRibbonGallery(galleryName, galleryButtons,
visibleButtonCounts, 6, 4, RibbonElementPriority.TOP);
}
}
/**
* Update the residue ribbon gallery. a)First checks if a gallery with the
* given name already exists on the ribbon band and removes it if it does
* b)Adds a new gallery with the given name
*
* @param galleryName
* @param band
*/
private void updateInsertResidueRibbonGallery(String galleryName,
JRibbonBand band) {
final GlycanCanvas self = this;
if (band != null && band.getControlPanel() != null) {
if (band.getControlPanel().getRibbonGallery(galleryName) != null) {
band.getControlPanel().removeRibbonGallery(galleryName);
// System.err.println("Removing insert residue gallery");
} else {
this.residueGalleries.get(RESIDUE_INSERT_MODES.INSERT).add(
new ResidueGalleryIndex(band, galleryName));
}
ICON_SIZE iconSize = ICON_SIZE.L6;
List<StringValuePair<List<JCommandToggleButton>>> galleryButtons = new ArrayList<StringValuePair<List<JCommandToggleButton>>>();
for (String superclass : ResidueDictionary.getSuperclasses()) {
Collection<ResidueType> core_types = ResidueDictionary
.getResidues(superclass);
if (core_types.size() > 0) {
List<JCommandToggleButton> galleryButtonsList = new ArrayList<JCommandToggleButton>();
for (ResidueType t : ResidueDictionary
.getResidues(superclass)) {
if (t.canHaveParent() && t.canHaveChildren()) {
// && t.getMaxLinkages() >= 2
ResizableIcon icon = ImageWrapperResizableIcon
.getIcon(this.getGlycanRenderer()
.getResidueRenderer().getImage(t,
iconSize.getSize()),
new Dimension(iconSize.getSize(),
iconSize.getSize()));
JCommandToggleButtonAction button = new JCommandToggleButtonAction(
t.getName(), icon);
button.addActionListener(self);
button.setActionCommand("insert=" + t.getName());
galleryButtonsList.add(button);
}
}
galleryButtons
.add(new StringValuePair<List<JCommandToggleButton>>(
superclass, galleryButtonsList));
}
}
Map<RibbonElementPriority, Integer> visibleButtonCounts = new HashMap<RibbonElementPriority, Integer>();
visibleButtonCounts.put(RibbonElementPriority.LOW, 4);
visibleButtonCounts.put(RibbonElementPriority.MEDIUM, 4);
visibleButtonCounts.put(RibbonElementPriority.TOP, 4);
band.addRibbonGallery(galleryName, galleryButtons,
visibleButtonCounts, 6, 4, RibbonElementPriority.TOP);
}
}
/**
* Update the residue ribbon gallery. a)First checks if a gallery with the
* given name already exists on the ribbon band and removes it if it does
* b)Adds a new gallery with the given name
*
* @param galleryName
* @param band
*/
private void updateChangeResidueRibbonGallery(String galleryName,
JRibbonBand band) {
final GlycanCanvas self = this;
if (band != null && band.getControlPanel() != null) {
if (band.getControlPanel().getRibbonGallery(galleryName) != null) {
band.getControlPanel().removeRibbonGallery(galleryName);
// System.err.println("Removing change residue gallery");
} else {
this.residueGalleries.get(RESIDUE_INSERT_MODES.REPLACE).add(
new ResidueGalleryIndex(band, galleryName));
}
ICON_SIZE iconSize = ICON_SIZE.L6;
List<StringValuePair<List<JCommandToggleButton>>> galleryButtons = new ArrayList<StringValuePair<List<JCommandToggleButton>>>();
for (String superclass : ResidueDictionary.getSuperclasses()) {
Collection<ResidueType> core_types = ResidueDictionary
.getResidues(superclass);
if (core_types.size() > 0) {
List<JCommandToggleButton> galleryButtonsList = new ArrayList<JCommandToggleButton>();
for (ResidueType t : ResidueDictionary
.getResidues(superclass)) {
// if (t.canHaveParent() && t.canHaveChildren()) {
// && t.getMaxLinkages() >= 2
ResizableIcon icon = ImageWrapperResizableIcon.getIcon(
this.getGlycanRenderer().getResidueRenderer()
.getImage(t, iconSize.getSize()),
new Dimension(iconSize.getSize(), iconSize
.getSize()));
JCommandToggleButtonAction button = new JCommandToggleButtonAction(
t.getName(), icon);
button.addActionListener(self);
button.setActionCommand("change=" + t.getName());
galleryButtonsList.add(button);
// }
}
galleryButtons
.add(new StringValuePair<List<JCommandToggleButton>>(
superclass, galleryButtonsList));
}
}
Map<RibbonElementPriority, Integer> visibleButtonCounts = new HashMap<RibbonElementPriority, Integer>();
visibleButtonCounts.put(RibbonElementPriority.LOW, 4);
visibleButtonCounts.put(RibbonElementPriority.MEDIUM, 4);
visibleButtonCounts.put(RibbonElementPriority.TOP, 4);
band.addRibbonGallery(galleryName, galleryButtons,
visibleButtonCounts, 6, 4, RibbonElementPriority.TOP);
}
}
/**
* Update the residue ribbon gallery. a)First checks if a gallery with the
* given name already exists on the ribbon band and removes it if it does
* b)Adds a new gallery with the given name
*
* @param galleryName
* @param band
*/
private void updateAddResidueRibbonGallery(String galleryName,
JRibbonBand band) {
final GlycanCanvas self = this;
if (band != null && band.getControlPanel() != null) {
if (band.getControlPanel().getRibbonGallery(galleryName) != null) {
band.getControlPanel().removeRibbonGallery(galleryName);
// System.err.println("Removing add residue gallery");
} else {
this.residueGalleries.get(RESIDUE_INSERT_MODES.ADD).add(
new ResidueGalleryIndex(band, galleryName));
}
ICON_SIZE iconSize = ICON_SIZE.L6;
List<StringValuePair<List<JCommandToggleButton>>> galleryButtons = new ArrayList<StringValuePair<List<JCommandToggleButton>>>();
for (String superclass : ResidueDictionary.getSuperclasses()) {
Collection<ResidueType> core_types = ResidueDictionary
.getResidues(superclass);
if (core_types.size() > 0) {
List<JCommandToggleButton> galleryButtonsList = new ArrayList<JCommandToggleButton>();
for (ResidueType t : ResidueDictionary
.getResidues(superclass)) {
if (t.canHaveParent()) {
// && t.getMaxLinkages() >= 2
ResizableIcon icon = ImageWrapperResizableIcon
.getIcon(this.getGlycanRenderer()
.getResidueRenderer().getImage(t,
iconSize.getSize()),
new Dimension(iconSize.getSize(),
iconSize.getSize()));
JCommandToggleButtonAction button = new JCommandToggleButtonAction(
t.getName(), icon);
button.addActionListener(self);
button.setActionCommand("add=" + t.getName());
galleryButtonsList.add(button);
}
}
galleryButtons
.add(new StringValuePair<List<JCommandToggleButton>>(
superclass, galleryButtonsList));
}
}
Map<RibbonElementPriority, Integer> visibleButtonCounts = new HashMap<RibbonElementPriority, Integer>();
visibleButtonCounts.put(RibbonElementPriority.LOW, 4);
visibleButtonCounts.put(RibbonElementPriority.MEDIUM, 4);
visibleButtonCounts.put(RibbonElementPriority.TOP, 4);
band.addRibbonGallery(galleryName, galleryButtons,
visibleButtonCounts, 6, 4, RibbonElementPriority.TOP);
}
}
private void updateTerminalRibbonGallery(String galleryName,
JRibbonBand band) {
final GlycanCanvas self = this;
if (band != null && band.getControlPanel() != null) {
if (band.getControlPanel().getRibbonGallery(galleryName) != null) {
band.getControlPanel().removeRibbonGallery(galleryName);
// System.err.println("Removing terminal residue gallery");
} else {
this.residueGalleries.get(RESIDUE_INSERT_MODES.TERMINAL).add(
new ResidueGalleryIndex(band, galleryName));
}
ICON_SIZE iconSize = ICON_SIZE.L6;
List<StringValuePair<List<JCommandToggleButton>>> galleryButtons = new ArrayList<StringValuePair<List<JCommandToggleButton>>>();
for (String superclass : TerminalDictionary.getSuperclasses()) {
Collection<TerminalType> terminal_types = TerminalDictionary
.getTerminals(superclass);
if (terminal_types.size() > 0) {
for (TerminalType terminalType : terminal_types) {
List<JCommandToggleButton> galleryButtonsList = new ArrayList<JCommandToggleButton>();
ResizableIcon icon = ImageWrapperResizableIcon.getIcon(
this.getGlycanRenderer().getImage(
Glycan.fromString(terminalType
.getStructure()), false, false,
false), new Dimension(iconSize
.getSize(), iconSize.getSize()));
JCommandToggleButtonAction button1 = new JCommandToggleButtonAction(
"x-linked", icon);
button1.addActionListener(self);
button1.setActionCommand("addterminal="
+ terminalType.getName());
galleryButtonsList.add(button1);
for (int l = 1; l < 9; l++) {
JCommandToggleButtonAction button = new JCommandToggleButtonAction(
l + "-linked", icon);
button.addActionListener(self);
button.setActionCommand("addterminal=" + l + "-"
+ terminalType.getName());
galleryButtonsList.add(button);
}
galleryButtons
.add(new StringValuePair<List<JCommandToggleButton>>(
superclass + "["
+ terminalType.getDescription()
+ "]", galleryButtonsList));
}
}
}
Map<RibbonElementPriority, Integer> visibleButtonCounts = new HashMap<RibbonElementPriority, Integer>();
visibleButtonCounts.put(RibbonElementPriority.LOW, 4);
visibleButtonCounts.put(RibbonElementPriority.MEDIUM, 4);
visibleButtonCounts.put(RibbonElementPriority.TOP, 4);
band.addRibbonGallery(galleryName, galleryButtons,
visibleButtonCounts, 4, 4, RibbonElementPriority.TOP);
}
}
/**
* Initialise the structure selection ribbon band.
*
* @return
*/
public JRibbonBand createStructureRibbonBand() {
structureSelectionBand = new JRibbonBand(
STRUCTURE_GALLERY_NAME,
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
ArrayList<RibbonBandResizePolicy> resizePolicies = new ArrayList<RibbonBandResizePolicy>();
resizePolicies.add(new CoreRibbonResizePolicies.Mirror(
structureSelectionBand.getControlPanel()));
resizePolicies.add(new CoreRibbonResizePolicies.Mid2Low(
structureSelectionBand.getControlPanel()));
resizePolicies.add(new IconRibbonBandResizePolicy(
structureSelectionBand.getControlPanel()));
structureSelectionBand.setResizePolicies(resizePolicies);
updateStructureRibbonGallery(STRUCTURE_GALLERY_NAME,
structureSelectionBand);
structureSelectionBand.addCommandButton(theActionManager.get(
"addstructurestr").getJCommandButton(ICON_SIZE.L3, "Write",
this, new RichTooltip(" ", "Import structure from string")),
RibbonElementPriority.TOP);
structureSelectionBand.addCommandButton(theActionManager.get(
"addcomposition").getJCommandButton(ICON_SIZE.L3,
"Create composition", this, new RichTooltip("Open", " ")),
RibbonElementPriority.TOP);
return structureSelectionBand;
}
private RibbonTask createStructureRibbonTask() {
structureRibbonBandCFG = createStructureRibbonBand();
JRibbonBand band1 = createAddResidueBand();
RibbonTask task = new RibbonTask("Structure", structureRibbonBandCFG,
band1, createAddTerminalRibbon());
return task;
}
private JRibbonBand createStructureRibbonControls() {
JRibbonBand band = new JRibbonBand(
"Edit glycan",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
ThemeManager.setDefaultResizePolicy(band);
band.addCommandButton(theActionManager.get("bracket")
.getJCommandButton(ICON_SIZE.L3, "Bracket", this,
new RichTooltip("Add bracket ", "Insert bracket")),
RibbonElementPriority.TOP);
band.addCommandButton(theActionManager.get("repeat").getJCommandButton(
ICON_SIZE.L3, "Repeat", this,
new RichTooltip("Add repeat", "Add repeat unit")),
RibbonElementPriority.TOP);
band.addCommandButton(theActionManager.get("moveccw")
.getJCommandButton(
ICON_SIZE.L3,
"Rotate CCW",
this,
new RichTooltip("Rotate residue",
"Rotate residue counter-clockwise")),
RibbonElementPriority.TOP);
band.addCommandButton(theActionManager.get("movecw").getJCommandButton(
ICON_SIZE.L3, "Rotate CW", this,
new RichTooltip("Rotate residue", "Rotate residue clockwise")),
RibbonElementPriority.TOP);
band.addCommandButton(theActionManager.get("changeredend")
.getJCommandButton(
ICON_SIZE.L3,
"Reducing end Type",
this,
new RichTooltip("Reducing end Type",
"Change reducing end type")),
RibbonElementPriority.TOP);
band.addCommandButton(theActionManager.get("properties")
.getJCommandButton(
ICON_SIZE.L3,
"Properties",
this,
new RichTooltip("Residue Properties",
"Get residue properties")),
RibbonElementPriority.TOP);
band.addCommandButton(theActionManager.get("massoptstruct")
.getJCommandButton(
ICON_SIZE.L3,
"Mass options",
this,
new RichTooltip("Mass options",
"Mass options of selected structure")),
RibbonElementPriority.TOP);
return band;
}
private JRibbonBand createAddTerminalRibbon() {
terminalRibbonBand = new JRibbonBand(
"Add Terminal",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
ArrayList<RibbonBandResizePolicy> resizePolicies = new ArrayList<RibbonBandResizePolicy>();
resizePolicies.add(new CoreRibbonResizePolicies.Mirror(
terminalRibbonBand.getControlPanel()));
resizePolicies.add(new CoreRibbonResizePolicies.Mid2Low(
terminalRibbonBand.getControlPanel()));
resizePolicies.add(new IconRibbonBandResizePolicy(terminalRibbonBand
.getControlPanel()));
terminalRibbonBand.setResizePolicies(resizePolicies);
updateTerminalRibbonGallery(TERMINAL_GAL_NAME, terminalRibbonBand);
return terminalRibbonBand;
}
private JRibbonBand createAddResidueBand() {
final GlycanCanvas self = this;
insertResidueJRibbonBand = new JRibbonBand(
"Add residue",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
ArrayList<RibbonBandResizePolicy> resizePolicies = new ArrayList<RibbonBandResizePolicy>();
resizePolicies.add(new CoreRibbonResizePolicies.Mirror(
insertResidueJRibbonBand.getControlPanel()));
resizePolicies.add(new CoreRibbonResizePolicies.Mid2Low(
insertResidueJRibbonBand.getControlPanel()));
resizePolicies.add(new IconRibbonBandResizePolicy(
insertResidueJRibbonBand.getControlPanel()));
insertResidueJRibbonBand.setResizePolicies(resizePolicies);
updateAddResidueRibbonGallery(RESIDUE_GALLERY_NAME,
insertResidueJRibbonBand);
return insertResidueJRibbonBand;
}
private JMenu createEditMenu() {
JMenu edit_menu = new JMenu("Edit");
edit_menu.setMnemonic(KeyEvent.VK_E);
edit_menu.add(theActionManager.get("undo"));
edit_menu.add(theActionManager.get("redo"));
edit_menu.addSeparator();
edit_menu.add(theActionManager.get("cut"));
edit_menu.add(theActionManager.get("copy"));
edit_menu.add(theActionManager.get("paste"));
edit_menu.add(theActionManager.get("delete"));
edit_menu.addSeparator();
edit_menu.add(theActionManager.get("orderstructuresasc"));
edit_menu.add(theActionManager.get("orderstructuresdesc"));
edit_menu.addSeparator();
edit_menu.add(theActionManager.get("selectstructure"));
edit_menu.add(theActionManager.get("selectall"));
edit_menu.add(theActionManager.get("selectnone"));
edit_menu.add(theActionManager.get("gotostart"));
edit_menu.add(theActionManager.get("gotoend"));
edit_menu.addSeparator();
edit_menu.add(theActionManager.get("navup"));
edit_menu.add(theActionManager.get("navdown"));
edit_menu.add(theActionManager.get("navleft"));
edit_menu.add(theActionManager.get("navright"));
// edit_menu.addSeparator();
// edit_menu.add(theActionManager.get("screenshot"));
return edit_menu;
}
private JMenu createStructureMenu() {
JMenu structure_menu = new JMenu("Structure");
structure_menu.setMnemonic(KeyEvent.VK_S);
structure_menu.add(theActionManager.get("addcomposition"));
structure_menu.add(theActionManager.get("addstructurestr"));
structure_menu.add(createAddStructureMenu());
structure_menu.addSeparator();
structure_menu.add(createAddResidueMenu());
structure_menu.add(createAddTerminalMenu());
structure_menu.add(createInsertResidueMenu());
structure_menu.add(createChangeResidueTypeMenu());
// structure_menu.add(createChangeRedEndMenu());
structure_menu.add(theActionManager.get("bracket"));
structure_menu.add(theActionManager.get("repeat"));
structure_menu.addSeparator();
structure_menu.add(theActionManager.get("properties"));
structure_menu.add(theActionManager.get("changeredend"));
structure_menu.add(theActionManager.get("massoptstruct"));
structure_menu.addSeparator();
structure_menu.add(theActionManager.get("moveccw"));
// structure_menu.add(theActionManager.get("resetplace"));
structure_menu.add(theActionManager.get("movecw"));
return structure_menu;
}
/**
* Return a popup menu to be used with this component
*/
public JPopupMenu createPopupMenu() {
return createPopupMenu(true);
}
/**
* Return a popup menu to be used with this component
*
* @param change_properties
* <code>true</code> if the actions to change the properties of
* the current residue should be added to the menu
*/
public JPopupMenu createPopupMenu(boolean change_properties) {
JPopupMenu menu = new JPopupMenu();
menu.setDoubleBuffered(true);
// edit actions
menu.add(theActionManager.get("cut"));
menu.add(theActionManager.get("copy"));
menu.add(theActionManager.get("paste"));
menu.add(theActionManager.get("delete"));
menu.addSeparator();
// add actions
if (!hasCurrentSelection()) {
menu.add(theActionManager.get("addcomposition"));
menu.add(createAddStructureMenu());
}
if (!hasCurrentLinkage()) {
menu.add(createAddResidueMenu());
menu.add(createAddTerminalMenu());
}
// modify structure
if (hasCurrentResidue()) {
menu.add(createInsertResidueMenu());
menu.add(createChangeResidueTypeMenu());
// menu.add(createChangeRedEndMenu());
menu.add(theActionManager.get("bracket"));
menu.add(theActionManager.get("repeat"));
if (change_properties) {
menu.addSeparator();
menu.add(theActionManager.get("properties"));
menu.add(theActionManager.get("changeredend"));
menu.add(theActionManager.get("massoptstruct"));
}
}
// visual placement
if (hasCurrentSelection()) {
menu.addSeparator();
menu.add(theActionManager.get("moveccw"));
// menu.add(theActionManager.get("resetplace"));
menu.add(theActionManager.get("movecw"));
}
return menu;
}
private JToolBar createToolBarDocument() {
JToolBar toolbar = new JToolBar();
toolbar.setFloatable(false);
toolbar.add(theActionManager.get("undo"));
toolbar.add(theActionManager.get("redo"));
toolbar.addSeparator();
toolbar.add(theActionManager.get("cut"));
toolbar.add(theActionManager.get("copy"));
toolbar.add(theActionManager.get("paste"));
toolbar.add(theActionManager.get("delete"));
return toolbar;
}
private JToolBar createToolBarStructure() {
JToolBar toolbar = new JToolBar();
toolbar.setVisible(true);
toolbar.setFloatable(false);
for (Iterator<ResidueType> i = ResidueDictionary.directResidues()
.iterator(); i.hasNext();) {
ResidueType t = i.next();
if (t.canHaveParent()) {
toolbar.add(theActionManager.get("add=" + t.getName()));
}
}
toolbar.addSeparator();
// recent residues
recent_residues_index = toolbar.getComponentCount();
no_recent_residues_buttons = 0;
updateRecentResiduesToolbar(toolbar);
toolbar.addSeparator();
toolbar.add(theActionManager.get("bracket"));
toolbar.add(theActionManager.get("repeat"));
toolbar.add(theActionManager.get("properties"));
toolbar.addSeparator();
toolbar.add(theActionManager.get("moveccw"));
// toolbar.add(theActionManager.get("resetplace"));
toolbar.add(theActionManager.get("movecw"));
toolbar.addSeparator();
toolbar.add(theActionManager.get("orientation"));
return toolbar;
}
private JLabel createLabel(String text, int margin) {
JLabel ret = new JLabel(text);
ret.setBorder(new EmptyBorder(0, margin, 0, margin));
return ret;
}
private JToolBar createToolBarProperties() {
JToolBar toolbar = new JToolBar();
toolbar.setFloatable(false);
toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));
toolbar.add(createLabel("Linkage", 5));
toolbar.add(field_anomeric_state = new JComboBox(new String[] { "?",
"a", "b" }));
toolbar.add(field_anomeric_carbon = new JComboBox(new String[] { "?",
"1", "2", "3" }));
toolbar.add(createLabel("->", 1));
toolbar.add(field_linkage_position = new DropDownList(new String[] {
"?", "1", "2", "3", "4", "5", "6", "7", "8", "9" }));
toolbar.add(createLabel("Chirality", 5));
toolbar.add(field_chirality = new JComboBox(new String[] { "?", "D",
"L" }));
toolbar.add(createLabel("Ring", 5));
toolbar.add(field_ring_size = new JComboBox(new String[] { "?", "p",
"f", "o" }));
toolbar.add(createLabel("2nd bond", 5));
toolbar.add(field_second_bond = new JCheckBox(""));
toolbar.add(field_second_child_position = new JComboBox(new String[] {
"?", "1", "2", "3" }));
toolbar.add(createLabel("->", 1));
toolbar
.add(field_second_parent_position = new DropDownList(
new String[] { "?", "1", "2", "3", "4", "5", "6", "7",
"8", "9" }));
field_anomeric_state.setActionCommand("setproperties");
field_anomeric_carbon.setActionCommand("setproperties");
field_linkage_position.setActionCommand("setproperties");
field_chirality.setActionCommand("setproperties");
field_ring_size.setActionCommand("setproperties");
field_second_bond.setActionCommand("setproperties");
field_second_child_position.setActionCommand("setproperties");
field_second_parent_position.setActionCommand("setproperties");
field_anomeric_state.addActionListener(this);
field_anomeric_carbon.addActionListener(this);
field_linkage_position.addActionListener(this);
field_chirality.addActionListener(this);
field_ring_size.addActionListener(this);
field_second_bond.addActionListener(this);
field_second_child_position.addActionListener(this);
field_second_parent_position.addActionListener(this);
return toolbar;
}
private RibbonContextualTaskGroup createLinkageRibbon() {
JFlowRibbonBand band1 = new JFlowRibbonBand(
"Linkage specification",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
JToolBar toolbar = new JToolBar();
toolbar.setFloatable(false);
toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));
toolbar.add(createLabel("Linkage", 5));
toolbar.add(field_anomeric_state = new JComboBox(new String[] { "?",
"a", "b" }));
toolbar.add(field_anomeric_carbon = new JComboBox(new String[] { "?",
"1", "2", "3" }));
toolbar.add(createLabel("->", 1));
toolbar.add(field_linkage_position = new DropDownList(new String[] {
"?", "1", "2", "3", "4", "5", "6", "7", "8", "9" }));
toolbar.add(createLabel("Chirality", 5));
toolbar.add(field_chirality = new JComboBox(new String[] { "?", "D",
"L" }));
toolbar.add(createLabel("Ring", 5));
toolbar.add(field_ring_size = new JComboBox(new String[] { "?", "p",
"f", "o" }));
toolbar.add(createLabel("2nd bond", 5));
toolbar.add(field_second_bond = new JCheckBox(""));
toolbar.add(field_second_child_position = new JComboBox(new String[] {
"?", "1", "2", "3" }));
toolbar.add(createLabel("->", 1));
toolbar
.add(field_second_parent_position = new DropDownList(
new String[] { "?", "1", "2", "3", "4", "5", "6", "7",
"8", "9" }));
field_anomeric_state.setActionCommand("setproperties");
field_anomeric_carbon.setActionCommand("setproperties");
field_linkage_position.setActionCommand("setproperties");
field_chirality.setActionCommand("setproperties");
field_ring_size.setActionCommand("setproperties");
field_second_bond.setActionCommand("setproperties");
field_second_child_position.setActionCommand("setproperties");
field_second_parent_position.setActionCommand("setproperties");
field_anomeric_state.addActionListener(this);
field_anomeric_carbon.addActionListener(this);
field_linkage_position.addActionListener(this);
field_chirality.addActionListener(this);
field_ring_size.addActionListener(this);
field_second_bond.addActionListener(this);
field_second_child_position.addActionListener(this);
field_second_parent_position.addActionListener(this);
// band1.setLayout(new BorderLayout());
band1.addFlowComponent(toolbar);
JRibbonBand band2 = new JRibbonBand(
"Insert residue",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
// ArrayList<RibbonBandResizePolicy> resizePolicies = new
// ArrayList<RibbonBandResizePolicy>();
// resizePolicies.add(new
// CoreRibbonResizePolicies.Mirror(insertResidueJRibbonBand.getControlPanel()));
// resizePolicies.add(new
// CoreRibbonResizePolicies.Mid2Low(insertResidueJRibbonBand.getControlPanel()));
// resizePolicies.add(new
// IconRibbonBandResizePolicy(insertResidueJRibbonBand.getControlPanel()));
// band2.setResizePolicies(resizePolicies);
this.updateInsertResidueRibbonGallery("Insert residue", band2);
JRibbonBand band3 = new JRibbonBand(
"Add residue",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
this.updateAddResidueRibbonGallery("Add residue", band3);
JRibbonBand band4 = new JRibbonBand(
"Change residue",
new org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon(
10));
this.updateChangeResidueRibbonGallery("Change residue", band4);
RibbonTask task1 = new RibbonTask("Linkage specification", band1);
return new RibbonContextualTaskGroup("Residue options", Color.GREEN,
new RibbonTask("Residue input", band2, band3, band4), task1);// ,new
// RibbonTask("Add residue",band3),new
// RibbonTask("Change residue",band4));
}
// -------------------
// JComponent
public Dimension getPreferredSize() {
return theGlycanRenderer.computeSize(all_structures_bbox);
}
public Dimension getMinimumSize() {
return new Dimension(0, 0);
}
/**
* Return the position manager used by this component to render the
* structures
*/
public PositionManager getPositionManager() {
return thePosManager;
}
// -------------------
// clipboard handling
/**
* Return a screenshot of the component
*/
public void getScreenshot() {
ClipUtils.setContents(new GlycanSelection(theGlycanRenderer, theDoc
.getStructures()));
}
/**
* Delete the selected residues/structures and copy them to the clipboard
*/
public void cut() {
copy();
delete();
}
/**
* Copy the selected residues/structures to the clipboard
*/
public void copy() {
Collection<Glycan> sel = theDoc.extractView(selected_residues);
ClipUtils.setContents(new GlycanSelection(theGlycanRenderer, sel));
}
/**
* Copy all selected structures to the clipboard
*/
public void copySelectedStructures() {
ClipUtils.setContents(new GlycanSelection(theGlycanRenderer,
getSelectedStructures()));
}
/**
* Copy all structures to the clipboard
*/
public void copyAllStructures() {
ClipUtils.setContents(new GlycanSelection(theGlycanRenderer, theDoc
.getStructures()));
}
/**
* Paste the content of the clipboard into the editor
*/
public void paste() {
try {
Transferable t = ClipUtils.getContents();
if (t != null
&& t.isDataFlavorSupported(GlycanSelection.glycoFlavor)) {
String content = TextUtils.consume((InputStream) t
.getTransferData(GlycanSelection.glycoFlavor));
theDoc.addStructures(current_residue, theDoc
.parseString(content));
}
} catch (Exception e) {
LogUtils.report(e);
}
}
/**
* Delete the selected residues/structures
*/
public void delete() {
Residue new_current = (current_residue != null) ? current_residue
.getParent() : null;
// cut
theDoc.removeResidues(selected_residues);
// update selection
if (theDoc.contains(new_current))
setSelection(new_current, false);
}
/**
* Copy the selected residues and add them to another residue
*
* @param position
* the destination
*/
public void copyTo(Residue position) {
theDoc.copyResidues(position, theBBoxManager
.getLinkedResidues(position), selected_residues);
}
/**
* Move the selected residues from their current positions and add them to
* another residue
*
* @param position
* the destination
*/
public void moveTo(Residue position) {
theDoc.moveResidues(position, theBBoxManager
.getLinkedResidues(position), selected_residues);
}
// -------------------
// painting
private void xorRectangle(Point start_point, Point end_point) {
Graphics g = getGraphics();
g.setXORMode(Color.white);
g.setColor(Color.black);
Rectangle rect = makeRectangle(start_point, end_point);
g.drawRect(rect.x, rect.y, rect.width, rect.height);
}
/**
* Return <code>true</code> if the specified residue is displayed around the
* border of its parent
*/
public boolean isOnBorder(Residue r) {
return thePosManager.isOnBorder(r);
}
protected void paintComponent(Graphics g) {
if (isOpaque()) { // paint background
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
// prepare graphic object
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// set clipping area
Rectangle clipRect = new Rectangle();
g.getClipBounds(clipRect);
// set scale
theGlycanRenderer.getGraphicOptions().setScale(
theGlycanRenderer.getGraphicOptions().SCALE_CANVAS);
// draw
boolean show_masses = is_printing ? theGlycanRenderer
.getGraphicOptions().SHOW_MASSES : theGlycanRenderer
.getGraphicOptions().SHOW_MASSES_CANVAS;
boolean show_redend = is_printing ? theGlycanRenderer
.getGraphicOptions().SHOW_REDEND : theGlycanRenderer
.getGraphicOptions().SHOW_REDEND_CANVAS;
all_structures_bbox = theGlycanRenderer.computeBoundingBoxes(theDoc
.getStructures(), show_masses, show_redend, thePosManager,
theBBoxManager);
for (Glycan s : theDoc.getStructures())
theGlycanRenderer.paint(g2d, s, selected_residues,
selected_linkages, show_masses, show_redend, thePosManager,
theBBoxManager);
if (!is_printing)
paintSelection(g2d, show_redend);
//
// if(theDoc.has_changed)
if (this.respondToDocumentChange) {
this.respondToDocumentChange = false;
revalidate();
}
// dispose graphic object
g2d.dispose();
theGlycanRenderer.getGraphicOptions().setScale(
theGlycanRenderer.getGraphicOptions().SCALE);
}
private void paintSelection(Graphics2D g2d, boolean show_redend) {
GraphicOptions theGraphicOptions = theGlycanRenderer
.getGraphicOptions();
Collection<Glycan> sel_structures = theDoc.findStructuresWith(
selected_residues, selected_linkages);
Glycan cur_structure = getCurrentStructure();
for (Iterator<Glycan> i = theDoc.getStructures().iterator(); i
.hasNext();) {
Glycan s = i.next();
if (sel_structures.contains(s)) {
Rectangle bbox = theBBoxManager.getBBox(s, show_redend);
for (; i.hasNext();) {
Glycan t = i.next();
if (sel_structures.contains(t))
bbox = union(bbox, theBBoxManager.getBBox(t,
show_redend));
else
break;
}
if (bbox != null) {
g2d.setColor(UIManager
.getColor("Table.selectionBackground"));
g2d.fill(new Rectangle(
theGraphicOptions.MARGIN_LEFT / 2 - 3, bbox.y, 5,
bbox.height + theGraphicOptions.MASS_TEXT_SPACE
+ theGraphicOptions.MASS_TEXT_SIZE));
}
}
}
// paint cur_structure
if (cur_structure != null) {
Rectangle cur_bbox = theBBoxManager.getBBox(cur_structure,
show_redend);
if (cur_bbox != null) {
UIManager.getBorder("Table.focusCellHighlightBorder")
.paintBorder(
sel_label,
g2d,
theGraphicOptions.MARGIN_LEFT / 2 - 3,
cur_bbox.y,
5,
cur_bbox.height
+ theGraphicOptions.MASS_TEXT_SPACE
+ theGraphicOptions.MASS_TEXT_SIZE);
}
}
}
// ---------------
// selection
/**
* Return the residue displayed at the specified position, or
* <code>null</code> if none is there
*/
public Residue getResidueAtPoint(Point p) {
for (Glycan g : theDoc.getStructures()) {
Residue ret = getResidueAtPoint(g.getRoot(), p);
if (ret != null)
return ret;
ret = getResidueAtPoint(g.getBracket(), p);
if (ret != null)
return ret;
}
return null;
}
/**
* Return the child of a residue that is displayed at the specified
* position, or <code>null</code> if none is there
*
* @param r
* the parent
*/
public Residue getResidueAtPoint(Residue r, Point p) {
if (r == null)
return null;
Rectangle cur_bbox = theBBoxManager.getCurrent(r);
if (cur_bbox != null && cur_bbox.contains(p))
return r;
for (Linkage l : r.getChildrenLinkages()) {
Residue ret = getResidueAtPoint(l.getChildResidue(), p);
if (ret != null)
return ret;
}
return null;
}
/**
* Return the linkage displayed at the specified position, or
* <code>null</code> if none is there
*/
public Linkage getLinkageAtPoint(Point p) {
for (Glycan g : theDoc.getStructures()) {
Linkage ret = getLinkageAtPoint(g.getRoot(), p);
if (ret != null)
return ret;
ret = getLinkageAtPoint(g.getBracket(), p);
if (ret != null)
return ret;
}
return null;
}
/**
* Return the linkage from a residue that is displayed at the specified
* position, or <code>null</code> if none is there
*
* @param r
* the parent
*/
public Linkage getLinkageAtPoint(Residue r, Point p) {
if (r == null)
return null;
Rectangle cur_bbox = theBBoxManager.getCurrent(r);
for (Linkage l : r.getChildrenLinkages()) {
Rectangle child_bbox = theBBoxManager.getCurrent(l
.getChildResidue());
if (cur_bbox != null && child_bbox != null
&& distance(p, center(cur_bbox), center(child_bbox)) < 4.)
return l;
Linkage ret = getLinkageAtPoint(l.getChildResidue(), p);
if (ret != null)
return ret;
}
return null;
}
/**
* Return <code>true</code> if any residue or linkage is selected
*/
public boolean hasSelection() {
return (selected_residues.size() > 0 || selected_linkages.size() > 0);
}
/**
* Clear the selection
*/
public void resetSelection() {
selected_residues.clear();
selected_linkages.clear();
current_residue = null;
current_linkage = null;
fireUpdatedSelection(true);
}
/**
* Return <code>true</code> if any residue or linkage has the focus.
* Rectangle selection may not give the focus to a specific residue or
* linkage
*/
public boolean hasCurrentSelection() {
return (current_residue != null || current_linkage != null);
}
/**
* Return the residue with the focus. If a linkage has the focus, the child
* residue is returned
*/
public Residue getCurrentSelection() {
if (current_residue != null)
return current_residue;
if (current_linkage != null)
return current_linkage.getChildResidue();
return null;
}
/**
* Return the structure containing the residue with the focus
*/
public Glycan getCurrentStructure() {
if (current_residue != null)
return theDoc.findStructureWith(current_residue);
if (current_linkage != null)
return theDoc.findStructureWith(current_linkage.getChildResidue());
return null;
}
/**
* Return all the structures containing the selected residues and linkages
*/
public Collection<Glycan> getSelectedStructures() {
return theDoc.findStructuresWith(selected_residues, selected_linkages);
}
/**
* Return <code>true</code> if a residue has the focus
*/
public boolean hasCurrentResidue() {
return (current_residue != null);
}
/**
* Return the residue with the focus
*/
public Residue getCurrentResidue() {
return current_residue;
}
/**
* Return all the residues that are shown at the same position of the
* residue with the focus
*/
public Vector<Residue> getLinkedResidues() {
return theBBoxManager.getLinkedResidues(current_residue);
}
private void setCurrentResidue(Residue node) {
if (node != null)
selected_residues.add(node);
selected_linkages.clear();
current_residue = node;
current_linkage = null;
fireUpdatedSelection(false);
}
/**
* Return <code>true</code> if a linkage has the focus
*/
public boolean hasCurrentLinkage() {
return (current_linkage != null);
}
/**
* Return the linkage with the focus
*/
public Linkage getCurrentLinkage() {
return current_linkage;
}
/**
* Return <code>true</code> if the specified residue is selected
*/
public boolean isSelected(Residue node) {
if (node == null)
return false;
return selected_residues.contains(node);
}
/**
* Return <code>true</code> if the specified linkage is selected
*/
public boolean isSelected(Linkage link) {
if (link == null)
return false;
return selected_linkages.contains(link);
}
/**
* Return <code>true</code> if any residue is selected
*/
public boolean hasSelectedResidues() {
return !selected_residues.isEmpty();
}
/**
* Return <code>true</code> if any linkage is selected
*/
public boolean hasSelectedLinkages() {
return !selected_linkages.isEmpty();
}
/**
* Return a list containing the selected residues
*/
public Collection<Residue> getSelectedResiduesList() {
return selected_residues;
}
/**
* Return an array containing the selected residues
*/
public Residue[] getSelectedResidues() {
return (Residue[]) selected_residues.toArray(new Residue[0]);
}
/**
* Select a specific set of residues
*/
public void setSelection(Collection<Residue> nodes) {
if (nodes == null || nodes.isEmpty()) {
resetSelection();
} else {
selected_residues.clear();
selected_linkages.clear();
current_residue = null;
current_linkage = null;
for (Residue node : nodes) {
selected_residues.add(node);
selected_residues
.addAll(theBBoxManager.getLinkedResidues(node));
}
fireUpdatedSelection(false);
}
}
public void setSelection(Residue node) {
this.setSelection(node, false);
}
/**
* Select a specific residue and set the focus on it
*/
public void setSelection(Residue node, boolean showResidueControls) {
if (node == null)
resetSelection();
else {
selected_residues.clear();
selected_linkages.clear();
selected_residues.add(node);
selected_residues.addAll(theBBoxManager.getLinkedResidues(node));
current_residue = node;
current_linkage = null;
fireUpdatedSelection(showResidueControls);
}
}
public void setSelection(Linkage link) {
setSelection(link, false);
}
/**
* Select a specific linkage and set the focus to it
*/
public void setSelection(Linkage link, boolean showResidueControls) {
if (link == null)
resetSelection();
else {
selected_residues.clear();
selected_linkages.clear();
selected_linkages.add(link);
current_residue = null;
current_linkage = link;
fireUpdatedSelection(showResidueControls);
}
}
/**
* Make sure that the residue at the specified point is selected
*/
public void enforceSelection(Point p) {
Residue r = getResidueAtPoint(p);
if (r != null)
enforceSelection(r);
else {
Linkage l = getLinkageAtPoint(p);
if (l != null)
enforceSelection(l);
else
resetSelection();
}
}
/**
* Make sure that the specified residue is selected
*/
public void enforceSelection(Residue node) {
if (isSelected(node)) {
current_residue = node;
fireUpdatedSelection(false);
} else
setSelection(node);
}
/**
* Make sure that the specified linkage is selected
*/
public void enforceSelection(Linkage link) {
if (isSelected(link)) {
current_linkage = link;
fireUpdatedSelection(false);
} else
setSelection(link);
}
/**
* Make sure that something is selected. In case select the first residue of
* the first structure if any
*/
public boolean enforceSelection() {
if (!hasCurrentSelection()) {
if (theDoc.getNoStructures() == 0)
return false;
if (theDoc.getFirstStructure().getRoot() == null)
return false;
setSelection(theDoc.getFirstStructure().getRoot());
}
return true;
}
/**
* Add a list of residues to the selection
*/
public void addSelection(Collection<Residue> nodes) {
if (nodes != null) {
for (Residue node : nodes) {
selected_residues.add(node);
selected_residues
.addAll(theBBoxManager.getLinkedResidues(node));
}
selected_linkages.clear();
current_residue = null;
current_linkage = null;
fireUpdatedSelection(false);
}
}
/**
* Add a residue to the selection
*/
public void addSelection(Residue node) {
if (node != null) {
selected_residues.add(node);
selected_residues.addAll(theBBoxManager.getLinkedResidues(node));
selected_linkages.clear();
current_residue = node;
current_linkage = null;
fireUpdatedSelection(false);
this.respondToDocumentChange = true;
repaint();
}
}
/**
* Add to the selection all the residues that are between the residue with
* the focus and the specified residue
*/
public void addSelectionPathTo(Residue node) {
if (node != null) {
if (current_residue == null) {
selected_residues.add(node);
selected_residues
.addAll(theBBoxManager.getLinkedResidues(node));
} else {
for (Residue r : Glycan.getPath(current_residue, node)) {
selected_residues.add(r);
selected_residues.addAll(theBBoxManager
.getLinkedResidues(node));
}
}
selected_linkages.clear();
current_residue = node;
current_linkage = null;
fireUpdatedSelection(false);
}
}
/**
* Select all the residues from the structure with the focus
*/
public void selectStructure() {
selected_linkages.clear();
selected_residues.clear();
Glycan s = getCurrentStructure();
if (s != null) {
selectAll(s.getRoot());
selectAll(s.getBracket());
}
current_linkage = null;
fireUpdatedSelection(true);
}
/**
* Select all residues from all structures
*/
public void selectAll() {
for (Iterator<Glycan> i = theDoc.iterator(); i.hasNext();) {
Glycan structure = i.next();
selectAll(structure.getRoot());
selectAll(structure.getBracket());
}
selected_linkages.clear();
current_residue = null;
current_linkage = null;
if (theDoc.getFirstStructure() != null)
current_residue = theDoc.getFirstStructure().getRoot();
fireUpdatedSelection(true);
}
private void selectAll(Residue node) {
if (node == null)
return;
selected_residues.add(node);
for (Iterator<Linkage> i = node.iterator(); i.hasNext();)
selectAll(i.next().getChildResidue());
}
private Residue findNearest(Point p, Collection<Residue> nodes) {
if (p == null)
return null;
Residue best_node = null;
double best_dist = 0.;
for (Residue cur_node : nodes) {
Rectangle cur_rect = theBBoxManager.getCurrent(cur_node);
if (cur_rect != null) {
double cur_dist = distance(p, cur_rect);
if (best_node == null || best_dist > cur_dist) {
best_node = cur_node;
best_dist = cur_dist;
}
}
}
return best_node;
}
// ---------------
// visual structure rearrangement
private Residue getResidueAfter(Residue parent, Residue current,
ResAngle cur_pos) {
Vector<Residue> linked = theBBoxManager.getLinkedResidues(current);
for (int i = parent.indexOf(current) + 1; i < parent.getNoChildren(); i++) {
Residue other = parent.getChildAt(i);
if (thePosManager.getRelativePosition(other).equals(cur_pos)
&& !linked.contains(other))
return other;
}
return null;
}
private Residue getResidueBefore(Residue parent, Residue current,
ResAngle cur_pos) {
Vector<Residue> linked = theBBoxManager.getLinkedResidues(current);
for (int i = parent.indexOf(current) - 1; i >= 0; i--) {
Residue other = parent.getChildAt(i);
if (thePosManager.getRelativePosition(other).equals(cur_pos)
&& !linked.contains(other))
return other;
}
return null;
}
private Residue getFirstResidue(Residue parent, Residue current,
ResAngle cur_pos) {
for (int i = 0; i < parent.getNoChildren(); i++) {
Residue other = parent.getChildAt(i);
if (thePosManager.getRelativePosition(other).equals(cur_pos)
&& other != current)
return other;
}
return null;
}
private Residue getLastResidue(Residue parent, Residue current,
ResAngle cur_pos) {
for (int i = parent.getNoChildren() - 1; i >= 0; i--) {
Residue other = parent.getChildAt(i);
if (thePosManager.getRelativePosition(other).equals(cur_pos)
&& other != current)
return other;
}
return null;
}
private void updateAndMantainSelection() {
if (current_residue != null) {
Residue old_current = current_residue;
theDoc.fireDocumentChanged();
setSelection(old_current);
} else if (current_linkage != null) {
Linkage old_current = current_linkage;
theDoc.fireDocumentChanged();
setSelection(old_current);
}
}
private void swapAndMantainSelection(Residue r1, Residue r2) {
if (current_residue != null) {
Residue old_current = current_residue;
theDoc.swap(r1, r2);
setSelection(old_current);
} else if (current_linkage != null) {
Linkage old_current = current_linkage;
theDoc.swap(r1, r2);
setSelection(old_current);
}
}
/*
* public void resetPlacement() { Residue current = getCurrentSelection();
* if( current == null ) return;
*
* current.resetPreferredPlacement(); updateAndMantainSelection(); }
*/
/*
* public void toggleSticky() { Residue current = getCurrentSelection(); if(
* current == null || current.getPreferredPlacement()==null ) return;
*
* current_residue.getPreferredPlacement().toggleSticky();
* updateAndMantainSelection(); }
*/
private void setPlacement(Residue current, ResiduePlacement new_rp) {
current.setPreferredPlacement(new_rp);
for (Residue r : theBBoxManager.getLinkedResidues(current))
r.setPreferredPlacement(new_rp);
}
private void setWasSticky(Residue current, boolean f) {
current.setWasSticky(f);
for (Residue r : theBBoxManager.getLinkedResidues(current))
r.setWasSticky(f);
}
private void moveBefore(Residue parent, Residue current, Residue other) {
parent.moveChildBefore(current, other);
for (Residue r : theBBoxManager.getLinkedResidues(current)) {
if (r.getParent() == parent)
parent.moveChildBefore(r, other);
}
}
private void moveAfter(Residue parent, Residue current, Residue other) {
parent.moveChildAfter(current, other);
for (Residue r : theBBoxManager.getLinkedResidues(current)) {
if (r.getParent() == parent)
parent.moveChildAfter(r, other);
}
}
/**
* Move counter-clockwise the display position of the residue with the focus
*/
public void onMoveCCW() {
Residue current = getCurrentSelection();
if (current == null || current.getParent() == null)
return;
Residue parent = current.getParent();
ResAngle cur_pos = thePosManager.getRelativePosition(current);
// try to move the children in the list
Residue other = getResidueBefore(parent, current, cur_pos);
if (other != null) {
moveBefore(parent, current, other);
updateAndMantainSelection();
return;
}
// set preferred position
if (!current.hasPreferredPlacement())
setWasSticky(current, thePosManager.isSticky(current));
ResAngle new_pos = null;
ResiduePlacement new_rp = null;
if (thePosManager.isOnBorder(current)) {
new_pos = (cur_pos.getIntAngle() == -90) ? new ResAngle(90)
: new ResAngle(-90);
new_rp = new ResiduePlacement(new_pos, true, false);
} else {
new_pos = (cur_pos.getIntAngle() == -90) ? new ResAngle(90)
: cur_pos.combine(-45);
new_rp = (new_pos.getIntAngle() == -90 || new_pos.getIntAngle() == 90) ? new ResiduePlacement(
new_pos, false, current.getWasSticky())
: new ResiduePlacement(new_pos, false, false);
}
setPlacement(current, new_rp);
// put residue in the correct order
other = getLastResidue(parent, current, new_pos);
moveAfter(parent, current, other);
updateAndMantainSelection();
}
/**
* Move clockwise the display position of the residue with the focus
*/
public void onMoveCW() {
Residue current = getCurrentSelection();
if (current == null || current.getParent() == null)
return;
ResAngle cur_pos = thePosManager.getRelativePosition(current);
Residue parent = current.getParent();
// try to move the children in the list
Residue other = getResidueAfter(parent, current, cur_pos);
if (other != null) {
moveAfter(parent, current, other);
updateAndMantainSelection();
return;
}
// set preferred position
if (!current.hasPreferredPlacement())
setWasSticky(current, thePosManager.isSticky(current));
ResAngle new_pos = null;
ResiduePlacement new_rp = null;
if (thePosManager.isOnBorder(current)) {
new_pos = (cur_pos.getIntAngle() == -90) ? new ResAngle(90)
: new ResAngle(-90);
new_rp = new ResiduePlacement(new_pos, true, false);
} else {
new_pos = (cur_pos.getIntAngle() == 90) ? new ResAngle(-90)
: cur_pos.combine(45);
new_rp = (new_pos.getIntAngle() == -90 || new_pos.getIntAngle() == 90) ? new ResiduePlacement(
new_pos, false, current.getWasSticky())
: new ResiduePlacement(new_pos, false, false);
}
setPlacement(current, new_rp);
// put residue in the correct order
other = getFirstResidue(parent, current, new_pos);
moveBefore(parent, current, other);
updateAndMantainSelection();
}
// ---------------
// structure navigation
/**
* Scroll the component to the beginning
*/
public void goToStart() {
JViewport vp = theScrollPane.getViewport();
vp.setViewPosition(new Point(0, 0));
vp.setViewPosition(new Point(0, 0));
}
/**
* Scroll the component to the end
*/
public void goToEnd() {
JViewport vp = theScrollPane.getViewport();
Dimension all = getPreferredSize();
Dimension view = vp.getExtentSize();
vp.setViewPosition(new Point(0, all.height - view.height));
vp.setViewPosition(new Point(0, all.height - view.height));
}
/**
* Move the focus to the residue immediately above the current one. If no
* residue has the focus select the root of the last structure
*/
public void onNavigateUp() {
Residue current = getCurrentSelection();
if (current == null) {
Glycan s = theDoc.getLastStructure();
if (s != null)
setSelection(s.getRoot());
} else {
Residue best_node = theBBoxManager.getNearestUp(current);
if (best_node != null)
setSelection(best_node);
}
}
/**
* Move the focus to the residue immediately below the current one. If no
* residue has the focus select the root of the first structure
*/
public void onNavigateDown() {
Residue current = getCurrentSelection();
if (current == null) {
Glycan s = theDoc.getFirstStructure();
if (s != null)
setSelection(s.getRoot());
} else {
Residue best_node = theBBoxManager.getNearestDown(current);
if (best_node != null)
setSelection(best_node);
}
}
/**
* Move the focus to the residue immediately to the left the current one. If
* no residue has the focus select the root of the last structure
*/
public void onNavigateLeft() {
Residue current = getCurrentSelection();
if (current == null) {
Glycan s = theDoc.getLastStructure();
if (s != null)
setSelection(s.getRoot());
} else {
Residue best_node = theBBoxManager.getNearestLeft(current);
if (best_node != null)
setSelection(best_node);
}
}
/**
* Move the focus to the residue immediately to the right the current one.
* If no residue has the focus select the root of the first structure
*/
public void onNavigateRight() {
Residue current = getCurrentSelection();
if (current == null) {
Glycan s = theDoc.getFirstStructure();
if (s != null)
setSelection(s.getRoot());
} else {
Residue best_node = theBBoxManager.getNearestRight(current);
if (best_node != null)
setSelection(best_node);
}
}
// -----------------
// print
/**
* Print the content of the component
*/
public void print(PrinterJob job) throws PrinterException {
// do something before
is_printing = true;
job.print();
// do something after
is_printing = false;
}
public int print(Graphics g, PageFormat pageFormat, int pageIndex)
throws PrinterException {
if (pageIndex > 0) {
return NO_SUCH_PAGE;
} else {
Graphics2D g2d = (Graphics2D) g;
g2d.setBackground(Color.white);
g2d.translate(pageFormat.getImageableX(), pageFormat
.getImageableY());
Dimension td = this.getPreferredSize();
double sx = pageFormat.getImageableWidth() / td.width;
double sy = pageFormat.getImageableHeight() / td.height;
double s = Math.min(sx, sy);
if (s < 1.)
g2d.scale(s, s);
RepaintManager.currentManager(this)
.setDoubleBufferingEnabled(false);
this.respondToDocumentChange = true;
this.paint(g2d);
RepaintManager.currentManager(this).setDoubleBufferingEnabled(true);
return PAGE_EXISTS;
}
}
// ----------------------
// Edit actions
/**
* Restore the state of the underlying document after a change
*/
public void onUndo() {
try {
theDoc.getUndoManager().undo();
} catch (Exception e) {
LogUtils.report(e);
}
}
/**
* Apply again the changes after the state of the underlying document has
* been restored
*/
public void onRedo() {
try {
theDoc.getUndoManager().redo();
} catch (Exception e) {
LogUtils.report(e);
}
}
// ------------
// Display actions
/**
* Set the mass options of a list of structures. Display a
* {@link MassOptionsStructureDialog}
*/
public boolean onMassOptionsStructures(Collection<Glycan> structures) {
// open dialog
MassOptionsStructureDialog mdlg = new MassOptionsStructureDialog(
theParent, structures, theWorkspace.getDefaultMassOptions());
mdlg.setVisible(true);
if (mdlg.getReturnStatus().equals("OK")) {
// set mass options for selected structures
theDoc.setMassOptions(structures, mdlg.getMassOptions());
// set default mass options
theWorkspace.getDefaultMassOptions().setValues(
mdlg.getMassOptions());
// update view
this.respondToDocumentChange = true;
repaint();
return true;
}
return false;
}
/**
* Set the mass options of all structures. Display a
* {@link MassOptionsStructureDialog}
*/
public boolean onMassOptionsAllStructures() {
return onMassOptionsStructures(theDoc.getStructures());
}
/**
* Set the mass options of the selected structures. Display a
* {@link MassOptionsStructureDialog}
*/
public boolean onMassOptionsSelectedStructures() {
return onMassOptionsStructures(getSelectedStructures());
}
/**
* Change the orientation of the display
*/
public void onChangeOrientation() {
theWorkspace.getGraphicOptions().ORIENTATION = (theWorkspace
.getGraphicOptions().ORIENTATION + 1) % 4;
this.respondToDocumentChange = true;
repaint();
}
/**
* Change the cartoon notation to the specified value
*
* @see GraphicOptions
*/
public void setNotation(String notation) {
theWorkspace.setNotation(notation);
this.respondToDocumentChange = true;
repaint();
updateResidueActions();
}
public void fireNotationChangedEvent(String notation) {
for (NotationChangeListener notationChangeListener : notationChangeListeners) {
notationChangeListener.notationChanged(notation);
}
}
/**
* Change the display style to the specified value
*
* @see GraphicOptions
*/
public void setDisplay(String display) {
theWorkspace.setDisplay(display);
this.respondToDocumentChange = true;
repaint();
updateResidueActions();
}
/**
* Change the graphic settings. Display a {@link GraphicOptionsDialog}
*/
public void onChangeDisplaySettings() {
GraphicOptions options = theWorkspace.getGraphicOptions();
GraphicOptionsDialog dlg = new GraphicOptionsDialog(theParent, options);
dlg.setVisible(true);
if (dlg.getReturnStatus().equals("OK")) {
theWorkspace.setDisplay(options.DISPLAY);
display_button_group.setSelected(display_models
.get(options.DISPLAY), true);
this.respondToDocumentChange = true;
repaint();
updateResidueActions();
}
}
// --------------------
// Structure
/**
* Add a glycan composition to the component. Display a
* {@link CompositionDialog}
*/
public void onAddComposition() {
try {
CompositionDialog dlg = new CompositionDialog(theParent,
theWorkspace.getCompositionOptions());
dlg.setVisible(true);
if (dlg.getReturnStatus().equals("OK"))
theDoc.addStructure(theWorkspace.getCompositionOptions()
.getCompositionAsGlycan(
theWorkspace.getDefaultMassOptions()));
} catch (Exception e) {
LogUtils.report(e);
}
}
/**
* Add a new structure from a core motif
*
* @param name
* the identifier of the core motif
* @see CoreDictionary
*/
public void onAddStructure(String name) {
try {
theDoc.addStructure(CoreDictionary.newCore(name));
} catch (Exception e) {
LogUtils.report(e);
}
}
/**
* Add a new structure from its string representation. Display a
* {@link ImportStructureDialog}
*/
public void onAddStructureFromString() {
try {
ImportStructureDialog dlg = new ImportStructureDialog(theParent);
dlg.setVisible(true);
if (!dlg.isCanceled())
theDoc.importFromString(dlg.getStringEncoded(), dlg
.getStringFormat());
} catch (Exception e) {
LogUtils.report(e);
}
}
/**
* Add a new structure from a terminal motif
*
* @param name
* the identifier of the terminal motif
* @see TerminalDictionary
*/
public void onAddTerminal(String name) {
try {
Residue toadd = TerminalDictionary.newTerminal(name);
Residue current = getCurrentResidue();
if (theDoc.addResidue(current, getLinkedResidues(), toadd) != null)
setSelection(current);
} catch (Exception e) {
LogUtils.report(e);
}
}
/**
* Add a bracket residue to the structure with the focus
*/
public void onAddBracket() {
Residue bracket = theDoc.addBracket(getCurrentResidue());
if (bracket != null)
setSelection(bracket);
}
/**
* Add a repeating unit containing the selected residues. If the end point
* of the unit cannot be easily determined a {@link ResidueSelectorDialog}
* is shown
*/
public void onAddRepeat() {
try {
Collection<Residue> nodes = getSelectedResiduesList();
if (!theDoc.createRepetition(null, nodes)) {
Vector<Residue> end_points = new Vector<Residue>();
for (Residue r : nodes)
if (r.isSaccharide())
end_points.add(r);
Glycan structure = getSelectedStructures().iterator().next();
ResidueSelectorDialog rsd = new ResidueSelectorDialog(
theParent, "Select ending point",
"Select ending point of the repetition", structure,
end_points, false, theGlycanRenderer);
rsd.setVisible(true);
if (!rsd.isCanceled())
theDoc.createRepetition(rsd.getCurrentResidue(),
getSelectedResiduesList());
}
} catch (Exception e) {
JOptionPane.showMessageDialog(theParent, e.getMessage(),
"Error while creating the repeating unit",
JOptionPane.ERROR_MESSAGE);
}
}
/**
* Add a new child to the residue with the focus.
*
* @param sacc_name
* the type name of the new residue to add
*/
public void onAdd(String sacc_name) {
try {
Residue toadd = ResidueDictionary.newResidue(sacc_name);
if (theDoc.addResidue(getCurrentResidue(), getLinkedResidues(),
toadd) != null) {
setSelection(toadd);
theWorkspace.getResidueHistory().add(toadd);
}
} catch (Exception e) {
LogUtils.report(e);
}
}
/**
* Insert a new residue between the residue with the focus and its parent
*
* @param sacc_name
* the type name of the new residue to add
*/
public void onInsertBefore(String sacc_name) {
try {
Residue toinsert = ResidueDictionary.newResidue(sacc_name);
Residue current = getCurrentResidue();
if (theDoc.insertResidueBefore(current, getLinkedResidues(),
toinsert) != null) {
setSelection(toinsert);
theWorkspace.getResidueHistory().add(toinsert);
}
} catch (Exception e) {
LogUtils.report(e);
}
}
/**
* Change the type of the residue with the focus
*
* @param sacc_name
* the new type name
*/
public void onChangeResidueType(String sacc_name) {
try {
ResidueType new_type = ResidueDictionary.getResidueType(sacc_name);
Residue current = getCurrentResidue();
if (theDoc
.changeResidueType(current, getLinkedResidues(), new_type)) {
setSelection(current);
theWorkspace.getResidueHistory().add(current);
}
} catch (Exception e) {
LogUtils.report(e);
}
}
/**
* Change the reducing end of the structure with the focus
*
* @param sacc_name
* the type name of the new reducing end marker
*/
public void onChangeReducingEnd(String sacc_name) {
try {
ResidueType new_type = ResidueDictionary.getResidueType(sacc_name);
Residue current = getCurrentResidue();
theDoc.changeReducingEndType(current, new_type);
} catch (Exception e) {
LogUtils.report(e);
}
}
/**
* 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 = getCurrentResidue();
if (current == null)
return;
if (current.getParent() != null
&& (!current.isSpecial() || current.isCleavage())) {
new ResiduePropertiesDialog(theParent, current,
getLinkedResidues(), theDoc).setVisible(true);
setSelection(current);
this.respondToDocumentChange = true;
repaint();
} else if (current.isStartRepetition()) {
new ResiduePropertiesDialog(theParent, current, theDoc)
.setVisible(true);
setSelection(current);
this.respondToDocumentChange = true;
repaint();
} else if (current.isEndRepetition()) {
new RepetitionPropertiesDialog(theParent, current, theDoc)
.setVisible(true);
setSelection(current);
this.respondToDocumentChange = true;
repaint();
}
}
private char getSelectedValueChar(JComboBox field) {
if (field.getSelectedItem() == null)
return '?';
return ((String) field.getSelectedItem()).charAt(0);
}
private char[] getSelectedPositions(DropDownList field) {
Object[] sel = field.getSelectedValues();
if (sel.length == 0)
return new char[] { '?' };
char[] ret = new char[sel.length];
for (int i = 0; i < sel.length; i++)
ret[i] = ((String) sel[i]).charAt(0);
return ret;
}
/**
* Set the properties of the residue with the focus using the values in the
* properties toolbar
*
* @see #getToolBarProperties
*/
public void onSetProperties() {
Residue current = 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 (field_second_bond.isSelected()) {
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);
}
theDoc.fireDocumentChanged();
setSelection(current);
this.respondToDocumentChange = true;
repaint();
}
}
/**
* Specify if the reducing end marker should be visible in the component
*/
public void setShowRedendCanvas(boolean f) {
theWorkspace.getGraphicOptions().SHOW_REDEND_CANVAS = f;
theActionManager.get("showredendcanvas").setSelected(f);
this.respondToDocumentChange = true;
repaint();
}
// ---------------
// events
public void actionPerformed(ActionEvent e) {
if (ignore_actions)
return;
String action = GlycanAction.getAction(e);
String param = GlycanAction.getParam(e);
// editing n
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();
else if (action.equals("delete"))
delete();
else if (action.equals("selectstructure"))
selectStructure();
else if (action.equals("selectall"))
selectAll();
else if (action.equals("selectnone"))
resetSelection();
else if (action.equals("gotostart")) {
resetSelection();
goToStart();
} else if (action.equals("gotoend")) {
resetSelection();
goToEnd();
}
else if (action.equals("orderstructuresasc"))
theDoc.orderStructures(false);
else if (action.equals("orderstructuresdesc"))
theDoc.orderStructures(true);
// structure
else if (action.equals("addterminal"))
onAddTerminal(param);
else if (action.equals("addcomposition"))
onAddComposition();
else if (action.equals("addstructure"))
onAddStructure(param);
else if (action.equals("addstructurestr"))
onAddStructureFromString();
else if (action.equals("add"))
onAdd(param);
else if (action.equals("insert"))
onInsertBefore(param);
else if (action.equals("change"))
onChangeResidueType(param);
else if (action.equals("redend"))
onChangeReducingEnd(param);
else if (action.equals("bracket"))
onAddBracket();
else if (action.equals("repeat"))
onAddRepeat();
else if (action.equals("changeredend"))
onMassOptionsSelectedStructures();
else if (action.equals("massoptstruct"))
onMassOptionsSelectedStructures();
// display
else if (action.equals("notation"))
setNotation(param);
else if (action.equals("display"))
setDisplay(param);
else if (action.equals("displaysettings"))
onChangeDisplaySettings();
else if (action.equals("showinfo")) {
theWorkspace.getGraphicOptions().SHOW_INFO = ((JCheckBoxMenuItem) e
.getSource()).getState();
this.respondToDocumentChange = true;
repaint();
} else if (action.equals("scale")) {
theWorkspace.getGraphicOptions().SCALE_CANVAS = Double
.parseDouble(param) / 100.;
this.respondToDocumentChange = true;
repaint();
} else if (action.equals("collapsemultipleantennae")) {
theWorkspace.getGraphicOptions().COLLAPSE_MULTIPLE_ANTENNAE = ((JCheckBox) e
.getSource()).isSelected();
this.respondToDocumentChange = true;
repaint();
} else if (action.equals("showmassescanvas")) {
theWorkspace.getGraphicOptions().SHOW_MASSES_CANVAS = ((JCheckBox) e
.getSource()).isSelected();
this.respondToDocumentChange = true;
repaint();
} else if (action.equals("showmasses")) {
theWorkspace.getGraphicOptions().SHOW_MASSES = ((JCheckBox) e
.getSource()).isSelected();
this.respondToDocumentChange = true;
repaint();
} else if (action.equals("showredendcanvas")) {
theWorkspace.getGraphicOptions().SHOW_REDEND_CANVAS = ((JCheckBox) e
.getSource()).isSelected();
this.respondToDocumentChange = true;
repaint();
} else if (action.equals("showredend")) {
theWorkspace.getGraphicOptions().SHOW_REDEND = ((JCheckBox) e
.getSource()).isSelected();
this.respondToDocumentChange = true;
repaint();
}
else if (action.equals("orientation")) {
onChangeOrientation();
updateOrientationButton();
updateResidueActions();
repaint();
} else if (action.equals("properties"))
onProperties();
else if (action.equals("setproperties"))
onSetProperties();
else if (action.equals("moveccw"))
onMoveCCW();
// else if( action.equals("resetplace") )
// resetPlacement();
else if (action.equals("movecw"))
onMoveCW();
else if (action.equals("navup"))
onNavigateUp();
else if (action.equals("navdown"))
onNavigateDown();
else if (action.equals("navleft"))
onNavigateLeft();
else if (action.equals("navright"))
onNavigateRight();
updateActions();
}
public void residueHistoryChanged() {
updateRecentResiduesToolbar(theToolBarStructure);
}
public void documentInit(BaseDocument.DocumentChangeEvent e) {
updateActions();
resetSelection();
this.respondToDocumentChange = true;
repaint();
}
protected boolean respondToDocumentChange;
public void documentChanged(BaseDocument.DocumentChangeEvent e) {
updateActions();
resetSelection();
respondToDocumentChange = true;
this.respondToDocumentChange = true;
repaint();
// moved from repaint, so we only revalidate when we need too.
}
/**
* Register a listener that will be notified of a change in the selection
*/
public void addSelectionChangeListener(SelectionChangeListener l) {
if (l != null)
listeners.add(l);
}
/**
* Deregister one of the listeners that are notified of a change in the
* selection
*/
public void removeSelectionChangeListener(SelectionChangeListener l) {
if (l != null)
listeners.remove(l);
}
/**
* Send an event to all listeners notifying a change in the selection
*
* @param completeStructure
*/
public void fireUpdatedSelection(boolean completeStructure) {
// update actions
updateActions();
updateToolbarProperties(!completeStructure);
// fire events
for (Iterator<SelectionChangeListener> i = listeners.iterator(); i
.hasNext();)
i.next().selectionChanged(new SelectionChangeEvent(this));
// update view
this.respondToDocumentChange = true;
repaint();
showSelection();
}
/**
* Make sure that the selected residues are visible in the component by
* moving the scroll pane
*/
public void showSelection() {
// update bounding boxes
boolean show_masses = is_printing ? theGlycanRenderer
.getGraphicOptions().SHOW_MASSES : theGlycanRenderer
.getGraphicOptions().SHOW_MASSES_CANVAS;
boolean show_redend = is_printing ? theGlycanRenderer
.getGraphicOptions().SHOW_REDEND : theGlycanRenderer
.getGraphicOptions().SHOW_REDEND_CANVAS;
theGlycanRenderer.computeBoundingBoxes(theDoc.getStructures(),
show_masses, show_redend, thePosManager, theBBoxManager);
//
Rectangle bbox = null;
for (Residue r : selected_residues)
bbox = union(bbox, theBBoxManager.getCurrent(r));
for (Linkage l : selected_linkages) {
bbox = union(bbox, theBBoxManager.getCurrent(l.getChildResidue()));
bbox = union(bbox, theBBoxManager.getCurrent(l.getParentResidue()));
}
if (bbox != null) {
bbox = expand(bbox, 5);
// show bbox in viewport
Rectangle view = theScrollPane.getViewport().getViewRect();
int new_x = left(view);
int new_y = top(view);
if (left(view) > left(bbox))
new_x = left(bbox);
else if (right(view) < right(bbox)) {
int min_move = right(bbox) - right(view);
int max_move = left(bbox) - left(view);
new_x += Math.min(min_move, max_move);
}
if (top(view) > top(bbox))
new_y = top(bbox);
else if (bottom(view) < bottom(bbox)) {
int min_move = bottom(bbox) - bottom(view);
int max_move = top(bbox) - top(view);
new_y += Math.min(min_move, max_move);
}
theScrollPane.getViewport()
.setViewPosition(new Point(new_x, new_y));
theScrollPane.getViewport()
.setViewPosition(new Point(new_x, new_y));
}
}
// ---------------
// mouse handling
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
lastMouseButton = e.getButton();
if (MouseUtils.isPushTrigger(e) || MouseUtils.isCtrlPushTrigger(e)) {
Residue start_position = getResidueAtPoint(e.getPoint());
if (start_position != null) {
// start DnD
is_dragndrop = true;
if (!isSelected(start_position)) {
if (MouseUtils.isCtrlPushTrigger(e))
addSelection(start_position);
else
setSelection(start_position);
}
} else {
// start selection
mouse_start_point = e.getPoint();
}
}
was_dragged = false;
lastMouseButton = null;
}
public void mouseMoved(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
was_dragged = true;
lastMouseButton = e.getButton();
// if is dragging don't update selection
if (is_dragndrop) {
// set cursor
if (MouseUtils.isNothingPressed(e))
setCursor((canDrop(e)) ? dndmove_cursor : dndnomove_cursor);
else if (MouseUtils.isCtrlPressed(e))
setCursor((canDrop(e)) ? dndcopy_cursor : dndnocopy_cursor);
else
setCursor(Cursor.getDefaultCursor());
} else if (mouse_start_point != null) {
if (mouse_end_point != null)
xorRectangle(mouse_start_point, mouse_end_point);
mouse_end_point = e.getPoint();
xorRectangle(mouse_start_point, mouse_end_point);
}
dragAndScroll(e);
lastMouseButton = null;
}
public void mouseReleased(MouseEvent e) {
lastMouseButton = e.getButton();
// Drag and drop
if (is_dragndrop && was_dragged) {
Residue position = getResidueAtPoint(e.getPoint());
if (canDrop(e)) {
if (MouseUtils.isNothingPressed(e))
moveTo(position);
else if (MouseUtils.isCtrlPressed(e))
copyTo(position);
}
} else if (mouse_end_point != null) {
if (mouse_end_point != null)
xorRectangle(mouse_start_point, mouse_end_point);
Rectangle mouse_rect = makeRectangle(mouse_start_point,
mouse_end_point);
if (MouseUtils.isNothingPressed(e))
setSelection(theBBoxManager.getNodesInside(mouse_rect));
else if (MouseUtils.isCtrlPressed(e))
addSelection(theBBoxManager.getNodesInside(mouse_rect));
setCurrentResidue(findNearest(e.getPoint(), selected_residues));
}
// reset
if (is_dragndrop)
setCursor(Cursor.getDefaultCursor());
is_dragndrop = false;
was_dragged = false;
mouse_start_point = null;
mouse_end_point = null;
repaint();
lastMouseButton = null;
}
protected Integer lastMouseButton;
public Integer getLastMouseButton() {
return lastMouseButton;
}
public void setLastMouseButton(Integer lastMouseButton) {
this.lastMouseButton = lastMouseButton;
}
public void mouseClicked(MouseEvent e) {
lastMouseButton = e.getButton();
Residue r = getResidueAtPoint(e.getPoint());
if (r != null) {
if (MouseUtils.isSelectTrigger(e)) {
setSelection(r);
} else if (MouseUtils.isAddSelectTrigger(e)) {
addSelection(r);
} else if (MouseUtils.isSelectAllTrigger(e)) {
addSelectionPathTo(r);
}
} else {
Linkage l = getLinkageAtPoint(e.getPoint());
if (MouseUtils.isSelectTrigger(e)
|| MouseUtils.isAddSelectTrigger(e)
|| MouseUtils.isSelectAllTrigger(e))
setSelection(l);
}
lastMouseButton = null;
}
private void dragAndScroll(MouseEvent e) {
// move view if near borders
Point point = e.getPoint();
JViewport view = theScrollPane.getViewport();
Rectangle inner = view.getViewRect();
inner.grow(-10, -10);
if (!inner.contains(point)) {
Point orig = view.getViewPosition();
if (point.x < inner.x)
orig.x -= 10;
else if (point.x > (inner.x + inner.width))
orig.x += 10;
if (point.y < inner.y)
orig.y -= 10;
else if (point.y > (inner.y + inner.height))
orig.y += 10;
int maxx = getBounds().width - view.getViewRect().width;
int maxy = getBounds().height - view.getViewRect().height;
if (orig.x < 0)
orig.x = 0;
if (orig.x > maxx)
orig.x = maxx;
if (orig.y < 0)
orig.y = 0;
if (orig.y > maxy)
orig.y = maxy;
view.setViewPosition(orig);
}
}
private boolean canDrop(MouseEvent e) {
Residue target = getResidueAtPoint(e.getPoint());
if (target == null)
return true;
if (isSelected(target) && !e.isControlDown())
return false;
return theDoc.canAddStructures(target, selected_residues);
}
public void clearResidueGalleries() {
for (List<ResidueGalleryIndex> indexList : this.residueGalleries
.values()) {
for (ResidueGalleryIndex index : indexList) {
if (index.band.getControlPanel() != null) {
// System.err.println("Removing gallery " +
// index.galleryName);
index.band.getControlPanel().removeRibbonGallery(
index.galleryName);
}
}
}
if (structureSelectionBand != null) {
structureSelectionBand.getControlPanel().removeRibbonGallery(
STRUCTURE_GALLERY_NAME);
// System.err.println("Removing structure gallery");
}
if (terminalRibbonBand != null
&& terminalRibbonBand.getControlPanel() != null) {
// System.err.println("Removing terminal gallery");
terminalRibbonBand.getControlPanel().removeRibbonGallery(
TERMINAL_GAL_NAME);
}
}
}