|
68 | 68 | import java.util.List; |
69 | 69 | import java.util.Set; |
70 | 70 | import java.util.HashSet; |
| 71 | +import java.util.concurrent.ScheduledFuture; |
| 72 | +import java.util.concurrent.TimeUnit; |
71 | 73 | import java.util.logging.Level; |
72 | 74 | import java.util.logging.Logger; |
73 | 75 | import javax.accessibility.AccessibleContext; |
@@ -915,73 +917,82 @@ public void setAutoWaitCursor(boolean enable) { |
915 | 917 | autoWaitCursor = enable; |
916 | 918 | } |
917 | 919 |
|
918 | | - // |
919 | | - // showing and removing the wait cursor |
920 | | - // |
921 | | - private void showWaitCursor (boolean show) { |
922 | | - JRootPane rPane = getRootPane(); |
923 | | - if (rPane == null) { |
| 920 | + private void maybeShowWaitCursor(Node node) { |
| 921 | + if (node == null || !autoWaitCursor) { |
924 | 922 | return; |
925 | 923 | } |
926 | | - |
927 | | - if (SwingUtilities.isEventDispatchThread()) { |
928 | | - doShowWaitCursor(rPane.getGlassPane(), show); |
929 | | - } else { |
930 | | - SwingUtilities.invokeLater(new CursorR(rPane.getGlassPane(), show)); |
| 924 | + JRootPane rootPane = getRootPane(); |
| 925 | + if (rootPane == null) { |
| 926 | + return; |
931 | 927 | } |
| 928 | + // not sure whenter throughput 1 is OK... |
| 929 | + ViewUtil.uiProcessor().post(() -> { |
| 930 | + try (DelayedWaitCursor cursor = new DelayedWaitCursor(rootPane)) { |
| 931 | + cursor.enable(); |
| 932 | + node.getChildren().getNodesCount(true); |
| 933 | + } catch (Exception e) { |
| 934 | + LOG.log(Level.WARNING, "can't determine node count", e); |
| 935 | + } |
| 936 | + }); |
932 | 937 | } |
933 | 938 |
|
934 | | - private static void doShowWaitCursor (Component glassPane, boolean show) { |
935 | | - if (show) { |
936 | | - glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); |
937 | | - glassPane.setVisible(true); |
938 | | - } else { |
939 | | - glassPane.setVisible(false); |
940 | | - glassPane.setCursor(null); |
941 | | - } |
942 | | - } |
| 939 | + /// Shows the wait cursor after an initial delay. |
| 940 | + /// Can be used in ARM-blocks. |
| 941 | + private static class DelayedWaitCursor implements AutoCloseable { |
943 | 942 |
|
944 | | - private static class CursorR implements Runnable { |
945 | | - private Component glassPane; |
946 | | - private boolean show; |
| 943 | + private static final RequestProcessor RP = new RequestProcessor(DelayedWaitCursor.class.getName()); |
947 | 944 |
|
948 | | - private CursorR(Component cont, boolean show) { |
949 | | - this.glassPane = cont; |
950 | | - this.show = show; |
951 | | - } |
| 945 | + private static final int SPAWN_DELAY = 200; |
| 946 | + private static final int MAX_LIFE_SPAN = 60_000; |
952 | 947 |
|
953 | | - @Override |
954 | | - public void run() { |
955 | | - doShowWaitCursor(glassPane, show); |
956 | | - } |
957 | | - } |
| 948 | + private final JRootPane root; |
| 949 | + private ScheduledFuture<?> scheduled; |
958 | 950 |
|
959 | | - private void prepareWaitCursor(final Node node) { |
960 | | - // check type of node |
961 | | - if (node == null || !autoWaitCursor) { |
962 | | - return; |
| 951 | + private DelayedWaitCursor(JRootPane root) { |
| 952 | + this.root = root; |
963 | 953 | } |
964 | 954 |
|
965 | | - showWaitCursor(true); |
966 | | - // not sure whenter throughput 1 is OK... |
967 | | - ViewUtil.uiProcessor().post(new Runnable() { |
968 | | - @Override |
969 | | - public void run() { |
970 | | - try { |
971 | | - node.getChildren().getNodesCount(true); |
972 | | - } catch (Exception e) { |
973 | | - // log a exception |
974 | | - LOG.log(Level.WARNING, null, e); |
975 | | - } finally { |
976 | | - // show normal cursor above all |
977 | | - showWaitCursor(false); |
| 955 | + private void enable() { |
| 956 | + if (scheduled != null) { |
| 957 | + return; |
| 958 | + } |
| 959 | + scheduled = RP.schedule(() -> { |
| 960 | + if (!scheduled.isCancelled()) { |
| 961 | + // switch to wait |
| 962 | + SwingUtilities.invokeLater(() -> { |
| 963 | + if (!scheduled.isCancelled()) { |
| 964 | + root.getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); |
| 965 | + root.getGlassPane().setVisible(true); |
| 966 | + } |
| 967 | + }); |
| 968 | + // block to limit lifespan |
| 969 | + try { |
| 970 | + Thread.sleep(MAX_LIFE_SPAN); |
| 971 | + } catch (InterruptedException cancelled) { |
| 972 | + Thread.interrupted(); |
| 973 | + } |
978 | 974 | } |
| 975 | + // reset |
| 976 | + SwingUtilities.invokeLater(() -> { |
| 977 | + root.getGlassPane().setVisible(false); |
| 978 | + root.getGlassPane().setCursor(null); |
| 979 | + }); |
| 980 | + }, SPAWN_DELAY, TimeUnit.MILLISECONDS); |
| 981 | + } |
| 982 | + |
| 983 | + private void disable() { |
| 984 | + if (scheduled != null) { |
| 985 | + scheduled.cancel(true); |
| 986 | + scheduled = null; |
979 | 987 | } |
980 | | - }); |
| 988 | + } |
| 989 | + |
| 990 | + @Override |
| 991 | + public void close() { |
| 992 | + disable(); |
| 993 | + } |
981 | 994 | } |
982 | | - |
983 | | - |
984 | | - |
| 995 | + |
985 | 996 | /** Synchronize the selected nodes from the manager of this Explorer. |
986 | 997 | * The default implementation does nothing. |
987 | 998 | */ |
@@ -1499,7 +1510,7 @@ public void treeWillExpand(TreeExpansionEvent event) |
1499 | 1510 | throws ExpandVetoException { |
1500 | 1511 | // prepare wait cursor and optionally show it |
1501 | 1512 | TreePath path = event.getPath(); |
1502 | | - prepareWaitCursor(DragDropUtilities.secureFindNode(path.getLastPathComponent())); |
| 1513 | + maybeShowWaitCursor(DragDropUtilities.secureFindNode(path.getLastPathComponent())); |
1503 | 1514 | } |
1504 | 1515 | } |
1505 | 1516 | // end of TreePropertyListener |
|
0 commit comments