+ else
+ {
+ jalview.bin.Console
+ .debug("Couldn't resolve dataflavor for drop: "
+ + t.toString());
+ }
+ }
+ }
+ }
+ if (Platform.isWindowsAndNotJS())
+ {
+ jalview.bin.Console
+ .debug("Scanning dropped content for Windows Link Files");
+
+ // resolve any .lnk files in the file drop
+ for (int f = 0; f < files.size(); f++)
+ {
+ String source = files.get(f).toString().toLowerCase(Locale.ROOT);
+ if (protocols.get(f).equals(DataSourceType.FILE)
+ && (source.endsWith(".lnk") || source.endsWith(".url")
+ || source.endsWith(".site")))
+ {
+ try
+ {
+ Object obj = files.get(f);
+ File lf = (obj instanceof File ? (File) obj
+ : new File((String) obj));
+ // process link file to get a URL
+ jalview.bin.Console.debug("Found potential link file: " + lf);
+ WindowsShortcut wscfile = new WindowsShortcut(lf);
+ String fullname = wscfile.getRealFilename();
+ protocols.set(f, FormatAdapter.checkProtocol(fullname));
+ files.set(f, fullname);
+ jalview.bin.Console.debug("Parsed real filename " + fullname
+ + " to extract protocol: " + protocols.get(f));
+ } catch (Exception ex)
+ {
+ jalview.bin.Console.error(
+ "Couldn't parse " + files.get(f) + " as a link file.",
+ ex);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the Preferences property for experimental features to True or False
+ * depending on the state of the controlling menu item
+ */
+ @Override
+ protected void showExperimental_actionPerformed(boolean selected)
+ {
+ Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));
+ }
+
+ /**
+ * Answers a (possibly empty) list of any structure viewer frames (currently
+ * for either Jmol or Chimera) which are currently open. This may optionally
+ * be restricted to viewers of a specified class, or viewers linked to a
+ * specified alignment panel.
+ *
+ * @param apanel
+ * if not null, only return viewers linked to this panel
+ * @param structureViewerClass
+ * if not null, only return viewers of this class
+ * @return
+ */
+ public List<StructureViewerBase> getStructureViewers(
+ AlignmentPanel apanel,
+ Class<? extends StructureViewerBase> structureViewerClass)
+ {
+ List<StructureViewerBase> result = new ArrayList<>();
+ JInternalFrame[] frames = Desktop.instance.getAllFrames();
+
+ for (JInternalFrame frame : frames)
+ {
+ if (frame instanceof StructureViewerBase)
+ {
+ if (structureViewerClass == null
+ || structureViewerClass.isInstance(frame))
+ {
+ if (apanel == null
+ || ((StructureViewerBase) frame).isLinkedWith(apanel))
+ {
+ result.add((StructureViewerBase) frame);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ public static final String debugScaleMessage = "Desktop graphics transform scale=";
+
+ private static boolean debugScaleMessageDone = false;
+
+ public static void debugScaleMessage(Graphics g)
+ {
+ if (debugScaleMessageDone)
+ {
+ return;
+ }
+ // output used by tests to check HiDPI scaling settings in action
+ try
+ {
+ Graphics2D gg = (Graphics2D) g;
+ if (gg != null)
+ {
+ AffineTransform t = gg.getTransform();
+ double scaleX = t.getScaleX();
+ double scaleY = t.getScaleY();
+ jalview.bin.Console.debug(debugScaleMessage + scaleX + " (X)");
+ jalview.bin.Console.debug(debugScaleMessage + scaleY + " (Y)");
+ debugScaleMessageDone = true;
+ }
+ else
+ {
+ jalview.bin.Console.debug("Desktop graphics null");
+ }
+ } catch (Exception e)
+ {
+ jalview.bin.Console.debug(Cache.getStackTraceString(e));
+ }
+ }
+
+ /**
+ * closes the current instance window, disposes and forgets about it.
+ */
+ public static void closeDesktop()
+ {
+ if (Desktop.instance != null)
+ {
+ Desktop.instance.closeAll_actionPerformed(null);
+ Desktop.instance.setVisible(false);
+ 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
+ * @return
+ */
+ public boolean operationsAreInProgress()
+ {
+ JInternalFrame[] frames = getAllFrames();
+ for (JInternalFrame frame:frames)
+ {
+ if (frame instanceof IProgressIndicator)
+ {
+ if (((IProgressIndicator)frame).operationInProgress())
+ {
+ return true;