ability to open a file in new window

This commit is contained in:
Konstantin Bulenkov
2013-03-19 12:46:36 +01:00
parent 644930d5ce
commit 4c6a755766
8 changed files with 176 additions and 57 deletions
@@ -0,0 +1,47 @@
/*
* Copyright 2000-2013 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.ide.actions;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.vfs.VirtualFile;
/**
* @author Konstantin Bulenkov
*/
public class EditSourceInNewWindowAction extends DumbAwareAction {
@Override
public void actionPerformed(AnActionEvent e) {
final FileEditorManager manager = FileEditorManager.getInstance(getEventProject(e));
((FileEditorManagerImpl)manager).openFileInNewWindow(getVirtualFiles(e)[0]);
}
protected VirtualFile[] getVirtualFiles(AnActionEvent e) {
final VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
if (files != null) return files;
final VirtualFile file = e.getData(PlatformDataKeys.VIRTUAL_FILE);
return file == null ? VirtualFile.EMPTY_ARRAY : new VirtualFile[]{file};
}
@Override
public void update(AnActionEvent e) {
e.getPresentation().setEnabledAndVisible(getEventProject(e) != null && getVirtualFiles(e).length == 1);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -100,7 +100,7 @@ public class DockableEditorTabbedContainer implements DockContainer.Persistent {
@Nullable
private JBTabs getTabsAt(DockableContent content, RelativePoint point) {
if (content instanceof EditorTabbedContainer.MyDragOutDelegate.DockableEditor) {
if (content instanceof EditorTabbedContainer.DockableEditor) {
JBTabs targetTabs = mySplitters.getTabsAt(point);
if (targetTabs != null) {
return targetTabs;
@@ -135,7 +135,7 @@ public class DockableEditorTabbedContainer implements DockContainer.Persistent {
}
}
final EditorTabbedContainer.MyDragOutDelegate.DockableEditor dockableEditor = (EditorTabbedContainer.MyDragOutDelegate.DockableEditor)content;
final EditorTabbedContainer.DockableEditor dockableEditor = (EditorTabbedContainer.DockableEditor)content;
VirtualFile file = dockableEditor.getFile();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -71,7 +71,7 @@ import java.util.Map;
* @author Anton Katilin
* @author Vladimir Kondratyev
*/
final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget {
public final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget {
private final EditorWindow myWindow;
private final Project myProject;
private final JBEditorTabs myTabs;
@@ -162,6 +162,11 @@ final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget
return myTabs.select(myTabs.getTabAt(indexToSelect), focusEditor);
}
public static DockableEditor createDockableEditor(Project project, Image image, VirtualFile file, Presentation presentation, EditorWindow window) {
return new DockableEditor(project, image, file, presentation, window);
}
private void updateTabBorder() {
if (!myProject.isOpen()) return;
@@ -582,7 +587,7 @@ final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget
myFile = (VirtualFile)info.getObject();
Presentation presentation = new Presentation(info.getText());
presentation.setIcon(info.getIcon());
mySession = getDockManager().createDragSession(mouseEvent, new DockableEditor(img, myFile, presentation, myWindow));
mySession = getDockManager().createDragSession(mouseEvent, createDockableEditor(myProject, img, myFile, presentation, myWindow));
}
private DockManager getDockManager() {
@@ -625,63 +630,64 @@ final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget
mySession = null;
}
class DockableEditor implements DockableContent<VirtualFile> {
final Image myImg;
private DockableEditorTabbedContainer myContainer;
private Presentation myPresentation;
private EditorWindow myEditorWindow;
private Dimension myPreferredSize;
private boolean myPinned;
}
public static class DockableEditor implements DockableContent<VirtualFile> {
final Image myImg;
private DockableEditorTabbedContainer myContainer;
private Presentation myPresentation;
private EditorWindow myEditorWindow;
private Dimension myPreferredSize;
private boolean myPinned;
private VirtualFile myFile;
public DockableEditor(Image img, VirtualFile file, Presentation presentation, EditorWindow window) {
myImg = img;
myFile = file;
myPresentation = presentation;
myContainer = new DockableEditorTabbedContainer(myProject);
myEditorWindow = window;
myPreferredSize = myEditorWindow.getSize();
myPinned = window.isFilePinned(file);
}
public DockableEditor(Project project, Image img, VirtualFile file, Presentation presentation, EditorWindow window) {
myImg = img;
myFile = file;
myPresentation = presentation;
myContainer = new DockableEditorTabbedContainer(project);
myEditorWindow = window;
myPreferredSize = myEditorWindow.getSize();
myPinned = window.isFilePinned(file);
}
@NotNull
@Override
public VirtualFile getKey() {
return myFile;
}
@NotNull
@Override
public VirtualFile getKey() {
return myFile;
}
@Override
public Image getPreviewImage() {
return myImg;
}
@Override
public Image getPreviewImage() {
return myImg;
}
@Override
public Dimension getPreferredSize() {
return myPreferredSize;
}
@Override
public Dimension getPreferredSize() {
return myPreferredSize;
}
@Override
public String getDockContainerType() {
return DockableEditorContainerFactory.TYPE;
}
@Override
public String getDockContainerType() {
return DockableEditorContainerFactory.TYPE;
}
@Override
public Presentation getPresentation() {
return myPresentation;
}
@Override
public Presentation getPresentation() {
return myPresentation;
}
@Override
public void close() {
myContainer.close(myFile);
}
@Override
public void close() {
myContainer.close(myFile);
}
public VirtualFile getFile() {
return myFile;
}
public VirtualFile getFile() {
return myFile;
}
public boolean isPinned() {
return myPinned;
}
public boolean isPinned() {
return myPinned;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -68,6 +68,7 @@ import com.intellij.ui.FocusTrackback;
import com.intellij.ui.Gray;
import com.intellij.ui.docking.DockContainer;
import com.intellij.ui.docking.DockManager;
import com.intellij.ui.docking.impl.DockManagerImpl;
import com.intellij.ui.tabs.impl.JBTabsImpl;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBusConnection;
@@ -83,6 +84,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.ref.WeakReference;
@@ -598,6 +600,11 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
}
assertDispatchThread();
if (isShiftEnter(EventQueue.getCurrentEvent())) {
return openFileInNewWindow(file);
}
EditorWindow wndToOpenIn = null;
if (searchForSplitter) {
Set<EditorsSplitters> all = getAllSplitters();
@@ -630,6 +637,16 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
return openFileImpl2(wndToOpenIn, file, focusEditor);
}
public Pair<FileEditor[], FileEditorProvider[]> openFileInNewWindow(VirtualFile file) {
return ((DockManagerImpl)DockManager.getInstance(getProject())).createNewDockContainerFor(file, this);
}
private static boolean isShiftEnter(AWTEvent event) {
return event instanceof KeyEvent
&& ((KeyEvent)event).getKeyCode() == KeyEvent.VK_ENTER
&& ((KeyEvent)event).isShiftDown();
}
private void openAssociatedFile(VirtualFile file, EditorWindow wndToOpenIn, EditorsSplitters splitters) {
EditorWindow[] windows = splitters.getWindows();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -19,16 +19,19 @@ import com.intellij.ide.IdeEventQueue;
import com.intellij.ide.ui.UISettings;
import com.intellij.ide.ui.UISettingsListener;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.extensions.ExtensionPointListener;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorProvider;
import com.intellij.openapi.fileEditor.impl.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.FrameWrapper;
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.IdeRootPaneNorthExtension;
@@ -405,6 +408,46 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
}
});
}
public Pair<FileEditor[], FileEditorProvider[]> createNewDockContainerFor(VirtualFile file, FileEditorManagerImpl fileEditorManager) {
DockContainer container = getFactory(DockableEditorContainerFactory.TYPE).createContainer(null);
register(container);
final DockWindow window = createWindowFor(null, container);
Point showPoint = DimensionService.getInstance().getLocation("new.editor.frame", myProject);
Dimension size = DimensionService.getInstance().getSize("new.editor.frame", myProject);
if (size == null) {
final IdeFrame frame = WindowManagerEx.getInstanceEx().findFrameFor(myProject);
size = new Dimension(((Window)frame).getWidth() - 200, ((Window)frame).getHeight() - 200);
}
if (showPoint == null) {
final IdeFrame frame = WindowManagerEx.getInstanceEx().findFrameFor(myProject);
showPoint = new Point(((Window)frame).getX() + 100, ((Window)frame).getY() + 100);
}
Rectangle target = new Rectangle(showPoint, size);
ScreenUtil.moveRectangleToFitTheScreen(target);
ScreenUtil.cropRectangleToFitTheScreen(target);
window.setLocation(target.getLocation());
window.myDockContentUiContainer.setPreferredSize(target.getSize());
window.setDimensionKey("new.editor.frame");
window.show(false);
window.getFrame().pack();
final EditorWindow editorWindow = ((DockableEditorTabbedContainer)container).getSplitters().getOrCreateCurrentWindow(file);
final Pair<FileEditor[], FileEditorProvider[]> result = fileEditorManager.openFileImpl2(editorWindow, file, true);
container.add(EditorTabbedContainer.createDockableEditor(myProject, null, file, new Presentation(file.getName()),
editorWindow), new RelativePoint(target.getLocation()));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
window.myUiContainer.setPreferredSize(null);
}
});
return result;
}
private DockWindow createWindowFor(@Nullable String id, DockContainer container) {
String windowId = id != null ? id : String.valueOf(myWindowIdCounter++);
@@ -374,6 +374,8 @@ action.ProjectViewChangeView.text=Change View...
action.ProjectViewChangeView.description=Choose Project, Sourcepath or Classpath tree in the Project View window
action.EditSource.text=_Jump to Source
action.EditSource.description=Open editor for the selected item and give focus to it
action.EditSourceInNewWindow.text=Open source in new window
action.EditSourceInNewWindow.description=Open editor for the selected item in new window and give focus to it
action.ViewSource.text=Sho_w Source
action.ViewSource.description=Open editor for the selected item
action.ExternalJavaDoc.text=E_xternal Documentation
@@ -568,6 +568,9 @@
<action id="EditSource">
<keyboard-shortcut first-keystroke="F4"/>
</action>
<action id="EditSourceInNewWindow">
<keyboard-shortcut first-keystroke="shift F4"/>
</action>
<action id="CodeCompletion">
<keyboard-shortcut first-keystroke="control SPACE"/>
</action>
@@ -20,6 +20,7 @@
<action id="TextComponent.ClearAction" class="com.intellij.ui.ClearTextAction"/>
<action id="Switcher" class="com.intellij.ide.actions.Switcher" text="Switcher"/>
<action id="QuickDocCopy" class="com.intellij.codeInsight.documentation.actions.CopyQuickDocAction" use-shortcut-of="$Copy"/>
<action id="EditSourceInNewWindow" class="com.intellij.ide.actions.EditSourceInNewWindowAction" />
<group id="TemplateParametersNavigation">
<action id="NextTemplateParameter" class="com.intellij.codeInsight.completion.NextPrevParameterAction$Next" text="Next Parameter">