diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java index 6a4145a2a387..c1cfae48f8ee 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java @@ -33,15 +33,14 @@ import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Splitter; -import com.intellij.openapi.util.ActionCallback; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Iconable; -import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.*; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.LayeredIcon; import com.intellij.util.IconUtil; +import com.intellij.util.containers.Stack; import com.intellij.util.ui.EmptyIcon; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -74,6 +73,15 @@ public class EditorWindow { private boolean myIsDisposed = false; private static final Icon PIN_ICON = AllIcons.Nodes.TabPin; public static final Key INITIAL_INDEX_KEY = Key.create("initial editor index"); + private Stack> myRemovedTabs = new Stack>(UISettings.getInstance().EDITOR_TAB_LIMIT) { + @Override + public void push(Pair pair) { + if (size() >= UISettings.getInstance().EDITOR_TAB_LIMIT) { + remove(0); + } + super.push(pair); + } + }; protected EditorWindow(final EditorsSplitters owner) { myOwner = owner; @@ -264,6 +272,21 @@ public class EditorWindow { closeFile(file, unsplit, true); } + public boolean hasClosedTabs() { + return !myRemovedTabs.empty(); + } + + public void restoreClosedTab() { + assert hasClosedTabs() : "Nothing to restore"; + + final Pair info = myRemovedTabs.pop(); + final VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(info.getFirst()); + final Integer second = info.getSecond(); + if (file != null) { + getManager().openFileImpl4(this, file, true, null, true, second == null ? -1 : second.intValue()); + } + } + public void closeFile(final VirtualFile file, final boolean unsplit, final boolean transferFocus) { final FileEditorManagerImpl editorManager = getManager(); editorManager.runChange(new FileEditorManagerChange() { @@ -282,6 +305,7 @@ public class EditorWindow { final int componentIndex = findComponentIndex(editor.getComponent()); if (componentIndex >= 0) { // editor could close itself on decomposition final int indexToSelect = calcIndexToSelect(file, componentIndex); + myRemovedTabs.push(Pair.create(file.getUrl(), componentIndex)); final ActionCallback removeTab = myTabbedPane.removeTabAt(componentIndex, indexToSelect, transferFocus); final Runnable disposer = new Runnable() { public void run() { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index ebd4fbb63c5a..d73e0ee92783 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -683,6 +683,16 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec final boolean focusEditor, @Nullable final HistoryEntry entry, boolean current) { + return openFileImpl4(window, file, focusEditor, entry, current, -1); + } + + @NotNull + Pair openFileImpl4(@NotNull final EditorWindow window, + @NotNull final VirtualFile file, + final boolean focusEditor, + @Nullable final HistoryEntry entry, + boolean current, + int index) { // Open file FileEditor[] editors; FileEditorProvider[] providers; @@ -748,6 +758,10 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec // Now we have to create EditorComposite and insert it into the TabbedEditorComponent. // After that we have to select opened editor. newSelectedComposite = new EditorWithProviderComposite(file, editors, providers, this); + + if (index >= 0) { + newSelectedComposite.getFile().putUserData(EditorWindow.INITIAL_INDEX_KEY, index); + } } window.setEditor(newSelectedComposite, focusEditor); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/ReopenClosedTabAction.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/ReopenClosedTabAction.java new file mode 100644 index 000000000000..6f091e4d2815 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/ReopenClosedTabAction.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2012 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.fileEditor.impl; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class ReopenClosedTabAction extends AnAction { + public ReopenClosedTabAction() { + super("Reopen Closed Tab"); + } + + @Override + public void actionPerformed(AnActionEvent e) { + final EditorWindow window = getEditorWindow(e); + if (window != null) { + window.restoreClosedTab(); + } + } + + @Nullable + private static EditorWindow getEditorWindow(AnActionEvent e) { + final Component component = e.getData(PlatformDataKeys.CONTEXT_COMPONENT); + if (component != null) { + final EditorsSplitters splitters = UIUtil.getParentOfType(EditorsSplitters.class, component); + if (splitters != null) { + return splitters.getCurrentWindow(); + } + } + return null; + } + + @Override + public void update(AnActionEvent e) { + final EditorWindow window = getEditorWindow(e); + e.getPresentation().setEnabled(window != null && window.hasClosedTabs()); + } +} diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index 7d6faf452ca8..fb6855d75139 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -331,6 +331,7 @@ + @@ -422,6 +423,7 @@ +