From 6eb70944ea0a415a1f985cd0850178e34b972b03 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 26 Nov 2012 19:40:53 +0400 Subject: [PATCH] [git] Fix blinking temporary notifications about "unregistered Git roots" IDEA-83015, IDEA-85606 PROBLEM CAUSE: Notifications blinked because 2 events were arriving from different threads almost simultaneously: creating .git, and registering the mapping. The first event initiated rescan => notification was shown. The second event initiated another rescan => notification was hidden. FIX: Queue scan requests instead of immediate scanning, and add a delay before beginning the scan. Use an Alarm (1s delay, pooled thread) instead of self-made state-aware handler. Don't queue requests: only one (the latest) is needed, because consecutive scan won't add more information. --- .../src/git4idea/roots/GitRootScanner.java | 58 ++++++------------- 1 file changed, 19 insertions(+), 39 deletions(-) diff --git a/plugins/git4idea/src/git4idea/roots/GitRootScanner.java b/plugins/git4idea/src/git4idea/roots/GitRootScanner.java index 37e15beea9d2..b67491e2cd40 100644 --- a/plugins/git4idea/src/git4idea/roots/GitRootScanner.java +++ b/plugins/git4idea/src/git4idea/roots/GitRootScanner.java @@ -17,7 +17,6 @@ package git4idea.roots; import com.intellij.ProjectTopics; import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootEvent; @@ -28,12 +27,13 @@ import com.intellij.openapi.vcs.VcsListener; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import com.intellij.util.Alarm; import com.intellij.util.messages.MessageBus; import git4idea.GitUtil; import org.jetbrains.annotations.NotNull; -import javax.swing.*; import java.util.List; +import java.util.concurrent.TimeUnit; /** * @author Kirill Likhodedov @@ -45,11 +45,13 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis private volatile boolean myProjectIsInitialized; private volatile boolean myMappingsAreReady; - private volatile boolean myScanning; - @NotNull private final Object SCAN_LOCK = new Object(); + + @NotNull private final Alarm myAlarm; + private static final long WAIT_BEFORE_SCAN = TimeUnit.SECONDS.toMillis(1); public GitRootScanner(@NotNull Project project, @NotNull Runnable executeAfterScan) { myExecuteAfterScan = executeAfterScan; + myRootProblemNotifier = GitRootProblemNotifier.getInstance(project); StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() { @Override @@ -64,7 +66,7 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, this); messageBus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, this); - myRootProblemNotifier = GitRootProblemNotifier.getInstance(project); + myAlarm = new Alarm(Alarm.ThreadToUse.OWN_THREAD, project); } @Override @@ -102,40 +104,7 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis private void scanIfReady() { if (readyToScan()) { - scan(); - } - } - - private void scan() { - if (myScanning) { - return; - } - - if (SwingUtilities.isEventDispatchThread()) { - ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { - public void run() { - scanWithLock(); - } - }); - } - else { - scanWithLock(); - } - } - - private void scanWithLock() { - synchronized (SCAN_LOCK) { - if (myScanning) { - return; - } - myScanning = true; - try { - myRootProblemNotifier.rescanAndNotifyIfNeeded(); - myExecuteAfterScan.run(); - } - finally { - myScanning = false; - } + scheduleScan(); } } @@ -143,4 +112,15 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis return myMappingsAreReady && myProjectIsInitialized; } + private void scheduleScan() { + myAlarm.cancelAllRequests(); // one scan is enough, no need to queue, they all do the same + myAlarm.addRequest(new Runnable() { + @Override + public void run() { + myRootProblemNotifier.rescanAndNotifyIfNeeded(); + myExecuteAfterScan.run(); + } + }, WAIT_BEFORE_SCAN); + } + }