IDEADEV-36399
[fedora-idea.git] / platform-impl / src / com / intellij / openapi / keymap / impl / IdeMouseEventDispatcher.java
blobfee35d2cc231f6d3d07a21a31a033dd6070f3bf5
1 package com.intellij.openapi.keymap.impl;
3 import com.intellij.ide.DataManager;
4 import com.intellij.openapi.actionSystem.*;
5 import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
6 import com.intellij.openapi.actionSystem.impl.PresentationFactory;
7 import com.intellij.openapi.keymap.Keymap;
8 import com.intellij.openapi.keymap.KeymapManager;
9 import com.intellij.openapi.wm.impl.IdeGlassPaneImpl;
10 import com.intellij.util.containers.HashMap;
11 import com.intellij.util.ui.UIUtil;
13 import javax.swing.*;
14 import java.awt.*;
15 import java.awt.event.MouseEvent;
16 import java.util.ArrayList;
17 import java.util.Map;
19 /**
20 * TODO[vova] rewrite comments
21 * Current implementation of the dispatcher is intended to filter mouse event addressed to
22 * the editor. Also it allows to map middle mouse's button to some action.
24 * @author Vladimir Kondratyev
26 public final class IdeMouseEventDispatcher{
27 private final PresentationFactory myPresentationFactory;
28 private final ArrayList<AnAction> myActions;
30 private final Map<Container, Integer> myRootPane2BlockedId = new HashMap<Container, Integer>();
32 public IdeMouseEventDispatcher(){
33 myPresentationFactory=new PresentationFactory();
34 myActions=new ArrayList<AnAction>(1);
37 private void fillActionsList(Component component,MouseShortcut shortcut,boolean isModalContext){
38 myActions.clear();
40 // here we try to find "local" shortcuts
42 if(component instanceof JComponent){
43 ArrayList<AnAction> listOfActions = (ArrayList<AnAction>)((JComponent)component).getClientProperty(AnAction.ourClientProperty);
44 if (listOfActions != null) {
45 for (AnAction action : listOfActions) {
46 Shortcut[] shortcuts = action.getShortcutSet().getShortcuts();
47 for (Shortcut shortcut1 : shortcuts) {
48 if (shortcut.equals(shortcut1) && !myActions.contains(action)) {
49 myActions.add(action);
53 // once we've found a proper local shortcut(s), we exit
54 if (!myActions.isEmpty()) {
55 return;
60 // search in main keymap
62 KeymapManager keymapManager = KeymapManager.getInstance();
63 if (keymapManager != null) {
64 Keymap keymap = keymapManager.getActiveKeymap();
65 String[] actionIds=keymap.getActionIds(shortcut);
67 ActionManager actionManager = ActionManager.getInstance();
68 for (String actionId : actionIds) {
69 AnAction action = actionManager.getAction(actionId);
70 if (action == null) {
71 continue;
73 if (isModalContext && !action.isEnabledInModalContext()) {
74 continue;
76 if (!myActions.contains(action)) {
77 myActions.add(action);
83 /**
84 * @return <code>true</code> if and only if the passed event is already dispatched by the
85 * <code>IdeMouseEventDispatcher</code> and there is no need for any other processing of the event.
86 * If the method returns <code>false</code> then it means that the event should be delivered
87 * to normal event dispatching.
89 public boolean dispatchMouseEvent(MouseEvent e){
90 boolean toIgnore = false;
92 if (!(e.getID() == MouseEvent.MOUSE_PRESSED ||
93 e.getID() == MouseEvent.MOUSE_RELEASED ||
94 e.getID() == MouseEvent.MOUSE_CLICKED)) {
95 toIgnore = true;
99 if(
100 e.isConsumed()||
101 e.isPopupTrigger()||
102 MouseEvent.MOUSE_RELEASED!=e.getID()||
103 e.getClickCount()<1 ||// TODO[vova,anton] is it possible. it seems that yes! but how???
104 e.getButton() == MouseEvent.NOBUTTON // See #16995. It did happen
106 toIgnore = true;
110 JRootPane root = findRoot(e);
112 if (root != null) {
113 final Integer lastId = myRootPane2BlockedId.get(root);
114 if (lastId != null) {
115 if (e.getID() <= lastId.intValue()) {
116 myRootPane2BlockedId.remove(root);
117 } else {
118 myRootPane2BlockedId.put(root, e.getID());
119 return true;
124 if (toIgnore) return false;
126 Component component=e.getComponent();
127 if(component==null){
128 throw new IllegalStateException("component cannot be null");
130 component=SwingUtilities.getDeepestComponentAt(component,e.getX(),e.getY());
132 if (component instanceof IdeGlassPaneImpl) {
133 component = ((IdeGlassPaneImpl)component).getTargetComponentFor(e);
136 if(component==null){ // do nothing if component doesn't contains specified point
137 return false;
140 MouseShortcut shortcut=new MouseShortcut(e.getButton(),e.getModifiersEx(),e.getClickCount());
141 fillActionsList(component,shortcut,IdeKeyEventDispatcher.isModalContext(component));
142 ActionManagerEx actionManager=ActionManagerEx.getInstanceEx();
143 if (actionManager != null) {
144 for(int i=0;i<myActions.size();i++){
145 AnAction action=myActions.get(i);
146 DataContext dataContext=DataManager.getInstance().getDataContext(component);
147 Presentation presentation=myPresentationFactory.getPresentation(action);
148 AnActionEvent actionEvent=new AnActionEvent(e,dataContext,ActionPlaces.MAIN_MENU,presentation,
149 ActionManager.getInstance(),
150 e.getModifiers());
151 action.beforeActionPerformedUpdate(actionEvent);
152 if(presentation.isEnabled()){
153 actionManager.fireBeforeActionPerformed(action, dataContext);
154 Component c = (Component)dataContext.getData(DataConstants.CONTEXT_COMPONENT);
155 if (c != null && !c.isShowing()) {
156 continue;
158 action.actionPerformed(actionEvent);
159 e.consume();
163 return false;
166 public void blockNextEvents(final MouseEvent e) {
167 JRootPane root = findRoot(e);
168 if (root == null) return;
170 myRootPane2BlockedId.put(root, e.getID());
173 private JRootPane findRoot(MouseEvent e) {
174 Component parent = UIUtil.findUltimateParent(e.getComponent());
175 JRootPane root = null;
176 if (parent instanceof JWindow) {
177 root = ((JWindow)parent).getRootPane();
178 } else if (parent instanceof JDialog) {
179 root = ((JDialog)parent).getRootPane();
180 } else if (parent instanceof JFrame) {
181 root = ((JFrame)parent).getRootPane();
183 return root;