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
;
15 import java
.awt
.event
.MouseEvent
;
16 import java
.util
.ArrayList
;
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
){
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()) {
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
);
73 if (isModalContext
&& !action
.isEnabledInModalContext()) {
76 if (!myActions
.contains(action
)) {
77 myActions
.add(action
);
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
)) {
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
110 JRootPane root
= findRoot(e
);
113 final Integer lastId
= myRootPane2BlockedId
.get(root
);
114 if (lastId
!= null) {
115 if (e
.getID() <= lastId
.intValue()) {
116 myRootPane2BlockedId
.remove(root
);
118 myRootPane2BlockedId
.put(root
, e
.getID());
124 if (toIgnore
) return false;
126 Component component
=e
.getComponent();
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
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(),
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()) {
158 action
.actionPerformed(actionEvent
);
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();