JAL-4420 new drag'n'drop behaviour is now an 'Experimental Feature'
authorJim Procter <jprocter@dundee.ac.uk>
Mon, 26 Aug 2024 16:30:37 +0000 (17:30 +0100)
committerJim Procter <jprocter@dundee.ac.uk>
Mon, 26 Aug 2024 16:30:37 +0000 (17:30 +0100)
src/jalview/gui/Desktop.java

index efd1756..10067cf 100644 (file)
@@ -1214,186 +1214,261 @@ public class Desktop extends jalview.jbgui.GDesktop
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param evt
-   *          DOCUMENT ME!
+   * load all files dropped (2.11.4.0 behaviour)
+   * @return false if any file resulted in an error
    */
-  @Override
-  public void drop(DropTargetDropEvent evt)
+  public boolean loadDroppedFiles(List<Object> files,
+          List<DataSourceType> protocols, List<Object> failed,
+          List<Exception> failed_exceptions)
   {
-    boolean success = true;
-    // JAL-1552 - acceptDrop required before getTransferable call for
-    // Java's Transferable for native dnd
-    evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
-    Transferable t = evt.getTransferable();
-    List<Object> files = new ArrayList<>();
-    List<DataSourceType> protocols = new ArrayList<>();
-
-    try
+    for (int i = 0; i < files.size(); i++)
     {
-      Desktop.transferFromDropTarget(files, protocols, evt, t);
-    } catch (Exception e)
+      Object file = files.get(i);
+      try
+      {
+        // BH 2018 File or String
+        String fileName = file.toString();
+        DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
+                : protocols.get(i);
+        FileFormatI format = null;
+
+        if (fileName.endsWith(".jar"))
+        {
+          format = FileFormat.Jalview;
+        }
+        else
+        {
+          format = new IdentifyFile().identify(file, protocol);
+        }
+        if (file instanceof File)
+        {
+          Platform.cacheFileData((File) file);
+        }
+        new FileLoader().LoadFile(null, file, protocol, format);
+      } catch (Exception x)
+      {
+        failed.add(file);
+        failed_exceptions.add(x);
+        jalview.bin.Console.warn(
+                "Unexpected Exception when handling " + file.toString(), x);
+      }
+    }
+    return failed.size()==0; // at least one was loaded.
+  }
+
+  /**
+   * analyse dropped files and process them according to type: load alignments,
+   * add annotation, trees or features to alignments with the same basename
+   * 
+   * @return false if any exception was raised
+   */
+  public boolean processAndLoadDroppedFiles(List<Object> files,
+          List<DataSourceType> protocols, List<Object> failed,
+          List<Exception> failed_exceptions)
+  {
+    // map list to list of strings
+    List<String> filenames = new ArrayList<>();
+    for (int i = 0; i < files.size(); i++)
     {
-      e.printStackTrace();
-      success = false;
+      filenames.add(files.get(i).toString());
     }
 
-    if (files != null)
+    // processFilenames will take likely associated files OUT of the list of
+    // filenames and return them in a BaseInfo object in the Map
+    Map<String, BaseInfo> baseInfoMap = ArgParserUtils
+            .processFilenames(filenames, false, files);
+    // so we can catch exceptions for this file
+    Object file = null;
+    try
     {
-      try
+
+      for (int i = 0; i < files.size(); i++)
       {
-        // map list to list of strings
-        List<String> filenames = new ArrayList<>();
-        for (int i = 0; i < files.size(); i++)
+        // BH 2018 File or String
+        file = files.get(i);
+        String fileName = file.toString();
+        DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
+                : protocols.get(i);
+        FileFormatI format = null;
+
+        if (fileName.toLowerCase(Locale.ROOT).endsWith(".jar"))
         {
-          filenames.add(files.get(i).toString());
+          format = FileFormat.Jalview;
         }
-
-        // processFilenames will take likely associated files OUT of the list of
-        // filenames and return them in a BaseInfo object in the Map
-        Map<String, BaseInfo> baseInfoMap = ArgParserUtils
-                .processFilenames(filenames, false, files);
-        for (int i = 0; i < files.size(); i++)
+        else
         {
-          // BH 2018 File or String
-          Object file = files.get(i);
-          String fileName = file.toString();
-          DataSourceType protocol = (protocols == null)
-                  ? DataSourceType.FILE
-                  : protocols.get(i);
-          FileFormatI format = null;
-
-          if (fileName.toLowerCase(Locale.ROOT).endsWith(".jar"))
-          {
-            format = FileFormat.Jalview;
-          }
-          else
+          format = new IdentifyFile().identify(file, protocol);
+        }
+        // If features/annotations/tree file that hasn't been put into the
+        // baseInfoMap, look through titles of opened AlignFrames to add.
+        String ext = FileUtils.getExtension(fileName);
+        boolean isFeatures = ArgParserUtils.featuresExtensions
+                .contains(ext);
+        boolean isAnnotations = ArgParserUtils.annotationsExtensions
+                .contains(ext);
+        boolean isTree = ArgParserUtils.treeExtensions.contains(ext);
+        if (isFeatures || isAnnotations || isTree)
+        {
+          String base = FileUtils.getBase(fileName);
+          AlignFrame matchingAf = null;
+          AlignFrame[] afs = Desktop.instance.getAlignFrames();
+          boolean dontSkip = false;
+          for (AlignFrame af : afs)
           {
-            format = new IdentifyFile().identify(file, protocol);
+            String afFilename = af.fileName;
+            String afTitle = af.getTitle();
+            /**
+             * don't need to check the matching afFilename or afTitle has an
+             * alignment extenstion. It's obviously an alignment!
+             */
+            /*
+            if ((base.equals(FileUtils.getBase(afFilename))
+                    && ArgParserUtils.alignmentExtensions
+                            .contains(FileUtils.getExtension(afFilename)))
+                    || (base.equals(FileUtils.getBase(afTitle))
+                            && ArgParserUtils.alignmentExtensions
+                                    .contains(FileUtils
+                                            .getExtension(afTitle))))
+            */
+            if (base.equals(FileUtils.getBase(afFilename))
+                    || base.equals(FileUtils.getBase(afTitle)))
+            {
+              matchingAf = af;
+              break;
+            }
           }
-          // If features/annotations/tree file that hasn't been put into the
-          // baseInfoMap, look through titles of opened AlignFrames to add.
-          String ext = FileUtils.getExtension(fileName);
-          boolean isFeatures = ArgParserUtils.featuresExtensions
-                  .contains(ext);
-          boolean isAnnotations = ArgParserUtils.annotationsExtensions
-                  .contains(ext);
-          boolean isTree = ArgParserUtils.treeExtensions.contains(ext);
-          if (isFeatures || isAnnotations || isTree)
+          if (matchingAf != null)
           {
-            String base = FileUtils.getBase(fileName);
-            AlignFrame matchingAf = null;
-            AlignFrame[] afs = Desktop.instance.getAlignFrames();
-            boolean dontSkip = false;
-            for (AlignFrame af : afs)
+            if (isFeatures)
             {
-              String afFilename = af.fileName;
-              String afTitle = af.getTitle();
-              /**
-               * don't need to check the matching afFilename or afTitle has an
-               * alignment extenstion. It's obviously an alignment!
-               */
-              /*
-              if ((base.equals(FileUtils.getBase(afFilename))
-                      && ArgParserUtils.alignmentExtensions
-                              .contains(FileUtils.getExtension(afFilename)))
-                      || (base.equals(FileUtils.getBase(afTitle))
-                              && ArgParserUtils.alignmentExtensions
-                                      .contains(FileUtils
-                                              .getExtension(afTitle))))
-              */
-              if (base.equals(FileUtils.getBase(afFilename))
-                      || base.equals(FileUtils.getBase(afTitle)))
-              {
-                matchingAf = af;
-                break;
-              }
+              matchingAf.parseFeaturesFile(fileName,
+                      AppletFormatAdapter.checkProtocol(fileName));
+            }
+            else if (isAnnotations)
+            {
+              matchingAf.loadJalviewDataFile(fileName, null, null, null);
             }
-            if (matchingAf != null)
+            else if (isTree)
             {
-              if (isFeatures)
+              try
               {
-                matchingAf.parseFeaturesFile(fileName,
+                NewickFile nf = new NewickFile(fileName,
                         AppletFormatAdapter.checkProtocol(fileName));
-              }
-              else if (isAnnotations)
-              {
-                matchingAf.loadJalviewDataFile(fileName, null, null, null);
-              }
-              else if (isTree)
-              {
-                try
-                {
-                  NewickFile nf = new NewickFile(fileName,
-                          AppletFormatAdapter.checkProtocol(fileName));
-                  matchingAf.getViewport().setCurrentTree(matchingAf
-                          .showNewickTree(nf, fileName).getTree());
-                } catch (IOException e)
-                {
-                  jalview.bin.Console.warn(
-                          "Couldn't add potential tree '" + fileName + "'");
-                  dontSkip = true;
-                }
-              }
-              if (!dontSkip)
+                matchingAf.getViewport().setCurrentTree(
+                        matchingAf.showNewickTree(nf, fileName).getTree());
+              } catch (IOException e)
               {
-                // skip to next file
-                continue;
+                jalview.bin.Console.warn(
+                        "Couldn't add potential tree '" + fileName + "'");
+                dontSkip = true;
               }
             }
+            if (!dontSkip)
+            {
+              // skip to next file
+              continue;
+            }
           }
+        }
 
-          if (file instanceof File)
+        if (file instanceof File)
+        {
+          Platform.cacheFileData((File) file);
+        }
+        // new FileLoader().LoadFile(null, file, protocol, format);
+        AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(fileName,
+                protocol, format);
+        // now we add any associated files to the alignframe
+        if (baseInfoMap.containsKey(fileName) && baseInfoMap.get(fileName)
+                .getAssociatedFilesMap() != null)
+        {
+          BaseInfo bi = baseInfoMap.get(fileName);
+          if (bi.getAssociatedFilesMap().containsKey(Arg.FEATURES))
           {
-            Platform.cacheFileData((File) file);
+            String featuresfile = bi.getAssociatedFilesMap()
+                    .get(Arg.FEATURES);
+            af.parseFeaturesFile(featuresfile,
+                    AppletFormatAdapter.checkProtocol(featuresfile));
           }
-          // new FileLoader().LoadFile(null, file, protocol, format);
-          AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(fileName,
-                  protocol, format);
-          // now we add any associated files to the alignframe
-          if (baseInfoMap.containsKey(fileName) && baseInfoMap.get(fileName)
-                  .getAssociatedFilesMap() != null)
+          if (bi.getAssociatedFilesMap().containsKey(Arg.ANNOTATIONS))
           {
-            BaseInfo bi = baseInfoMap.get(fileName);
-            if (bi.getAssociatedFilesMap().containsKey(Arg.FEATURES))
-            {
-              String featuresfile = bi.getAssociatedFilesMap()
-                      .get(Arg.FEATURES);
-              af.parseFeaturesFile(featuresfile,
-                      AppletFormatAdapter.checkProtocol(featuresfile));
-            }
-            if (bi.getAssociatedFilesMap().containsKey(Arg.ANNOTATIONS))
+            String annotationsfile = bi.getAssociatedFilesMap()
+                    .get(Arg.ANNOTATIONS);
+            af.loadJalviewDataFile(annotationsfile, null, null, null);
+          }
+          if (bi.getAssociatedFilesMap().containsKey(Arg.TREE))
+          {
+            String treefile = bi.getAssociatedFilesMap().get(Arg.TREE);
+            try
             {
-              String annotationsfile = bi.getAssociatedFilesMap()
-                      .get(Arg.ANNOTATIONS);
-              af.loadJalviewDataFile(annotationsfile, null, null, null);
-            }
-            if (bi.getAssociatedFilesMap().containsKey(Arg.TREE))
+              NewickFile nf = new NewickFile(treefile,
+                      AppletFormatAdapter.checkProtocol(treefile));
+              af.getViewport().setCurrentTree(
+                      af.showNewickTree(nf, treefile).getTree());
+            } catch (IOException e)
             {
-              String treefile = bi.getAssociatedFilesMap().get(Arg.TREE);
-              try
-              {
-                NewickFile nf = new NewickFile(treefile,
-                        AppletFormatAdapter.checkProtocol(treefile));
-                af.getViewport().setCurrentTree(
-                        af.showNewickTree(nf, treefile).getTree());
-              } catch (IOException e)
-              {
-                jalview.bin.Console.warn(
-                        "Couldn't add potential tree '" + treefile + "'");
-              }
-
+              jalview.bin.Console.warn(
+                      "Couldn't add potential tree '" + treefile + "'");
             }
 
           }
 
         }
-      } catch (Exception ex)
+
+      }
+    } catch (Exception ex)
+    {
+
+      jalview.bin.Console.warn(
+              "Unexpected exception whilst handling drop to Desktop.", ex);
+      failed.add(file);
+      failed_exceptions.add(ex);
+      return false;
+    }
+    return failed.size() == 0; // redundant for 2.11.4.0 implementation
+  }
+  
+  @Override
+  public void drop(DropTargetDropEvent evt)
+  {
+    boolean success = true;
+    // JAL-1552 - acceptDrop required before getTransferable call for
+    // Java's Transferable for native dnd
+    evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
+    Transferable t = evt.getTransferable();
+    List<Object> files = new ArrayList<>();
+    List<DataSourceType> protocols = new ArrayList<>();
+
+    try
+    {
+      Desktop.transferFromDropTarget(files, protocols, evt, t);
+    } catch (Exception e)
+    {
+      e.printStackTrace();
+      success = false;
+    }
+    try
+    {
+      if (files != null)
       {
-        jalview.bin.Console.warn("Unexpected exception whilst handling drop to Desktop.",ex);
-        success = false;
+        List<Object> failed = new ArrayList<Object>();
+        List<Exception> failed_exceptions = new ArrayList<Exception>();
+        if (!showExperimental())
+        {
+          success = loadDroppedFiles(files, protocols, failed,
+                  failed_exceptions);
+        }
+        else
+        {
+          success = processAndLoadDroppedFiles(files, protocols, failed,
+                  failed_exceptions);
+        }
       }
+    } catch (Throwable ex)
+    {
+      jalview.bin.Console.warn(
+              "Unexpected exception whilst handling drop to Desktop.", ex);
+      success = false;
     }
     evt.dropComplete(success); // need this to ensure input focus is properly
                                // transfered to any new windows created