IDEA-72801 (Provide keyboard shortcut for switching between project windows)

IDEA-32997 (Window menu should show open project windows)
This commit is contained in:
Bas Leijdekkers
2011-09-08 11:35:55 +02:00
parent 9077ef3e99
commit b7ebd2c3fe
9 changed files with 336 additions and 0 deletions
@@ -0,0 +1,32 @@
/*
* Copyright 2000-2011 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.
*/
package com.intellij.openapi.wm.impl;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAware;
public class NextProjectWindow extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
WindowDressing.getWindowActionGroup().activateNextWindow(e);
}
@Override
public void update(AnActionEvent e) {
e.getPresentation().setEnabled(WindowDressing.getWindowActionGroup().isEnabled());
}
}
@@ -0,0 +1,32 @@
/*
* Copyright 2000-2011 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.
*/
package com.intellij.openapi.wm.impl;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAware;
public class PreviousProjectWindow extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
WindowDressing.getWindowActionGroup().activatePreviousWindow(e);
}
@Override
public void update(AnActionEvent e) {
e.getPresentation().setEnabled(WindowDressing.getWindowActionGroup().isEnabled());
}
}
@@ -0,0 +1,114 @@
/*
* Copyright 2000-2011 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.
*/
package com.intellij.openapi.wm.impl;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.wm.WindowManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
/**
* This class is programmatically instantiated and registered when opening and closing projects
* and thus not registered in plugin.xml
*/
@SuppressWarnings({"ComponentNotRegistered"})
public class ProjectWindowAction extends ToggleAction implements DumbAware {
private ProjectWindowAction previous;
private ProjectWindowAction next;
public ProjectWindowAction(@NotNull String projectName, ProjectWindowAction previous) {
super(projectName);
if (previous != null) {
this.previous = previous;
this.next = previous.next;
previous.next = this;
if (previous.previous == previous) {
previous.previous = this;
}
} else {
this.previous = this;
this.next = this;
}
}
public void dispose() {
if (previous == this) {
assert next == this;
return;
}
if (next == this) {
assert false;
return;
}
previous.next = next;
next.previous = previous;
}
public ProjectWindowAction getPrevious() {
return previous;
}
public ProjectWindowAction getNext() {
return next;
}
@Nullable
public static Frame findProjectFrame(@NotNull String projectName) {
final Project[] projects = ProjectManager.getInstance().getOpenProjects();
for (Project project : projects) {
if (projectName.equals(project.getName())) {
final WindowManager windowManager = WindowManager.getInstance();
return windowManager.getFrame(project);
}
}
return null;
}
public boolean isSelected(AnActionEvent e) {
// show check mark for active and visible project frame
final Project project = e.getData(PlatformDataKeys.PROJECT);
if (project == null) {
return false;
}
final String text = getTemplatePresentation().getText();
return text.equals(project.getName());
}
public void setSelected(@Nullable AnActionEvent e, boolean selected) {
if (!selected) {
return;
}
final Frame projectFrame = findProjectFrame(getTemplatePresentation().getText());
if (projectFrame == null) {
return;
}
final int frameState = projectFrame.getExtendedState();
if ((frameState & Frame.ICONIFIED) == Frame.ICONIFIED) {
// restore the frame if it is minimized
projectFrame.setExtendedState(frameState ^ Frame.ICONIFIED);
}
// bring the frame forward
projectFrame.toFront();
}
}
@@ -0,0 +1,98 @@
/*
* Copyright 2000-2011 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.
*/
package com.intellij.openapi.wm.impl;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
public class ProjectWindowActionGroup extends DefaultActionGroup {
private ProjectWindowAction latest = null;
public void addProject(@NotNull String name) {
final ProjectWindowAction windowAction = new ProjectWindowAction(name, latest);
add(windowAction);
latest = windowAction;
}
public void removeProject(@NotNull String name) {
final ProjectWindowAction windowAction = findWindowAction(name);
if (windowAction == null) {
return;
}
if (latest == windowAction) {
final ProjectWindowAction previous = latest.getPrevious();
if (previous != latest) {
latest = previous;
} else {
latest = null;
}
}
windowAction.dispose();
remove(windowAction);
}
public boolean isEnabled() {
return latest.getPrevious() != latest;
}
@Override
public boolean isDumbAware() {
return true;
}
public void activateNextWindow(AnActionEvent e) {
final Project project = e.getData(PlatformDataKeys.PROJECT);
if (project == null) {
return;
}
final ProjectWindowAction windowAction = findWindowAction(project.getName());
final ProjectWindowAction next = windowAction.getNext();
if (next != null) {
next.setSelected(e, true);
}
}
public void activatePreviousWindow(AnActionEvent e) {
final Project project = e.getData(PlatformDataKeys.PROJECT);
if (project == null) {
return;
}
final ProjectWindowAction windowAction = findWindowAction(project.getName());
final ProjectWindowAction previous = windowAction.getPrevious();
if (previous != null) {
previous.setSelected(e, true);
}
}
private ProjectWindowAction findWindowAction(String name) {
final AnAction[] children = getChildren(null);
for (AnAction child : children) {
if (!(child instanceof ProjectWindowAction)) {
continue;
}
final ProjectWindowAction windowAction = (ProjectWindowAction) child;
if (name.equals(windowAction.getTemplatePresentation().getText())) {
return windowAction;
}
}
return null;
}
}
@@ -0,0 +1,40 @@
/*
* Copyright 2000-2011 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.
*/
package com.intellij.openapi.wm.impl;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
public class WindowDressing extends AbstractProjectComponent {
public WindowDressing(@NotNull Project project) {
super(project);
}
public void projectOpened() {
getWindowActionGroup().addProject(myProject.getName());
}
public void projectClosed() {
getWindowActionGroup().removeProject(myProject.getName());
}
public static ProjectWindowActionGroup getWindowActionGroup() {
return (ProjectWindowActionGroup)ActionManager.getInstance().getAction("OpenProjectWindows");
}
}
@@ -785,6 +785,11 @@ action.NextSplitter.text=_Goto Next Splitter
action.NextSplitter.description=Goto next splitter window
action.PrevSplitter.text=Goto Previous Splitter
action.PrevSplitter.description=Goto previous splitter window
action.NextProjectWindow.text=Next Project Window
action.NextProjectWindow.description=Switch to the next project window
action.PreviousProjectWindow.text=Previous Project Window
action.PreviousProjectWindow.description=Switch to the previous project window
group.OpenProjectWindows.text=Open Project Windows
group.HelpMenu.text=_Help
action.HelpTopics.text=Help _Topics
action.HelpTopics.description=Show help contents
@@ -19,5 +19,9 @@
<implementation-class>com.intellij.openapi.wm.impl.IdeFocusManagerImpl</implementation-class>
<headless-implementation-class>com.intellij.openapi.wm.impl.IdeFocusManagerHeadless</headless-implementation-class>
</component>
<component>
<implementation-class>com.intellij.openapi.wm.impl.WindowDressing</implementation-class>
<skipForDefaultProject/>
</component>
</project-components>
</components>
@@ -894,6 +894,12 @@
<keyboard-shortcut first-keystroke="ctrl TAB"/>
<keyboard-shortcut first-keystroke="ctrl shift TAB"/>
</action>
<action id="NextProjectWindow">
<keyboard-shortcut first-keystroke="control alt CLOSE_BRACKET"/>
</action>
<action id="PreviousProjectWindow">
<keyboard-shortcut first-keystroke="control alt OPEN_BRACKET"/>
</action>
<action id="Vcs.QuickListPopupAction">
<keyboard-shortcut first-keystroke="alt BACK_QUOTE"/>
@@ -301,6 +301,11 @@
<action id="UnsplitAll" class="com.intellij.ide.actions.UnsplitAllAction"/>
<action id="NextSplitter" class="com.intellij.ide.actions.NextSplitAction"/>
<action id="PrevSplitter" class="com.intellij.ide.actions.PrevSplitAction"/>
<separator/>
<group id="OpenProjectWindows" class="com.intellij.openapi.wm.impl.ProjectWindowActionGroup">
<action id="NextProjectWindow" class="com.intellij.openapi.wm.impl.NextProjectWindow"/>
<action id="PreviousProjectWindow" class="com.intellij.openapi.wm.impl.PreviousProjectWindow"/>
</group>
</group>
<!-- Help -->