Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Bas Leijdekkers
2011-09-19 12:57:56 +02:00
9 changed files with 164 additions and 61 deletions
@@ -18,6 +18,7 @@ package com.intellij.openapi.util;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -30,21 +31,23 @@ public class SimpleTimer {
private final Timer ourTimer;
private static final SimpleTimer ourInstance = new SimpleTimer();
@NonNls private static final String THREAD_NAME = "SimpleTimer";
private static final SimpleTimer ourInstance = newInstance("Shared SimpleTimer");
private long myNextScheduledTime = Long.MAX_VALUE;
private TimerTask myNextProcessingTask;
private final Map<Long, ArrayList<SimpleTimerTask>> myTime2Task = new TreeMap<Long, ArrayList<SimpleTimerTask>>();
private String myThreadName;
private SimpleTimer() {
private SimpleTimer(@NotNull String threadName) {
myThreadName = threadName;
final Thread thread = Thread.currentThread();
final int currentPrio = thread.getPriority();
try {
// need this becase the timer's thread will inherit the priority on creation
thread.setPriority(Thread.MIN_PRIORITY + 1);
ourTimer = new Timer(THREAD_NAME, true);
ourTimer = new Timer(threadName, true);
}
finally {
thread.setPriority(currentPrio);
@@ -54,6 +57,10 @@ public class SimpleTimer {
public static SimpleTimer getInstance() {
return ourInstance;
}
public static SimpleTimer newInstance(@NotNull String name) {
return new SimpleTimer(name);
}
public SimpleTimerTask setUp(final Runnable runnable, long delay) {
synchronized (myTime2Task) {
@@ -150,7 +157,7 @@ public class SimpleTimer {
}
public boolean isTimerThread(Thread thread) {
return THREAD_NAME.equals(thread.getName());
return myThreadName.equals(thread.getName());
}
void onCancelled(SimpleTimerTask task) {
@@ -0,0 +1,6 @@
%startTest Generate actions
%include extract_Superclass.ijs
%include newClass_projectView.ijs
%endTest
@@ -1,12 +1,15 @@
%startTest Create superclass
%startTest Create superclass from popup menu
%%include ../include/project1Init.ijs
%%action GotoClass
%%PsiManager\n
%include ../include/init.ijs
%include ../include/project1Init.ijs
%action GotoClass
FileEditorManager\n
%call checkFocus(editorTab=FileEditorManager.java)
%call contextMenu(Refactor|Extract Superclass)
TestSuperclass\n
%call checkFocus(dialog=Analyze and Replace Usages)
%call waitForDialog(Analyze and Replace Usages)
%[space]
%call waitForDialog(Use Interface Where Possible)
%[space]
%call checkFocus(editorTab=FileEditorManager.java)
%endTest
@@ -8,9 +8,9 @@ PsiManager\n
%[left]
%[left]
%[down]
%call checkFocus(navBar=module1>src>com>intellij>[testProject]>idea>PsiManager|navBarPopup=[fabrique]>idea>mps)
%call checkFocus(navBar=module1>src>com>intellij>[testProject]>idea>PsiManager|navBarPopup=fabrique>[idea]>mps)
\n
%call flushUi()
\n
%call checkFocus(editorTab=ActiveLibrary.java)
%call checkFocus(editorTab=FileEditorManager.java)
@@ -17,15 +17,28 @@ package com.intellij.openapi.util;
import com.intellij.util.ui.UIUtil;
public abstract class EdtRunnable implements Runnable {
public abstract class EdtRunnable implements ExpirableRunnable {
private boolean myExpired;
public final void run() {
UIUtil.invokeLaterIfNeeded(new Runnable() {
public void run() {
runEdt();
if (!isExpired()) {
runEdt();
}
}
});
}
public void expire() {
myExpired = true;
}
@Override
public boolean isExpired() {
return myExpired;
}
public abstract void runEdt();
}
@@ -319,10 +319,8 @@ public class DataManagerImpl extends DataManager implements ApplicationComponent
myEventCount + "; current event count = " + currentEventCount
);
*/
if (false) {
LOG.error("cannot share data context between Swing events; initial event count = " + myEventCount + "; current event count = " +
currentEventCount);
}
}
Component _component = myRef.get();
@@ -247,19 +247,25 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa
super.stop();
if (myDialog != null) {
myDialog.hide();
if (myDialog.wasShown()) {
myFocusTrackback.restoreFocus();
}
else {
myFocusTrackback.consume();
}
}
myStoppedAlready = true;
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
if (myDialog != null) {
myDialog.hide();
if (myDialog.wasShown()) {
myFocusTrackback.restoreFocus();
}
else {
myFocusTrackback.consume();
}
}
Disposer.dispose(this);
myStoppedAlready = true;
Disposer.dispose(ProgressWindow.this);
}
});
SwingUtilities.invokeLater(EmptyRunnable.INSTANCE); // Just to give blocking dispatching a chance to go out.
}
@@ -24,6 +24,9 @@ import com.intellij.openapi.ui.Queryable;
import com.intellij.openapi.ui.playback.PlaybackContext;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SimpleTimer;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.ToolWindow;
@@ -34,8 +37,10 @@ import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.AWTEventListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.util.*;
public class WindowSystemPlaybackCall {
@@ -67,6 +72,46 @@ public class WindowSystemPlaybackCall {
return result;
}
public static AsyncResult<String> waitForDialog(final PlaybackContext context, final String title) {
final AsyncResult<String> result = new AsyncResult<String>();
final Ref<AWTEventListener> listener = new Ref<AWTEventListener>();
listener.set(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
if (event.getID() == WindowEvent.WINDOW_ACTIVATED) {
final Window wnd = ((WindowEvent)event).getWindow();
if (wnd instanceof JDialog) {
if (title.equals(((JDialog)wnd).getTitle())) {
Toolkit.getDefaultToolkit().removeAWTEventListener(listener.get());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
getUiReady(context).notify(result);
}
});
}
}
}
}
});
Toolkit.getDefaultToolkit().addAWTEventListener(listener.get(), WindowEvent.WINDOW_EVENT_MASK);
SimpleTimer.getInstance().setUp(new Runnable() {
@Override
public void run() {
Toolkit.getDefaultToolkit().removeAWTEventListener(listener.get());
if (!result.isProcessed()) {
result.setRejected("Timed out waiting for window: " + title);
}
}
}, Registry.intValue("actionSystem.commandProcessingTimeout"));
return result;
}
public static AsyncResult<String> checkFocus(final PlaybackContext context, String expected) {
final AsyncResult<String> result = new AsyncResult<String>();
final Map<String, String> expectedMap = new LinkedHashMap<String, String>();
@@ -27,10 +27,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.EdtRunnable;
import com.intellij.openapi.util.Expirable;
import com.intellij.openapi.util.ExpirableRunnable;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.*;
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
@@ -79,24 +76,11 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
final EdtAlarm myFocusedComponentAlaram;
private final EdtAlarm myForcedFocusRequestsAlarm;
private SimpleTimer myTimer = SimpleTimer.newInstance("FocusManager timer");
private final EdtAlarm myIdleAlarm;
private final Set<Runnable> myIdleRequests = new LinkedHashSet<Runnable>();
private final EdtRunnable myIdleRunnable = new EdtRunnable() {
public void runEdt() {
if (canFlushIdleRequests()) {
flushIdleRequests();
}
else {
if (processFocusRevalidation()) {
if (isFocusTransferReady()) {
flushIdleRequests();
}
}
restartIdleAlarm();
}
}
};
private boolean myFlushWasDelayedToFixFocus;
private ExpirableRunnable myFocusRevalidator;
@@ -106,6 +90,24 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
private UiActivityMonitor myActivityMonitor;
private boolean myTypeaheadEnabled = true;
private class IdleRunnable extends EdtRunnable {
public void runEdt() {
if (canFlushIdleRequests()) {
flushIdleRequests();
}
else {
if (processFocusRevalidation()) {
if (isFocusTransferReady()) {
flushIdleRequests();
}
}
restartIdleAlarm();
}
}
}
private boolean canFlushIdleRequests() {
Component focusOwner = getFocusOwner();
return isFocusTransferReady()
@@ -128,9 +130,9 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
myQueue = IdeEventQueue.getInstance();
myActivityMonitor = UiActivityMonitor.getInstance();
myFocusedComponentAlaram = new EdtAlarm(this);
myForcedFocusRequestsAlarm = new EdtAlarm(this);
myIdleAlarm = new EdtAlarm(this);
myFocusedComponentAlaram = new EdtAlarm();
myForcedFocusRequestsAlarm = new EdtAlarm();
myIdleAlarm = new EdtAlarm();
final AppListener myAppListener = new AppListener();
myApp.getMessageBus().connect().subscribe(ApplicationActivationListener.TOPIC, myAppListener);
@@ -183,6 +185,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
@NotNull
public ActionCallback requestFocus(@NotNull final FocusCommand command, final boolean forced) {
assertDispatchThread();
if (isInternalMode) {
recordCommand(command, new Throwable(), forced);
}
@@ -460,7 +464,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
private void restartIdleAlarm() {
myIdleAlarm.cancelAllRequests();
myIdleAlarm.addRequest(myIdleRunnable, Registry.intValue("actionSystem.focusIdleTimeout"));
myIdleAlarm.addRequest(new IdleRunnable(), Registry.intValue("actionSystem.focusIdleTimeout"));
}
private void flushIdleRequests() {
@@ -602,6 +606,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
}
public boolean isFocusTransferReady() {
assertDispatchThread();
if (myRunContext != null) return true;
invalidateFocusRequestsQueue();
@@ -741,6 +747,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
}
public void suspendKeyProcessingUntil(@NotNull final ActionCallback done) {
assertDispatchThread();
requestFocus(new FocusCommand(done) {
public ActionCallback run() {
return done;
@@ -749,6 +757,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
}
public Expirable getTimestamp(final boolean trackOnlyForcedCommands) {
assertDispatchThread();
return new Expirable() {
long myOwnStamp = trackOnlyForcedCommands ? myForcedCmdTimestamp : myCmdTimestamp;
@@ -760,6 +770,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
@Override
public FocusRequestor getFurtherRequestor() {
assertDispatchThread();
FurtherRequestor requestor = new FurtherRequestor(this, getTimestamp(true));
myValidFurtherRequestors.add(requestor);
revalidateFurtherRequestors();
@@ -789,6 +801,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
@Override
public Component getFocusOwner() {
assertDispatchThread();
Component result = null;
if (myRunContext != null) {
result = (Component)myRunContext.getData(PlatformDataKeys.CONTEXT_COMPONENT.getName());
@@ -815,6 +829,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
@Override
public void runOnOwnContext(DataContext context, Runnable runnable) {
assertDispatchThread();
myRunContext = context;
try {
runnable.run();
@@ -825,12 +841,16 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
@Override
public Component getLastFocusedFor(IdeFrame frame) {
assertDispatchThread();
WeakReference<Component> ref = myLastFocused.get(frame);
return ref != null ? ref.get() : null;
}
@Override
public void toFront(JComponent c) {
assertDispatchThread();
if (c == null) return;
final Window window = UIUtil.getParentOfType(Window.class, c);
@@ -877,19 +897,20 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
}
static class EdtAlarm {
private final Alarm myAlarm;
private EdtAlarm(Disposable parent) {
myAlarm = new Alarm(Alarm.ThreadToUse.OWN_THREAD, parent);
}
class EdtAlarm {
private Set<EdtRunnable> myRequests = new HashSet<EdtRunnable>();
public void cancelAllRequests() {
myAlarm.cancelAllRequests();
for (EdtRunnable each : myRequests) {
each.expire();
}
myRequests.clear();
}
public void addRequest(EdtRunnable runnable, int delay) {
myAlarm.addRequest(runnable, delay);
myRequests.add(runnable);
myTimer.setUp(runnable, delay);
}
}
@@ -1018,4 +1039,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
public boolean isFocusTransferEnabled() {
return myApp.isActive() || !Registry.is("actionSystem.suspendFocusTransferIfApplicationInactive");
}
private void assertDispatchThread() {
ApplicationManager.getApplication().assertIsDispatchThread();
}
}