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 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;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
import jalview.structures.models.AAStructureBindingModel;
import jalview.util.BrowserLauncher;
import jalview.util.MessageManager;
+import jalview.ws.dbsources.EBIAlfaFold;
import jalview.ws.dbsources.Pdb;
+import jalview.ws.utils.UrlDownloadClient;
/**
* Base class with common functionality for JMol, Chimera or other structure
}
/**
+ * 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<>();
public StructureViewerBase()
{
super();
+ setFrameIcon(null);
+ svbs.add(this);
}
/**
}
/**
+ * called by the binding model to indicate when adding structures is happening
+ * or has been completed
+ *
+ * @param addingStructures
+ */
+ public synchronized void setAddingStructures(boolean addingStructures)
+ {
+ this.addingStructures = addingStructures;
+ }
+
+ /**
*
* @param ap2
* @return true if this Jmol instance is linked with the given alignPanel
return _aps.contains(ap2.av.getSequenceSetId());
}
+ @Override
public boolean isUsedforaligment(AlignmentViewPanel ap2)
{
_alignwith.add(ap);
}
;
+ // TODO: refactor to allow concrete classes to register buttons for adding
+ // here
+ // currently have to override to add buttons back in after they are cleared
+ // in this loop
for (Component c : viewerActionMenu.getMenuComponents())
{
if (c != alignStructs)
{
return;
}
- AlignmentPanel alignPanel = (AlignmentPanel) apanel; // Implementation error if this
- // cast fails
+ AlignmentPanel alignPanel = (AlignmentPanel) apanel; // Implementation error
+ // if this
+ // cast fails
useAlignmentPanelForSuperposition(alignPanel);
addStructure(pdbentry, seq, chains, alignPanel.alignFrame);
}
public void changeColour_actionPerformed(String colourSchemeName)
{
AlignmentI al = getAlignmentPanel().av.getAlignment();
- ColourSchemeI cs = ColourSchemes.getInstance()
- .getColourScheme(colourSchemeName, getAlignmentPanel().av, al,
- null);
+ ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(
+ colourSchemeName, getAlignmentPanel().av, al, null);
getBinding().colourByJalviewColourScheme(cs);
}
{
sp.append("'" + alignPanel.getViewName() + "' ");
}
- Cache.log.info("Couldn't align structures with the " + sp.toString()
+ Console.info("Couldn't align structures with the " + sp.toString()
+ "associated alignment panels.", e);
}
return reply;
* enable 'Superpose with' if more than one mapped structure
*/
viewSelectionMenu.setEnabled(false);
- if (getBinding().getStructureFiles().length > 1
+ if (getBinding().getMappedStructureCount() > 1
&& getBinding().getSequence().length > 1)
{
viewSelectionMenu.setEnabled(true);
{
return false;
}
- int p=0;
- for (String pdbid:pdbids) {
+ int p = 0;
+ for (String pdbid : pdbids)
+ {
StructureMapping sm[] = getBinding().getSsm().getMapping(pdbid);
- if (sm!=null && sm.length>0 && sm[0]!=null) {
+ if (sm != null && sm.length > 0 && sm[0] != null)
+ {
p++;
}
}
- // only return true if there is a mapping for every structure file we have loaded
+ // only return true if there is a mapping for every structure file we have
+ // loaded
if (p == 0 || p != pdbids.length)
{
return false;
progressBar = pi;
}
- protected void setProgressMessage(String message, long id)
+ public void setProgressMessage(String message, long id)
{
if (progressBar != null)
{
{
String filePath = null;
Pdb pdbclient = new Pdb();
+ EBIAlfaFold afclient = new EBIAlfaFold();
AlignmentI pdbseq = null;
String pdbid = processingEntry.getId();
long handle = System.currentTimeMillis()
+ Thread.currentThread().hashCode();
-
+
/*
* Write 'fetching PDB' progress on AlignFrame as we are not yet visible
*/
// { pdbid }));
try
{
- pdbseq = pdbclient.getSequenceRecords(pdbid);
+ if (afclient.isValidReference(pdbid))
+ {
+ pdbseq = afclient.getSequenceRecords(pdbid,
+ processingEntry.getRetrievalUrl());
+ }
+ else
+ {
+ if (processingEntry.hasRetrievalUrl())
+ {
+ String safePDBId = java.net.URLEncoder.encode(pdbid, "UTF-8")
+ .replace("%", "__");
+
+ // retrieve from URL to new local tmpfile
+ File tmpFile = File.createTempFile(safePDBId,
+ "." + (PDBEntry.Type.MMCIF.toString().equals(
+ processingEntry.getType().toString()) ? "cif"
+ : "pdb"));
+ String fromUrl = processingEntry.getRetrievalUrl();
+ UrlDownloadClient.download(fromUrl, tmpFile);
+
+ // may not need this check ?
+ String file = tmpFile.getAbsolutePath();
+ if (file != null)
+ {
+ pdbseq = EBIAlfaFold.importDownloadedStructureFromUrl(fromUrl,
+ tmpFile, pdbid, null, null, null);
+ }
+ }
+ else
+ {
+ pdbseq = pdbclient.getSequenceRecords(pdbid);
+ }
+ }
} catch (Exception e)
{
- System.err.println(
+ jalview.bin.Console.errPrintln(
"Error retrieving PDB id " + pdbid + ": " + e.getMessage());
} finally
{
*/
public File saveSession()
{
- // TODO: a wait loop to ensure the file is written fully before returning?
- return getBinding() == null ? null : getBinding().saveSession();
+ if (getBinding() == null)
+ {
+ return null;
+ }
+ File session = getBinding().saveSession();
+ long l = session.length();
+ int wait = 50;
+ do
+ {
+ try
+ {
+ Thread.sleep(5);
+ } catch (InterruptedException e)
+ {
+ }
+ long nextl = session.length();
+ if (nextl != l)
+ {
+ wait = 50;
+ l = nextl;
+ }
+ } while (--wait > 0);
+ 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();
}
/**
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;
}
+ }
+ if (binding != null)
+ {
binding.closeViewer(forceClose);
}
setAlignmentPanel(null);
// 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()
{
+ /*
try
{
- String url = getBinding().getHelpURL();
- if (url != null)
- {
- BrowserLauncher.openURL(url);
- }
- } catch (IOException ex)
+ */
+ String url = getBinding().getHelpURL();
+ if (url != null)
+ {
+ BrowserLauncher.openURL(url);
+ }
+ /*
+ }
+ catch (IOException ex)
{
System.err
.println("Show " + getViewerName() + " failed with: "
+ ex.getMessage());
}
+ */
+ }
+
+ @Override
+ public boolean hasViewerActionsMenu()
+ {
+ return viewerActionMenu != null && viewerActionMenu.isEnabled()
+ && viewerActionMenu.getItemCount() > 0
+ && viewerActionMenu.isVisible();
}
}