X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FDesktop.java;h=7d549f62caee30a5a46706eee9dbe812e2387af7;hb=b419d3b17606d478c234678487ff34d97bfa83cc;hp=e7be7653ef07ff89861f6c465c55087dd92bcc9c;hpb=d50fd279e22d3939612cac97cd08815c98bf10e4;p=jalview.git diff --git a/src/jalview/gui/Desktop.java b/src/jalview/gui/Desktop.java index e7be765..7d549f6 100644 --- a/src/jalview/gui/Desktop.java +++ b/src/jalview/gui/Desktop.java @@ -20,13 +20,12 @@ */ package jalview.gui; -import static jalview.util.UrlConstants.SEQUENCE_ID; - import jalview.api.AlignViewportI; import jalview.api.AlignmentViewPanel; import jalview.bin.Cache; import jalview.bin.Jalview; import jalview.gui.ImageExporter.ImageWriterI; +import jalview.io.BackupFiles; import jalview.io.DataSourceType; import jalview.io.FileFormat; import jalview.io.FileFormatException; @@ -39,6 +38,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.BrowserLauncher; @@ -46,7 +46,6 @@ import jalview.util.ImageMaker.TYPE; import jalview.util.MessageManager; import jalview.util.Platform; import jalview.util.UrlConstants; -import jalview.util.dialogrunner.RunResponse; import jalview.viewmodel.AlignmentViewport; import jalview.ws.params.ParamManager; import jalview.ws.utils.UrlDownloadClient; @@ -83,13 +82,14 @@ import java.beans.PropertyChangeListener; import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; +import java.io.FileWriter; import java.io.IOException; import java.net.URL; import java.util.ArrayList; +import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.ListIterator; -import java.util.StringTokenizer; import java.util.Vector; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -108,7 +108,6 @@ import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JDesktopPane; -import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.JLabel; import javax.swing.JMenuItem; @@ -148,6 +147,10 @@ public class Desktop extends jalview.jbgui.GDesktop private static final String EXPERIMENTAL_FEATURES = "EXPERIMENTAL_FEATURES"; + protected static final String CONFIRM_KEYBOARD_QUIT = "CONFIRM_KEYBOARD_QUIT"; + + public static HashMap savingFiles = new HashMap<>(); + private JalviewChangeSupport changeSupport = new JalviewChangeSupport(); /** @@ -346,39 +349,85 @@ public class Desktop extends jalview.jbgui.GDesktop */ public Desktop() { + super(); /** - * A note to implementors. It is ESSENTIAL that any activities that might block - * are spawned off as threads rather than waited for during this constructor. + * A note to implementors. It is ESSENTIAL that any activities that might + * block are spawned off as threads rather than waited for during this + * constructor. */ instance = this; - if (!Jalview.isJS()) + if (!Platform.isJS()) { doVamsasClientCheck(); } doConfigureStructurePrefs(); setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION")); - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + /* + if (!Platform.isAMac()) + { + // this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + } + else + { + this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + } + */ + + try + { + APQHandlers.setAPQHandlers(this); + } catch (Exception e) + { + System.out.println("Cannot set APQHandlers"); + // e.printStackTrace(); + } catch (Throwable t) + { + System.out.println("Cannot set APQHandlers"); + // t.printStackTrace(); + } + + + addWindowListener(new WindowAdapter() + { + + @Override + public void windowClosing(WindowEvent ev) + { + quit(); + } + }); + boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE", false); + boolean showjconsole = jalview.bin.Cache.getDefault("SHOW_JAVA_CONSOLE", false); desktop = new MyDesktopPane(selmemusage); + showMemusage.setSelected(selmemusage); desktop.setBackground(Color.white); + getContentPane().setLayout(new BorderLayout()); // alternate config - have scrollbars - see notes in JAL-153 // JScrollPane sp = new JScrollPane(); // sp.getViewport().setView(desktop); // getContentPane().add(sp, BorderLayout.CENTER); + + // BH 2018 - just an experiment to try unclipped JInternalFrames. + if (Platform.isJS()) + { + getRootPane().putClientProperty("swingjs.overflow.hidden", "false"); + } + getContentPane().add(desktop, BorderLayout.CENTER); desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); // This line prevents Windows Look&Feel resizing all new windows to maximum // if previous window was maximised desktop.setDesktopManager(new MyDesktopManager( - (Platform.isWindows() ? new DefaultDesktopManager() - : Platform.isAMac() + (Platform.isWindowsAndNotJS() ? new DefaultDesktopManager() + : Platform.isAMacAndNotJS() ? new AquaInternalFrameManager( desktop.getDesktopManager()) : desktop.getDesktopManager()))); @@ -395,11 +444,15 @@ public class Desktop extends jalview.jbgui.GDesktop int yPos = Math.max(5, (screenSize.height - 650) / 2); setBounds(xPos, yPos, 900, 650); } - - boolean doFullLoad = /** @j2sNative ! */true; - - if (doFullLoad) { - + + if (!Platform.isJS()) + /** + * Java only + * + * @j2sIgnore + */ + { + jconsole = new Console(this, showjconsole); // add essential build information jconsole.setHeader("Jalview Version: " @@ -411,7 +464,14 @@ public class Desktop extends jalview.jbgui.GDesktop + "Java version: " + System.getProperty("java.version") + "\n" + System.getProperty("os.arch") + " " + System.getProperty("os.name") + " " - + System.getProperty("os.version")); + + System.getProperty("os.version") + + (jalview.bin.Cache.getProperty("VERSION").equals("DEVELOPMENT") + ? "\nJava path:" + + System.getProperty( + "java.home") + + File.separator + "bin" + + File.separator + "java" + : "")); showConsole(showjconsole); @@ -434,8 +494,8 @@ public class Desktop extends jalview.jbgui.GDesktop } }); - // Thread off a new instance of the file chooser - this reduces the time it - // takes to open it later on. + // Thread off a new instance of the file chooser - this reduces the time + // it takes to open it later on. new Thread(new Runnable() { @Override @@ -463,7 +523,7 @@ public class Desktop extends jalview.jbgui.GDesktop }); - } + } this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this)); @@ -574,7 +634,7 @@ public class Desktop extends jalview.jbgui.GDesktop } } }).start(); - ; + } @Override @@ -874,8 +934,7 @@ public class Desktop extends jalview.jbgui.GDesktop frame.setResizable(resizable); frame.setMaximizable(resizable); frame.setIconifiable(resizable); - frame.setOpaque(/** @j2sNative true || */ - false); + frame.setOpaque(Platform.isJS()); if (frame.getX() < 1 && frame.getY() < 1) { @@ -926,7 +985,7 @@ public class Desktop extends jalview.jbgui.GDesktop menuItem.removeActionListener(menuItem.getActionListeners()[0]); } windowMenu.remove(menuItem); - }; + } }); menuItem.addActionListener(new ActionListener() @@ -990,7 +1049,7 @@ public class Desktop extends jalview.jbgui.GDesktop KeyStroke ctrlWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK); KeyStroke cmdWKey = KeyStroke.getKeyStroke(KeyEvent.VK_W, - Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()); + jalview.util.ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx()); InputMap inputMap = frame .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); @@ -1082,7 +1141,10 @@ public class Desktop extends jalview.jbgui.GDesktop { format = new IdentifyFile().identify(file, protocol); } - + if (file instanceof File) + { + Platform.cacheFileData((File) file); + } new FileLoader().LoadFile(null, file, protocol, format); } @@ -1106,16 +1168,15 @@ public class Desktop extends jalview.jbgui.GDesktop { String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT"); JalviewFileChooser chooser = JalviewFileChooser - .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat); + .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat, BackupFiles.getEnabled()); chooser.setFileView(new JalviewFileView()); chooser.setDialogTitle( MessageManager.getString("label.open_local_file")); chooser.setToolTipText(MessageManager.getString("action.open")); - chooser.response(new RunResponse(JalviewFileChooser.APPROVE_OPTION) + chooser.setResponseHandler(0, new Runnable() { - @Override public void run() { @@ -1144,7 +1205,8 @@ public class Desktop extends jalview.jbgui.GDesktop new FileLoader().LoadFile(viewport, selectedFile, DataSourceType.FILE, format); } - }).showOpenDialog(this); + }); + chooser.showOpenDialog(this); } /** @@ -1162,7 +1224,7 @@ public class Desktop extends jalview.jbgui.GDesktop JPanel panel = new JPanel(new GridLayout(2, 1)); panel.add(label); - + /* * the URL to fetch is * Java: an editable combobox with history @@ -1170,11 +1232,16 @@ public class Desktop extends jalview.jbgui.GDesktop */ JComponent history; String urlBase = "http://www."; - if (Jalview.isJS()) + if (Platform.isJS()) { history = new JTextField(urlBase, 35); } else + /** + * Java only + * + * @j2sIgnore + */ { JComboBox asCombo = new JComboBox<>(); asCombo.setPreferredSize(new Dimension(400, 20)); @@ -1194,13 +1261,16 @@ public class Desktop extends jalview.jbgui.GDesktop Object[] options = new Object[] { MessageManager.getString("action.ok"), MessageManager.getString("action.cancel") }; - RunResponse action = new RunResponse(JvOptionPane.OK_OPTION) { + Runnable action = new Runnable() + { @Override public void run() { - String url = Jalview.isJS() ? ((JTextField) history).getText() + @SuppressWarnings("unchecked") + String url = (history instanceof JTextField + ? ((JTextField) history).getText() : ((JComboBox) history).getSelectedItem() - .toString(); + .toString()); if (url.toLowerCase().endsWith(".jar")) { @@ -1229,7 +1299,8 @@ public class Desktop extends jalview.jbgui.GDesktop if (format == null) { - String msg = MessageManager.formatMessage("label.couldnt_locate", url); + String msg = MessageManager + .formatMessage("label.couldnt_locate", url); JvOptionPane.showInternalMessageDialog(Desktop.desktop, msg, MessageManager.getString("label.url_not_found"), JvOptionPane.WARNING_MESSAGE); @@ -1247,10 +1318,11 @@ public class Desktop extends jalview.jbgui.GDesktop new FileLoader().LoadFile(url, DataSourceType.URL, format); } } - }}; + } + }; String dialogOption = MessageManager .getString("label.input_alignment_from_url"); - JvOptionPane.newOptionDialog(desktop).response(action) + JvOptionPane.newOptionDialog(desktop).setResponseHandler(0, action) .showInternalDialog(panel, dialogOption, JvOptionPane.YES_NO_CANCEL_OPTION, JvOptionPane.PLAIN_MESSAGE, null, options, @@ -1423,11 +1495,16 @@ public class Desktop extends jalview.jbgui.GDesktop { try { - if (Jalview.isJS()) + if (Platform.isJS()) { BrowserLauncher.openURL("http://www.jalview.org/help.html"); } else + /** + * Java only + * + * @j2sIgnore + */ { Help.showHelpWindow(); } @@ -1641,20 +1718,45 @@ public class Desktop extends jalview.jbgui.GDesktop * Jalview project file */ @Override - public void saveState_actionPerformed(boolean asCastor) + public void saveState_actionPerformed() { - JalviewFileChooser chooser = new JalviewFileChooser( - asCastor ? "jvp" : "jvx", - "Jalview Project"); + saveState_actionPerformed(false); + } - chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle(MessageManager.getString("label.save_state")); - int option = chooser.showSaveDialog(this); - if (option == JalviewFileChooser.APPROVE_OPTION) + 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(); + + // System.out.println("autoSave="+autoSave+", projectFile='"+projectFile+"', + // saveAs="+saveAs+", Backups + // "+(BackupFiles.getEnabled()?"enabled":"disabled")); + + boolean approveSave = false; + if (!autoSave) { - 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 @@ -1663,46 +1765,52 @@ 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 { - if (asCastor) - { - new Jalview2XML().saveState(choice); - } - else + boolean doBackup = BackupFiles.getEnabled(); + BackupFiles backupfiles = doBackup ? new BackupFiles(chosenFile) : null; + + new Jalview2XML().saveState(doBackup ? backupfiles.getTempFile() : chosenFile); + + if (doBackup) { - new jalview.project.Jalview2XML().saveState(choice); + backupfiles.setWriteSuccess(true); + backupfiles.rollBackupsAndRenameTempFile(); } } catch (OutOfMemoryError oom) { - new OOMWarning( - "Whilst saving current state to " + choice.getName(), - oom); + new OOMWarning("Whilst saving current state to " + + chosenFile.getName(), oom); } catch (Exception ex) { - Cache.log.error( - "Problems whilst trying to save to " + choice.getName(), - ex); - JvOptionPane.showMessageDialog(Desktop.this, + Cache.log.error("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(); } } - void setProjectFile(File choice) + @Override + public void saveAsState_actionPerformed(ActionEvent e) + { + saveState_actionPerformed(true); + } + + private void setProjectFile(File choice) { this.projectFile = choice; } @@ -1713,64 +1821,53 @@ public class Desktop extends jalview.jbgui.GDesktop } /** - * Prompts the user to choose a file and loads in as a Jalview project file + * Shows a file chooser dialog and tries to read in the selected file as a + * Jalview project */ @Override - public void loadState_actionPerformed(boolean asCastor) - { - // TODO: GET RID OF .JVX BEFORE RELEASE JIM! - final String[] suffix = asCastor ? new String[] { "jvp", "jar" } - : new String[] - { "jvx" }; - final String[] desc = asCastor - ? new String[] - { "Jalview Project", "Jalview Project (old)" } - : new String[] - { "Jalview Project" }; + 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"), suffix, - desc, - "Jalview Project"); + Cache.getProperty("LAST_DIRECTORY"), suffix, desc, + "Jalview Project", true, BackupFiles.getEnabled()); // last two booleans: allFiles, + // allowBackupFiles chooser.setFileView(new JalviewFileView()); chooser.setDialogTitle(MessageManager.getString("label.restore_state")); - chooser.response(new RunResponse(JalviewFileChooser.APPROVE_OPTION) + chooser.setResponseHandler(0, new Runnable() { @Override public void run() { File selectedFile = chooser.getSelectedFile(); setProjectFile(selectedFile); - final String choice = selectedFile.getAbsolutePath(); + String choice = selectedFile.getAbsolutePath(); Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent()); new Thread(new Runnable() { @Override public void run() { - try { - if (asCastor) - { - new Jalview2XML().loadJalviewAlign(choice); - } - else - { - new jalview.project.Jalview2XML().loadJalviewAlign(choice); - } - } catch (OutOfMemoryError oom) - { - new OOMWarning("Whilst loading project from " + choice, oom); - } catch (Exception ex) + try { - Cache.log.error( - "Problems whilst loading project from " + choice, ex); - JvOptionPane.showMessageDialog(Desktop.desktop, - MessageManager.formatMessage( - "label.error_whilst_loading_project_from", - new Object[] - { choice }), - MessageManager.getString("label.couldnt_load_project"), - JvOptionPane.WARNING_MESSAGE); - } + new Jalview2XML().loadJalviewAlign(choice); + } catch (OutOfMemoryError oom) + { + new OOMWarning("Whilst loading project from " + choice, oom); + } catch (Exception ex) + { + Cache.log.error( + "Problems whilst loading project from " + choice, ex); + JvOptionPane.showMessageDialog(Desktop.desktop, + MessageManager.formatMessage( + "label.error_whilst_loading_project_from", + new Object[] + { choice }), + MessageManager.getString("label.couldnt_load_project"), + JvOptionPane.WARNING_MESSAGE); + } } }).start(); } @@ -2290,7 +2387,7 @@ public class Desktop extends jalview.jbgui.GDesktop }); rthr.start(); } - }; + } }); VamsasStMenu.add(sessit); } @@ -2435,7 +2532,7 @@ public class Desktop extends jalview.jbgui.GDesktop while (li.hasNext()) { String link = li.next(); - if (link.contains(SEQUENCE_ID) + if (link.contains(jalview.util.UrlConstants.SEQUENCE_ID) && !UrlConstants.isDefaultString(link)) { check = true; @@ -2742,7 +2839,7 @@ public class Desktop extends jalview.jbgui.GDesktop { getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, - Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), + jalview.util.ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx()), "Quit"); getRootPane().getActionMap().put("Quit", new AbstractAction() { @@ -2793,24 +2890,26 @@ public class Desktop extends jalview.jbgui.GDesktop @Override public void setProgressBar(String message, long id) { + Platform.timeCheck("Desktop " + message, Platform.TIME_MARK); + if (progressBars == null) { progressBars = new Hashtable<>(); progressBarHandlers = new Hashtable<>(); } - if (progressBars.get(new Long(id)) != null) + if (progressBars.get(Long.valueOf(id)) != null) { - JPanel panel = progressBars.remove(new Long(id)); - if (progressBarHandlers.contains(new Long(id))) + JPanel panel = progressBars.remove(Long.valueOf(id)); + if (progressBarHandlers.contains(Long.valueOf(id))) { - progressBarHandlers.remove(new Long(id)); + progressBarHandlers.remove(Long.valueOf(id)); } removeProgressPanel(panel); } else { - progressBars.put(new Long(id), addProgressPanel(message)); + progressBars.put(Long.valueOf(id), addProgressPanel(message)); } } @@ -2825,13 +2924,13 @@ public class Desktop extends jalview.jbgui.GDesktop final IProgressIndicatorHandler handler) { if (progressBarHandlers == null - || !progressBars.containsKey(new Long(id))) + || !progressBars.containsKey(Long.valueOf(id))) { throw new Error(MessageManager.getString( "error.call_setprogressbar_before_registering_handler")); } - progressBarHandlers.put(new Long(id), handler); - final JPanel progressPanel = progressBars.get(new Long(id)); + progressBarHandlers.put(Long.valueOf(id), handler); + final JPanel progressPanel = progressBars.get(Long.valueOf(id)); if (handler.canCancel()) { JButton cancel = new JButton( @@ -3185,7 +3284,6 @@ public class Desktop extends jalview.jbgui.GDesktop } catch (InterruptedException x) { } - ; } if (instance == null) { @@ -3468,12 +3566,11 @@ public class Desktop extends jalview.jbgui.GDesktop } else { - if (Platform.isAMac()) + if (Platform.isAMacAndNotJS()) { System.err.println( "Please ignore plist error - occurs due to problem with java 8 on OSX"); } - ; } } catch (Throwable ex) { @@ -3585,8 +3682,7 @@ public class Desktop extends jalview.jbgui.GDesktop } } } - if (Platform.isWindows()) - + if (Platform.isWindowsAndNotJS()) { Cache.log.debug("Scanning dropped content for Windows Link Files");