X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FStructureViewerBase.java;h=085be71e6af6bf59075c21cf8f60cd1cd90b4550;hb=cd669a0e8c7b91b379bca8fe6e702cf0fcbd1ce0;hp=ec5579cb57bc116f40435f11cab0fcc33dbf61dc;hpb=f4b18ae31d37e694b59875f26e0863179de248f1;p=jalview.git diff --git a/src/jalview/gui/StructureViewerBase.java b/src/jalview/gui/StructureViewerBase.java index ec5579c..085be71 100644 --- a/src/jalview/gui/StructureViewerBase.java +++ b/src/jalview/gui/StructureViewerBase.java @@ -26,6 +26,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; +import java.beans.PropertyVetoException; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; @@ -34,6 +35,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Random; import java.util.Vector; @@ -46,6 +48,7 @@ import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; import jalview.api.AlignmentViewPanel; +import jalview.api.structures.JalviewStructureDisplayI; import jalview.bin.Cache; import jalview.bin.Console; import jalview.datamodel.AlignmentI; @@ -87,6 +90,29 @@ public abstract class StructureViewerBase extends GStructureViewer } /** + * Singleton list of all (open) instances of structureViewerBase + * TODO: JAL-3362 - review and adopt the swingJS-safe singleton pattern so each structure viewer base instance is kept to its own JalviewJS parent + */ + private static List svbs = new ArrayList<>(); + + /** + * + * @return list with all existing StructureViewers instance + */ + public static List getAllStructureViewerBases() + { + List goodSvbs = new ArrayList<>(); + for (JalviewStructureDisplayI s : svbs) + { + if (s != null && !goodSvbs.contains(s)) + { + goodSvbs.add(s); + } + } + return goodSvbs; + } + + /** * list of sequenceSet ids associated with the view */ protected List _aps = new ArrayList<>(); @@ -116,6 +142,8 @@ public abstract class StructureViewerBase extends GStructureViewer protected boolean allChainsSelected = false; + protected boolean allHetatmBeingSelected = false; + protected JMenu viewSelectionMenu; /** @@ -135,6 +163,8 @@ public abstract class StructureViewerBase extends GStructureViewer public StructureViewerBase() { super(); + setFrameIcon(null); + svbs.add(this); } /** @@ -178,6 +208,7 @@ public abstract class StructureViewerBase extends GStructureViewer return _aps.contains(ap2.av.getSequenceSetId()); } + @Override public boolean isUsedforaligment(AlignmentViewPanel ap2) { @@ -576,6 +607,81 @@ public abstract class StructureViewerBase extends GStructureViewer chainMenu.add(menuItem); } } + void setHetatmMenuItems(Map hetatmNames) + { + hetatmMenu.removeAll(); + if (hetatmNames == null || hetatmNames.isEmpty()) + { + hetatmMenu.setVisible(false); + return; + } + hetatmMenu.setVisible(true); + allHetatmBeingSelected=false; + JMenuItem allMenuItem = new JMenuItem( + MessageManager.getString("label.all")); + JMenuItem noneMenuItem = new JMenuItem( + MessageManager.getString("label.none")); + allMenuItem.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) { + { + allHetatmBeingSelected=true; + // Toggle state of everything - on + for (int i = 0; i < hetatmMenu.getItemCount(); i++) + { + if (hetatmMenu.getItem(i) instanceof JCheckBoxMenuItem) + { + ((JCheckBoxMenuItem) hetatmMenu.getItem(i)).setSelected(true); + } + } + allHetatmBeingSelected=false; + showSelectedHetatms(); + } + }}); + + noneMenuItem.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) { + { + allHetatmBeingSelected=true; + // Toggle state of everything off + for (int i = 0; i < hetatmMenu.getItemCount(); i++) + { + if (hetatmMenu.getItem(i) instanceof JCheckBoxMenuItem) + { + ((JCheckBoxMenuItem) hetatmMenu.getItem(i)).setSelected(false); + } + } + allHetatmBeingSelected=false; + showSelectedHetatms(); + } + }}); + hetatmMenu.add(noneMenuItem); + hetatmMenu.add(allMenuItem); + + for (Map.Entry chain : hetatmNames.entrySet()) + { + JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(chain.getKey(), false); + menuItem.setToolTipText(chain.getValue()); + menuItem.addItemListener(new ItemListener() + { + @Override + public void itemStateChanged(ItemEvent evt) + { + if (!allHetatmBeingSelected) + { + // update viewer only when we were clicked, not programmatically + // checked/unchecked + showSelectedHetatms(); + } + } + }); + + hetatmMenu.add(menuItem); + } + } /** * Action on selecting one of Jalview's registered colour schemes @@ -981,6 +1087,7 @@ public abstract class StructureViewerBase extends GStructureViewer return; } setChainMenuItems(binding.getChainNames()); + setHetatmMenuItems(binding.getHetatmNames()); this.setTitle(binding.getViewerTitle(getViewerName(), true)); @@ -1130,7 +1237,25 @@ public abstract class StructureViewerBase extends GStructureViewer } getBinding().showChains(toshow); } - + /** + * Display selected hetatms in viewer + */ + protected void showSelectedHetatms() + { + List toshow = new ArrayList<>(); + for (int i = 0; i < hetatmMenu.getItemCount(); i++) + { + if (hetatmMenu.getItem(i) instanceof JCheckBoxMenuItem) + { + JCheckBoxMenuItem item = (JCheckBoxMenuItem) hetatmMenu.getItem(i); + if (item.isSelected()) + { + toshow.add(item.getText()); + } + } + } + getBinding().showHetatms(toshow); + } /** * Tries to fetch a PDB file and save to a temporary local file. Returns the * saved file path if successful, or null if not. @@ -1195,7 +1320,7 @@ public abstract class StructureViewerBase extends GStructureViewer } } catch (Exception e) { - System.err.println( + jalview.bin.Console.errPrintln( "Error retrieving PDB id " + pdbid + ": " + e.getMessage()); } finally { @@ -1250,6 +1375,20 @@ public abstract class StructureViewerBase extends GStructureViewer return session; } + private static boolean quitClose = false; + + public static void setQuitClose(boolean b) + { + quitClose = b; + } + + @Override + public boolean stillRunning() + { + AAStructureBindingModel binding = getBinding(); + return binding != null && binding.isViewerRunning(); + } + /** * Close down this instance of Jalview's Chimera viewer, giving the user the * option to close the associated Chimera window (process). They may wish to @@ -1262,24 +1401,48 @@ public abstract class StructureViewerBase extends GStructureViewer public void closeViewer(boolean forceClose) { AAStructureBindingModel binding = getBinding(); - if (binding != null && binding.isViewerRunning()) + if (stillRunning()) { if (!forceClose) { String viewerName = getViewerName(); - String prompt = MessageManager - .formatMessage("label.confirm_close_viewer", new Object[] - { binding.getViewerTitle(viewerName, false), viewerName }); - prompt = JvSwingUtils.wrapTooltip(true, prompt); - int confirm = JvOptionPane.showConfirmDialog(this, prompt, - MessageManager.getString("label.close_viewer"), - JvOptionPane.YES_NO_CANCEL_OPTION); + + int confirm = JvOptionPane.CANCEL_OPTION; + if (QuitHandler.quitting()) + { + // already asked about closing external windows + confirm = quitClose ? JvOptionPane.YES_OPTION + : JvOptionPane.NO_OPTION; + } + else + { + String prompt = MessageManager + .formatMessage("label.confirm_close_viewer", new Object[] + { binding.getViewerTitle(viewerName, false), + viewerName }); + prompt = JvSwingUtils.wrapTooltip(true, prompt); + String title = MessageManager.getString("label.close_viewer"); + confirm = showCloseDialog(title, prompt); + } + /* * abort closure if user hits escape or Cancel */ if (confirm == JvOptionPane.CANCEL_OPTION || confirm == JvOptionPane.CLOSED_OPTION) { + // abort possible quit handling if CANCEL chosen + if (confirm == JvOptionPane.CANCEL_OPTION) + { + try + { + // this is a bit futile + this.setClosed(false); + } catch (PropertyVetoException e) + { + } + QuitHandler.abortQuit(); + } return; } forceClose = confirm == JvOptionPane.YES_OPTION; @@ -1296,9 +1459,26 @@ public abstract class StructureViewerBase extends GStructureViewer // TODO: check for memory leaks where instance isn't finalised because jmb // holds a reference to the window // jmb = null; + + try { + svbs.remove(this); + } catch (Throwable t) + { + Console.info("Unexpected exception when deregistering structure viewer",t); + } dispose(); } + private int showCloseDialog(final String title, final String prompt) + { + int confirmResponse = JvOptionPane.CANCEL_OPTION; + confirmResponse = JvOptionPane.showConfirmDialog(this, prompt, + MessageManager.getString("label.close_viewer"), + JvOptionPane.YES_NO_CANCEL_OPTION, + JvOptionPane.WARNING_MESSAGE); + return confirmResponse; + } + @Override public void showHelp_actionPerformed() { @@ -1329,4 +1509,5 @@ public abstract class StructureViewerBase extends GStructureViewer && viewerActionMenu.getItemCount() > 0 && viewerActionMenu.isVisible(); } + }