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;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.Random;
import java.util.Vector;
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;
}
/**
+ * 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<JalviewStructureDisplayI> svbs = new ArrayList<>();
+
+ /**
+ *
+ * @return list with all existing StructureViewers instance
+ */
+ public static List<JalviewStructureDisplayI> getAllStructureViewerBases()
+ {
+ List<JalviewStructureDisplayI> 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<String> _aps = new ArrayList<>();
protected boolean allChainsSelected = false;
+ protected boolean allHetatmBeingSelected = false;
+
protected JMenu viewSelectionMenu;
/**
public StructureViewerBase()
{
super();
- setFrameIcon(WindowIcons.structureIcon);
+ setFrameIcon(null);
+ svbs.add(this);
}
/**
return _aps.contains(ap2.av.getSequenceSetId());
}
+ @Override
public boolean isUsedforaligment(AlignmentViewPanel ap2)
{
}
}
+ void setHetatmMenuItems(Map<String, String> 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<String, String> 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
*/
return;
}
setChainMenuItems(binding.getChainNames());
+ setHetatmMenuItems(binding.getHetatmNames());
this.setTitle(binding.getViewerTitle(getViewerName(), true));
}
/**
+ * Display selected hetatms in viewer
+ */
+ protected void showSelectedHetatms()
+ {
+ List<String> 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.
*
}
} catch (Exception e)
{
- System.err.println(
+ jalview.bin.Console.errPrintln(
"Error retrieving PDB id " + pdbid + ": " + e.getMessage());
} finally
{
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
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;
// 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()
{
&& viewerActionMenu.getItemCount() > 0
&& viewerActionMenu.isVisible();
}
+
}