From: jprocter Date: Fri, 27 Aug 2010 11:35:14 +0000 (+0000) Subject: revised sequence/structure binding so one structure associated with x-seuqenceI's... X-Git-Tag: Release_2_6~88 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=4fe775d619d3587a4037a79a67b7391a82b8a130;p=jalview.git revised sequence/structure binding so one structure associated with x-seuqenceI's, and bugfixed superposition code(See JAL-583) --- diff --git a/src/jalview/ext/jmol/JalviewJmolBinding.java b/src/jalview/ext/jmol/JalviewJmolBinding.java index c2eceed..8831bd6 100644 --- a/src/jalview/ext/jmol/JalviewJmolBinding.java +++ b/src/jalview/ext/jmol/JalviewJmolBinding.java @@ -77,7 +77,10 @@ public abstract class JalviewJmolBinding implements StructureListener, public Vector chainNames; - String[] chains; + /** + * array of target chains for seuqences - tied to pdbentry and sequence[] + */ + protected String[][] chains; boolean colourBySequence = true; @@ -113,20 +116,26 @@ public abstract class JalviewJmolBinding implements StructureListener, StringBuffer resetLastRes = new StringBuffer(); - public SequenceI[] sequence; + /** + * sequences mapped to each pdbentry + */ + public SequenceI[][] sequence; StructureSelectionManager ssm; public JmolViewer viewer; - public JalviewJmolBinding(PDBEntry[] pdbentry, SequenceI[] seq, - String[] chains, String protocol) + public JalviewJmolBinding(PDBEntry[] pdbentry, SequenceI[][] sequenceIs, + String[][] chains, String protocol) { - this.sequence = seq; + this.sequence = sequenceIs; this.chains = chains; this.pdbentry = pdbentry; this.protocol = protocol; - + if (chains == null) + { + this.chains = new String[pdbentry.length][]; + } /* * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(), * "jalviewJmol", ap.av.applet .getDocumentBase(), @@ -156,7 +165,7 @@ public abstract class JalviewJmolBinding implements StructureListener, { return ("Jalview Jmol Window"); } - StringBuffer title = new StringBuffer(sequence[0].getName() + ":" + StringBuffer title = new StringBuffer(sequence[0][0].getName() + ":" + pdbentry[0].getId()); if (pdbentry[0].getProperty() != null) @@ -236,12 +245,55 @@ public abstract class JalviewJmolBinding implements StructureListener, */ public void superposeStructures(AlignmentI alignment) { - String[] files = getPdbFile(); + superposeStructures(alignment, -1, null); + } - StringBuffer command = new StringBuffer(); + /** + * superpose the structures associated with sequences in the alignment + * according to their corresponding positions. ded) + * + * @param refStructure + * - select which pdb file to use as reference (default is -1 - the + * first structure in the alignment) + */ + public void superposeStructures(AlignmentI alignment, int refStructure) + { + superposeStructures(alignment, refStructure, null); + } + + /** + * superpose the structures associated with sequences in the alignment + * according to their corresponding positions. ded) + * @param refStructure + * - select which pdb file to use as reference (default is -1 - the + * first structure in the alignment) + * @param hiddenCols TODO + */ + public void superposeStructures(AlignmentI alignment, int refStructure, ColumnSelection hiddenCols) + { + String[] files = getPdbFile(); + if (refStructure>=files.length) + { + System.err.println("Invalid reference structure value "+refStructure); + refStructure= -1; + } + if (refStructure<-1) + { + refStructure=-1; + } + StringBuffer command = new StringBuffer(), selectioncom = new StringBuffer(); + boolean matched[] = new boolean[alignment.getWidth()]; - String commonpositions[][] = new String[files.length][alignment - .getWidth()]; + for (int m = 0; m < matched.length; m++) + { + + matched[m] = (hiddenCols!=null) ? hiddenCols.isVisible(m) : true; + } + + int commonrpositions[][] = new int[files.length][alignment.getWidth()]; + String isel[] = new String[files.length]; + // reference structure - all others are superposed in it + String[] targetC = new String[files.length]; for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) { StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]); @@ -250,60 +302,156 @@ public abstract class JalviewJmolBinding implements StructureListener, continue; int lastPos = -1; - for (int s = 0; s < sequence.length; s++) + for (int s = 0; s < sequence[pdbfnum].length; s++) { for (int sp, m = 0; m < mapping.length; m++) { - if (mapping[m].getSequence() == sequence[s] - && (sp = alignment.findIndex(sequence[s])) > -1) + if (mapping[m].getSequence() == sequence[pdbfnum][s] + && (sp = alignment.findIndex(sequence[pdbfnum][s])) > -1) { + if (refStructure == -1) + { + refStructure = pdbfnum; + } SequenceI asp = alignment.getSequenceAt(sp); - for (int r = 0; r < asp.getLength(); r++) + for (int r = 0; r < matched.length; r++) { - // no mapping to gaps in sequence + if (!matched[r]) + { + continue; + } + matched[r] = false; // assume this is not a good site + if (r >= asp.getLength()) + { + continue; + } + if (jalview.util.Comparison.isGap(asp.getCharAt(r))) { - matched[r] = false; // exclude from common set + // no mapping to gaps in sequence continue; } - int pos = mapping[m].getPDBResNum(asp.findPosition(r)); + int t = asp.findPosition(r); // sequence position + int apos = mapping[m].getAtomNum(t); + int pos = mapping[m].getPDBResNum(t); if (pos < 1 || pos == lastPos) + { + // can't align unmapped sequence continue; - + } + matched[r] = true; // this is a good ite lastPos = pos; - - commonpositions[m][r] = (mapping[m].getChain() != " " ? ":" - + mapping[m].getChain() : "") - + "/" + (pdbfnum + 1) + ".1"; + // just record this residue position + commonrpositions[pdbfnum][r] = pos; + } + // create model selection suffix + isel[pdbfnum] = "/" + (pdbfnum + 1) + ".1"; + if (mapping[m].getChain() == null + || mapping[m].getChain().trim().length() == 0) + { + targetC[pdbfnum] = ""; + } + else + { + targetC[pdbfnum] = ":" + mapping[m].getChain(); } + // move on to next pdb file + s = sequence[pdbfnum].length; break; } } } } - command.append("select "); - // form the matched pair selection strings - String sep = ""; - for (int r = 0; r < matched.length; r++) + StringBuffer selcom[] = new StringBuffer[files.length]; + // generate select statements to select regions to superimpose structures { - if (matched[r]) + for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) { - command.append(sep); - command.append("("); - for (int s = 0; s < commonpositions.length; s++) + String chainCd = targetC[pdbfnum]; + int lpos = -1; + boolean run = false; + StringBuffer molsel = (selcom[pdbfnum] = new StringBuffer()); + molsel.append("{"); + for (int r = 0; r < matched.length; r++) { - if (s > 0) + if (matched[r]) { - command.append(" | "); + + if (lpos != commonrpositions[pdbfnum][r] - 1) + { + // discontinuity + if (lpos != -1) + { + molsel.append(lpos); + molsel.append(chainCd); + // molsel.append("} {"); + molsel.append("|"); + } + } + else + { + // continuous run - and lpos >-1 + if (!run) + { + // at the beginning, so add dash + molsel.append(lpos); + molsel.append("-"); + } + run = true; + } + lpos = commonrpositions[pdbfnum][r]; + // molsel.append(lpos); } - command.append(commonpositions[s][r]); } - command.append(")"); - sep = " | "; + // add final selection phrase + if (lpos != -1) + { + molsel.append(lpos); + molsel.append(chainCd); + molsel.append("}"); + } + selectioncom.append("(("); + selectioncom.append(molsel.subSequence(1, molsel.length()-1)); + selectioncom.append(" )& "); + selectioncom.append(pdbfnum+1); + selectioncom.append(".1)"); + if (pdbfnum -1) + if (mapping[m].getSequence() == sequence[pdbfnum][s] + && (sp = alignment.findIndex(sequence[pdbfnum][s])) > -1) { SequenceI asp = alignment.getSequenceAt(sp); for (int r = 0; r < asp.getLength(); r++) @@ -371,10 +519,10 @@ public abstract class JalviewJmolBinding implements StructureListener, lastPos = pos; - Color col = sr.getResidueBoxColour(sequence[s], r); + Color col = sr.getResidueBoxColour(sequence[pdbfnum][s], r); if (showFeatures) - col = fr.findFeatureColour(col, sequence[s], r); + col = fr.findFeatureColour(col, sequence[pdbfnum][s], r); String newSelcom = (mapping[m].getChain() != " " ? ":" + mapping[m].getChain() : "") + "/" @@ -896,7 +1044,7 @@ public abstract class JalviewJmolBinding implements StructureListener, if (loadedInline) { // TODO: replace with getData ? - pdb = ssm.setMapping(sequence, chains, + pdb = ssm.setMapping(sequence[pe], chains[pe], pdbentry[pe].getFile(), AppletFormatAdapter.PASTE); pdbentry[pe].setFile("INLINE" + pdb.id); } @@ -921,7 +1069,7 @@ public abstract class JalviewJmolBinding implements StructureListener, { } ; - pdb = ssm.setMapping(sequence, chains, + pdb = ssm.setMapping(sequence[pe], chains[pe], pdbentry[pe].getFile(), protocol); } @@ -1066,21 +1214,23 @@ public abstract class JalviewJmolBinding implements StructureListener, */ public abstract void refreshGUI(); - /** * @param renderPanel - * @param jmolfileio - when true will initialise jmol's file IO system (should be false in applet context) + * @param jmolfileio + * - when true will initialise jmol's file IO system (should be false + * in applet context) * @param htmlName * @param documentBase * @param codeBase * @param commandOptions */ - public void allocateViewer(Component renderPanel, boolean jmolfileio, String htmlName, - URL documentBase, URL codeBase, String commandOptions) + public void allocateViewer(Component renderPanel, boolean jmolfileio, + String htmlName, URL documentBase, URL codeBase, + String commandOptions) { viewer = JmolViewer.allocateViewer(renderPanel, - (jmolfileio ? new SmarterJmolAdapter() : null), - htmlName + ((Object) this).toString(), documentBase, codeBase, + (jmolfileio ? new SmarterJmolAdapter() : null), htmlName + + ((Object) this).toString(), documentBase, codeBase, commandOptions, this); } diff --git a/src/jalview/gui/AppJmol.java b/src/jalview/gui/AppJmol.java index 6312cb1..df4efd9 100644 --- a/src/jalview/gui/AppJmol.java +++ b/src/jalview/gui/AppJmol.java @@ -73,7 +73,7 @@ public class AppJmol extends GStructureViewer implements Runnable, // / TODO: check if protocol is needed to be set, and if chains are // autodiscovered. jmb = new AppJmolBinding(this, new PDBEntry[] - { pdbentry }, seq, null, null); + { pdbentry }, new SequenceI[][] { seq }, null, null); jmb.setLoadingFromArchive(true); this.ap = ap; @@ -141,7 +141,7 @@ public class AppJmol extends GStructureViewer implements Runnable, { if (topJmol.jmb.pdbentry[pe].getFile().equals(alreadyMapped)) { - topJmol.jmb.addSequence(seq); + topJmol.jmb.addSequence(pe, seq); break; } } @@ -152,9 +152,33 @@ public class AppJmol extends GStructureViewer implements Runnable, } } // ///////////////////////////////// + // Check if there are other Jmol views involving this alignment + // and prompt user about adding this molecule to one of them + Vector existingViews = getJmolsFor(ap); + if (existingViews.size()>0) + { + Enumeration jm = existingViews.elements(); + while (jm.hasMoreElements()) { + AppJmol topJmol = (AppJmol) jm.nextElement(); + // TODO: highlight topJmol in view somehow + int option = JOptionPane + .showInternalConfirmDialog( + Desktop.desktop, "Do you want to add "+ + pdbentry.getId()+" to the view called\n'"+topJmol.getTitle() + + "'\n", + "Align to existing structure view" + , JOptionPane.YES_NO_OPTION); + if (option == JOptionPane.YES_OPTION) + { + topJmol.jmb.addStructure(pdbentry, seq, chains,true); + return; + } + } + } + // ///////////////////////////////// jmb = new AppJmolBinding(this, new PDBEntry[] - { pdbentry }, seq, null, null); + { pdbentry }, new SequenceI[][]{seq}, null, null); this.ap = ap; setSize(400, 400); // probably should be a configurable/dynamic default here @@ -178,6 +202,27 @@ public class AppJmol extends GStructureViewer implements Runnable, } + private Vector getJmolsFor(AlignmentPanel ap2) + { + Vector otherJmols= new Vector(); + // Now this AppJmol is mapped to new sequences. We must add them to + // the exisiting array + JInternalFrame[] frames = Desktop.instance.getAllFrames(); + + for (int i = 0; i < frames.length; i++) + { + if (frames[i] instanceof AppJmol) + { + AppJmol topJmol = ((AppJmol) frames[i]); + if (topJmol.ap==ap2) + { + otherJmols.addElement(topJmol); + } + } + } + return otherJmols; + } + void initJmol(String command) { jmb.setFinishedInit(false); @@ -617,8 +662,27 @@ public class AppJmol extends GStructureViewer implements Runnable, } setChainMenuItems(jmb.chainNames); jmb.colourBySequence(ap.av.getShowSequenceFeatures(), ap.av.alignment); - + this.setTitle(jmb.getViewerTitle()); + if (jmb.getPdbFile().length>1 && jmb.sequence.length>1) { + jmolActionMenu.setVisible(true); + } + } + + /* (non-Javadoc) + * @see jalview.jbgui.GStructureViewer#alignStructs_actionPerformed(java.awt.event.ActionEvent) + */ + @Override + protected void alignStructs_actionPerformed(ActionEvent actionEvent) + { + + try { + jmb.superposeStructures(ap.av.getAlignment(), -1, ap.av.getColumnSelection()); + } catch (Exception e) + { + Cache.log.info("Couldn't align structures in alignframe "+ap.alignFrame.getTitle(),e); + + } } public void setJalviewColourScheme(ColourSchemeI ucs) diff --git a/src/jalview/gui/AppJmolBinding.java b/src/jalview/gui/AppJmolBinding.java index 39d198d..d6535e3 100644 --- a/src/jalview/gui/AppJmolBinding.java +++ b/src/jalview/gui/AppJmolBinding.java @@ -21,12 +21,14 @@ class AppJmolBinding extends jalview.ext.jmol.JalviewJmolBinding private AppJmol appJmolWindow; public AppJmolBinding(AppJmol appJmol, PDBEntry[] pdbentry, - SequenceI[] seq, String[] chains, String protocol) + SequenceI[][] sequenceIs, String[][] chains, String protocol) { - super(pdbentry, seq, chains, protocol); + super(pdbentry, sequenceIs, chains, protocol); appJmolWindow = appJmol; } - FeatureRenderer fr=null; + + FeatureRenderer fr = null; + @Override public jalview.api.FeatureRenderer getFeatureRenderer() { @@ -38,7 +40,7 @@ class AppJmolBinding extends jalview.ext.jmol.JalviewJmolBinding } fr.transferSettings(appJmolWindow.ap.seqPanel.seqCanvas - .getFeatureRenderer()); + .getFeatureRenderer()); } return fr; @@ -60,10 +62,9 @@ class AppJmolBinding extends jalview.ext.jmol.JalviewJmolBinding public void sendConsoleMessage(String strStatus) { - if (appJmolWindow.scriptWindow!=null && strStatus != null - ) - // && !strStatus.equals("Script completed")) - // should we squash the script completed string ? + if (appJmolWindow.scriptWindow != null && strStatus != null) + // && !strStatus.equals("Script completed")) + // should we squash the script completed string ? { appJmolWindow.scriptWindow.sendConsoleMessage(strStatus); } @@ -72,9 +73,11 @@ class AppJmolBinding extends jalview.ext.jmol.JalviewJmolBinding @Override public void showUrl(String url, String target) { - try { + try + { jalview.util.BrowserLauncher.openURL(url); - } catch (Exception e) { + } catch (Exception e) + { Cache.log.error("Failed to launch Jmol-associated url " + url, e); // TODO: 2.6 : warn user if browser was not configured. } @@ -90,21 +93,22 @@ class AppJmolBinding extends jalview.ext.jmol.JalviewJmolBinding public void updateColours(Object source) { AlignmentPanel ap = (AlignmentPanel) source; - if (appJmolWindow.ap.alignFrame.getCurrentView()!=ap.av) + if (appJmolWindow.ap.alignFrame.getCurrentView() != ap.av) return; - + colourBySequence(ap.av.getShowSequenceFeatures(), ap.av.alignment); } public void notifyScriptTermination(String strStatus, int msWalltime) { if (appJmolWindow.scriptWindow != null) - appJmolWindow.scriptWindow.notifyScriptTermination(strStatus, msWalltime); + appJmolWindow.scriptWindow.notifyScriptTermination(strStatus, + msWalltime); } public void showUrl(String url) { - showUrl(url,"jmol"); + showUrl(url, "jmol"); } public void newJmolPopup(boolean translateLocale, String menuName, @@ -114,30 +118,228 @@ class AppJmolBinding extends jalview.ext.jmol.JalviewJmolBinding jmolpopup = JmolPopup.newJmolPopup(viewer, translateLocale, menuName, asPopup); } - public synchronized void addSequence(SequenceI[] seq) + + /** + * add structures and any known sequence associations + * + * @returns the pdb entries added to the current set. + */ + private PDBEntry[] addSequenceAndChain(PDBEntry[] pdbe, + SequenceI[][] seq, String[][] chns) { + int pe = -1; Vector v = new Vector(); - for (int i = 0; i < sequence.length; i++) - v.addElement(sequence[i]); + Vector rtn = new Vector(); + for (int i = 0; i < pdbentry.length; i++) + { + v.addElement(pdbentry[i]); + } + for (int i = 0; i < pdbe.length; i++) + { + int r = v.indexOf(pdbe[i]); + if (r == -1 || r >= pdbentry.length) + { + rtn.addElement(new int[] + { v.size(), i }); + v.addElement(pdbe[i]); + } + else + { + // just make sure the sequence/chain entries are all up to date + addSequenceAndChain(r, seq[i], chns[i]); + } + } + pdbe = new PDBEntry[v.size()]; + v.copyInto(pdbe); + pdbentry = pdbe; + if (rtn.size() > 0) + { + // expand the tied seuqence[] and string[] arrays + SequenceI[][] sqs = new SequenceI[pdbentry.length][]; + String[][] sch = new String[pdbentry.length][]; + System.arraycopy(sequence, 0, sqs, 0, sequence.length); + System.arraycopy(chains, 0, sch, 0, this.chains.length); + sequence = sqs; + chains = sch; + pdbe = new PDBEntry[rtn.size()]; + for (int r = 0; r < pdbe.length; r++) + { + int[] stri = ((int[]) rtn.elementAt(r)); + // record the pdb file as a new addition + pdbe[r] = pdbentry[stri[0]]; + // and add the new sequence/chain entries + addSequenceAndChain(stri[0], seq[stri[1]], chns[stri[1]]); + } + } + else + { + pdbe = null; + } + return pdbe; + } - for (int i = 0; i < seq.length; i++) - if (!v.contains(seq[i])) - v.addElement(seq[i]); + void addSequence(int pe, SequenceI[] seq) + { + // add sequences to the pe'th pdbentry's seuqence set. + addSequenceAndChain(pe, seq, null); + } - SequenceI[] tmp = new SequenceI[v.size()]; - v.copyInto(tmp); - sequence = tmp; + private void addSequenceAndChain(int pe, SequenceI[] seq, String[] tchain) + { + if (pe < 0 || pe >= pdbentry.length) + { + throw new Error( + "Implementation error - no corresponding pdbentry (for index " + + pe + ") to add sequences mappings to"); + } + final String nullChain = "TheNullChain"; + Vector s = new Vector(); + Vector c = new Vector(); + if (chains == null) + { + chains = new String[pdbentry.length][]; + } + if (sequence[pe] != null) + { + for (int i = 0; i < sequence[pe].length; i++) + { + s.addElement(sequence[pe][i]); + if (chains[pe] != null) + { + if (i < chains[pe].length) + { + c.addElement(chains[pe][i]); + } + else + { + c.addElement(nullChain); + } + } + else + { + if (tchain != null && tchain.length > 0) + { + c.addElement(nullChain); + } + } + } + } + for (int i = 0; i < seq.length; i++) + { + if (!s.contains(seq[i])) + { + s.addElement(seq[i]); + if (tchain != null && i < tchain.length) + { + c.addElement(tchain[i] == null ? nullChain : tchain[i]); + } + } + } + SequenceI[] tmp = new SequenceI[s.size()]; + s.copyInto(tmp); + sequence[pe] = tmp; + if (c.size() > 0) + { + String[] tch = new String[c.size()]; + c.copyInto(tch); + for (int i = 0; i < tch.length; i++) + { + if (tch[i] == nullChain) + { + tch[i] = null; + } + } + chains[pe] = tch; + } + else + { + chains[pe] = null; + } } public void selectionChanged(BitSet arg0) { // TODO Auto-generated method stub - + } public void refreshPdbEntries() { // TODO Auto-generated method stub - + } + + /** + * add another pdb entry into the view, with associated sequences and chains + * + * @param pdbentry + * @param seq + * @param chains + * @param align + * if true, new structure(s) will be align using associated alignment + */ + public synchronized void addStructure(PDBEntry pdbentry, SequenceI[] seq, + String[] chains, final boolean align) + { + PDBEntry[] pe = addSequenceAndChain(new PDBEntry[] + { pdbentry }, new SequenceI[][] + { seq }, new String[][] + { chains }); + if (pe != null) + { + StringBuffer cmd = new StringBuffer(); + cmd.append("load APPEND"); + for (int p = 0; p < pe.length; p++) + { + cmd.append(" \""); + cmd.append(pe[p].getFile()); + cmd.append("\""); + } + cmd.append("\n"); + final String command = cmd.toString(); + cmd = null; + new Thread(new Runnable() + { + public void run() + { + evalStateCommand(command); + if (align) + { + // may need to wait around until script has finished + while (viewer.isScriptExecuting()) + { + try + { + Thread.sleep(20); + } catch (Exception e) + { + } + ; + } + superposeStructures(appJmolWindow.ap.av.getAlignment(), -1, null); + } + } + }).start(); + } + } + + /** + * add the given sequences to the mapping scope for the given pdb file handle + * + * @param pdbFile + * - pdbFile identifier + * @param seq + * - set of sequences it can be mapped to + */ + public void addSequenceForStructFile(String pdbFile, SequenceI[] seq) + { + for (int pe = 0; pe < pdbentry.length; pe++) + { + if (pdbentry[pe].getFile().equals(pdbFile)) + { + addSequence(pe, seq); + } + } + } + } \ No newline at end of file diff --git a/src/jalview/gui/Jalview2XML.java b/src/jalview/gui/Jalview2XML.java index fd93d7f..c9e8bdd 100755 --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@ -604,7 +604,8 @@ public class Jalview2XML } for (int s = 0; s < jmol.jmb.sequence.length; s++) { - if (jal.findIndex(jmol.jmb.sequence[s]) > -1) + for (int smap=0;smap -1) { pdb.addStructureState(state); } @@ -2587,8 +2588,8 @@ public class Jalview2XML StructureSelectionManager.getStructureSelectionManager() .setMapping(seq, null, pdbFile, jalview.io.AppletFormatAdapter.FILE); - - ((AppJmol) comp).jmb.addSequence(seq); + + ((AppJmol) comp).jmb.addSequenceForStructFile(pdbFile, seq); } } } diff --git a/src/jalview/jbgui/GStructureViewer.java b/src/jalview/jbgui/GStructureViewer.java index f7fa6db..bfaee67 100644 --- a/src/jalview/jbgui/GStructureViewer.java +++ b/src/jalview/jbgui/GStructureViewer.java @@ -181,9 +181,20 @@ public class GStructureViewer extends JInternalFrame jmolHelp_actionPerformed(actionEvent); } }); + alignStructs.setText("Align structures"); + alignStructs.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent actionEvent) + { + alignStructs_actionPerformed(actionEvent); + } + }); + jmolActionMenu.setText("Jmol"); menuBar.add(fileMenu); menuBar.add(viewMenu); menuBar.add(colourMenu); + menuBar.add(jmolActionMenu); + jmolActionMenu.setVisible(false); menuBar.add(helpMenu); fileMenu.add(savemenu); fileMenu.add(viewMapping); @@ -218,6 +229,11 @@ public class GStructureViewer extends JInternalFrame colourButtons.add(userColour); helpMenu.add(jmolHelp); + jmolActionMenu.add(alignStructs); + } + + protected void alignStructs_actionPerformed(ActionEvent actionEvent) + { } JMenuBar menuBar = new JMenuBar(); @@ -242,6 +258,10 @@ public class GStructureViewer extends JInternalFrame JMenu colourMenu = new JMenu(); + protected JMenu jmolActionMenu = new JMenu(); + + JMenuItem alignStructs = new JMenuItem(); + JMenuItem backGround = new JMenuItem(); protected JRadioButtonMenuItem seqColour = new JRadioButtonMenuItem();