changedUpdate exception
[fedora-idea.git] / platform / platform-impl / src / com / intellij / ui / popup / StackingPopupDispatcherImpl.java
blobe1845da7a2679ecad0b12e90ba3c791f0c4238e7
1 /*
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;
26 import javax.swing.*;
27 import java.awt.*;
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) {
45 if (inStack) {
46 myStack.push(popup);
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) {
94 return false;
97 if (myStack.isEmpty()) {
98 return false;
101 AbstractPopup popup = (AbstractPopup)findPopup();
103 final MouseEvent mouseEvent = ((MouseEvent) event);
105 Point point = (Point) mouseEvent.getPoint().clone();
106 SwingUtilities.convertPointToScreen(point, mouseEvent.getComponent());
108 while (true) {
109 if (popup != null && !popup.isDisposed()) {
110 final Component content = popup.getContent();
111 if (!content.isShowing()) {
112 popup.cancel();
113 return false;
116 final Rectangle bounds = new Rectangle(content.getLocationOnScreen(), content.getSize());
117 if (bounds.contains(point) || !popup.isCancelOnClickOutside()) {
118 return false;
121 if (!popup.canClose()){
122 return false;
124 popup.cancel(mouseEvent);
127 if (myStack.isEmpty()) {
128 return false;
131 popup = (AbstractPopup)myStack.peek();
132 if (popup == null || popup.isDisposed()) {
133 myStack.pop();
138 protected JBPopup findPopup() {
139 while(true) {
140 if (myStack.isEmpty()) break;
141 final AbstractPopup each = (AbstractPopup)myStack.peek();
142 if (each == null || each.isDisposed()) {
143 myStack.pop();
144 } else {
145 return each;
149 return null;
152 public boolean dispatchKeyEvent(final KeyEvent e) {
153 final boolean closeRequest = e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_ESCAPE && e.getModifiers() == 0;
155 JBPopup popup;
157 if (closeRequest) {
158 popup = findPopup();
159 } else {
160 popup = getFocusedPopup();
163 if (popup == null) return false;
166 if (closeRequest) {
167 if (popup.isCancelKeyEnabled()) {
168 popup.cancel();
169 return true;
173 return false;
177 @Nullable
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);
187 } else {
188 return false;
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()){
209 popup.cancel();
210 return true;
212 return false;
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;
223 return null;