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.
16 package com
.intellij
.openapi
.wm
.impl
.commands
;
18 import com
.intellij
.openapi
.diagnostic
.Logger
;
19 import com
.intellij
.openapi
.util
.ActionCallback
;
20 import com
.intellij
.openapi
.util
.Expirable
;
21 import com
.intellij
.openapi
.wm
.FocusCommand
;
22 import com
.intellij
.openapi
.wm
.FocusWatcher
;
23 import com
.intellij
.openapi
.wm
.IdeFocusManager
;
24 import com
.intellij
.openapi
.wm
.WindowManager
;
25 import com
.intellij
.openapi
.wm
.ex
.IdeFocusTraversalPolicy
;
26 import com
.intellij
.openapi
.wm
.impl
.FloatingDecorator
;
27 import com
.intellij
.openapi
.wm
.impl
.ToolWindowImpl
;
28 import com
.intellij
.openapi
.wm
.impl
.WindowManagerImpl
;
29 import com
.intellij
.openapi
.wm
.impl
.WindowWatcher
;
35 * Requests focus for the specified tool window.
37 * @author Vladimir Kondratyev
39 public final class RequestFocusInToolWindowCmd
extends FinalizableCommand
{
40 private static final Logger LOG
= Logger
.getInstance("#com.intellij.openapi.wm.impl.commands.RequestFocusInToolWindowCmd");
41 private final ToolWindowImpl myToolWindow
;
42 private final FocusWatcher myFocusWatcher
;
44 private final boolean myForced
;
45 private IdeFocusManager myFocusManager
;
46 private Expirable myTimestamp
;
48 public RequestFocusInToolWindowCmd(IdeFocusManager focusManager
, final ToolWindowImpl toolWindow
, final FocusWatcher focusWatcher
, final Runnable finishCallBack
, boolean forced
) {
49 super(finishCallBack
);
50 myToolWindow
= toolWindow
;
51 myFocusWatcher
= focusWatcher
;
53 myFocusManager
= focusManager
;
55 myTimestamp
= myFocusManager
.getTimestamp(true);
58 public final void run() {
59 myToolWindow
.getActivation().doWhenDone(new Runnable() {
61 processRequestFocus();
66 private void processRequestFocus() {
69 if (myTimestamp
.isExpired()) {
73 Component preferredFocusedComponent
= myFocusWatcher
.getFocusedComponent();
75 if (preferredFocusedComponent
== null && myToolWindow
.getContentManager().getSelectedContent() != null) {
76 preferredFocusedComponent
= myToolWindow
.getContentManager().getSelectedContent().getPreferredFocusableComponent();
77 if (preferredFocusedComponent
!= null) {
78 preferredFocusedComponent
= IdeFocusTraversalPolicy
.getPreferredFocusedComponent((JComponent
)preferredFocusedComponent
);
82 if (preferredFocusedComponent
== null) {
83 preferredFocusedComponent
= myFocusWatcher
.getNearestFocusableComponent();
84 if (preferredFocusedComponent
instanceof JComponent
) {
85 preferredFocusedComponent
= IdeFocusTraversalPolicy
.getPreferredFocusedComponent((JComponent
)preferredFocusedComponent
);
89 if (preferredFocusedComponent
!= null) {
90 // When we get remembered component this component can be already invisible
91 if (!preferredFocusedComponent
.isShowing()) {
92 preferredFocusedComponent
= null;
96 if (preferredFocusedComponent
== null) {
97 final JComponent component
= myToolWindow
.getComponent();
98 preferredFocusedComponent
= IdeFocusTraversalPolicy
.getPreferredFocusedComponent(component
);
101 // Try to focus component which is preferred one for the tool window
102 if (preferredFocusedComponent
!= null) {
103 requestFocus(preferredFocusedComponent
).doWhenDone(new Runnable() {
110 // If there is no preferred component then try to focus tool window itself
111 final JComponent componentToFocus
= myToolWindow
.getComponent();
112 requestFocus(componentToFocus
).doWhenDone(new Runnable() {
124 private void bringOwnerToFront() {
125 final Window owner
= SwingUtilities
.getWindowAncestor(myToolWindow
.getComponent());
126 //if (owner == null) {
127 // System.out.println("owner = " + owner);
130 // if owner is active window or it has active child window which isn't floating decorator then
131 // don't bring owner window to font. If we will make toFront every time then it's possible
132 // the following situation:
133 // 1. user prform refactoring
134 // 2. "Do not show preview" dialog is popping up.
135 // 3. At that time "preview" tool window is being activated and modal "don't show..." dialog
137 if (owner
!= null && owner
.getFocusOwner() == null) {
138 final Window activeWindow
= getActiveWindow(owner
.getOwnedWindows());
139 if (activeWindow
== null || (activeWindow
instanceof FloatingDecorator
)) {
140 LOG
.debug("owner.toFront()");
141 //Thread.dumpStack();
142 //System.out.println("------------------------------------------------------");
149 private ActionCallback
requestFocus(final Component c
) {
150 ActionCallback result
= new ActionCallback();
151 final Component owner
= KeyboardFocusManager
.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
152 if (owner
!= null && owner
== c
) {
153 myManager
.getFocusManager().requestFocus(new FocusCommand() {
154 public ActionCallback
run() {
155 return new ActionCallback
.Done();
157 }, myForced
).doWhenProcessed(new Runnable() {
164 myManager
.getFocusManager().requestFocus(new FocusCommand
.ByComponent(c
, myToolWindow
.getComponent()), myForced
).doWhenProcessed(new Runnable() {
174 private void updateToolWindow(Component c
) {
175 if (c
.isFocusOwner()) {
176 myFocusWatcher
.setFocusedComponentImpl(c
);
177 if (myToolWindow
.isAvailable() && !myToolWindow
.isActive()) {
178 myToolWindow
.activate(null, true, false);
182 updateFocusedComponentForWatcher(c
);
185 private void updateFocusedComponentForWatcher(final Component c
) {
186 final WindowWatcher watcher
= ((WindowManagerImpl
)WindowManager
.getInstance()).getWindowWatcher();
187 final FocusWatcher focusWatcher
= watcher
.getFocusWatcherFor(c
);
188 if (focusWatcher
!= null && c
.isFocusOwner()) {
189 focusWatcher
.setFocusedComponentImpl(c
);
194 * @return first active window from hierarchy with specified roots. Returns <code>null</code>
195 * if there is no active window in the hierarchy.
197 private Window
getActiveWindow(final Window
[] windows
) {
198 for (int i
= 0; i
< windows
.length
; i
++) {
199 Window window
= windows
[i
];
200 if (window
.isShowing() && window
.isActive()) {
203 window
= getActiveWindow(window
.getOwnedWindows());
204 if (window
!= null) {