diff options
Diffstat (limited to 'platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java')
-rw-r--r-- | platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java | 786 |
1 files changed, 411 insertions, 375 deletions
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java index 723956ef9daa..c5a9b01c4d21 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java @@ -39,6 +39,7 @@ import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.keymap.ex.KeymapManagerEx; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.project.ProjectType; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; @@ -71,28 +72,6 @@ import java.util.*; import java.util.List; public final class ActionManagerImpl extends ActionManagerEx implements ApplicationComponent { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.actionSystem.impl.ActionManagerImpl"); - private static final int DEACTIVATED_TIMER_DELAY = 5000; - private static final int TIMER_DELAY = 500; - private static final int UPDATE_DELAY_AFTER_TYPING = 500; - - private final Object myLock = new Object(); - private final Map<String,Object> myId2Action = new THashMap<String, Object>(); - private final Map<PluginId, THashSet<String>> myPlugin2Id = new THashMap<PluginId, THashSet<String>>(); - private final TObjectIntHashMap<String> myId2Index = new TObjectIntHashMap<String>(); - private final Map<Object,String> myAction2Id = new THashMap<Object, String>(); - private final MultiMap<String,String> myId2GroupId = new MultiMap<String, String>(); - private final List<String> myNotRegisteredInternalActionIds = new ArrayList<String>(); - private MyTimer myTimer; - - private int myRegisteredActionsCount; - private final List<AnActionListener> myActionListeners = ContainerUtil.createLockFreeCopyOnWriteList(); - private String myLastPreformedActionId; - private final KeymapManager myKeymapManager; - private final DataManager myDataManager; - private String myPrevPerformedActionId; - private long myLastTimeEditorWasTypedIn = 0; - @NonNls public static final String ACTION_ELEMENT_NAME = "action"; @NonNls public static final String GROUP_ELEMENT_NAME = "group"; @NonNls public static final String ACTIONS_ELEMENT_NAME = "actions"; @@ -130,14 +109,32 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat @NonNls public static final String USE_SHORTCUT_OF_ATTR_NAME = "use-shortcut-of"; @NonNls public static final String OVERRIDES_ATTR_NAME = "overrides"; @NonNls public static final String KEEP_CONTENT_ATTR_NAME = "keep-content"; - + @NonNls public static final String PROJECT_TYPE = "project-type"; + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.actionSystem.impl.ActionManagerImpl"); + private static final int DEACTIVATED_TIMER_DELAY = 5000; + private static final int TIMER_DELAY = 500; + private static final int UPDATE_DELAY_AFTER_TYPING = 500; + private final Object myLock = new Object(); + private final Map<String,AnAction> myId2Action = new THashMap<String, AnAction>(); + private final Map<PluginId, THashSet<String>> myPlugin2Id = new THashMap<PluginId, THashSet<String>>(); + private final TObjectIntHashMap<String> myId2Index = new TObjectIntHashMap<String>(); + private final Map<Object,String> myAction2Id = new THashMap<Object, String>(); + private final MultiMap<String,String> myId2GroupId = new MultiMap<String, String>(); + private final List<String> myNotRegisteredInternalActionIds = new ArrayList<String>(); + private final List<AnActionListener> myActionListeners = ContainerUtil.createLockFreeCopyOnWriteList(); + private final KeymapManager myKeymapManager; + private final DataManager myDataManager; private final List<ActionPopupMenuImpl> myPopups = new ArrayList<ActionPopupMenuImpl>(); - private final Map<AnAction, DataContext> myQueuedNotifications = new LinkedHashMap<AnAction, DataContext>(); private final Map<AnAction, AnActionEvent> myQueuedNotificationsEvents = new LinkedHashMap<AnAction, AnActionEvent>(); - + private MyTimer myTimer; + private int myRegisteredActionsCount; + private String myLastPreformedActionId; + private String myPrevPerformedActionId; + private long myLastTimeEditorWasTypedIn = 0; private Runnable myPreloadActionsRunnable; private boolean myTransparentOnlyUpdate; + private int myActionsPreloaded = 0; ActionManagerImpl(KeymapManager keymapManager, DataManager dataManager) { myKeymapManager = keymapManager; @@ -146,6 +143,257 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat registerPluginActions(); } + static AnAction convertStub(ActionStub stub) { + Object obj; + String className = stub.getClassName(); + try { + Class<?> aClass = Class.forName(className, true, stub.getLoader()); + obj = ReflectionUtil.newInstance(aClass); + } + catch (ClassNotFoundException e) { + PluginId pluginId = stub.getPluginId(); + if (pluginId != null) { + throw new PluginException("class with name \"" + className + "\" not found", e, pluginId); + } + else { + throw new IllegalStateException("class with name \"" + className + "\" not found"); + } + } + catch(UnsupportedClassVersionError e) { + PluginId pluginId = stub.getPluginId(); + if (pluginId != null) { + throw new PluginException(e, pluginId); + } + else { + throw new IllegalStateException(e); + } + } + catch (Exception e) { + PluginId pluginId = stub.getPluginId(); + if (pluginId != null) { + throw new PluginException("cannot create class \"" + className + "\"", e, pluginId); + } + else { + throw new IllegalStateException("cannot create class \"" + className + "\"", e); + } + } + + if (!(obj instanceof AnAction)) { + throw new IllegalStateException("class with name '" + className + "' must be an instance of '" + AnAction.class.getName()+"'; got "+obj); + } + + AnAction anAction = (AnAction)obj; + stub.initAction(anAction); + if (StringUtil.isNotEmpty(stub.getText())) { + anAction.getTemplatePresentation().setText(stub.getText()); + } + String iconPath = stub.getIconPath(); + if (iconPath != null) { + Class<? extends AnAction> actionClass = anAction.getClass(); + setIconFromClass(actionClass, actionClass.getClassLoader(), iconPath, anAction.getTemplatePresentation(), stub.getPluginId()); + } + return anAction; + } + + private static void processAbbreviationNode(Element e, String id) { + final String abbr = e.getAttributeValue(VALUE_ATTR_NAME); + if (!StringUtil.isEmpty(abbr)) { + final AbbreviationManagerImpl abbreviationManager = ((AbbreviationManagerImpl)AbbreviationManager.getInstance()); + abbreviationManager.register(abbr, id, true); + } + } + + @Nullable + private static ResourceBundle getActionsResourceBundle(ClassLoader loader, IdeaPluginDescriptor plugin) { + @NonNls final String resBundleName = plugin != null && !"com.intellij".equals(plugin.getPluginId().getIdString()) + ? plugin.getResourceBundleBaseName() : ACTIONS_BUNDLE; + ResourceBundle bundle = null; + if (resBundleName != null) { + bundle = AbstractBundle.getResourceBundle(resBundleName, loader); + } + return bundle; + } + + private static boolean isSecondary(Element element) { + return "true".equalsIgnoreCase(element.getAttributeValue(SECONDARY)); + } + + private static void setIcon(@Nullable final String iconPath, + @NotNull String className, + @NotNull ClassLoader loader, + @NotNull Presentation presentation, + final PluginId pluginId) { + if (iconPath == null) return; + + try { + final Class actionClass = Class.forName(className, true, loader); + setIconFromClass(actionClass, loader, iconPath, presentation, pluginId); + } + catch (ClassNotFoundException e) { + LOG.error(e); + reportActionError(pluginId, "class with name \"" + className + "\" not found"); + } + catch (NoClassDefFoundError e) { + LOG.error(e); + reportActionError(pluginId, "class with name \"" + className + "\" not found"); + } + } + + private static void setIconFromClass(@NotNull final Class actionClass, + @NotNull final ClassLoader classLoader, + @NotNull final String iconPath, + @NotNull Presentation presentation, + final PluginId pluginId) { + final IconLoader.LazyIcon lazyIcon = new IconLoader.LazyIcon() { + @Override + protected Icon compute() { + //try to find icon in idea class path + Icon icon = IconLoader.findIcon(iconPath, actionClass, true); + if (icon == null) { + icon = IconLoader.findIcon(iconPath, classLoader); + } + + if (icon == null) { + reportActionError(pluginId, "Icon cannot be found in '" + iconPath + "', action '" + actionClass + "'"); + } + + return icon; + } + + @Override + public String toString() { + return "LazyIcon@ActionManagerImpl (path: " + iconPath + ", action class: " + actionClass + ")"; + } + }; + + if (!Registry.is("ide.lazyIconLoading")) { + lazyIcon.load(); + } + + presentation.setIcon(lazyIcon); + } + + private static String loadDescriptionForElement(final Element element, final ResourceBundle bundle, final String id, String elementType) { + final String value = element.getAttributeValue(DESCRIPTION); + if (bundle != null) { + @NonNls final String key = elementType + "." + id + ".description"; + return CommonBundle.messageOrDefault(bundle, key, value == null ? "" : value); + } else { + return value; + } + } + + private static String loadTextForElement(final Element element, final ResourceBundle bundle, final String id, String elementType) { + final String value = element.getAttributeValue(TEXT_ATTR_NAME); + return CommonBundle.messageOrDefault(bundle, elementType + "." + id + "." + TEXT_ATTR_NAME, value == null ? "" : value); + } + + public static boolean checkRelativeToAction(final String relativeToActionId, + @NotNull final Anchor anchor, + @NotNull final String actionName, + @Nullable final PluginId pluginId) { + if ((Anchor.BEFORE == anchor || Anchor.AFTER == anchor) && relativeToActionId == null) { + reportActionError(pluginId, actionName + ": \"relative-to-action\" cannot be null if anchor is \"after\" or \"before\""); + return false; + } + return true; + } + + @Nullable + public static Anchor parseAnchor(final String anchorStr, + @Nullable final String actionName, + @Nullable final PluginId pluginId) { + if (anchorStr == null) { + return Anchor.LAST; + } + + if (FIRST.equalsIgnoreCase(anchorStr)) { + return Anchor.FIRST; + } + else if (LAST.equalsIgnoreCase(anchorStr)) { + return Anchor.LAST; + } + else if (BEFORE.equalsIgnoreCase(anchorStr)) { + return Anchor.BEFORE; + } + else if (AFTER.equalsIgnoreCase(anchorStr)) { + return Anchor.AFTER; + } + else { + reportActionError(pluginId, actionName + ": anchor should be one of the following constants: \"first\", \"last\", \"before\" or \"after\""); + return null; + } + } + + private static void processMouseShortcutNode(Element element, String actionId, PluginId pluginId) { + String keystrokeString = element.getAttributeValue(KEYSTROKE_ATTR_NAME); + if (keystrokeString == null || keystrokeString.trim().isEmpty()) { + reportActionError(pluginId, "\"keystroke\" attribute must be specified for action with id=" + actionId); + return; + } + MouseShortcut shortcut; + try { + shortcut = KeymapUtil.parseMouseShortcut(keystrokeString); + } + catch (Exception ex) { + reportActionError(pluginId, "\"keystroke\" attribute has invalid value for action with id=" + actionId); + return; + } + + String keymapName = element.getAttributeValue(KEYMAP_ATTR_NAME); + if (keymapName == null || keymapName.isEmpty()) { + reportActionError(pluginId, "attribute \"keymap\" should be defined"); + return; + } + Keymap keymap = KeymapManager.getInstance().getKeymap(keymapName); + if (keymap == null) { + reportActionError(pluginId, "keymap \"" + keymapName + "\" not found"); + return; + } + + final String removeOption = element.getAttributeValue(REMOVE_SHORTCUT_ATTR_NAME); + if (Boolean.valueOf(removeOption)) { + keymap.removeShortcut(actionId, shortcut); + } else { + keymap.addShortcut(actionId, shortcut); + } + } + + private static void assertActionIsGroupOrStub(final AnAction action) { + if (!(action instanceof ActionGroup || action instanceof ActionStub)) { + LOG.error("Action : " + action + "; class: " + action.getClass()); + } + } + + private static void reportActionError(final PluginId pluginId, @NonNls @NotNull String message) { + if (pluginId == null) { + LOG.error(message); + } + else { + LOG.error(new PluginException(message, null, pluginId)); + } + } + + @NonNls + private static String getPluginInfo(@Nullable PluginId id) { + if (id != null) { + final IdeaPluginDescriptor plugin = PluginManager.getPlugin(id); + if (plugin != null) { + String name = plugin.getName(); + if (name == null) { + name = id.getIdString(); + } + return " Plugin: " + name; + } + } + return ""; + } + + private static DataContext getContextBy(Component contextComponent) { + final DataManager dataManager = DataManager.getInstance(); + return contextComponent != null ? dataManager.getDataContext(contextComponent) : dataManager.getDataContext(); + } + @Override public void initComponent() {} @@ -213,7 +461,6 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat return new ActionToolbarImpl(place, group, horizontal, decorateButtons, myDataManager, this, (KeymapManagerEx)myKeymapManager); } - private void registerPluginActions() { final IdeaPluginDescriptor[] plugins = PluginManagerCore.getPlugins(); for (IdeaPluginDescriptor plugin : plugins) { @@ -229,12 +476,28 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat @Override public AnAction getAction(@NotNull String id) { - return getActionImpl(id, false); + return getActionImpl(id, false, null); } - private AnAction getActionImpl(String id, boolean canReturnStub) { + @Override + public AnAction getAction(@NonNls @NotNull String actionId, @Nullable ProjectType projectType) { + return getActionImpl(actionId, false, projectType); + } + + private AnAction getActionImpl(String id, boolean canReturnStub, ProjectType projectType) { synchronized (myLock) { - AnAction action = (AnAction)myId2Action.get(id); + AnAction action; + Object o = myId2Action.get(id); + if (o == null) { + return null; + } + if (o instanceof AnAction) { + action = (AnAction)o; + } + else { + //noinspection unchecked + action = ((Map<ProjectType, AnAction>)o).get(projectType); + } if (!canReturnStub && action instanceof ActionStub) { action = convert((ActionStub)action); } @@ -252,61 +515,14 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat LOG.assertTrue(myId2Action.containsKey(stub.getId())); - AnAction action = (AnAction)myId2Action.remove(stub.getId()); + AnAction action = myId2Action.remove(stub.getId()); LOG.assertTrue(action != null); LOG.assertTrue(action.equals(stub)); - Object obj; - String className = stub.getClassName(); - try { - Class<?> aClass = Class.forName(className, true, stub.getLoader()); - obj = ReflectionUtil.newInstance(aClass); - } - catch (ClassNotFoundException e) { - PluginId pluginId = stub.getPluginId(); - if (pluginId != null) { - throw new PluginException("class with name \"" + className + "\" not found", e, pluginId); - } - else { - throw new IllegalStateException("class with name \"" + className + "\" not found"); - } - } - catch(UnsupportedClassVersionError e) { - PluginId pluginId = stub.getPluginId(); - if (pluginId != null) { - throw new PluginException(e, pluginId); - } - else { - throw new IllegalStateException(e); - } - } - catch (Exception e) { - PluginId pluginId = stub.getPluginId(); - if (pluginId != null) { - throw new PluginException("cannot create class \"" + className + "\"", e, pluginId); - } - else { - throw new IllegalStateException("cannot create class \"" + className + "\"", e); - } - } - - if (!(obj instanceof AnAction)) { - throw new IllegalStateException("class with name '" + className + "' must be an instance of '" + AnAction.class.getName()+"'; got "+obj); - } + AnAction anAction = convertStub(stub); - AnAction anAction = (AnAction)obj; - stub.initAction(anAction); - if (StringUtil.isNotEmpty(stub.getText())) { - anAction.getTemplatePresentation().setText(stub.getText()); - } - String iconPath = stub.getIconPath(); - if (iconPath != null) { - Class<? extends AnAction> actionClass = anAction.getClass(); - setIconFromClass(actionClass, actionClass.getClassLoader(), iconPath, anAction.getTemplatePresentation(), stub.getPluginId()); - } - - myId2Action.put(stub.getId(), obj); - myAction2Id.put(obj, stub.getId()); + addToMap(stub.getId(), anAction, stub.getPluginId(), stub.getProjectType() == null ? null : new ProjectType(stub.getProjectType())); + myAction2Id.put(anAction, stub.getId()); return anAction; } @@ -334,7 +550,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat @Override public boolean isGroup(@NotNull String actionId) { - return getActionImpl(actionId, true) instanceof ActionGroup; + return getActionImpl(actionId, true, null) instanceof ActionGroup; } @Override @@ -344,7 +560,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat @Override public AnAction getActionOrStub(String id) { - return getActionImpl(id, true); + return getActionImpl(id, true, null); } /** @@ -386,7 +602,8 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat return null; } - ActionStub stub = new ActionStub(className, id, text, loader, pluginId, iconPath); + String projectType = element.getAttributeValue(PROJECT_TYPE); + ActionStub stub = new ActionStub(className, id, text, loader, pluginId, iconPath, projectType); Presentation presentation = stub.getTemplatePresentation(); presentation.setText(text); @@ -441,99 +658,6 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat } } - private static void processAbbreviationNode(Element e, String id) { - final String abbr = e.getAttributeValue(VALUE_ATTR_NAME); - if (!StringUtil.isEmpty(abbr)) { - final AbbreviationManagerImpl abbreviationManager = ((AbbreviationManagerImpl)AbbreviationManager.getInstance()); - abbreviationManager.register(abbr, id, true); - } - } - - @Nullable - private static ResourceBundle getActionsResourceBundle(ClassLoader loader, IdeaPluginDescriptor plugin) { - @NonNls final String resBundleName = plugin != null && !"com.intellij".equals(plugin.getPluginId().getIdString()) - ? plugin.getResourceBundleBaseName() : ACTIONS_BUNDLE; - ResourceBundle bundle = null; - if (resBundleName != null) { - bundle = AbstractBundle.getResourceBundle(resBundleName, loader); - } - return bundle; - } - - private static boolean isSecondary(Element element) { - return "true".equalsIgnoreCase(element.getAttributeValue(SECONDARY)); - } - - private static void setIcon(@Nullable final String iconPath, - @NotNull String className, - @NotNull ClassLoader loader, - @NotNull Presentation presentation, - final PluginId pluginId) { - if (iconPath == null) return; - - try { - final Class actionClass = Class.forName(className, true, loader); - setIconFromClass(actionClass, loader, iconPath, presentation, pluginId); - } - catch (ClassNotFoundException e) { - LOG.error(e); - reportActionError(pluginId, "class with name \"" + className + "\" not found"); - } - catch (NoClassDefFoundError e) { - LOG.error(e); - reportActionError(pluginId, "class with name \"" + className + "\" not found"); - } - } - - private static void setIconFromClass(@NotNull final Class actionClass, - @NotNull final ClassLoader classLoader, - @NotNull final String iconPath, - @NotNull Presentation presentation, - final PluginId pluginId) { - final IconLoader.LazyIcon lazyIcon = new IconLoader.LazyIcon() { - @Override - protected Icon compute() { - //try to find icon in idea class path - Icon icon = IconLoader.findIcon(iconPath, actionClass, true); - if (icon == null) { - icon = IconLoader.findIcon(iconPath, classLoader); - } - - if (icon == null) { - reportActionError(pluginId, "Icon cannot be found in '" + iconPath + "', action '" + actionClass + "'"); - } - - return icon; - } - - @Override - public String toString() { - return "LazyIcon@ActionManagerImpl (path: " + iconPath + ", action class: " + actionClass + ")"; - } - }; - - if (!Registry.is("ide.lazyIconLoading")) { - lazyIcon.load(); - } - - presentation.setIcon(lazyIcon); - } - - private static String loadDescriptionForElement(final Element element, final ResourceBundle bundle, final String id, String elementType) { - final String value = element.getAttributeValue(DESCRIPTION); - if (bundle != null) { - @NonNls final String key = elementType + "." + id + ".description"; - return CommonBundle.messageOrDefault(bundle, key, value == null ? "" : value); - } else { - return value; - } - } - - private static String loadTextForElement(final Element element, final ResourceBundle bundle, final String id, String elementType) { - final String value = element.getAttributeValue(TEXT_ATTR_NAME); - return CommonBundle.messageOrDefault(bundle, elementType + "." + id + "." + TEXT_ATTR_NAME, value == null ? "" : value); - } - private AnAction processGroupElement(Element element, final ClassLoader loader, PluginId pluginId) { final IdeaPluginDescriptor plugin = PluginManager.getPlugin(pluginId); ResourceBundle bundle = getActionsResourceBundle(loader, plugin); @@ -723,43 +847,6 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat myId2GroupId.putValue(myAction2Id.get(action), myAction2Id.get(group)); } - public static boolean checkRelativeToAction(final String relativeToActionId, - @NotNull final Anchor anchor, - @NotNull final String actionName, - @Nullable final PluginId pluginId) { - if ((Anchor.BEFORE == anchor || Anchor.AFTER == anchor) && relativeToActionId == null) { - reportActionError(pluginId, actionName + ": \"relative-to-action\" cannot be null if anchor is \"after\" or \"before\""); - return false; - } - return true; - } - - @Nullable - public static Anchor parseAnchor(final String anchorStr, - @Nullable final String actionName, - @Nullable final PluginId pluginId) { - if (anchorStr == null) { - return Anchor.LAST; - } - - if (FIRST.equalsIgnoreCase(anchorStr)) { - return Anchor.FIRST; - } - else if (LAST.equalsIgnoreCase(anchorStr)) { - return Anchor.LAST; - } - else if (BEFORE.equalsIgnoreCase(anchorStr)) { - return Anchor.BEFORE; - } - else if (AFTER.equalsIgnoreCase(anchorStr)) { - return Anchor.AFTER; - } - else { - reportActionError(pluginId, actionName + ": anchor should be one of the following constants: \"first\", \"last\", \"before\" or \"after\""); - return null; - } - } - @Nullable public AnAction getParentGroup(final String groupId, @Nullable final String actionName, @@ -768,10 +855,10 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat reportActionError(pluginId, actionName + ": attribute \"group-id\" should be defined"); return null; } - AnAction parentGroup = getActionImpl(groupId, true); + AnAction parentGroup = getActionImpl(groupId, true, null); if (parentGroup == null) { reportActionError(pluginId, actionName + ": group with id \"" + groupId + "\" isn't registered; action will be added to the \"Other\" group"); - parentGroup = getActionImpl(IdeActions.GROUP_OTHER_MENU, true); + parentGroup = getActionImpl(IdeActions.GROUP_OTHER_MENU, true, null); } if (!(parentGroup instanceof DefaultActionGroup)) { reportActionError(pluginId, actionName + ": group with id \"" + groupId + "\" should be instance of " + DefaultActionGroup.class.getName() + @@ -850,40 +937,6 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat } } - private static void processMouseShortcutNode(Element element, String actionId, PluginId pluginId) { - String keystrokeString = element.getAttributeValue(KEYSTROKE_ATTR_NAME); - if (keystrokeString == null || keystrokeString.trim().isEmpty()) { - reportActionError(pluginId, "\"keystroke\" attribute must be specified for action with id=" + actionId); - return; - } - MouseShortcut shortcut; - try { - shortcut = KeymapUtil.parseMouseShortcut(keystrokeString); - } - catch (Exception ex) { - reportActionError(pluginId, "\"keystroke\" attribute has invalid value for action with id=" + actionId); - return; - } - - String keymapName = element.getAttributeValue(KEYMAP_ATTR_NAME); - if (keymapName == null || keymapName.isEmpty()) { - reportActionError(pluginId, "attribute \"keymap\" should be defined"); - return; - } - Keymap keymap = KeymapManager.getInstance().getKeymap(keymapName); - if (keymap == null) { - reportActionError(pluginId, "keymap \"" + keymapName + "\" not found"); - return; - } - - final String removeOption = element.getAttributeValue(REMOVE_SHORTCUT_ATTR_NAME); - if (Boolean.valueOf(removeOption)) { - keymap.removeShortcut(actionId, shortcut); - } else { - keymap.addShortcut(actionId, shortcut); - } - } - @Nullable private AnAction processReferenceElement(Element element, PluginId pluginId) { if (!REFERENCE_ELEMENT_NAME.equals(element.getName())) { @@ -902,7 +955,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat return null; } - AnAction action = getActionImpl(ref, true); + AnAction action = getActionImpl(ref, true, null); if (action == null) { if (!myNotRegisteredInternalActionIds.contains(ref)) { @@ -936,27 +989,15 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat } } - private static void assertActionIsGroupOrStub(final AnAction action) { - if (!(action instanceof ActionGroup || action instanceof ActionStub)) { - LOG.error("Action : " + action + "; class: " + action.getClass()); - } - } - @Override public void registerAction(@NotNull String actionId, @NotNull AnAction action, @Nullable PluginId pluginId) { synchronized (myLock) { - if (myId2Action.containsKey(actionId)) { - reportActionError(pluginId, "action with the ID \"" + actionId + "\" was already registered. Action being registered is " + action + - "; Registered action is " + - myId2Action.get(actionId) + getPluginInfo(pluginId)); - return; - } + if (!addToMap(actionId, action, pluginId, null)) return; if (myAction2Id.containsKey(action)) { reportActionError(pluginId, "action was already registered for another ID. ID is " + myAction2Id.get(action) + getPluginInfo(pluginId)); return; } - myId2Action.put(actionId, action); myId2Index.put(actionId, myRegisteredActionsCount++); myAction2Id.put(action, actionId); if (pluginId != null && !(action instanceof ActionGroup)){ @@ -971,28 +1012,31 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat } } - private static void reportActionError(final PluginId pluginId, @NonNls @NotNull String message) { - if (pluginId == null) { - LOG.error(message); + public boolean addToMap(String actionId, AnAction action, PluginId pluginId, ProjectType projectType) { + if (myId2Action.containsKey(actionId)) { + // make sure id+projectType is unique + AnAction o = myId2Action.get(actionId); + ChameleonAction chameleonAction; + if (o instanceof ChameleonAction) { + chameleonAction = (ChameleonAction)o; + } + else { + chameleonAction = new ChameleonAction(o, projectType); + myId2Action.put(actionId, chameleonAction); + } + AnAction old = chameleonAction.addAction(action, projectType); + if (old != null) { + reportActionError(pluginId, + "action with the ID \"" + actionId + "\" was already registered. Action being registered is " + action + + "; Registered action is " + + myId2Action.get(actionId) + getPluginInfo(pluginId)); + return false; + } } else { - LOG.error(new PluginException(message, null, pluginId)); - } - } - - @NonNls - private static String getPluginInfo(@Nullable PluginId id) { - if (id != null) { - final IdeaPluginDescriptor plugin = PluginManager.getPlugin(id); - if (plugin != null) { - String name = plugin.getName(); - if (name == null) { - name = id.getIdString(); - } - return " Plugin: " + name; - } + myId2Action.put(actionId, action); } - return ""; + return true; } @Override @@ -1067,6 +1111,12 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat } } + //@Override + //public AnAction replaceAction(String actionId, @NotNull AnAction newAction) { + // synchronized (myLock) { + // return replaceAction(actionId, newAction, null); + // } + //} @Override public boolean isActionPopupStackEmpty() { @@ -1078,13 +1128,6 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat return myTransparentOnlyUpdate; } - //@Override - //public AnAction replaceAction(String actionId, @NotNull AnAction newAction) { - // synchronized (myLock) { - // return replaceAction(actionId, newAction, null); - // } - //} - private AnAction replaceAction(@NotNull String actionId, @NotNull AnAction newAction, @Nullable PluginId pluginId) { AnAction oldAction = getActionOrStub(actionId); if (oldAction != null) { @@ -1208,8 +1251,6 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat } } - private int myActionsPreloaded = 0; - public void preloadActions() { if (myPreloadActionsRunnable == null) { myPreloadActionsRunnable = new Runnable() { @@ -1281,6 +1322,85 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat } } + @Override + public ActionCallback tryToExecute(@NotNull final AnAction action, @NotNull final InputEvent inputEvent, @Nullable final Component contextComponent, @Nullable final String place, + boolean now) { + + final Application app = ApplicationManager.getApplication(); + assert app.isDispatchThread(); + + final ActionCallback result = new ActionCallback(); + final Runnable doRunnable = new Runnable() { + @Override + public void run() { + tryToExecuteNow(action, inputEvent, contextComponent, place, result); + } + }; + + if (now) { + doRunnable.run(); + } else { + //noinspection SSBasedInspection + SwingUtilities.invokeLater(doRunnable); + } + + return result; + } + + private void tryToExecuteNow(final AnAction action, final InputEvent inputEvent, final Component contextComponent, final String place, final ActionCallback result) { + final Presentation presentation = action.getTemplatePresentation().clone(); + + IdeFocusManager.findInstanceByContext(getContextBy(contextComponent)).doWhenFocusSettlesDown(new Runnable() { + @Override + public void run() { + final DataContext context = getContextBy(contextComponent); + + AnActionEvent event = new AnActionEvent( + inputEvent, context, + place != null ? place : ActionPlaces.UNKNOWN, + presentation, ActionManagerImpl.this, + inputEvent.getModifiersEx() + ); + + ActionUtil.performDumbAwareUpdate(action, event, false); + if (!event.getPresentation().isEnabled()) { + result.setRejected(); + return; + } + + ActionUtil.lastUpdateAndCheckDumb(action, event, false); + if (!event.getPresentation().isEnabled()) { + result.setRejected(); + return; + } + + Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(context); + if (component != null && !component.isShowing()) { + result.setRejected(); + return; + } + + fireBeforeActionPerformed(action, context, event); + + UIUtil.addAwtListener(new AWTEventListener() { + @Override + public void eventDispatched(AWTEvent event) { + if (event.getID() == WindowEvent.WINDOW_OPENED ||event.getID() == WindowEvent.WINDOW_ACTIVATED) { + if (!result.isProcessed()) { + final WindowEvent we = (WindowEvent)event; + IdeFocusManager.findInstanceByComponent(we.getWindow()).doWhenFocusSettlesDown(result.createSetDoneRunnable()); + } + } + } + }, AWTEvent.WINDOW_EVENT_MASK, result); + + ActionUtil.performActionDumbAware(action, event); + result.setDone(); + queueActionPerformedEvent(action, context, event); + } + }); + } + private class MyTimer extends Timer implements ActionListener { private final List<TimerListener> myTimerListeners = ContainerUtil.createLockFreeCopyOnWriteList(); private final List<TimerListener> myTransparentTimerListeners = ContainerUtil.createLockFreeCopyOnWriteList(); @@ -1371,88 +1491,4 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat } } } - - @Override - public ActionCallback tryToExecute(@NotNull final AnAction action, @NotNull final InputEvent inputEvent, @Nullable final Component contextComponent, @Nullable final String place, - boolean now) { - - final Application app = ApplicationManager.getApplication(); - assert app.isDispatchThread(); - - final ActionCallback result = new ActionCallback(); - final Runnable doRunnable = new Runnable() { - @Override - public void run() { - tryToExecuteNow(action, inputEvent, contextComponent, place, result); - } - }; - - if (now) { - doRunnable.run(); - } else { - //noinspection SSBasedInspection - SwingUtilities.invokeLater(doRunnable); - } - - return result; - } - - private void tryToExecuteNow(final AnAction action, final InputEvent inputEvent, final Component contextComponent, final String place, final ActionCallback result) { - final Presentation presentation = action.getTemplatePresentation().clone(); - - IdeFocusManager.findInstanceByContext(getContextBy(contextComponent)).doWhenFocusSettlesDown(new Runnable() { - @Override - public void run() { - final DataContext context = getContextBy(contextComponent); - - AnActionEvent event = new AnActionEvent( - inputEvent, context, - place != null ? place : ActionPlaces.UNKNOWN, - presentation, ActionManagerImpl.this, - inputEvent.getModifiersEx() - ); - - ActionUtil.performDumbAwareUpdate(action, event, false); - if (!event.getPresentation().isEnabled()) { - result.setRejected(); - return; - } - - ActionUtil.lastUpdateAndCheckDumb(action, event, false); - if (!event.getPresentation().isEnabled()) { - result.setRejected(); - return; - } - - Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(context); - if (component != null && !component.isShowing()) { - result.setRejected(); - return; - } - - fireBeforeActionPerformed(action, context, event); - - UIUtil.addAwtListener(new AWTEventListener() { - @Override - public void eventDispatched(AWTEvent event) { - if (event.getID() == WindowEvent.WINDOW_OPENED ||event.getID() == WindowEvent.WINDOW_ACTIVATED) { - if (!result.isProcessed()) { - final WindowEvent we = (WindowEvent)event; - IdeFocusManager.findInstanceByComponent(we.getWindow()).doWhenFocusSettlesDown(result.createSetDoneRunnable()); - } - } - } - }, AWTEvent.WINDOW_EVENT_MASK, result); - - ActionUtil.performActionDumbAware(action, event); - result.setDone(); - queueActionPerformedEvent(action, context, event); - } - }); - } - - private static DataContext getContextBy(Component contextComponent) { - final DataManager dataManager = DataManager.getInstance(); - return contextComponent != null ? dataManager.getDataContext(contextComponent) : dataManager.getDataContext(); - } } |