Merge branch 'feature/JAL-3063jaxbNoCastor' into feature/JAL-3141_Create_a_backup_whe...
[jalview.git] / src / jalview / gui / Desktop.java
index 259e693..aefcf08 100644 (file)
@@ -26,6 +26,7 @@ import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
 import jalview.bin.Cache;
 import jalview.bin.Jalview;
+import jalview.io.BackupFiles;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
 import jalview.io.FileFormatException;
@@ -38,6 +39,7 @@ import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
 import jalview.jbgui.GSplitFrame;
 import jalview.jbgui.GStructureViewer;
+import jalview.project.Jalview2XML;
 import jalview.structure.StructureSelectionManager;
 import jalview.urls.IdOrgSettings;
 import jalview.util.ImageMaker;
@@ -69,6 +71,7 @@ import java.awt.dnd.DropTargetEvent;
 import java.awt.dnd.DropTargetListener;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
@@ -92,10 +95,13 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Semaphore;
 
 import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.ActionMap;
 import javax.swing.Box;
 import javax.swing.BoxLayout;
 import javax.swing.DefaultDesktopManager;
 import javax.swing.DesktopManager;
+import javax.swing.InputMap;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
@@ -904,8 +910,6 @@ public class Desktop extends jalview.jbgui.GDesktop
           menuItem.removeActionListener(menuItem.getActionListeners()[0]);
         }
         windowMenu.remove(menuItem);
-
-        System.gc();
       };
     });
 
@@ -925,6 +929,8 @@ public class Desktop extends jalview.jbgui.GDesktop
       }
     });
 
+    setKeyBindings(frame);
+
     desktop.add(frame);
 
     windowMenu.add(menuItem);
@@ -944,6 +950,42 @@ public class Desktop extends jalview.jbgui.GDesktop
     }
   }
 
+  /**
+   * Add key bindings to a JInternalFrame so that Ctrl-W and Cmd-W will close
+   * the window
+   * 
+   * @param frame
+   */
+  private static void setKeyBindings(JInternalFrame frame)
+  {
+    @SuppressWarnings("serial")
+    final Action closeAction = new AbstractAction()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        frame.dispose();
+      }
+    };
+
+    /*
+     * set up key bindings for Ctrl-W and Cmd-W, with the same (Close) action
+     */
+    KeyStroke ctrlWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W,
+            InputEvent.CTRL_DOWN_MASK);
+    KeyStroke cmdWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
+
+    InputMap inputMap = frame
+            .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+    String ctrlW = ctrlWKey.toString();
+    inputMap.put(ctrlWKey, ctrlW);
+    inputMap.put(cmdWKey, ctrlW);
+
+    ActionMap actionMap = frame.getActionMap();
+    actionMap.put(ctrlW, closeAction);
+  }
+
   @Override
   public void lostOwnership(Clipboard clipboard, Transferable contents)
   {
@@ -1393,7 +1435,6 @@ public class Desktop extends jalview.jbgui.GDesktop
     {
       ssm.resetAll();
     }
-    System.gc();
   }
 
   @Override
@@ -1560,28 +1601,45 @@ public class Desktop extends jalview.jbgui.GDesktop
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
+   * Shows a file chooser dialog and writes out the current session as a Jalview
+   * project file
    */
   @Override
-  public void saveState_actionPerformed(ActionEvent e)
+  public void saveState_actionPerformed()
   {
-    JalviewFileChooser chooser = new JalviewFileChooser("jvp",
-            "Jalview Project");
+    saveState_actionPerformed(false);
+  }
 
-    chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager.getString("label.save_state"));
+  public void saveState_actionPerformed(boolean saveAs)
+  {
+    java.io.File projectFile = getProjectFile();
+    // autoSave indicates we already have a file and don't need to ask
+    boolean autoSave = projectFile != null && !saveAs && BackupFiles.getEnabled();
 
-    int value = chooser.showSaveDialog(this);
+    System.out.println("autoSave="+autoSave+", projectFile='"+projectFile+"', saveAs="+saveAs+", Backups "+(BackupFiles.getEnabled()?"enabled":"disabled"));
 
-    if (value == JalviewFileChooser.APPROVE_OPTION)
+    boolean approveSave = false;
+    if (!autoSave)
     {
-      final Desktop me = this;
-      final java.io.File choice = chooser.getSelectedFile();
-      setProjectFile(choice);
+      JalviewFileChooser chooser = new JalviewFileChooser("jvp",
+              "Jalview Project");
+
+      chooser.setFileView(new JalviewFileView());
+      chooser.setDialogTitle(MessageManager.getString("label.save_state"));
+
+      int value = chooser.showSaveDialog(this);
+
+      if (value == JalviewFileChooser.APPROVE_OPTION)
+      {
+        projectFile = chooser.getSelectedFile();
+        setProjectFile(projectFile);
+        approveSave = true;
+      }
+    }
 
+    if (approveSave || autoSave) {
+      final Desktop me = this;
+      final java.io.File chosenFile = projectFile;
       new Thread(new Runnable()
       {
         @Override
@@ -1590,38 +1648,49 @@ public class Desktop extends jalview.jbgui.GDesktop
           // TODO: refactor to Jalview desktop session controller action.
           setProgressBar(MessageManager.formatMessage(
                   "label.saving_jalview_project", new Object[]
-                  { choice.getName() }), choice.hashCode());
+                  { chosenFile.getName() }), chosenFile.hashCode());
           jalview.bin.Cache.setProperty("LAST_DIRECTORY",
-                  choice.getParent());
+                  chosenFile.getParent());
           // TODO catch and handle errors for savestate
           // TODO prevent user from messing with the Desktop whilst we're saving
           try
           {
-            new Jalview2XML().saveState(choice);
+            BackupFiles backupfiles = new BackupFiles(chosenFile);
+
+            new Jalview2XML().saveState(backupfiles.getTempFile());
+
+            backupfiles.setWriteSuccess(true);
+            backupfiles.rollBackupsAndRenameTempFile();
           } catch (OutOfMemoryError oom)
           {
             new OOMWarning(
-                    "Whilst saving current state to " + choice.getName(),
+                    "Whilst saving current state to " + chosenFile.getName(),
                     oom);
           } catch (Exception ex)
           {
             Cache.log.error(
-                    "Problems whilst trying to save to " + choice.getName(),
+                    "Problems whilst trying to save to " + chosenFile.getName(),
                     ex);
             JvOptionPane.showMessageDialog(me,
                     MessageManager.formatMessage(
                             "label.error_whilst_saving_current_state_to",
                             new Object[]
-                            { choice.getName() }),
+                            { chosenFile.getName() }),
                     MessageManager.getString("label.couldnt_save_project"),
                     JvOptionPane.WARNING_MESSAGE);
           }
-          setProgressBar(null, choice.hashCode());
+          setProgressBar(null, chosenFile.hashCode());
         }
       }).start();
     }
   }
 
+  @Override
+  public void saveAsState_actionPerformed(ActionEvent e)
+  {
+    saveState_actionPerformed(true);
+  }
+
   private void setProjectFile(File choice)
   {
     this.projectFile = choice;
@@ -1633,19 +1702,18 @@ public class Desktop extends jalview.jbgui.GDesktop
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
+   * Shows a file chooser dialog and tries to read in the selected file as a
+   * Jalview project
    */
   @Override
-  public void loadState_actionPerformed(ActionEvent e)
+  public void loadState_actionPerformed()
   {
+    final String[] suffix = new String[] { "jvp", "jar" };
+    final String[] desc = new String[] { "Jalview Project",
+        "Jalview Project (old)" };
     JalviewFileChooser chooser = new JalviewFileChooser(
-            Cache.getProperty("LAST_DIRECTORY"), new String[]
-            { "jvp", "jar" },
-            new String[]
-            { "Jalview Project", "Jalview Project (old)" },
+            Cache.getProperty("LAST_DIRECTORY"), suffix,
+            desc,
             "Jalview Project");
     chooser.setFileView(new JalviewFileView());
     chooser.setDialogTitle(MessageManager.getString("label.restore_state"));