|
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