X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FDesktop.java;h=ee24c250a238c7b097c3a818d521b937b4cdd860;hb=fd86db8856109e69c21a5f4102bc8dd94664ae1f;hp=b901ae416c8311664b4e692863820d7f4862d7dc;hpb=4a6e033ecbe830a86d77f8910beb90b09522aceb;p=jalview.git diff --git a/src/jalview/gui/Desktop.java b/src/jalview/gui/Desktop.java index b901ae4..ee24c25 100644 --- a/src/jalview/gui/Desktop.java +++ b/src/jalview/gui/Desktop.java @@ -22,6 +22,7 @@ package jalview.gui; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics; @@ -51,6 +52,7 @@ import java.awt.event.WindowEvent; import java.awt.geom.AffineTransform; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.beans.PropertyVetoException; import java.io.File; import java.io.FileWriter; import java.io.IOException; @@ -63,6 +65,7 @@ import java.util.Hashtable; import java.util.List; import java.util.ListIterator; import java.util.Locale; +import java.util.Map; import java.util.Vector; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -85,9 +88,12 @@ import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.JLabel; import javax.swing.JMenuItem; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JProgressBar; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; @@ -104,6 +110,7 @@ import jalview.api.AlignmentViewPanel; import jalview.api.structures.JalviewStructureDisplayI; import jalview.bin.Cache; import jalview.bin.Jalview; +import jalview.bin.Jalview.ExitCode; import jalview.datamodel.Alignment; import jalview.datamodel.HiddenColumns; import jalview.datamodel.Sequence; @@ -439,7 +446,7 @@ public class Desktop extends jalview.jbgui.GDesktop * 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"; @@ -572,15 +579,16 @@ 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. + // 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."); @@ -632,6 +640,7 @@ public class Desktop extends jalview.jbgui.GDesktop // used for jalviewjsTest jalview.bin.Console.info("JALVIEWJS: CREATED DESKTOP"); } + } /** @@ -873,7 +882,7 @@ public class Desktop extends jalview.jbgui.GDesktop } } catch (Exception ex) { - System.out.println( + jalview.bin.Console.outPrintln( "Unable to paste alignment from system clipboard:\n" + ex); } } @@ -1078,7 +1087,38 @@ public class Desktop extends jalview.jbgui.GDesktop 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); @@ -1238,7 +1278,9 @@ public class Desktop extends jalview.jbgui.GDesktop @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()); @@ -1488,7 +1530,7 @@ public class Desktop extends jalview.jbgui.GDesktop // this will run the shutdownHook but QuitHandler.getQuitResponse() should // not run a second time if gotQuitResponse flag has been set (i.e. user // confirmed quit of some kind). - Jalview.exit("Desktop exiting.", 0); + Jalview.exit("Desktop exiting.", ExitCode.OK); } private void storeLastKnownDimensions(String string, Rectangle jc) @@ -1601,7 +1643,8 @@ public class Desktop extends jalview.jbgui.GDesktop } } catch (Exception ex) { - System.err.println("Error opening help: " + ex.getMessage()); + jalview.bin.Console + .errPrintln("Error opening help: " + ex.getMessage()); } } @@ -1832,7 +1875,8 @@ public class Desktop extends jalview.jbgui.GDesktop 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")); @@ -3381,7 +3425,7 @@ public class Desktop extends jalview.jbgui.GDesktop { if (Platform.isAMacAndNotJS()) { - System.err.println( + jalview.bin.Console.errPrintln( "Please ignore plist error - occurs due to problem with java 8 on OSX"); } } @@ -3623,23 +3667,41 @@ public class Desktop extends jalview.jbgui.GDesktop { 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(); } } /** - * checks if any progress bars are being displayed in any of the windows managed by the desktop + * checks if any progress bars are being displayed in any of the windows + * managed by the desktop + * * @return */ public boolean operationsAreInProgress() { JInternalFrame[] frames = getAllFrames(); - for (JInternalFrame frame:frames) + for (JInternalFrame frame : frames) { if (frame instanceof IProgressIndicator) { - if (((IProgressIndicator)frame).operationInProgress()) + if (((IProgressIndicator) frame).operationInProgress()) { return true; } @@ -3647,4 +3709,97 @@ public class Desktop extends jalview.jbgui.GDesktop } return operationInProgress(); } + + /** + * keep track of modal JvOptionPanes open as modal dialogs for AlignFrames. + * The way the modal JInternalFrame is made means it cannot be a child of an + * AlignFrame, so closing the AlignFrame might leave the modal open :( + */ + private static Map alignFrameModalMap = new HashMap<>(); + + protected static void addModal(AlignFrame af, JInternalFrame jif) + { + alignFrameModalMap.put(af, jif); + } + + protected static void closeModal(AlignFrame af) + { + if (!alignFrameModalMap.containsKey(af)) + { + return; + } + JInternalFrame jif = alignFrameModalMap.get(af); + if (jif != null) + { + try + { + jif.setClosed(true); + } catch (PropertyVetoException e) + { + e.printStackTrace(); + } + } + alignFrameModalMap.remove(af); + } + + public void nonBlockingDialog(String title, String message, String button, + int type, boolean scrollable, boolean modal) + { + nonBlockingDialog(32, 2, title, message, null, button, type, scrollable, + modal); + } + + public void nonBlockingDialog(int width, int height, String title, + String message, String boxtext, String button, int type, + boolean scrollable, boolean modal) + { + if (type < 0) + { + type = JvOptionPane.WARNING_MESSAGE; + } + JLabel jl = new JLabel(message); + + JTextArea jta = new JTextArea(height, width); + // jta.setLineWrap(true); + jta.setEditable(false); + jta.setWrapStyleWord(true); + jta.setAutoscrolls(true); + jta.setText(boxtext); + + JScrollPane jsp = scrollable + ? new JScrollPane(jta, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, + JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED) + : null; + + JvOptionPane jvp = JvOptionPane.newOptionDialog(this); + + JPanel jp = new JPanel(); + jp.setLayout(new BoxLayout(jp, BoxLayout.Y_AXIS)); + + if (message != null) + { + jl.setAlignmentX(Component.LEFT_ALIGNMENT); + jp.add(jl); + } + if (boxtext != null) + { + if (scrollable) + { + jsp.setAlignmentX(Component.LEFT_ALIGNMENT); + jp.add(jsp); + } + else + { + jta.setAlignmentX(Component.LEFT_ALIGNMENT); + jp.add(jta); + } + } + + jvp.setResponseHandler(JOptionPane.YES_OPTION, () -> { + }); + jvp.showDialogOnTopAsync(this, jp, title, JOptionPane.YES_OPTION, type, + null, new Object[] + { button }, button, modal, null, false); + } + }