X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FAppJmol.java;h=0aa4878d9263504541fa8bacf8f8a5ea6a76d328;hb=HEAD;hp=4058cda92763bb28cce91bd5fcb1af73d4f98935;hpb=4f30214e8098748469c6a4269ac2ed6c5750e4b0;p=jalview.git diff --git a/src/jalview/gui/AppJmol.java b/src/jalview/gui/AppJmol.java index 4058cda..4d0de1b 100644 --- a/src/jalview/gui/AppJmol.java +++ b/src/jalview/gui/AppJmol.java @@ -25,10 +25,13 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; -import java.awt.Rectangle; +import java.awt.Graphics2D; +import java.awt.RenderingHints; import java.io.File; -import java.util.ArrayList; import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.Executors; import javax.swing.JPanel; import javax.swing.JSplitPane; @@ -37,19 +40,22 @@ import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; import jalview.api.AlignmentViewPanel; -import jalview.bin.Cache; -import jalview.datamodel.AlignmentI; +import jalview.bin.Console; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceI; +import jalview.datamodel.StructureViewerModel; +import jalview.datamodel.StructureViewerModel.StructureData; import jalview.gui.ImageExporter.ImageWriterI; import jalview.gui.StructureViewer.ViewerType; +import jalview.io.exceptions.ImageOutputException; import jalview.structure.StructureCommand; import jalview.structures.models.AAStructureBindingModel; import jalview.util.BrowserLauncher; import jalview.util.ImageMaker; +import jalview.util.ImageMaker.TYPE; import jalview.util.MessageManager; import jalview.util.Platform; -import jalview.ws.dbsources.Pdb; +import jalview.util.imagemaker.BitmapImageSizing; public class AppJmol extends StructureViewerBase { @@ -87,48 +93,55 @@ public class AppJmol extends StructureViewerBase * @param bounds * @param viewid */ - public AppJmol(String[] files, String[] ids, SequenceI[][] seqs, - AlignmentPanel ap, boolean usetoColour, boolean useToAlign, - boolean leaveColouringToJmol, String loadStatus, Rectangle bounds, - String viewid) + public AppJmol(StructureViewerModel viewerModel, AlignmentPanel ap, + String sessionFile, String viewid) { - PDBEntry[] pdbentrys = new PDBEntry[files.length]; - for (int i = 0; i < pdbentrys.length; i++) + Map pdbData = viewerModel.getFileData(); + PDBEntry[] pdbentrys = new PDBEntry[pdbData.size()]; + SequenceI[][] seqs = new SequenceI[pdbData.size()][]; + int i = 0; + for (StructureData data : pdbData.values()) { - // PDBEntry pdbentry = new PDBEntry(files[i], ids[i]); - PDBEntry pdbentry = new PDBEntry(ids[i], null, PDBEntry.Type.PDB, - files[i]); + PDBEntry pdbentry = new PDBEntry(data.getPdbId(), null, + PDBEntry.Type.PDB, data.getFilePath()); pdbentrys[i] = pdbentry; + List sequencesForPdb = data.getSeqList(); + seqs[i] = sequencesForPdb + .toArray(new SequenceI[sequencesForPdb.size()]); + i++; } - // / TODO: check if protocol is needed to be set, and if chains are + + // TODO: check if protocol is needed to be set, and if chains are // autodiscovered. jmb = new AppJmolBinding(this, ap.getStructureSelectionManager(), pdbentrys, seqs, null); jmb.setLoadingFromArchive(true); addAlignmentPanel(ap); - if (useToAlign) + if (viewerModel.isAlignWithPanel()) { useAlignmentPanelForSuperposition(ap); } initMenus(); - if (leaveColouringToJmol || !usetoColour) + boolean useToColour = viewerModel.isColourWithAlignPanel(); + boolean leaveColouringToJmol = viewerModel.isColourByViewer(); + if (leaveColouringToJmol || !useToColour) { jmb.setColourBySequence(false); seqColour.setSelected(false); viewerColour.setSelected(true); } - else if (usetoColour) + else if (useToColour) { useAlignmentPanelForColourbyseq(ap); jmb.setColourBySequence(true); seqColour.setSelected(true); viewerColour.setSelected(false); } - this.setBounds(bounds); + + this.setBounds(viewerModel.getX(), viewerModel.getY(), + viewerModel.getWidth(), viewerModel.getHeight()); setViewId(viewid); - // jalview.gui.Desktop.addInternalFrame(this, "Loading File", - // bounds.width,bounds.height); this.addInternalFrameListener(new InternalFrameAdapter() { @@ -139,7 +152,10 @@ public class AppJmol extends StructureViewerBase closeViewer(false); } }); - initJmol(loadStatus); // pdbentry, seq, JBPCHECK! + StringBuilder cmd = new StringBuilder(); + cmd.append("load FILES ").append(QUOTE) + .append(Platform.escapeBackslashes(sessionFile)).append(QUOTE); + initJmol(cmd.toString()); } @Override @@ -147,8 +163,6 @@ public class AppJmol extends StructureViewerBase { super.initMenus(); - viewerActionMenu.setText(MessageManager.getString("label.jmol")); - viewerColour .setText(MessageManager.getString("label.colour_with_jmol")); viewerColour.setToolTipText(MessageManager @@ -174,8 +188,7 @@ public class AppJmol extends StructureViewerBase } private void openNewJmol(AlignmentPanel ap, boolean alignAdded, - PDBEntry[] pdbentrys, - SequenceI[][] seqs) + PDBEntry[] pdbentrys, SequenceI[][] seqs) { setProgressIndicator(ap.alignFrame); jmb = new AppJmolBinding(this, ap.getStructureSelectionManager(), @@ -224,7 +237,6 @@ public class AppJmol extends StructureViewerBase openNewJmol(ap, alignAdded, pe, seqs); } - void initJmol(String command) { jmb.setFinishedInit(false); @@ -252,6 +264,8 @@ public class AppJmol extends StructureViewerBase } jmb.executeCommand(new StructureCommand(command), false); jmb.executeCommand(new StructureCommand("set hoverDelay=0.1"), false); + jmb.executeCommand(new StructureCommand("set antialiasdisplay on"), + false); jmb.setFinishedInit(true); } @@ -261,7 +275,7 @@ public class AppJmol extends StructureViewerBase _started = true; try { - List files = fetchPdbFiles(); + List files = jmb.fetchPdbFiles(this); if (files.size() > 0) { showFilesInViewer(files); @@ -299,10 +313,10 @@ public class AppJmol extends StructureViewerBase } catch (OutOfMemoryError oomerror) { new OOMWarning("When trying to open the Jmol viewer!", oomerror); - Cache.log.debug("File locations are " + filesString); + Console.debug("File locations are " + filesString); } catch (Exception ex) { - Cache.log.error("Couldn't open Jmol viewer!", ex); + Console.error("Couldn't open Jmol viewer!", ex); ex.printStackTrace(); return; } @@ -323,11 +337,11 @@ public class AppJmol extends StructureViewerBase { new OOMWarning("When trying to add structures to the Jmol viewer!", oomerror); - Cache.log.debug("File locations are " + filesString); + Console.debug("File locations are " + filesString); return; } catch (Exception ex) { - Cache.log.error("Couldn't add files to Jmol viewer!", ex); + Console.error("Couldn't add files to Jmol viewer!", ex); ex.printStackTrace(); return; } @@ -343,17 +357,20 @@ public class AppJmol extends StructureViewerBase { try { - Cache.log.debug("Waiting around for jmb notify."); - Thread.sleep(waitFor); + Console.debug("Waiting around for jmb notify."); waitTotal += waitFor; + + // Thread.sleep() throws an exception in JS + Thread.sleep(waitFor); } catch (Exception e) { } if (waitTotal > waitMax) { - System.err.println("Timed out waiting for Jmol to load files after " - + waitTotal + "ms"); - // System.err.println("finished: " + jmb.isFinishedInit() + jalview.bin.Console.errPrintln( + "Timed out waiting for Jmol to load files after " + + waitTotal + "ms"); + // jalview.bin.Console.errPrintln("finished: " + jmb.isFinishedInit() // + "; loaded: " + Arrays.toString(jmb.getPdbFile()) // + "; files: " + files.toString()); jmb.getStructureFiles(); @@ -404,110 +421,14 @@ public class AppJmol extends StructureViewerBase } - /** - * Retrieves and saves as file any modelled PDB entries for which we do not - * already have a file saved. Returns a list of absolute paths to structure - * files which were either retrieved, or already stored but not modelled in - * the structure viewer (i.e. files to add to the viewer display). - * - * @return - */ - List fetchPdbFiles() + public boolean isRepainting() { - // todo - record which pdbids were successfully imported. - StringBuilder errormsgs = new StringBuilder(); - - List files = new ArrayList<>(); - String pdbid = ""; - try - { - String[] filesInViewer = jmb.getStructureFiles(); - // TODO: replace with reference fetching/transfer code (validate PDBentry - // as a DBRef?) - Pdb pdbclient = new Pdb(); - for (int pi = 0; pi < jmb.getPdbCount(); pi++) - { - String file = jmb.getPdbEntry(pi).getFile(); - if (file == null) - { - // todo: extract block as method and pull up (also ChimeraViewFrame) - // retrieve the pdb and store it locally - AlignmentI pdbseq = null; - pdbid = jmb.getPdbEntry(pi).getId(); - long hdl = pdbid.hashCode() - System.currentTimeMillis(); - setProgressMessage(MessageManager - .formatMessage("status.fetching_pdb", new String[] - { pdbid }), hdl); - try - { - pdbseq = pdbclient.getSequenceRecords(pdbid); - } catch (OutOfMemoryError oomerror) - { - new OOMWarning("Retrieving PDB id " + pdbid, oomerror); - } catch (Exception ex) - { - ex.printStackTrace(); - errormsgs.append("'").append(pdbid).append("'"); - } finally - { - setProgressMessage( - MessageManager.getString("label.state_completed"), hdl); - } - if (pdbseq != null) - { - // just transfer the file name from the first sequence's first - // PDBEntry - file = new File(pdbseq.getSequenceAt(0).getAllPDBEntries() - .elementAt(0).getFile()).getAbsolutePath(); - jmb.getPdbEntry(pi).setFile(file); - files.add(file); - } - else - { - errormsgs.append("'").append(pdbid).append("' "); - } - } - else - { - if (filesInViewer != null && filesInViewer.length > 0) - { - addingStructures = true; // already files loaded. - for (int c = 0; c < filesInViewer.length; c++) - { - if (Platform.pathEquals(filesInViewer[c], file)) - { - file = null; - break; - } - } - } - if (file != null) - { - files.add(file); - } - } - } - } catch (OutOfMemoryError oomerror) - { - new OOMWarning("Retrieving PDB files: " + pdbid, oomerror); - } catch (Exception ex) + if (renderPanel!=null && renderPanel.isVisible()) { - ex.printStackTrace(); - errormsgs.append("When retrieving pdbfiles : current was: '") - .append(pdbid).append("'"); + return renderPanel.repainting; } - if (errormsgs.length() > 0) - { - JvOptionPane.showInternalMessageDialog(Desktop.desktop, - MessageManager.formatMessage( - "label.pdb_entries_couldnt_be_retrieved", new String[] - { errormsgs.toString() }), - MessageManager.getString("label.couldnt_load_file"), - JvOptionPane.ERROR_MESSAGE); - } - return files; + return false; } - /** * Outputs the Jmol viewer image as an image file, after prompting the user to * choose a file and (for EPS) choice of Text or Lineart character rendering @@ -518,20 +439,113 @@ public class AppJmol extends StructureViewerBase @Override public void makePDBImage(ImageMaker.TYPE type) { + while (!isRepainting()) + { + try { + Thread.sleep(2); + } catch (Exception q) + {} + } + try + { + makePDBImage(null, type, null, + BitmapImageSizing.defaultBitmapImageSizing()); + } catch (ImageOutputException ioex) + { + Console.error("Unexpected error whilst writing " + type.toString(), + ioex); + } + } + + public void makePDBImage(File file, ImageMaker.TYPE type, String renderer, + BitmapImageSizing userBis) throws ImageOutputException + { int width = getWidth(); int height = getHeight(); + + BitmapImageSizing bis = ImageMaker.getScaleWidthHeight(width, height, + userBis); + float usescale = bis.scale(); + int usewidth = bis.width(); + int useheight = bis.height(); + ImageWriterI writer = new ImageWriterI() { @Override public void exportImage(Graphics g) throws Exception { - jmb.jmolViewer.renderScreenImage(g, width, height); + Graphics2D ig2 = (Graphics2D) g; + ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + if (type == TYPE.PNG && usescale > 0.0f) + { + // for a scaled image, this scales down a bigger image to give the + // right resolution + if (usescale > 0.0f) + { + ig2.scale(1 / usescale, 1 / usescale); + } + } + + jmb.jmolViewer.requestRepaintAndWait("image export"); + jmb.jmolViewer.renderScreenImage(ig2, usewidth, useheight); } }; - String view = MessageManager.getString("action.view").toLowerCase(); - ImageExporter exporter = new ImageExporter(writer, + String view = MessageManager.getString("action.view") + .toLowerCase(Locale.ROOT); + final ImageExporter exporter = new ImageExporter(writer, getProgressIndicator(), type, getTitle()); - exporter.doExport(null, this, width, height, view); + + final Throwable[] exceptions = new Throwable[1]; + exceptions[0] = null; + final AppJmol us = this; + try + { + Thread runner = Executors.defaultThreadFactory() + .newThread(new Runnable() + { + @Override + public void run() + { + try + { + exporter.doExport(file, us, width, height, view, + renderer, userBis); + } catch (Throwable t) + { + exceptions[0] = t; + } + } + }); + runner.start(); + long time = 0; + do + { + Thread.sleep(25); + } while (runner.isAlive() && time++ < 4000); + if (time >= 4000) + { + runner.interrupt(); + throw new ImageOutputException( + "Jmol took too long to export. Waited for 100 seconds."); + } + } catch (Throwable e) + { + throw new ImageOutputException( + "Unexpected error when generating image", e); + } + if (exceptions[0] != null) + { + if (exceptions[0] instanceof ImageOutputException) + { + throw ((ImageOutputException) exceptions[0]); + } + else + { + throw new ImageOutputException( + "Unexpected error when generating image", exceptions[0]); + } + } } @Override @@ -540,10 +554,11 @@ public class AppJmol extends StructureViewerBase try { BrowserLauncher // BH 2018 - .openURL("http://wiki.jmol.org");//http://jmol.sourceforge.net/docs/JmolUserGuide/"); + .openURL("http://wiki.jmol.org");// http://jmol.sourceforge.net/docs/JmolUserGuide/"); } catch (Exception ex) { - System.err.println("Show Jmol help failed with: " + ex.getMessage()); + jalview.bin.Console + .errPrintln("Show Jmol help failed with: " + ex.getMessage()); } } @@ -615,7 +630,8 @@ public class AppJmol extends StructureViewerBase } } } - else if (jmb == null || jmb.jmolViewer == null || !jmb.isFinishedInit()) + else if (jmb == null || jmb.jmolViewer == null + || !jmb.isFinishedInit()) { g.setColor(Color.black); g.fillRect(0, 0, currentSize.width, currentSize.height); @@ -626,10 +642,17 @@ public class AppJmol extends StructureViewerBase } else { - jmb.jmolViewer.renderScreenImage(g, currentSize.width, - currentSize.height); + repainting=true; + synchronized (jmb) + { + jmb.jmolViewer.renderScreenImage(g, currentSize.width, + currentSize.height); + + } + repainting=false; } } + volatile boolean repainting=false; } @Override