linux focus stealing: toFront() is done vie IdeFocusManager
[fedora-idea.git] / platform / platform-impl / src / com / intellij / openapi / wm / impl / CommandProcessor.java
blobecb1b78e5ea21f3c31a088f112687b9138c7401a
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.
16 package com.intellij.openapi.wm.impl;
18 import com.intellij.openapi.application.ApplicationManager;
19 import com.intellij.openapi.application.ModalityState;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.openapi.util.Condition;
22 import com.intellij.openapi.wm.impl.commands.FinalizableCommand;
23 import org.jetbrains.annotations.NotNull;
24 import org.jetbrains.annotations.Nullable;
26 import java.util.ArrayList;
27 import java.util.List;
29 public final class CommandProcessor implements Runnable {
30 private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.CommandProcessor");
31 private final Object myLock = new Object();
33 private final List<CommandGroup> myCommandGroupList = new ArrayList<CommandGroup>();
34 private int myCommandCount;
36 public final int getCommandCount() {
37 synchronized (myLock) {
38 return myCommandCount;
42 /**
43 * Executes passed batch of commands. Note, that the processor surround the
44 * commands with BlockFocusEventsCmd - UnbockFocusEventsCmd. It's required to
45 * prevent focus handling of events which is caused by the commands to be executed.
47 public final void execute(@NotNull List<FinalizableCommand> commandList, @NotNull Condition expired) {
48 synchronized (myLock) {
49 final boolean isBusy = myCommandCount > 0;
51 final CommandGroup commandGroup = new CommandGroup(commandList, expired);
52 myCommandGroupList.add(commandGroup);
53 myCommandCount += commandList.size();
55 if (!isBusy) {
56 run();
61 public final void run() {
62 synchronized (myLock) {
63 final CommandGroup commandGroup = getNextCommandGroup();
64 if (commandGroup == null || commandGroup.isEmpty()) return;
66 final Condition conditionForGroup = commandGroup.getExpireCondition();
68 final FinalizableCommand command = commandGroup.takeNextCommand();
69 myCommandCount--;
71 final Condition expire = command.getExpireCondition() != null ? command.getExpireCondition() : conditionForGroup;
73 if (LOG.isDebugEnabled()) {
74 LOG.debug("CommandProcessor.run " + command);
76 // max. I'm not actually quite sure this should have NON_MODAL modality but it should
77 // definitely have some since runnables in command list may (and do) request some PSI activity
78 final boolean queueNext = myCommandCount > 0;
79 ApplicationManager.getApplication().getInvokator().invokeLater(command, ModalityState.NON_MODAL, expire == null ? Condition.FALSE : expire).doWhenDone(new Runnable() {
80 public void run() {
81 if (queueNext) {
82 CommandProcessor.this.run();
85 });
89 @Nullable
90 private CommandGroup getNextCommandGroup() {
91 while (!myCommandGroupList.isEmpty()) {
92 final CommandGroup candidate = myCommandGroupList.get(0);
93 if (!candidate.isEmpty()) {
94 return candidate;
96 myCommandGroupList.remove(candidate);
99 return null;
102 private static class CommandGroup {
103 private final List<FinalizableCommand> myList;
104 private Condition myExpireCondition;
106 private CommandGroup(@NotNull List<FinalizableCommand> list, @NotNull Condition expireCondition) {
107 myList = list;
108 myExpireCondition = expireCondition;
111 public Condition getExpireCondition() {
112 return myExpireCondition;
115 public boolean isEmpty() {
116 return myList.isEmpty();
119 public FinalizableCommand takeNextCommand() {
120 FinalizableCommand command = myList.remove(0);
121 if (isEmpty()) {
122 // memory leak otherwise
123 myExpireCondition = Condition.TRUE;
125 return command;