Merge branch 'Jalview-BH/JAL-3026-JAL-3063-JAXB' into
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 17 Dec 2018 14:20:27 +0000 (14:20 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 17 Dec 2018 14:20:27 +0000 (14:20 +0000)
JAL-3048dialogRunner2

Conflicts:
src/jalview/io/JalviewFileChooser.java

1  2 
src/jalview/io/JalviewFileChooser.java

  package jalview.io;
  
  import jalview.bin.Cache;
 +import jalview.bin.Jalview;
  import jalview.gui.JvOptionPane;
  import jalview.util.MessageManager;
  import jalview.util.Platform;
  import jalview.util.dialogrunner.DialogRunner;
  import jalview.util.dialogrunner.DialogRunnerI;
 -import jalview.util.dialogrunner.Response;
  import jalview.util.dialogrunner.RunResponse;
  
  import java.awt.Component;
@@@ -50,8 -50,6 +50,8 @@@ import javax.swing.JList
  import javax.swing.JPanel;
  import javax.swing.JScrollPane;
  import javax.swing.SpringLayout;
 +import javax.swing.SwingUtilities;
 +import javax.swing.border.TitledBorder;
  import javax.swing.plaf.basic.BasicFileChooserUI;
  
  /**
   * @author AMW
   *
   */
 -public class JalviewFileChooser extends JFileChooser
 -        implements PropertyChangeListener, DialogRunnerI
 +public class JalviewFileChooser extends JFileChooser implements DialogRunnerI,
 +    PropertyChangeListener
  {
 -  DialogRunner<JalviewFileChooser> runner = new DialogRunner<>(this);
 +  private static final long serialVersionUID = 1L;
 +
 +  private DialogRunnerI runner = new DialogRunner();
    
 +  File selectedFile = null;
 +
    /**
     * Factory method to return a file chooser that offers readable alignment file
     * formats
    }
  
    JalviewFileChooser(String dir, String[] extensions, String[] descs,
 -          String selected, boolean allFiles)
 +          String selected, boolean acceptAny)
    {
      super(safePath(dir));
      if (extensions.length == descs.length)
        {
          formats.add(new String[] { extensions[i], descs[i] });
        }
 -      init(formats, selected, allFiles);
 +      init(formats, selected, acceptAny);
      }
      else
      {
      }
    }
  
 -  @Override
 -  public void propertyChange(PropertyChangeEvent evt)
 -  {
 -    // TODO other properties need runners...
 -    switch (evt.getPropertyName())
 -    {
 -    case "SelectedFile": 
 -      runner.run(APPROVE_OPTION);
 -      break;
 -    }
 -  }
 -
    private static File safePath(String dir)
    {
      if (dir == null)
    @Override
    public int showOpenDialog(Component parent)
    {
 -    runner.resetResponses();
 +   // runner.resetResponses();
      int value = super.showOpenDialog(this);
 -    /**
 -     * @j2sNative
 -     */
 +    if (!Jalview.isJS())
      {
 -      runner.firstRun(value);
 +      runner.handleResponse(value);
      }
      return value;
    }
     * @param formats
     *          a list of {extensions, description} for each file format
     * @param selected
 -   * @param allFiles
 +   * @param acceptAny
     *          if true, 'any format' option is included
     */
 -  void init(List<String[]> formats, String selected, boolean allFiles)
 +  void init(List<String[]> formats, String selected, boolean acceptAny)
    {
  
      JalviewFileFilter chosen = null;
  
      // SelectAllFilter needs to be set first before adding further
      // file filters to fix bug on Mac OSX
 -    setAcceptAllFileFilterUsed(allFiles);
 +    setAcceptAllFileFilterUsed(acceptAny);
  
      for (String[] format : formats)
      {
      }
      return null;
    }
 -  
 -  File ourselectedFile = null;
  
    @Override
    public File getSelectedFile()
    {
 -    File selfile = super.getSelectedFile();
 -    if (selfile == null && ourselectedFile != null)
 -    {
 -      return ourselectedFile;
 -    }
 -    return selfile;
 +    File f = super.getSelectedFile();
 +    return f == null ? selectedFile : f;
 +  }
 +
 +  /**
 +   * Overridden for JalviewJS compatibility: only one thread in Javascript, 
 +   * so we can't wait for user choice in another thread and then perform the 
 +   * desired action
 +   */
 +  @Override
 +  public int showSaveDialog(Component parent) throws HeadlessException
 +  {
 +    this.setAccessory(null);
 +    this.setSelectedFile(null);
 +    return super.showSaveDialog(parent);
    }
  
 -  Component saveparent;
 -  RunResponse overwriteCheck = new RunResponse(
 -          JalviewFileChooser.APPROVE_OPTION)
 +  /**
 +   * If doing a Save, and an existing file is chosen or entered, prompt for
 +   * confirmation of overwrite. Proceed if Yes, else leave the file chooser
 +   * open.
 +   * 
 +   * @see https://stackoverflow.com/questions/8581215/jfilechooser-and-checking-for-overwrite
 +   */
 +  @Override
 +  public void approveSelection()
    {
 -    @Override
 -    public void run()
 +    if (getDialogType() != SAVE_DIALOG)
      {
 -    ourselectedFile = getSelectedFile();
 +      super.approveSelection();
 +      return;
 +    }
 +
 +    selectedFile = getSelectedFile();
  
 -    if (getSelectedFile() == null)
 +    if (selectedFile == null)
      {
        // Workaround for Java 9,10 on OSX - no selected file, but there is a
        // filename typed in
          String filename = ((BasicFileChooserUI) getUI()).getFileName();
          if (filename != null && filename.length() > 0)
          {
 -          ourselectedFile = new File(getCurrentDirectory(), filename);
 +          selectedFile = new File(getCurrentDirectory(), filename);
          }
        } catch (Throwable x)
        {
                  "Unexpected exception when trying to get filename.");
          x.printStackTrace();
        }
 +      // TODO: ENSURE THAT FILES SAVED WITH A ':' IN THE NAME ARE REFUSED AND
 +      // THE
 +      // USER PROMPTED FOR A NEW FILENAME
      }
 -    if (ourselectedFile == null)
 +
 +    if (selectedFile == null)
      {
 -      returned = new Response(JalviewFileChooser.CANCEL_OPTION);
        return;
      }
 -      // JBP Note - this code was executed regardless of 'SAVE' being pressed
 -      // need to see if there were side effects
 -      if (getFileFilter() instanceof JalviewFileFilter)
 -      {
 -        JalviewFileFilter jvf = (JalviewFileFilter) getFileFilter();
  
 -        if (!jvf.accept(getSelectedFile()))
 -        {
 -          String withExtension = getSelectedFile() + "."
 -                  + jvf.getAcceptableExtension();
 -          setSelectedFile(new File(withExtension));
 -        }
 -      }
 -      // All good, so we continue to save
 -      returned = new Response(JalviewFileChooser.APPROVE_OPTION);
 +    if (getFileFilter() instanceof JalviewFileFilter)
 +    {
 +      JalviewFileFilter jvf = (JalviewFileFilter) getFileFilter();
  
 -      // TODO: ENSURE THAT FILES SAVED WITH A ':' IN THE NAME ARE REFUSED AND THE
 -      // USER PROMPTED FOR A NEW FILENAME
 -      /**
 -       * @j2sNative
 -       */
 +      if (!jvf.accept(selectedFile))
        {
 -        if (getSelectedFile().exists())
 -        {
 -          // JAL-3048 - may not need to raise this for browser saves
 -
 -          // yes/no cancel
 -          int confirm = JvOptionPane.showConfirmDialog(saveparent,
 -                  MessageManager.getString("label.overwrite_existing_file"),
 -                  MessageManager.getString("label.file_already_exists"),
 -                  JvOptionPane.YES_NO_OPTION);
 -
 -          if (confirm != JvOptionPane.YES_OPTION)
 -          {
 -            returned = new Response(JalviewFileChooser.CANCEL_OPTION);
 -          }
 -        }
 +        String withExtension = getSelectedFile().getName() + "."
 +                + jvf.getAcceptableExtension();
 +        selectedFile = (new File(getCurrentDirectory(), withExtension));
 +        setSelectedFile(selectedFile);
        }
 -    };
 -  };
 -
 -  /**
 -   * Overridden for JalviewJS compatibility: only one thread in Javascript, 
 -   * so we can't wait for user choice in another thread and then perform the 
 -   * desired action
 -   */
 -  @Override
 -  public int showSaveDialog(Component parent) throws HeadlessException
 -  {
 -    this.setAccessory(null);
 -
 -    /*
 -     * Save dialog is opened until user picks a file format 
 -     */
 -    if (!runner.isRegistered(overwriteCheck))
 -    {
 -      // first call for this instance
 -      runner.firstResponse(overwriteCheck);
 -    }
 -    else
 -    {
 -      // reset response flags
 -      runner.resetResponses();
      }
  
 -    setDialogType(SAVE_DIALOG);
 -    
 -    // Java 9,10,11 on OSX - clear selected file so name isn't auto populated
 -    this.setSelectedFile(null);
 - 
 -    saveparent = parent;
 -
 -    int value = showDialog(parent, MessageManager.getString("action.save"));
 -    /**
 -     * @j2sNative
 -     */
 +    if (selectedFile.exists())
      {
 -      runner.firstRun(value);
 +      int confirm = JvOptionPane.showConfirmDialog(this,
 +              MessageManager.getString("label.overwrite_existing_file"),
 +              MessageManager.getString("label.file_already_exists"),
 +              JvOptionPane.YES_NO_OPTION);
 +      if (confirm != JvOptionPane.YES_OPTION)
 +      {
 +        return;
 +      }
      }
 -    return value;
 +
 +    super.approveSelection();
    }
  
    void recentListSelectionChanged(Object selection)
      }
    }
  
 +  /**
 +   * A panel to set as the 'accessory' component to the file chooser dialog,
 +   * holding a list of recently opened files (if any). These are held as a
 +   * tab-separated list of file paths under key <code>RECENT_FILE</code> in
 +   * <code>.jalview_properties</code>. A click in the list calls a method in
 +   * JalviewFileChooser to set the chosen file as the selection.
 +   */
    class RecentlyOpened extends JPanel
    {
 +    private static final long serialVersionUID = 1L;
 +
      JList<String> list;
  
 -    public RecentlyOpened()
 +    RecentlyOpened()
      {
 -
+       setPreferredSize(new Dimension(300,100));
 -      String historyItems = jalview.bin.Cache.getProperty("RECENT_FILE");
 +      String historyItems = Cache.getProperty("RECENT_FILE");
        StringTokenizer st;
        Vector<String> recent = new Vector<>();
  
        if (historyItems != null)
        {
          st = new StringTokenizer(historyItems, "\t");
 -
          while (st.hasMoreTokens())
          {
            recent.addElement(st.nextToken());
        }
  
        list = new JList<>(recent);
+   
        DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
-       dlcr.setHorizontalAlignment(DefaultListCellRenderer.RIGHT);
+ //      dlcr.setHorizontalAlignment(DefaultListCellRenderer.RIGHT);
        list.setCellRenderer(dlcr);
  
        list.addMouseListener(new MouseAdapter()
          }
        });
  
 -      this.setBorder(new javax.swing.border.TitledBorder(
 +      this.setBorder(new TitledBorder(
                MessageManager.getString("label.recently_opened")));
  
        final JScrollPane scroller = new JScrollPane(list);
        }
        else
        {
-         scroller.setPreferredSize(new Dimension(130, 200));
+         scroller.setPreferredSize(new Dimension(530, 200));
        }
  
        this.add(scroller);
  
 -      javax.swing.SwingUtilities.invokeLater(new Runnable()
 +      SwingUtilities.invokeLater(new Runnable()
        {
          @Override
          public void run()
                    .setValue(scroller.getHorizontalScrollBar().getMaximum());
          }
        });
 -
      }
    }
  
    @Override
 -  public JalviewFileChooser addResponse(RunResponse action)
 +  public DialogRunnerI addResponse(Object response, RunResponse action)
    {
 -    return runner.addResponse(action);
 +    return runner.addResponse(response, action);
    }
  
 +  /**
 +   * JalviewJS signals file selection by a property change event
 +   * for property "SelectedFile".  This methods responds to that by
 +   * running the response action for 'OK' in the dialog.
 +   * 
 +   * @param evt
 +   */
 +  @Override
 +  public void propertyChange(PropertyChangeEvent evt)
 +  {
 +    // TODO other properties need runners...
 +    switch (evt.getPropertyName())
 +    {
 +    case "SelectedFile": 
 +      runner.handleResponse(APPROVE_OPTION);
 +      break;
 +    }
 +  }
  }