Skip to content

Commit e05c956

Browse files
mbienlkishalmi
andcommitted
Implement wait cursor delay for TreeView.
- initial delay for wait cursor change - adds max lifespan for reset failures - cancellable Co-authored-by: Laszlo Kishalmi <[email protected]>
1 parent 4de8ce2 commit e05c956

File tree

1 file changed

+65
-54
lines changed
  • platform/openide.explorer/src/org/openide/explorer/view

1 file changed

+65
-54
lines changed

platform/openide.explorer/src/org/openide/explorer/view/TreeView.java

Lines changed: 65 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@
6868
import java.util.List;
6969
import java.util.Set;
7070
import java.util.HashSet;
71+
import java.util.concurrent.ScheduledFuture;
72+
import java.util.concurrent.TimeUnit;
7173
import java.util.logging.Level;
7274
import java.util.logging.Logger;
7375
import javax.accessibility.AccessibleContext;
@@ -915,73 +917,82 @@ public void setAutoWaitCursor(boolean enable) {
915917
autoWaitCursor = enable;
916918
}
917919

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) {
924922
return;
925923
}
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;
931927
}
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+
});
932937
}
933938

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 {
943942

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());
947944

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;
952947

953-
@Override
954-
public void run() {
955-
doShowWaitCursor(glassPane, show);
956-
}
957-
}
948+
private final JRootPane root;
949+
private ScheduledFuture<?> scheduled;
958950

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;
963953
}
964954

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+
}
978974
}
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;
979987
}
980-
});
988+
}
989+
990+
@Override
991+
public void close() {
992+
disable();
993+
}
981994
}
982-
983-
984-
995+
985996
/** Synchronize the selected nodes from the manager of this Explorer.
986997
* The default implementation does nothing.
987998
*/
@@ -1499,7 +1510,7 @@ public void treeWillExpand(TreeExpansionEvent event)
14991510
throws ExpandVetoException {
15001511
// prepare wait cursor and optionally show it
15011512
TreePath path = event.getPath();
1502-
prepareWaitCursor(DragDropUtilities.secureFindNode(path.getLastPathComponent()));
1513+
maybeShowWaitCursor(DragDropUtilities.secureFindNode(path.getLastPathComponent()));
15031514
}
15041515
}
15051516
// end of TreePropertyListener

0 commit comments

Comments
 (0)