popups: handle final "onChosen" via focus manager
authorKirill Kalishev <kirill.kalishev@jetbrains.com>
Thu, 14 Jan 2010 11:05:51 +0000 (14:05 +0300)
committerKirill Kalishev <kirill.kalishev@jetbrains.com>
Thu, 14 Jan 2010 11:05:51 +0000 (14:05 +0300)
12 files changed:
java/debugger/impl/src/com/intellij/debugger/actions/PsiMethodListPopupStep.java
platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java
platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationAction.java
platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java
platform/platform-api/src/com/intellij/openapi/ui/popup/PopupStep.java
platform/platform-api/src/com/intellij/openapi/ui/popup/util/BaseStep.java
platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java
platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java
platform/platform-impl/src/com/intellij/ui/popup/list/ListPopupImpl.java
platform/platform-impl/src/com/intellij/ui/popup/tree/TreePopupImpl.java
plugins/ui-designer/src/com/intellij/uiDesigner/actions/PaletteListPopupStep.java

index c0f16c232003b1e6ad830f06ab5d031e4e07e751..7a6fde9805975dbbf07c81ddda2c8387ea3914ab 100644 (file)
@@ -93,6 +93,10 @@ class PsiMethodListPopupStep implements ListPopupStep {
     return FINAL_CHOICE;
   }
 
+  public Runnable getFinalRunnable() {
+    return null;
+  }
+
   public boolean hasSubstep(Object selectedValue) {
     return false;
   }
index 9db9a3fca2b7304ac0e39d12ac8c608e0ccf8759..d1e22c23e3585d1b8bd07912f26969138f8a614c 100644 (file)
@@ -63,6 +63,7 @@ class IntentionListStep implements ListPopupStep<IntentionActionWithTextCaching>
       return o1.getAction().getClass() == o2.getAction().getClass() && o1.getText().equals(o2.getText());
     }
   };
+  private Runnable myFinalRunnable;
 
   IntentionListStep(IntentionHintComponent intentionHintComponent, ShowIntentionsPass.IntentionsInfo intentions, Editor editor, PsiFile file,
                     Project project) {
@@ -163,8 +164,12 @@ class IntentionListStep implements ListPopupStep<IntentionActionWithTextCaching>
     return FINAL_CHOICE;
   }
 
+  public Runnable getFinalRunnable() {
+    return myFinalRunnable;
+  }
+
   private void applyAction(final IntentionActionWithTextCaching cachedAction) {
-    ApplicationManager.getApplication().invokeLater(new Runnable() {
+    myFinalRunnable = new Runnable() {
       public void run() {
         HintManager.getInstance().hideAllHints();
         ApplicationManager.getApplication().invokeLater(new Runnable() {
@@ -180,7 +185,7 @@ class IntentionListStep implements ListPopupStep<IntentionActionWithTextCaching>
           }
         });
       }
-    });
+    };
   }
 
   private PopupStep getSubStep(final IntentionActionWithTextCaching action) {
index a855a6b4d4c4d76587c90d0d7d5853008d1ef84e..93db0c5722f9a56962beef2dd035d8546dce326c 100644 (file)
@@ -614,13 +614,11 @@ public class ChooseRunConfigurationAction extends AnAction {
       if (myAction.myEditConfiguration) {
         final Object o = wrapper.getValue();
         if (o instanceof RunnerAndConfigurationSettingsImpl) {
-          SwingUtilities.invokeLater(new Runnable() {
+          return doFinalStep(new Runnable() {
             public void run() {
               myAction.editConfiguration(myProject, (RunnerAndConfigurationSettingsImpl)o);
             }
           });
-
-          return FINAL_CHOICE;
         }
       }
 
@@ -628,7 +626,7 @@ public class ChooseRunConfigurationAction extends AnAction {
       assert executor != null;
 
       if (finalChoice && wrapper.available(executor)) {
-        SwingUtilities.invokeLater(new Runnable() {
+        return doFinalStep(new Runnable() {
           public void run() {
             if (executor == myAction.getAlternateExecutor()) {
               PropertiesComponent.getInstance().setValue(myAction.getAdKey(), Boolean.toString(true));
@@ -637,8 +635,6 @@ public class ChooseRunConfigurationAction extends AnAction {
             wrapper.perform(myProject, executor, DataManager.getInstance().getDataContext());
           }
         });
-
-        return FINAL_CHOICE;
       }
       else {
         return wrapper.getNextStep(myProject, myAction);
@@ -715,13 +711,11 @@ public class ChooseRunConfigurationAction extends AnAction {
 
     @Override
     public PopupStep onChosen(final ActionWrapper selectedValue, boolean finalChoice) {
-      SwingUtilities.invokeLater(new Runnable() {
+      return doFinalStep(new Runnable() {
         public void run() {
           selectedValue.perform();
         }
       });
-
-      return FINAL_CHOICE;
     }
 
     @Override
index e32949479e2ec8c28b4f389fa15f376e96c4d655..7210208d166946fe1c49e9e318eee7d4fbb2b4a5 100644 (file)
@@ -48,6 +48,8 @@ public class ComboBoxTableRenderer<T> extends JLabel implements TableCellRendere
 
   protected EventListenerList myListenerList = new EventListenerList();
 
+  private Runnable myFinalRunnable;
+
   public ComboBoxTableRenderer(final T[] values) {
     myValues = values;
     setFont(UIUtil.getButtonFont());
@@ -71,14 +73,16 @@ public class ComboBoxTableRenderer<T> extends JLabel implements TableCellRendere
     return value.toString();
   }
 
-  protected void onChosen(@NotNull final T value) {
+
+
+  protected Runnable onChosen(@NotNull final T value) {
     stopCellEditing(value);
 
-    SwingUtilities.invokeLater(new Runnable() {
+    return new Runnable() {
       public void run() {
         stopCellEditing(value);
       }
-    });
+    };
   }
 
   @Override
@@ -117,13 +121,17 @@ public class ComboBoxTableRenderer<T> extends JLabel implements TableCellRendere
       }
 
       public PopupStep onChosen(T selectedValue, boolean finalChoice) {
-        ComboBoxTableRenderer.this.onChosen(selectedValue);
+        myFinalRunnable = ComboBoxTableRenderer.this.onChosen(selectedValue);
         return FINAL_CHOICE;
       }
 
       public void canceled() {
         ComboBoxTableRenderer.this.cancelCellEditing();
       }
+
+      public Runnable getFinalRunnable() {
+        return myFinalRunnable;
+      }
     });
 
     popup.addListener(this);
index 7075e84dd6cd0242cc3558c1b8ab010fa2102ecf..2d9738d5392b54c8de75d8c0bc9ceba5966d444a 100644 (file)
@@ -102,4 +102,10 @@ public interface PopupStep<T> {
    * @return true if the submenu for the first selectable item should be displayed automatically, false otherwise.
    */
   boolean isAutoSelectionEnabled();
+
+  /**
+   * @return runnable to be executed when final step is chosen
+   */
+  @Nullable
+  Runnable getFinalRunnable();
 }
index 45a2904e3e14ae0205417e9f64adb1b3f5cbeb6c..b2028f05b6b9fb011a26fd0c3054017e1bed65d8 100644 (file)
@@ -22,6 +22,8 @@ import com.intellij.util.ui.UIUtil;
 
 public abstract class BaseStep<T> implements PopupStep<T>, SpeedSearchFilter<T>, MnemonicNavigationFilter<T> {
 
+  private Runnable myFinalRunnable;
+
   public boolean isSpeedSearchEnabled() {
     return false;
   }
@@ -58,4 +60,13 @@ public abstract class BaseStep<T> implements PopupStep<T>, SpeedSearchFilter<T>,
   public MnemonicNavigationFilter<T> getMnemonicNavigationFilter() {
     return this;
   }
+
+  public Runnable getFinalRunnable() {
+    return myFinalRunnable;
+  }
+
+  public PopupStep doFinalStep(Runnable runnable) {
+    myFinalRunnable = runnable;
+    return FINAL_CHOICE;
+  }
 }
index 3c2a8d22df3cd8244fff92c762b9929b7078804a..7a695c256e03ad8326b11b207478cc0280dbf7d3 100644 (file)
@@ -115,6 +115,8 @@ public class AbstractPopup implements JBPopup {
 
   protected InputEvent myDisposeEvent;
 
+  protected Runnable myFinalRunnable;
+
   protected final SpeedSearch mySpeedSearch = new SpeedSearch() {
     boolean searchFieldShown = false;
     protected void update() {
@@ -456,6 +458,9 @@ public class AbstractPopup implements JBPopup {
   public void cancel(InputEvent e) {
     if (isDisposed()) return;
 
+    final Runnable finalRunnable = myFinalRunnable;
+    final IdeFocusManager focusManager = IdeFocusManager.findInstanceByComponent(myOwner);
+
     if (myPopup != null) {
       if (!canClose()) {
         return;
@@ -496,6 +501,14 @@ public class AbstractPopup implements JBPopup {
     }
 
     Disposer.dispose(this, false);
+
+    if (finalRunnable != null) {
+      SwingUtilities.invokeLater(new Runnable() {
+        public void run() {
+          focusManager.doWhenFocusSettlesDown(finalRunnable);
+        }
+      });
+    }
   }
 
 
index 5df613d0a068657b406d2072ead3f7e3947b8a76..88f180e5dee34cc60fe08d33b06a5bda8078fd87 100644 (file)
@@ -408,6 +408,7 @@ public class PopupFactoryImpl extends JBPopupFactory {
     private final boolean myEnableMnemonics;
     private final int myDefaultOptionIndex;
     private final boolean myAutoSelectionEnabled;
+    private Runnable myFinalRunnable;
 
     private ActionPopupStep(@NotNull final List<ActionItem> items,
                            final String title,
@@ -472,21 +473,21 @@ public class PopupFactoryImpl extends JBPopupFactory {
           return JBPopupFactory.getInstance().createActionsStep((ActionGroup)action, dataContext, myEnableMnemonics, false, null, myContext, false);
       }
       else {
-        // invokeLater is required to get a chance for the popup to hide in case the action called displays modal dialog
-        SwingUtilities.invokeLater(new Runnable() {
+        myFinalRunnable = new Runnable() {
           public void run() {
-            action.actionPerformed(new AnActionEvent(null,
-                                                     dataContext,
-                                                     ActionPlaces.UNKNOWN,
-                                                     (Presentation)action.getTemplatePresentation().clone(),
-                                                     ActionManager.getInstance(),
-                                                     0));
+            action.actionPerformed(
+              new AnActionEvent(null, dataContext, ActionPlaces.UNKNOWN, (Presentation)action.getTemplatePresentation().clone(),
+                                ActionManager.getInstance(), 0));
           }
-        });
+        };
         return FINAL_CHOICE;
       }
     }
 
+    public Runnable getFinalRunnable() {
+      return myFinalRunnable;
+    }
+
     public boolean hasSubstep(final ActionItem selectedValue) {
       return selectedValue != null && selectedValue.isEnabled() && selectedValue.getAction() instanceof ActionGroup;
     }
index d1cc96b7218164bb59f34bac2c6173fc65b3b1fc..b3647a99865ab78d427b36fa911af3591bef2d99 100644 (file)
@@ -409,4 +409,11 @@ public abstract class WizardPopup extends AbstractPopup implements ActionListene
     }
   }
 
+  protected final void setFinalRunnable(Runnable runnable) {
+    if (getParent() == null) {
+      myFinalRunnable = runnable;
+    } else {
+      getParent().setFinalRunnable(runnable);
+    }
+  }
 }
index b97170169374298f1fe7637f8e3038d89069178b..e465726bc63c4831aa8b0b96961b80d5fd8145f4 100644 (file)
@@ -332,12 +332,14 @@ public class ListPopupImpl extends WizardPopup implements ListPopup {
       return false;
     }
     else {
+      setFinalRunnable(myStep.getFinalRunnable());
       disposeAllParents(e);
       setIndexForShowingChild(-1);
       return true;
     }
   }
 
+
   public void addListSelectionListener(ListSelectionListener listSelectionListener) {
     myList.addListSelectionListener(listSelectionListener);
   }
index febbacb2c4604857047811099cad87871ca6cbb7..06d214216f78c22a68d03c206bffdc9d3a204dfa 100644 (file)
@@ -323,6 +323,7 @@ public class TreePopupImpl extends WizardPopup implements TreePopup {
 
         final PopupStep queriedStep = myStep.onChosen(userObject, handleFinalChoices);
         if (queriedStep == PopupStep.FINAL_CHOICE || !hasNextStep) {
+          setFinalRunnable(myStep.getFinalRunnable());
           disposeAllParents(e);
         }
         else {
index 22b99c747b32c9487524e954ef57cf1354431691..c0917101db7bd6ee1d61c8f27c1c6717e8f1071f 100644 (file)
@@ -97,6 +97,10 @@ class PaletteListPopupStep implements ListPopupStep<ComponentItem>, SpeedSearchF
     return PopupStep.FINAL_CHOICE;
   }
 
+  public Runnable getFinalRunnable() {
+    return null;
+  }
+
   public boolean hasSubstep(final ComponentItem selectedValue) {
     return false;
   }