JAL-3518 pull up closeViewer() and external viewer process monitor
[jalview.git] / src / jalview / structures / models / AAStructureBindingModel.java
index 5949847..05cfd5a 100644 (file)
@@ -175,6 +175,8 @@ public abstract class AAStructureBindingModel
 
   public String fileLoadingError;
 
+  protected Thread externalViewerMonitor;
+
   /**
    * Constructor
    * 
@@ -1109,40 +1111,22 @@ public abstract class AAStructureBindingModel
           boolean getReply);
 
   /**
-   * A helper method that converts list of commands to a vararg array
-   * 
-   * @param commands
-   * @param getReply
-   * @param msg
-   */
-  protected List<String> executeCommands(
-          List<StructureCommandI> commands,
-          boolean getReply, String msg)
-  {
-    return executeCommands(getReply, msg,
-            commands.toArray(new StructureCommandI[commands.size()]));
-  }
-
-  /**
    * Executes one or more structure viewer commands. If a progress message is
    * provided, it is shown first, and removed after all commands have been run.
    * 
+   * @param commands
    * @param getReply
    * @param msg
-   * @param commands
-   * @return
    */
-  protected List<String> executeCommands(boolean getReply, String msg,
-          StructureCommandI[] commands)
+  protected List<String> executeCommands(List<StructureCommandI> commands,
+          boolean getReply, String msg)
   {
-    // todo: tidy this up
-
     /*
      * show progress message if specified
      */
     final JalviewStructureDisplayI theViewer = getViewer();
     final long handle = msg == null ? 0 : theViewer.startProgressBar(msg);
-
+    
     List<String> response = getReply ? new ArrayList<>() : null;
     try
     {
@@ -1583,7 +1567,7 @@ public abstract class AAStructureBindingModel
   /**
    * Closes Jalview's structure viewer panel and releases associated resources.
    * If it is managing an external viewer program, and {@code forceClose} is
-   * true, also shuts down that program.
+   * true, also asks that program to close.
    * 
    * @param forceClose
    */
@@ -1592,8 +1576,23 @@ public abstract class AAStructureBindingModel
     getSsm().removeStructureViewerListener(this, this.getStructureFiles());
     releaseUIResources();
 
-    // add external viewer shutdown in overrides
-    // todo - or can maybe pull up to here
+    /*
+     * end the thread that closes this panel if the external viewer closes
+     */
+    if (externalViewerMonitor != null)
+    {
+      externalViewerMonitor.interrupt();
+      externalViewerMonitor = null;
+    }
+
+    if (forceClose)
+    {
+      StructureCommandI cmd = getCommandGenerator().closeViewer();
+      if (cmd != null)
+      {
+        executeCommand(cmd, false);
+      }
+    }
   }
 
   /**
@@ -1868,4 +1867,37 @@ public abstract class AAStructureBindingModel
     String[] files = getStructureFiles();
     return files == null ? 0 : files.length;
   }
+
+  /**
+   * Starts a thread that waits for the external viewer program process to
+   * finish, so that we can then close the associated resources. This avoids
+   * leaving orphaned viewer panels in Jalview if the user closes the external
+   * viewer.
+   * 
+   * @param p
+   */
+  protected void startExternalViewerMonitor(Process p)
+  {
+    externalViewerMonitor = new Thread(new Runnable()
+    {
+  
+      @Override
+      public void run()
+      {
+        try
+        {
+          p.waitFor();
+          JalviewStructureDisplayI display = getViewer();
+          if (display != null)
+          {
+            display.closeViewer(false);
+          }
+        } catch (InterruptedException e)
+        {
+          // exit thread if Chimera Viewer is closed in Jalview
+        }
+      }
+    });
+    externalViewerMonitor.start();
+  }
 }