2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com
.intellij
.ui
.popup
;
19 import com
.intellij
.ide
.IdeEventQueue
;
20 import com
.intellij
.openapi
.application
.ApplicationManager
;
21 import com
.intellij
.openapi
.ui
.popup
.JBPopup
;
22 import com
.intellij
.openapi
.ui
.popup
.StackingPopupDispatcher
;
23 import com
.intellij
.util
.containers
.WeakList
;
24 import org
.jetbrains
.annotations
.Nullable
;
28 import java
.awt
.event
.AWTEventListener
;
29 import java
.awt
.event
.KeyEvent
;
30 import java
.awt
.event
.MouseEvent
;
31 import java
.util
.Stack
;
33 public class StackingPopupDispatcherImpl
extends StackingPopupDispatcher
implements AWTEventListener
, KeyEventDispatcher
{
35 private final Stack
<JBPopup
> myStack
= new Stack
<JBPopup
>();
36 private final WeakList
<JBPopup
> myPersistentPopups
= new WeakList
<JBPopup
>();
38 private final WeakList
<JBPopup
> myAllPopups
= new WeakList
<JBPopup
>();
41 private StackingPopupDispatcherImpl() {
44 public void onPopupShown(JBPopup popup
, boolean inStack
) {
47 if (ApplicationManager
.getApplication() != null) {
48 IdeEventQueue
.getInstance().getPopupManager().push(getInstance());
50 } else if (popup
.isPersistent()) {
51 myPersistentPopups
.add(popup
);
54 myAllPopups
.add(popup
);
57 public void onPopupHidden(JBPopup popup
) {
58 boolean wasInStack
= myStack
.remove(popup
);
59 myPersistentPopups
.remove(popup
);
61 if (wasInStack
&& myStack
.isEmpty()) {
62 if (ApplicationManager
.getApplication() != null) {
63 IdeEventQueue
.getInstance().getPopupManager().remove(this);
67 myAllPopups
.remove(popup
);
70 public void hidePersistentPopups() {
71 final WeakList
<JBPopup
> list
= myPersistentPopups
;
72 for (JBPopup each
: list
) {
73 if (each
.isNativePopup()) {
74 each
.setUiVisible(false);
79 public void restorePersistentPopups() {
80 final WeakList
<JBPopup
> list
= myPersistentPopups
;
81 for (JBPopup each
: list
) {
82 if (each
.isNativePopup()) {
83 each
.setUiVisible(true);
88 public void eventDispatched(AWTEvent event
) {
89 dispatchMouseEvent(event
);
92 protected boolean dispatchMouseEvent(AWTEvent event
) {
93 if (event
.getID() != MouseEvent
.MOUSE_PRESSED
) {
97 if (myStack
.isEmpty()) {
101 AbstractPopup popup
= (AbstractPopup
)findPopup();
103 final MouseEvent mouseEvent
= ((MouseEvent
) event
);
105 Point point
= (Point
) mouseEvent
.getPoint().clone();
106 SwingUtilities
.convertPointToScreen(point
, mouseEvent
.getComponent());
109 if (popup
!= null && !popup
.isDisposed()) {
110 final Component content
= popup
.getContent();
111 if (!content
.isShowing()) {
116 final Rectangle bounds
= new Rectangle(content
.getLocationOnScreen(), content
.getSize());
117 if (bounds
.contains(point
) || !popup
.isCancelOnClickOutside()) {
121 if (!popup
.canClose()){
124 popup
.cancel(mouseEvent
);
127 if (myStack
.isEmpty()) {
131 popup
= (AbstractPopup
)myStack
.peek();
132 if (popup
== null || popup
.isDisposed()) {
138 protected JBPopup
findPopup() {
140 if (myStack
.isEmpty()) break;
141 final AbstractPopup each
= (AbstractPopup
)myStack
.peek();
142 if (each
== null || each
.isDisposed()) {
152 public boolean dispatchKeyEvent(final KeyEvent e
) {
153 final boolean closeRequest
= e
.getID() == KeyEvent
.KEY_PRESSED
&& e
.getKeyCode() == KeyEvent
.VK_ESCAPE
&& e
.getModifiers() == 0;
160 popup
= getFocusedPopup();
163 if (popup
== null) return false;
167 if (popup
.isCancelKeyEnabled()) {
178 public Component
getComponent() {
179 return myStack
.size() > 0 ?myStack
.peek().getContent() : null;
182 public boolean dispatch(AWTEvent event
) {
183 if (event
instanceof KeyEvent
) {
184 return dispatchKeyEvent(((KeyEvent
) event
));
185 } else if (event
instanceof MouseEvent
) {
186 return dispatchMouseEvent(event
);
192 public void requestFocus() {
193 if (myStack
.isEmpty()) return;
195 final AbstractPopup popup
= (AbstractPopup
)myStack
.peek();
196 popup
.requestFocus();
200 public boolean close() {
201 return closeActivePopup();
204 public boolean closeActivePopup() {
205 if (myStack
.isEmpty()) return false;
207 final AbstractPopup popup
= (AbstractPopup
)myStack
.pop();
208 if (popup
!= null && popup
.isVisible()){
215 public boolean isPopupFocused() {
216 return getFocusedPopup() != null;
219 private JBPopup
getFocusedPopup() {
220 for (JBPopup each
: myAllPopups
) {
221 if (each
!= null && each
.isFocused()) return each
;