Merge branch 'improvement/JAL-4206_improve_JalviewFileChooser_for_flatlaf' into merge...
authorBen Soares <b.soares@dundee.ac.uk>
Fri, 18 Aug 2023 14:36:13 +0000 (15:36 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Fri, 18 Aug 2023 14:36:13 +0000 (15:36 +0100)
1  2 
resources/lang/Messages.properties
resources/lang/Messages_es.properties
src/jalview/gui/AlignFrame.java
src/jalview/gui/Desktop.java
src/jalview/gui/PopupMenu.java
src/jalview/io/FileLoader.java
src/jalview/io/JalviewFileChooser.java
src/jalview/jbgui/GAlignFrame.java

@@@ -363,7 -363,6 +363,7 @@@ label.sequences_from = Sequences from {
  label.successfully_loaded_file  = Successfully loaded file {0}
  label.successfully_loaded_matrix  = Successfully loaded score matrix {0}
  label.successfully_saved_to_file_in_format = Successfully saved to file: {0} in {1} format.
 +label.successfully_printed_to_stdout_in_format = Successfully printed to STDOUT in {0} format.
  label.copied_sequences_to_clipboard = Copied {0} sequences to clipboard.
  label.check_file_matches_sequence_ids_alignment = Check that the file matches sequence IDs in the alignment.
  label.problem_reading_tcoffee_score_file = Problem reading T-COFFEE score file
@@@ -1453,8 -1452,8 +1453,8 @@@ label.choose_tempfac_type = Choose Temp
  label.interpret_tempfac_as = Interpret Temperature Factor as
  label.add_pae_matrix_file = Add PAE matrix file
  label.nothing_selected = Nothing selected
 -prompt.google_analytics_title = Jalview Usage Statistics
 -prompt.google_analytics = Do you want to help make Jalview better by enabling the collection of usage statistics with Google Analytics?\nYou can enable or disable usage tracking in the preferences.
 +prompt.analytics_title = Jalview Usage Statistics
 +prompt.analytics = Do you want to help make Jalview better by enabling the collection of usage statistics with Plausible analytics?\nYou can enable or disable usage tracking in the preferences.
  label.working_ellipsis = Working ... 
  action.show_groups_on_matrix = Show groups on matrix
  action.show_groups_on_matrix_tooltip = When enabled, clusters defined on the matrix's associated tree or below the assigned threshold are shown as different colours on the matrix annotation row
@@@ -1463,4 -1462,4 +1463,4 @@@ action.show_tree_for_matrix_tooltip = O
  action.cluster_matrix = Cluster matrix
  action.clustering_matrix_for = Calculating tree for matrix {0} and clustering at {1}
  action.cluster_matrix_tooltip = Computes an average distance tree for the matrix and displays it
+ label.all_known_alignment_files = All known alignment files
@@@ -326,7 -326,6 +326,7 @@@ label.sequences_from = Secuencias de {0
  label.successfully_loaded_file  = Fichero cargado exitosamente {0}
  label.successfully_loaded_matrix  = Matriz cargada exitosamente {0}
  label.successfully_saved_to_file_in_format = Guardado exitosamente en el fichero: {0} en formato {1}.
 +label.successfully_printed_to_stdout_in_format = Impresso exitosamente al STDOUT en formato {0}.
  label.copied_sequences_to_clipboard = Copiadas {0} secuencias en el portapapeles.
  label.check_file_matches_sequence_ids_alignment = Comprobar que el fichero coincide con el ID de la secuencia en el alineamiento.
  label.problem_reading_tcoffee_score_file = Problema de lectura del fichero de puntuaciones T-COFFEE
@@@ -1435,5 -1434,6 +1435,6 @@@ label.tftype_default = Defaul
  label.tftype_plddt = pLDDT
  label.add_pae_matrix_file = Añadir un fichero de matriz PAE
  label.nothing_selected = Nada seleccionado
 -prompt.google_analytics_title = Jalview Estadísticas de Uso
 -prompt.google_analytics = ¿Quiere ayudar a mejorar Jalview habilitando la recopilación de estadísticas de uso con Google Analytics?\nPuede habilitar o deshabilitar el seguimiento de uso en las preferencias.
 +prompt.analytics_title = Jalview Estadísticas de Uso
 +prompt.analytics = ¿Quiere ayudar a mejorar Jalview habilitando la recopilación de estadísticas de uso con análisis Plausible?\nPuede habilitar o deshabilitar el seguimiento de uso en las preferencias.
+ label.all_known_alignment_files = Todos los archivos de alineación conocidos
@@@ -49,7 -49,6 +49,7 @@@ import java.beans.PropertyChangeEvent
  import java.io.File;
  import java.io.FileWriter;
  import java.io.IOException;
 +import java.io.OutputStreamWriter;
  import java.io.PrintWriter;
  import java.net.URL;
  import java.util.ArrayList;
@@@ -624,12 -623,12 +624,12 @@@ public class AlignFrame extends GAlignF
          // if (viewport.cursorMode)
          // {
          // alignPanel.seqPanel.insertNucAtCursor(false,"A");
 -        // //System.out.println("A");
 +        // //jalview.bin.Console.outPrintln("A");
          // }
          // break;
          /*
           * case KeyEvent.VK_CLOSE_BRACKET: if (viewport.cursorMode) {
 -         * System.out.println("closing bracket"); } break;
 +         * jalview.bin.Console.outPrintln("closing bracket"); } break;
           */
          case KeyEvent.VK_DELETE:
          case KeyEvent.VK_BACK_SPACE:
                @Override
                public void propertyChange(PropertyChangeEvent evt)
                {
 -                // // System.out.println("Discoverer property change.");
 +                // // jalview.bin.Console.outPrintln("Discoverer property
 +                // change.");
                  // if (evt.getPropertyName().equals("services"))
                  {
                    SwingUtilities.invokeLater(new Runnable()
                      @Override
                      public void run()
                      {
 -                      System.err.println(
 +                      jalview.bin.Console.errPrintln(
                                "Rebuild WS Menu for service change");
                        BuildWebServiceMenu();
                      }
        public void internalFrameClosed(
                javax.swing.event.InternalFrameEvent evt)
        {
 -        // System.out.println("deregistering discoverer listener");
 +        // jalview.bin.Console.outPrintln("deregistering discoverer listener");
          Desktop.instance.removeJalviewPropertyChangeListener("services",
                  thisListener);
          closeMenuItem_actionPerformed(true);
     */
    public void saveAlignment(String file, FileFormatI format)
    {
 +    saveAlignment(file, format, false);
 +  }
 +
 +  public void saveAlignment(String file, FileFormatI format, boolean stdout)
 +  {
      lastSaveSuccessful = true;
 -    lastFilenameSaved = file;
 +    if (!stdout)
 +    {
 +      lastFilenameSaved = file;
 +    }
      lastFormatSaved = format;
  
      if (FileFormat.Jalview.equals(format))
          shortName = shortName
                  .substring(shortName.lastIndexOf(File.separatorChar) + 1);
        }
 +      // TODO deal with stdout=true
        lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
                shortName);
  
        else
        {
          // create backupfiles object and get new temp filename destination
 -        boolean doBackup = BackupFiles.getEnabled();
 +        boolean doBackup = BackupFiles.getEnabled() && !stdout;
          BackupFiles backupfiles = null;
          if (doBackup)
          {
            String tempFilePath = doBackup ? backupfiles.getTempFilePath()
                    : file;
            Console.trace("ALIGNFRAME setting PrintWriter");
 -          PrintWriter out = new PrintWriter(new FileWriter(tempFilePath));
 +          PrintWriter out = stdout
 +                  ? new PrintWriter(new OutputStreamWriter(System.out))
 +                  : new PrintWriter(new FileWriter(tempFilePath));
  
            if (backupfiles != null)
            {
            }
  
            out.print(output);
 -          Console.trace("ALIGNFRAME about to close file");
 -          out.close();
 -          Console.trace("ALIGNFRAME closed file");
 -          AlignFrame.this.setTitle(file);
 -          statusBar.setText(MessageManager.formatMessage(
 -                  "label.successfully_saved_to_file_in_format", new Object[]
 -                  { fileName, format.getName() }));
 +          out.flush();
 +          if (!stdout)
 +          {
 +            Console.trace("ALIGNFRAME about to close file");
 +            out.close();
 +            Console.trace("ALIGNFRAME closed file");
 +          }
 +          AlignFrame.this.setTitle(stdout ? "STDOUT" : file);
 +          if (stdout)
 +          {
 +            statusBar.setText(MessageManager.formatMessage(
 +                    "label.successfully_printed_to_stdout_in_format",
 +                    new Object[]
 +                    { format.getName() }));
 +          }
 +          else
 +          {
 +            statusBar.setText(MessageManager.formatMessage(
 +                    "label.successfully_saved_to_file_in_format",
 +                    new Object[]
 +                    { fileName, format.getName() }));
 +          }
            lastSaveSuccessful = true;
          } catch (IOException e)
          {
      } catch (Exception ex)
      {
        ex.printStackTrace();
 -      System.out.println("Exception whilst pasting: " + ex);
 +      jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
        // could be anything being pasted in here
      }
  
      } catch (Exception ex)
      {
        ex.printStackTrace();
 -      System.out.println("Exception whilst pasting: " + ex);
 +      jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
        // could be anything being pasted in here
      } catch (OutOfMemoryError oom)
      {
    @Override
    public void wrapMenuItem_actionPerformed(ActionEvent e)
    {
 -    scaleAbove.setVisible(wrapMenuItem.isSelected());
 -    scaleLeft.setVisible(wrapMenuItem.isSelected());
 -    scaleRight.setVisible(wrapMenuItem.isSelected());
 -    viewport.setWrapAlignment(wrapMenuItem.isSelected());
 +    setWrapFormat(wrapMenuItem.isSelected(), false);
 +  }
 +
 +  public void setWrapFormat(boolean b, boolean setMenuItem)
 +  {
 +    scaleAbove.setVisible(b);
 +    scaleLeft.setVisible(b);
 +    scaleRight.setVisible(b);
 +    viewport.setWrapAlignment(b);
      alignPanel.updateLayout();
 +    if (setMenuItem)
 +    {
 +      wrapMenuItem.setSelected(b);
 +    }
    }
  
    @Override
      }
  
      JInternalFrame frame = new JInternalFrame();
+     frame.setFrameIcon(null);
      frame.getContentPane().add(new JScrollPane(pane));
  
      Desktop.addInternalFrame(frame, MessageManager
        return alignPanel.overviewPanel;
      }
      JInternalFrame frame = new JInternalFrame();
+     frame.setFrameIcon(null);
      final OverviewPanel overview = new OverviewPanel(alignPanel, frame,
              showHidden);
      frame.setContentPane(overview);
      Desktop.addInternalFrame(frame, "", true, frame.getWidth(),
              frame.getHeight(), true, true);
-     frame.setFrameIcon(null);
      frame.pack();
      frame.setLayer(JLayeredPane.PALETTE_LAYER);
      final AlignmentPanel thePanel = this.alignPanel;
      else
      {
        JInternalFrame frame = new JInternalFrame();
+       frame.setFrameIcon(null);
        frame.setContentPane(new PairwiseAlignPanel(viewport));
        Desktop.addInternalFrame(frame,
                MessageManager.getString("action.pairwise_alignment"), 600,
      {
        NewickFile fin = new NewickFile(
                new FileParse(cm.getNewick(), DataSourceType.PASTE));
 -      String title = cm.getAnnotLabel() + " " + cm.getTreeMethod() + " tree"
 -              + aa.sequenceRef != null
 +      String title = aa.label + " " + cm.getTreeMethod() + " tree"
 +              + (aa.sequenceRef != null
                        ? (" for " + aa.sequenceRef.getDisplayId(false))
 -                      : "";
 +                      : "");
  
        showColumnWiseTree(fin, aa, title, w, h, x, y);
      } catch (Throwable xx)
        {
          return null;
        }
 -      TreePanel tp = new TreePanel(alignPanel, nf, aa, title);
 +      TreePanel tp = new TreePanel(alignPanel, nf, aa, treeTitle);
  
        tp.setSize(w, h);
  
          tp.setLocation(x, y);
        }
  
 -      Desktop.addInternalFrame(tp, title, w, h);
 +      Desktop.addInternalFrame(tp, treeTitle, w, h);
        return tp;
      } catch (Throwable xx)
      {
      {
        try
        {
 -        System.err.println("Waiting for building menu to finish.");
 +        jalview.bin.Console
 +                .errPrintln("Waiting for building menu to finish.");
          Thread.sleep(10);
        } catch (Exception e)
        {
          final List<JMenuItem> legacyItems = new ArrayList<>();
          try
          {
 -          // System.err.println("Building ws menu again "
 +          // jalview.bin.Console.errPrintln("Building ws menu again "
            // + Thread.currentThread());
            // TODO: add support for context dependent disabling of services based
            // on
                                      Desktop.instance);
                      if (pe != null)
                      {
 -                      System.err.println("Associated file : "
 +                      jalview.bin.Console.errPrintln("Associated file : "
                                + (fm[0].toString()) + " with "
                                + toassoc.getDisplayId(true));
                        assocfiles++;
                viewport.getAlignment()));
      } catch (Exception ex)
      {
 -      System.err.println(ex.getMessage());
 +      jalview.bin.Console.errPrintln(ex.getMessage());
        return;
      }
    }
          console.runScript();
        } catch (Exception ex)
        {
 -        System.err.println((ex.toString()));
 +        jalview.bin.Console.errPrintln((ex.toString()));
          JvOptionPane.showInternalMessageDialog(Desktop.desktop,
                  MessageManager.getString("label.couldnt_run_groovy_script"),
                  MessageManager.getString("label.groovy_support_failed"),
      }
      else
      {
 -      System.err.println("Can't run Groovy script as console not found");
 +      jalview.bin.Console
 +              .errPrintln("Can't run Groovy script as console not found");
      }
    }
  
@@@ -439,7 -439,7 +439,7 @@@ public class Desktop extends jalview.jb
           * Send this message to stderr as the warning that follows (due to
           * reflection) also goes to stderr.
           */
 -        System.err.println(
 +        jalview.bin.Console.errPrintln(
                  "Linux platform only! You may have the following warning next: \"WARNING: An illegal reflective access operation has occurred\"\nThis is expected and cannot be avoided, sorry about that.");
        }
        final String awtAppClassName = "awtAppClassName";
        }
  
        // Thread off a new instance of the file chooser - this reduces the time
-       // it
-       // takes to open it later on.
+       // it takes to open it later on.
        new Thread(new Runnable()
        {
          @Override
          public void run()
          {
            jalview.bin.Console.debug("Filechooser init thread started.");
-           String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
+           String fileFormat = FileLoader.getUseDefaultFileFormat()
+                   ? Cache.getProperty("DEFAULT_FILE_FORMAT")
+                   : null;
            JalviewFileChooser.forRead(Cache.getProperty("LAST_DIRECTORY"),
                    fileFormat);
            jalview.bin.Console.debug("Filechooser init thread finished.");
          }
        } catch (Exception ex)
        {
 -        System.out.println(
 +        jalview.bin.Console.outPrintln(
                  "Unable to paste alignment from system clipboard:\n" + ex);
        }
      }
  
      setKeyBindings(frame);
  
 -    desktop.add(frame);
 +    // Since the latest FlatLaf patch, we occasionally have problems showing structureViewer frames...
 +    int tries=3;
 +    boolean shown=false;
 +    Exception last=null;
 +    do
 +    {
 +      try
 +      {
 +        desktop.add(frame);
 +        shown=true;
 +      } catch (IllegalArgumentException iaex)
 +      {
 +        last=iaex;
 +        tries--;
 +        jalview.bin.Console.info(
 +                "Squashed IllegalArgument Exception (" + tries + " left) for "+frame.getTitle(),
 +                iaex);
 +        try
 +        {
 +          Thread.sleep(5);
 +        } catch (InterruptedException iex)
 +        {
 +        }
 +        ;
 +      }
 +    } while (!shown && tries > 0);
 +    if (!shown)
 +    {
 +      jalview.bin.Console.error("Serious Problem whilst showing window "+frame.getTitle(),last);
 +    }
  
      windowMenu.add(menuItem);
  
    @Override
    public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
    {
-     String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
+     String fileFormat = FileLoader.getUseDefaultFileFormat()
+             ? Cache.getProperty("DEFAULT_FILE_FORMAT")
+             : null;
      JalviewFileChooser chooser = JalviewFileChooser.forRead(
              Cache.getProperty("LAST_DIRECTORY"), fileFormat,
              BackupFiles.getEnabled());
        }
      } catch (Exception ex)
      {
 -      System.err.println("Error opening help: " + ex.getMessage());
 +      jalview.bin.Console.errPrintln("Error opening help: " + ex.getMessage());
      }
    }
  
      boolean autoSave = projectFile != null && !saveAs
              && BackupFiles.getEnabled();
  
 -    // System.out.println("autoSave="+autoSave+", projectFile='"+projectFile+"',
 +    // jalview.bin.Console.outPrintln("autoSave="+autoSave+", projectFile='"+projectFile+"',
      // saveAs="+saveAs+", Backups
      // "+(BackupFiles.getEnabled()?"enabled":"disabled"));
  
          {
            if (Platform.isAMacAndNotJS())
            {
 -            System.err.println(
 +            jalview.bin.Console.errPrintln(
                      "Please ignore plist error - occurs due to problem with java 8 on OSX");
            }
          }
      {
        Desktop.instance.closeAll_actionPerformed(null);
        Desktop.instance.setVisible(false);
 -      Desktop.instance.dispose();
 +      Desktop us = Desktop.instance;
        Desktop.instance = null;
 +      // call dispose in a separate thread - try to avoid indirect deadlocks
 +      new Thread(new Runnable() {
 +        @Override
 +        public void run()
 +        {
 +          ExecutorService dex = us.dialogExecutor;
 +          if (dex!=null) {
 +            dex.shutdownNow();
 +            us.dialogExecutor=null;
 +            us.block.drainPermits();
 +          }
 +          us.dispose();
 +        }
 +      }).start();
      }
    }
  
@@@ -906,6 -906,7 +906,7 @@@ public class PopupMenu extends JPopupMe
      if (Platform.isJS())
      {
        details = new JInternalFrame();
+       details.setFrameIcon(null);
        JPanel panel = new JPanel(new BorderLayout());
        panel.setOpaque(true);
        panel.setBackground(Color.white);
    protected void addReferenceAnnotations_actionPerformed(
            Map<SequenceI, List<AlignmentAnnotation>> candidates)
    {
 -    final SequenceGroup selectionGroup = this.ap.av.getSelectionGroup();
      final AlignmentI alignment = this.ap.getAlignment();
      AlignmentUtils.addReferenceAnnotations(candidates, alignment,
 -            selectionGroup);
 +            null);
      refresh();
    }
  
        pane.setBackground(Color.WHITE);
        pane.add(textLabel, BorderLayout.NORTH);
        frame = new JInternalFrame();
+       frame.setFrameIcon(null);
        frame.getContentPane().add(new JScrollPane(pane));
      }
      else
  
      String[] omitHidden = null;
  
 -    System.out.println("PROMPT USER HERE"); // TODO: decide if a prompt happens
 +    jalview.bin.Console.outPrintln("PROMPT USER HERE"); // TODO: decide if a prompt happens
      // or we simply trust the user wants
      // wysiwig behaviour
  
@@@ -74,6 -74,8 +74,8 @@@ public class FileLoader implements Runn
  
    private File selectedFile;
  
+   private static boolean useDefaultFileFormat = false;
    /**
     * default constructor always raised errors in GUI dialog boxes
     */
        if (format == null)
        {
          Desktop.instance.stopLoading();
 -        System.err.println("The input file \"" + file
 +        jalview.bin.Console.errPrintln("The input file \"" + file
                  + "\" has null or unidentifiable data content!");
          if (!Jalview.isHeadlessMode())
          {
          if (source != null)
          {
            // Tell the user (developer?) that this is going to cause a problem
 -          System.err.println(
 +          jalview.bin.Console.errPrintln(
                    "IMPLEMENTATION ERROR: Cannot read consecutive Jalview XML projects from a stream.");
            // We read the data anyway - it might make sense.
          }
            }
            else
            {
 -            System.err.println(errorMessage);
 +            jalview.bin.Console.errPrintln(errorMessage);
            }
          }
        }
  
      } catch (Exception er)
      {
 -      System.err.println("Exception whilst opening file '" + file);
 +      jalview.bin.Console.errPrintln("Exception whilst opening file '" + file);
        er.printStackTrace();
        if (raiseGUI)
        {
            }
          });
        }
 -      System.err.println("Out of memory loading file " + file + "!!");
 +      jalview.bin.Console.errPrintln("Out of memory loading file " + file + "!!");
  
      }
      loadtime += System.currentTimeMillis();
        {
          AlignmentI al = alignFrame.getViewport().getAlignment();
  
 -        System.out.println("Loaded '" + title + "' in "
 +        jalview.bin.Console.outPrintln("Loaded '" + title + "' in "
                  + (loadtime / 1000.0) + "s, took an additional "
                  + (1.0 * memused / (1024.0 * 1024.0)) + " MB ("
                  + al.getHeight() + " seqs by " + al.getWidth() + " cols)");
        {
          // report that we didn't load anything probably due to an out of memory
          // error
 -        System.out.println("Failed to load '" + title + "' in "
 +        jalview.bin.Console.outPrintln("Failed to load '" + title + "' in "
                  + (loadtime / 1000.0) + "s, took an additional "
                  + (1.0 * memused / (1024.0 * 1024.0))
                  + " MB (alignment is null)");
      }
  
      this.setShouldBeSaved();
+     // after first file loaded we revert to assuming a default file format
+     useDefaultFileFormat = true;
    }
  
    /**
              QuitHandler.Message.UNSAVED_ALIGNMENTS);
    }
  
+   public static boolean getUseDefaultFileFormat()
+   {
+     return useDefaultFileFormat;
+   }
  }
@@@ -40,15 -40,19 +40,19 @@@ import java.util.StringTokenizer
  import java.util.Vector;
  
  import javax.swing.BoxLayout;
  import javax.swing.JCheckBox;
  import javax.swing.JDialog;
  import javax.swing.JFileChooser;
+ import javax.swing.JLabel;
  import javax.swing.JList;
  import javax.swing.JOptionPane;
  import javax.swing.JPanel;
  import javax.swing.JScrollPane;
+ import javax.swing.ListCellRenderer;
  import javax.swing.SpringLayout;
+ import javax.swing.SwingConstants;
+ import javax.swing.SwingUtilities;
+ import javax.swing.border.TitledBorder;
  import javax.swing.filechooser.FileFilter;
  import javax.swing.plaf.basic.BasicFileChooserUI;
  
@@@ -193,7 -197,7 +197,7 @@@ public class JalviewFileChooser extend
      }
      else
      {
 -      System.err.println("JalviewFileChooser arguments mismatch: "
 +      jalview.bin.Console.errPrintln("JalviewFileChooser arguments mismatch: "
                + extensions + ", " + descs);
      }
    }
      // file filters to fix bug on Mac OSX
      setAcceptAllFileFilterUsed(acceptAny);
  
+     // add a "All known alignment files" option
+     List<String> allExtensions = new ArrayList<>();
+     for (String[] format : formats)
+     {
+       String[] extensions = format[0].split(",");
+       for (String ext : extensions)
+       {
+         if (!allExtensions.contains(ext))
+         {
+           allExtensions.add(ext);
+         }
+       }
+     }
+     allExtensions.sort(null);
+     JalviewFileFilter alljvf = new JalviewFileFilter(
+             allExtensions.toArray(new String[] {}),
+             MessageManager.getString("label.all_known_alignment_files"));
+     alljvf.setExtensionListInDescription(false);
+     addChoosableFileFilter(alljvf);
+     if (selected == null)
+     {
+       chosen = alljvf;
+     }
      for (String[] format : formats)
      {
        JalviewFileFilter jvf = new JalviewFileFilter(format[0], format[1]);
          return FileFormats.getInstance().forName(format);
        } catch (IllegalArgumentException e)
        {
 -        System.err.println("Unexpected format: " + format);
 +        jalview.bin.Console.errPrintln("Unexpected format: " + format);
        }
      }
      return null;
          }
        } catch (Throwable x)
        {
 -        System.err.println(
 +        jalview.bin.Console.errPrintln(
                  "Unexpected exception when trying to get filename.");
          x.printStackTrace();
        }
          }
        }
  
+       if (!file.isAbsolute() && file.exists())
+       {
+         file = file.getAbsoluteFile();
+       }
        setSelectedFile(file);
      }
    }
        }
  
        list = new JList<>(recent);
-       DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
-       dlcr.setHorizontalAlignment(DefaultListCellRenderer.RIGHT);
-       list.setCellRenderer(dlcr);
+       list.setCellRenderer(new recentlyOpenedCellRenderer());
  
        list.addMouseListener(new MouseAdapter()
        {
          }
        });
  
-       this.setBorder(new javax.swing.border.TitledBorder(
-               MessageManager.getString("label.recently_opened")));
+       TitledBorder recentlyOpenedBorder = new TitledBorder(
+               MessageManager.getString("label.recently_opened"));
+       recentlyOpenedBorder.setTitleFont(
+               recentlyOpenedBorder.getTitleFont().deriveFont(10f));
+       this.setBorder(recentlyOpenedBorder);
  
        final JScrollPane scroller = new JScrollPane(list);
  
        layout.putConstraint(SpringLayout.NORTH, scroller, 5,
                SpringLayout.NORTH, this);
  
-       if (Platform.isAMacAndNotJS())
-       {
-         scroller.setPreferredSize(new Dimension(500, 100));
-       }
-       else
-       {
-         scroller.setPreferredSize(new Dimension(530, 200));
-       }
+       // one size okay for all
+       scroller.setPreferredSize(new Dimension(280, 105));
        this.add(scroller);
  
-       javax.swing.SwingUtilities.invokeLater(new Runnable()
+       SwingUtilities.invokeLater(new Runnable()
        {
          @Override
          public void run()
  
    }
  
+   class recentlyOpenedCellRenderer extends JLabel
+           implements ListCellRenderer<String>
+   {
+     private final static int maxChars = 46;
+     private final static String ellipsis = "...";
+     @Override
+     public Component getListCellRendererComponent(
+             JList<? extends String> list, String value, int index,
+             boolean isSelected, boolean cellHasFocus)
+     {
+       String filename = value.toString();
+       String displayFilename;
+       if (filename.length() > maxChars)
+       {
+         StringBuilder displayFileSB = new StringBuilder();
+         File file = new File(filename);
+         displayFileSB.append(file.getName());
+         if (file.getParent() != null)
+         {
+           File parent = file;
+           boolean spaceleft = true;
+           while (spaceleft && parent.getParent() != null)
+           {
+             parent = parent.getParentFile();
+             String name = parent.getName();
+             displayFileSB.insert(0, File.separator);
+             if (displayFileSB.length() + name.length() < maxChars - 1)
+             {
+               displayFileSB.insert(0, name);
+             }
+             else
+             {
+               displayFileSB.insert(0, ellipsis);
+               spaceleft = false;
+             }
+           }
+           if (spaceleft && filename.startsWith(File.separator)
+                   && !(displayFileSB.charAt(0) == File.separatorChar))
+           {
+             displayFileSB.insert(0, File.separator);
+           }
+         }
+         displayFilename = displayFileSB.toString();
+       }
+       else
+       {
+         displayFilename = filename;
+       }
+       this.setText(displayFilename.toString());
+       this.setToolTipText(filename);
+       if (isSelected)
+       {
+         setBackground(list.getSelectionBackground());
+         setForeground(list.getSelectionForeground());
+       }
+       else
+       {
+         setBackground(list.getBackground());
+         setForeground(list.getForeground());
+       }
+       this.setHorizontalAlignment(SwingConstants.TRAILING);
+       this.setEnabled(list.isEnabled());
+       this.setFont(list.getFont().deriveFont(12f));
+       this.setOpaque(true);
+       return this;
+     }
+   }
    /*
    @Override
    public JalviewFileChooser setResponseHandler(Object response,
@@@ -57,7 -57,6 +57,6 @@@ import jalview.bin.Cache
  import jalview.gui.JvSwingUtils;
  import jalview.gui.Preferences;
  import jalview.io.FileFormats;
- import jalview.io.exceptions.ImageOutputException;
  import jalview.schemes.ResidueColourScheme;
  import jalview.util.MessageManager;
  import jalview.util.Platform;
@@@ -221,6 -220,7 +220,7 @@@ public class GAlignFrame extends JInter
    {
      try
      {
+       setFrameIcon(null);
  
        // for Web-page embedding using id=align-frame-div
        setName("jalview-alignment");
        }
      } catch (Exception e)
      {
 -      System.err.println(e.toString());
 +      jalview.bin.Console.errPrintln(e.toString());
      }
  
      if (Platform.allowMnemonics()) // was "not mac and not JS"
    protected void createPNG_actionPerformed(ActionEvent object)
    {
      // TODO Auto-generated method stub
-     
    }
  
    protected void createEPS_actionPerformed(ActionEvent object)
    {
      // TODO Auto-generated method stub
-     
    }
  
    protected void createSVG_actionPerformed(ActionEvent object)
    {
      // TODO Auto-generated method stub
-     
    }
  
    protected void copyHighlightedColumns_actionPerformed(
    {
    }
  
    protected void font_actionPerformed(ActionEvent e)
    {
    }
  
    }
  
    protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
    {