diff --git a/platform/openide.explorer/src/org/openide/explorer/view/TreeView.java b/platform/openide.explorer/src/org/openide/explorer/view/TreeView.java index 79527ac175d5..56ac23027d4e 100644 --- a/platform/openide.explorer/src/org/openide/explorer/view/TreeView.java +++ b/platform/openide.explorer/src/org/openide/explorer/view/TreeView.java @@ -68,6 +68,8 @@ import java.util.List; import java.util.Set; import java.util.HashSet; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import javax.accessibility.AccessibleContext; @@ -915,73 +917,82 @@ public void setAutoWaitCursor(boolean enable) { autoWaitCursor = enable; } - // - // showing and removing the wait cursor - // - private void showWaitCursor (boolean show) { - JRootPane rPane = getRootPane(); - if (rPane == null) { + private void maybeShowWaitCursor(Node node) { + if (node == null || !autoWaitCursor) { return; } - - if (SwingUtilities.isEventDispatchThread()) { - doShowWaitCursor(rPane.getGlassPane(), show); - } else { - SwingUtilities.invokeLater(new CursorR(rPane.getGlassPane(), show)); + JRootPane rootPane = getRootPane(); + if (rootPane == null) { + return; } + // not sure whenter throughput 1 is OK... + ViewUtil.uiProcessor().post(() -> { + try (DelayedWaitCursor cursor = new DelayedWaitCursor(rootPane)) { + cursor.enable(); + node.getChildren().getNodesCount(true); + } catch (Exception e) { + LOG.log(Level.WARNING, "can't determine node count", e); + } + }); } - private static void doShowWaitCursor (Component glassPane, boolean show) { - if (show) { - glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - glassPane.setVisible(true); - } else { - glassPane.setVisible(false); - glassPane.setCursor(null); - } - } + /// Shows the wait cursor after an initial delay. + /// Can be used in ARM-blocks. + private static class DelayedWaitCursor implements AutoCloseable { - private static class CursorR implements Runnable { - private Component glassPane; - private boolean show; + private static final RequestProcessor RP = new RequestProcessor(DelayedWaitCursor.class.getName()); - private CursorR(Component cont, boolean show) { - this.glassPane = cont; - this.show = show; - } + private static final int SPAWN_DELAY = 200; + private static final int MAX_LIFE_SPAN = 60_000; - @Override - public void run() { - doShowWaitCursor(glassPane, show); - } - } + private final JRootPane root; + private ScheduledFuture scheduled; - private void prepareWaitCursor(final Node node) { - // check type of node - if (node == null || !autoWaitCursor) { - return; + private DelayedWaitCursor(JRootPane root) { + this.root = root; } - showWaitCursor(true); - // not sure whenter throughput 1 is OK... - ViewUtil.uiProcessor().post(new Runnable() { - @Override - public void run() { - try { - node.getChildren().getNodesCount(true); - } catch (Exception e) { - // log a exception - LOG.log(Level.WARNING, null, e); - } finally { - // show normal cursor above all - showWaitCursor(false); + private void enable() { + if (scheduled != null) { + return; + } + scheduled = RP.schedule(() -> { + if (!scheduled.isCancelled()) { + // switch to wait + SwingUtilities.invokeLater(() -> { + if (!scheduled.isCancelled()) { + root.getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + root.getGlassPane().setVisible(true); + } + }); + // block to limit lifespan + try { + Thread.sleep(MAX_LIFE_SPAN); + } catch (InterruptedException cancelled) { + Thread.interrupted(); + } } + // reset + SwingUtilities.invokeLater(() -> { + root.getGlassPane().setVisible(false); + root.getGlassPane().setCursor(null); + }); + }, SPAWN_DELAY, TimeUnit.MILLISECONDS); + } + + private void disable() { + if (scheduled != null) { + scheduled.cancel(true); + scheduled = null; } - }); + } + + @Override + public void close() { + disable(); + } } - - - + /** Synchronize the selected nodes from the manager of this Explorer. * The default implementation does nothing. */ @@ -1499,7 +1510,7 @@ public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException { // prepare wait cursor and optionally show it TreePath path = event.getPath(); - prepareWaitCursor(DragDropUtilities.secureFindNode(path.getLastPathComponent())); + maybeShowWaitCursor(DragDropUtilities.secureFindNode(path.getLastPathComponent())); } } // end of TreePropertyListener