Merge branch 'features/r2_11_2_alphafold/JAL-629' into features/JAL-3858_PAEsInProjects features/JAL-3858_PAEsInProjects
authorJames Procter <j.procter@dundee.ac.uk>
Fri, 24 Feb 2023 15:13:37 +0000 (15:13 +0000)
committerJames Procter <j.procter@dundee.ac.uk>
Fri, 24 Feb 2023 15:13:37 +0000 (15:13 +0000)
 Conflicts:
src/jalview/bin/Jalview.java

1  2 
src/jalview/bin/Jalview.java
src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java

@@@ -40,11 -40,14 +40,14 @@@ import java.security.Policy
  import java.util.HashMap;
  import java.util.Locale;
  import java.util.Map;
+ import java.util.Properties;
  import java.util.Vector;
  import java.util.logging.ConsoleHandler;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  
+ import javax.swing.JDialog;
+ import javax.swing.JFrame;
  import javax.swing.JOptionPane;
  import javax.swing.SwingUtilities;
  import javax.swing.UIManager;
@@@ -52,6 -55,7 +55,7 @@@ import javax.swing.UIManager.LookAndFee
  import javax.swing.UnsupportedLookAndFeelException;
  
  import com.formdev.flatlaf.FlatLightLaf;
+ import com.formdev.flatlaf.themes.FlatMacLightLaf;
  import com.formdev.flatlaf.util.SystemInfo;
  import com.threerings.getdown.util.LaunchUtil;
  
@@@ -275,30 -279,11 +279,11 @@@ public class Jalvie
      if (!Platform.isJS())
      {
        System.setSecurityManager(null);
-       Runtime.getRuntime().addShutdownHook(new Thread()
-       {
-         public void run()
-         {
-           Console.debug("Running shutdown hook");
-           if (QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT)
-           {
-             // Got to here by a SIGTERM signal.
-             // Note we will not actually cancel the quit from here -- it's too
-             // late -- but we can wait for saving files.
-             Console.debug("Checking for saving files");
-             QuitHandler.getQuitResponse(false);
-           }
-           else
-           {
-             Console.debug("Nothing more to do");
-           }
-           Console.debug("Exiting, bye!");
-           // shutdownHook cannot be cancelled, JVM will now halt
-         }
-       });
      }
  
+     // get args needed before proper ArgParser
+     Map<String, String> bootstrapArgs = ArgParser.bootstrapArgs(args);
      System.out
              .println("Java version: " + System.getProperty("java.version"));
      System.out.println("Java Home: " + System.getProperty("java.home"));
        System.out.println("Launcher version: " + val);
      }
  
+     if (Platform.isLinux() && LaunchUtils.getJavaVersion() < 11)
+     {
+       System.setProperty("flatlaf.uiScale", "1");
+     }
+     // get bootstrap properties (mainly for the logger level)
+     Properties bootstrapProperties = Cache
+             .bootstrapProperties(bootstrapArgs.get("props"));
      // report Jalview version
      Cache.loadBuildProperties(true);
  
  
      try
      {
-       Console.initLogger();
+       String logLevel = bootstrapArgs.containsKey("debug") ? "DEBUG" : null;
+       if (logLevel == null && !(bootstrapProperties == null))
+       {
+         logLevel = bootstrapProperties.getProperty(Cache.JALVIEWLOGLEVEL);
+       }
+       Console.initLogger(logLevel);
      } catch (NoClassDefFoundError error)
      {
        error.printStackTrace();
        System.exit(0);
      }
  
-     String usrPropsFile = aparser.getValue("props");
-     Cache.loadProperties(usrPropsFile); // must do this
-                                         // before
+     // register SIGTERM listener
+     Runtime.getRuntime().addShutdownHook(new Thread()
+     {
+       public void run()
+       {
+         Console.debug("Running shutdown hook");
+         if (QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT)
+         {
+           // Got to here by a SIGTERM signal.
+           // Note we will not actually cancel the quit from here -- it's too
+           // late -- but we can wait for saving files.
+           Console.debug("Checking for saving files");
+           QuitHandler.getQuitResponse(false);
+         }
+         else
+         {
+           Console.debug("Nothing more to do");
+         }
+         Console.debug("Exiting, bye!");
+         // shutdownHook cannot be cancelled, JVM will now halt
+       }
+     });
+     String usrPropsFile = bootstrapArgs.containsKey("props")
+             ? bootstrapArgs.get("props")
+             : aparser.getValue("props");
+     Cache.loadProperties(usrPropsFile);
      if (usrPropsFile != null)
      {
        System.out.println(
                "CMD [-props " + usrPropsFile + "] executed successfully!");
      }
  
-     // set log level from cache properties
-     Console.setLogLevel(Cache.getDefault(Cache.JALVIEWLOGLEVEL, "INFO"));
      // new ArgParser
-     ArgParser argparser = new ArgParser(args); // do this after
-                                                // Console.initLogger, but TODO
-                                                // want --props before then
-                                                // CATCH22
+     ArgParser argparser = new ArgParser(args);
  
      if (argparser.isSet(Arg.HEADLESS))
        headless = argparser.getBool(Arg.HEADLESS);
      System.setProperty("http.agent",
              "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown"));
  
+     try
+     {
+       Console.initLogger();
+     } catch (
+     NoClassDefFoundError error)
+     {
+       error.printStackTrace();
+       System.out.println("\nEssential logging libraries not found."
+               + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview");
+       System.exit(0);
+     }
 -
      desktop = null;
  
      setLookAndFeel();
  
        startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
                format);
+       // don't ask to save when quitting if only the startup file has been
+       // opened
+       Console.debug("Resetting up-to-date flag for startup file");
+       startUpAlframe.getViewport().setSavedUpToDate(true);
        // extract groovy arguments before anything else.
      }
  
          Console.error("Could not set requested laf=" + laf);
        }
        break;
-     case "quaqua":
-       lafSet = setQuaquaLookAndFeel();
-       if (!lafSet)
-       {
-         Console.error("Could not set requested laf=" + laf);
-       }
-       break;
-     case "vaqua":
-       lafSet = setVaquaLookAndFeel();
-       if (!lafSet)
-       {
-         Console.error("Could not set requested laf=" + laf);
-       }
-       break;
      case "mac":
        lafSet = setMacLookAndFeel();
        if (!lafSet)
    private static boolean setFlatLookAndFeel()
    {
      boolean set = false;
-     if (Platform.isMac()) {
+     if (SystemInfo.isMacOS)
+     {
        try
        {
-         UIManager.setLookAndFeel("com.formdev.flatlaf.themes.FlatMacLightLaf");
+         UIManager.setLookAndFeel(
+                 "com.formdev.flatlaf.themes.FlatMacLightLaf");
          set = true;
+         Console.debug("Using FlatMacLightLaf");
        } catch (ClassNotFoundException | InstantiationException
                | IllegalAccessException | UnsupportedLookAndFeelException e)
        {
-         Console.debug("Exception loading FlatMacLightLaf", e);
+         Console.debug("Exception loading FlatLightLaf", e);
+       }
+       System.setProperty("apple.laf.useScreenMenuBar", "true");
+       System.setProperty("apple.awt.application.name",
+               ChannelProperties.getProperty("app_name"));
+       System.setProperty("apple.awt.application.appearance", "system");
+       if (SystemInfo.isMacFullWindowContentSupported
+               && Desktop.desktop != null)
+       {
+         Console.debug("Setting transparent title bar");
+         Desktop.desktop.getRootPane()
+                 .putClientProperty("apple.awt.fullWindowContent", true);
+         Desktop.desktop.getRootPane()
+                 .putClientProperty("apple.awt.transparentTitleBar", true);
+         Desktop.desktop.getRootPane()
+                 .putClientProperty("apple.awt.fullscreenable", true);
        }
+       SwingUtilities.invokeLater(() -> {
+         FlatMacLightLaf.setup();
+       });
+       Console.debug("Using FlatMacLightLaf");
+       set = true;
      }
-     if (!set) {
+     if (!set)
+     {
        try
        {
          UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
          set = true;
+         Console.debug("Using FlatLightLaf");
        } catch (ClassNotFoundException | InstantiationException
                | IllegalAccessException | UnsupportedLookAndFeelException e)
        {
          Console.debug("Exception loading FlatLightLaf", e);
        }
+       // Windows specific properties here
+       SwingUtilities.invokeLater(() -> {
+         FlatLightLaf.setup();
+       });
+       Console.debug("Using FlatLightLaf");
+       set = true;
      }
-     if (set)
+     else if (SystemInfo.isLinux)
      {
-       if (Platform.isMac())
+       try
        {
-         System.setProperty("apple.laf.useScreenMenuBar", "true");
-         System.setProperty("apple.awt.application.name",
-                 ChannelProperties.getProperty("app_name"));
-         System.setProperty("apple.awt.application.appearance", "system");
-         if (SystemInfo.isMacFullWindowContentSupported
-                 && Desktop.desktop != null)
-         {
-           Desktop.desktop.getRootPane()
-                   .putClientProperty("apple.awt.fullWindowContent", true);
-           Desktop.desktop.getRootPane()
-                   .putClientProperty("apple.awt.transparentTitleBar", true);
-         }
+         UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
+         set = true;
+         Console.debug("Using FlatLightLaf");
+       } catch (ClassNotFoundException | InstantiationException
+               | IllegalAccessException | UnsupportedLookAndFeelException e)
+       {
+         Console.debug("Exception loading FlatLightLaf", e);
+       }
+       // enable custom window decorations
+       JFrame.setDefaultLookAndFeelDecorated(true);
+       JDialog.setDefaultLookAndFeelDecorated(true);
+       SwingUtilities.invokeLater(() -> {
+         FlatLightLaf.setup();
+       });
+       Console.debug("Using FlatLightLaf");
+       set = true;
+     }
  
-         SwingUtilities.invokeLater(() -> {
-           FlatLightLaf.setup();
-         });
+     if (!set)
+     {
+       try
+       {
+         UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
+         set = true;
+         Console.debug("Using FlatLightLaf");
+       } catch (ClassNotFoundException | InstantiationException
+               | IllegalAccessException | UnsupportedLookAndFeelException e)
+       {
+         Console.debug("Exception loading FlatLightLaf", e);
        }
+     }
  
+     if (set)
+     {
+       UIManager.put("TabbedPane.tabType", "card");
        UIManager.put("TabbedPane.showTabSeparators", true);
+       UIManager.put("TabbedPane.showContentSeparator", true);
        UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
        UIManager.put("TabbedPane.tabsOverlapBorder", true);
-       // UIManager.put("TabbedPane.hasFullBorder", true);
+       UIManager.put("TabbedPane.hasFullBorder", true);
        UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
        UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
        UIManager.put("TabbedPane.smoothScrolling", true);
      return set;
    }
  
-   private static boolean setQuaquaLookAndFeel()
-   {
-     return setSpecificLookAndFeel("quaqua",
-             ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel().getClass()
-                     .getName(),
-             false);
-   }
-   private static boolean setVaquaLookAndFeel()
-   {
-     return setSpecificLookAndFeel("vaqua",
-             "org.violetlib.aqua.AquaLookAndFeel", false);
-   }
    private static boolean setMacLookAndFeel()
    {
      boolean set = false;
@@@ -29,21 -29,17 +29,21 @@@ public class PAEContactMatrix implement
  
    float maxscore;
  
 -  @SuppressWarnings("unchecked")
 -  public PAEContactMatrix(SequenceI _refSeq, Map<String, Object> pae_obj)
 +  private void setRefSeq(SequenceI _refSeq)
    {
      refSeq = _refSeq;
      while (refSeq.getDatasetSequence() != null)
      {
        refSeq = refSeq.getDatasetSequence();
      }
 -    // convert the lists to primitive arrays and store
      length = _refSeq.getEnd() - _refSeq.getStart() + 1;
 -
 +  }
 +  @SuppressWarnings("unchecked")
 +  public PAEContactMatrix(SequenceI _refSeq, Map<String, Object> pae_obj)
 +  {
 +    setRefSeq(_refSeq);
 +    // convert the lists to primitive arrays and store
 +    
      if (!MapUtils.containsAKey(pae_obj, "predicted_aligned_error", "pae"))
      {
        parse_version_1_pAE(pae_obj);
        parse_version_2_pAE(pae_obj);
      }
    }
 +  /**
 +   * construct a sequence associated PAE matrix directly from a float array
 +   * @param _refSeq
 +   * @param matrix
 +   */
 +  public PAEContactMatrix(SequenceI _refSeq, float[][] matrix)
 +  {
 +    setRefSeq(_refSeq);
 +    maxcol=0;
 +    for (float[] row:matrix)
 +    {
 +      if (row.length>maxcol)
 +      {
 +        maxcol=row.length;
 +      }
 +      maxscore=row[0];
 +      for (float f:row)
 +      {
 +        if (maxscore<f) {
 +          maxscore=f;
 +        }
 +      }
 +    }
 +    maxrow=matrix.length;
 +    elements = matrix;
 +    
 +  }
  
    /**
     * parse a sane JSON representation of the pAE
     * 
     * @param pae_obj
     */
 +  @SuppressWarnings("unchecked")
    private void parse_version_2_pAE(Map<String, Object> pae_obj)
    {
      elements = new float[length][length];
        Iterator<Long> scores = scoreRows.next().iterator();
        while (scores.hasNext())
        {
-         elements[row][col++] = scores.next();
+         Object d = scores.next();
+         if (d instanceof Double)
+           elements[row][col++] = ((Double) d).longValue();
+         else
+           elements[row][col++] = (float) d;
        }
        row++;
        col = 0;
     * 
     * @param pae_obj
     */
 +  @SuppressWarnings("unchecked")
    private void parse_version_1_pAE(Map<String, Object> pae_obj)
    {
      // assume indices are with respect to range defined by _refSeq on the
        @Override
        public int getContactHeight()
        {
 -        return maxcol - 1;
 +        return maxcol-1;
        }
  
        @Override
          {
            return -1;
          }
 -        // TODO Auto-generated method stub
          return elements[_column][column];
        }
      });
    {
      return "pAE Matrix";
    }
 +
 +  public static final String PAEMATRIX="PAE_MATRIX";
 +  @Override
 +  public String getType()
 +  {
 +    return PAEMATRIX;
 +  }
 +  @Override
 +  public int getWidth()
 +  {
 +    return length;
 +  }
 +  @Override
 +  public int getHeight()
 +  {
 +    return length;
 +  }
  }