blob: 2c681856a3289eeaa62aa7163e25c2d6c7d4d986 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Vladimir Kondratyev
*/
package com.intellij.openapi.wm.impl.commands;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.impl.EditorWindow;
import com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite;
import com.intellij.openapi.fileEditor.impl.EditorsSplitters;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Expirable;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.impl.FloatingDecorator;
import com.intellij.openapi.wm.impl.IdeFrameImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
/**
* Requests focus for the editor component.
*/
public final class RequestFocusInEditorComponentCmd extends FinalizableCommand{
private JComponent myComponent;
private final boolean myForced;
private final ActionCallback myDoneCallback;
private final IdeFocusManager myFocusManager;
private final Expirable myTimestamp;
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.commands.RequestFocusInEditorComponentCmd");
public RequestFocusInEditorComponentCmd(@NotNull final EditorsSplitters splitters, IdeFocusManager
focusManager, final Runnable finishCallBack, boolean forced){
super(finishCallBack);
boolean shouldLogFocuses = Registry.is("ide.log.focuses");
if (shouldLogFocuses) {
LOG.info(new Exception());
}
myComponent = null;
final EditorWindow window = splitters.getCurrentWindow();
if (window != null) {
final EditorWithProviderComposite editor = window.getSelectedEditor();
if (editor != null) {
myComponent = editor.getPreferredFocusedComponent();
}
}
myForced = forced;
myFocusManager = focusManager;
myDoneCallback = new ActionCallback();
myTimestamp = myFocusManager.getTimestamp(true);
}
public ActionCallback getDoneCallback() {
return myDoneCallback;
}
public final void run(){
try{
if (myTimestamp.isExpired()) {
final Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (owner != null && owner == myComponent) {
myDoneCallback.setDone();
} else {
myDoneCallback.setRejected();
}
}
final Window owner = myComponent != null ? SwingUtilities.getWindowAncestor(myComponent) : null;
if(owner==null){
myDoneCallback.setRejected();
return;
}
final Window activeFrame = IdeFrameImpl.getActiveFrame();
if (activeFrame != null && owner instanceof IdeFrameImpl && activeFrame != owner) {
myDoneCallback.setRejected();
return;
}
if(myComponent != null){
final boolean forced = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() == null;
myFocusManager.requestFocus(myComponent, myForced || forced).notifyWhenDone(myDoneCallback).doWhenDone(new Runnable() {
public void run() {
// if owner is active window or it has active child window which isn't floating decorator then
// don't bring owner window to font. If we will make toFront every time then it's possible
// the following situation:
// 1. user perform refactoring
// 2. "Do not show preview" dialog is popping up.
// 3. At that time "preview" tool window is being activated and modal "don't show..." dialog
// isn't active.
if(!owner.isActive()){
final Window activeWindow=getActiveWindow(owner.getOwnedWindows());
if(activeWindow == null || (activeWindow instanceof FloatingDecorator)){
//Thread.dumpStack();
//System.out.println("------------------------------------------------------");
owner.toFront();
}
}
}
});
} else {
myDoneCallback.setRejected();
}
}finally{
finish();
}
}
/**
* @return first active window from hierarchy with specified roots. Returns <code>null</code>
* if there is no active window in the hierarchy.
*/
@Nullable
private static Window getActiveWindow(final Window[] windows) {
for (Window window1 : windows) {
Window window = window1;
if (window.isShowing() && window.isActive()) {
return window;
}
window = getActiveWindow(window.getOwnedWindows());
if (window != null) {
return window;
}
}
return null;
}
}