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
.fileEditor
.impl
;
18 import com
.intellij
.ide
.ui
.UISettings
;
19 import com
.intellij
.openapi
.actionSystem
.DataConstants
;
20 import com
.intellij
.openapi
.actionSystem
.DataProvider
;
21 import com
.intellij
.openapi
.actionSystem
.ex
.DataConstantsEx
;
22 import com
.intellij
.openapi
.application
.ApplicationManager
;
23 import com
.intellij
.openapi
.diagnostic
.Logger
;
24 import com
.intellij
.openapi
.fileEditor
.FileEditorManagerListener
;
25 import com
.intellij
.openapi
.fileTypes
.FileTypes
;
26 import com
.intellij
.openapi
.ui
.Splitter
;
27 import com
.intellij
.openapi
.util
.Disposer
;
28 import com
.intellij
.openapi
.util
.IconLoader
;
29 import com
.intellij
.openapi
.util
.Iconable
;
30 import com
.intellij
.openapi
.vfs
.VirtualFile
;
31 import com
.intellij
.openapi
.wm
.ToolWindowManager
;
32 import com
.intellij
.ui
.LayeredIcon
;
33 import com
.intellij
.util
.IconUtil
;
34 import com
.intellij
.util
.ui
.EmptyIcon
;
35 import org
.jetbrains
.annotations
.NotNull
;
36 import org
.jetbrains
.annotations
.Nullable
;
40 import java
.util
.ArrayList
;
41 import java
.util
.List
;
47 public class EditorWindow
{
48 private static final Logger LOG
= Logger
.getInstance("#com.intellij.openapi.fileEditor.impl.EditorWindow");
50 protected JPanel myPanel
;
51 private EditorTabbedContainer myTabbedPane
;
52 private final EditorsSplitters myOwner
;
53 private static final Icon MODIFIED_ICON
= IconLoader
.getIcon("/general/modified.png");
54 private static final Icon GAP_ICON
= new EmptyIcon(MODIFIED_ICON
.getIconWidth(), MODIFIED_ICON
.getIconHeight());
56 private boolean myIsDisposed
= false;
57 private static final Icon PIN_ICON
= IconLoader
.getIcon("/nodes/tabPin.png");
59 protected EditorWindow(final EditorsSplitters owner
) {
61 myPanel
= new JPanel(new BorderLayout());
62 myPanel
.setOpaque(false);
66 final int tabPlacement
= UISettings
.getInstance().EDITOR_TAB_PLACEMENT
;
67 if (tabPlacement
!= UISettings
.TABS_NONE
) {
68 createTabs(tabPlacement
);
72 if (UISettings
.getInstance().SCROLL_TAB_LAYOUT_IN_EDITOR
) {
73 setTabLayoutPolicy(JTabbedPane
.SCROLL_TAB_LAYOUT
);
75 setTabLayoutPolicy(JTabbedPane
.WRAP_TAB_LAYOUT
);
78 getWindows().add(this);
79 if (myOwner
.getCurrentWindow() == null) {
80 myOwner
.setCurrentWindow(this, false);
84 private void createTabs(int tabPlacement
) {
85 LOG
.assertTrue (myTabbedPane
== null);
86 myTabbedPane
= new EditorTabbedContainer(this, getManager().getProject(), tabPlacement
);
87 myPanel
.add(myTabbedPane
.getComponent(), BorderLayout
.CENTER
);
90 private Set
<EditorWindow
> getWindows() {
91 return myOwner
.myWindows
;
94 private void dispose() {
97 getWindows ().remove(this);
104 public boolean isDisposed() {
108 private void disposeTabs() {
109 if (myTabbedPane
!= null) {
110 Disposer
.dispose(myTabbedPane
);
114 myPanel
.revalidate();
117 public void closeFile(final VirtualFile file
) {
118 closeFile (file
, true);
121 public void closeFile(final VirtualFile file
, final boolean unsplit
) {
122 closeFile(file
, unsplit
, true);
125 public void closeFile(final VirtualFile file
, final boolean unsplit
, final boolean transferFocus
) {
126 final FileEditorManagerImpl editorManager
= getManager();
127 editorManager
.runChange(new Runnable() {
130 final List
<EditorWithProviderComposite
> editors
= editorManager
.getEditorComposites(file
);
131 if (editors
.isEmpty()) return;
132 final EditorWithProviderComposite editor
= findFileComposite(file
);
134 if (myTabbedPane
!= null) {
135 final int componentIndex
= findComponentIndex(editor
.getComponent());
136 if (componentIndex
>= 0) { // editor could close itself on decomposition
137 final int indexToSelect
= calcIndexToSelect(file
, componentIndex
);
138 myTabbedPane
.removeTabAt(componentIndex
, indexToSelect
, transferFocus
).doWhenDone(new Runnable() {
140 editorManager
.disposeComposite(editor
);
146 myPanel
.removeAll ();
147 editorManager
.disposeComposite(editor
);
150 if (unsplit
&& getTabCount() == 0) {
153 myPanel
.revalidate ();
154 if (myTabbedPane
== null) {
160 final FileEditorManagerListener publisher
=
161 editorManager
.getProject().getMessageBus().syncPublisher(FileEditorManagerListener
.FILE_EDITOR_MANAGER
);
162 publisher
.fileClosed(editorManager
, file
);
168 private int calcIndexToSelect(VirtualFile fileBeingClosed
, final int fileIndex
) {
169 final int currentlySelectedIndex
= myTabbedPane
.getSelectedIndex();
170 if (currentlySelectedIndex
!= fileIndex
) {
171 // if the file being closed is not currently selected, keep the currently selected file open
172 return currentlySelectedIndex
;
174 if (UISettings
.getInstance().ACTIVATE_MRU_EDITOR_ON_CLOSE
) {
175 // try to open last visited file
176 final VirtualFile
[] histFiles
= EditorHistoryManager
.getInstance(getManager ().getProject()).getFiles();
177 for (int idx
= histFiles
.length
- 1; idx
>= 0; idx
--) {
178 final VirtualFile histFile
= histFiles
[idx
];
179 if (histFile
.equals(fileBeingClosed
)) {
182 final EditorWithProviderComposite editor
= findFileComposite(histFile
);
183 if (editor
== null) {
186 final int histFileIndex
= findComponentIndex(editor
.getComponent());
187 if (histFileIndex
>= 0) {
188 // if the file being closed is located before the hist file, then after closing the index of the histFile will be shifted by -1
189 return histFileIndex
;
193 // by default select previous neighbour
195 return fileIndex
- 1;
201 public FileEditorManagerImpl
getManager() { return myOwner
.getManager(); }
203 public int getTabCount() {
204 if (myTabbedPane
!= null) {
205 return myTabbedPane
.getTabCount();
207 return myPanel
.getComponentCount();
210 public void setForegroundAt(final int index
, final Color color
) {
211 if (myTabbedPane
!= null) {
212 myTabbedPane
.setForegroundAt(index
, color
);
216 public void setWaveColor(final int index
, @Nullable final Color color
) {
217 if (myTabbedPane
!= null) {
218 myTabbedPane
.setWaveColor(index
, color
);
222 private void setIconAt(final int index
, final Icon icon
) {
223 if (myTabbedPane
!= null) {
224 myTabbedPane
.setIconAt(index
, icon
);
228 private void setTitleAt(final int index
, final String text
) {
229 if (myTabbedPane
!= null) {
230 myTabbedPane
.setTitleAt(index
, text
);
234 private void setBackgroundColorAt(final int index
, final Color color
) {
235 if (myTabbedPane
!= null) {
236 myTabbedPane
.setBackgroundColorAt(index
, color
);
240 private void setToolTipTextAt(final int index
, final String text
) {
241 if (myTabbedPane
!= null) {
242 myTabbedPane
.setToolTipTextAt(index
, text
);
247 public void setTabLayoutPolicy(final int policy
) {
248 if (myTabbedPane
!= null) {
249 myTabbedPane
.setTabLayoutPolicy(policy
);
253 public void setTabsPlacement(final int tabPlacement
) {
254 if (tabPlacement
!= UISettings
.TABS_NONE
) {
255 if (myTabbedPane
== null) {
256 final EditorWithProviderComposite editor
= getSelectedEditor();
258 createTabs(tabPlacement
);
259 setEditor (editor
, true);
262 myTabbedPane
.setTabPlacement(tabPlacement
);
265 else if (myTabbedPane
!= null) {
266 final boolean focusEditor
= ToolWindowManager
.getInstance(getManager().getProject()).isEditorComponentActive();
267 final VirtualFile currentFile
= getSelectedFile();
268 final VirtualFile
[] files
= getFiles();
269 for (VirtualFile file
: files
) {
270 closeFile(file
, false);
273 if (currentFile
!= null) {
274 getManager().openFileImpl2(this, currentFile
, focusEditor
&& myOwner
.getCurrentWindow() == this, null);
282 public void setAsCurrentWindow(final boolean requestFocus
) {
283 myOwner
.setCurrentWindow(this, requestFocus
);
286 public void updateFileBackgroundColor(final VirtualFile file
) {
287 final int index
= findEditorIndex(findFileComposite(file
));
289 final Color color
= EditorTabbedContainer
.calcTabColor(getManager().getProject(), file
);
290 setBackgroundColorAt(index
, color
);
294 protected static class TComp
extends JPanel
implements DataProvider
{
295 final EditorWithProviderComposite myEditor
;
297 TComp(final EditorWithProviderComposite editor
) {
298 super(new BorderLayout());
300 add(editor
.getComponent(), BorderLayout
.CENTER
);
303 public Object
getData(String dataId
) {
304 if (dataId
.equals(DataConstants
.VIRTUAL_FILE
)){
305 final VirtualFile virtualFile
= myEditor
.getFile();
306 return virtualFile
.isValid() ? virtualFile
: null;
308 else if (dataId
.equals(DataConstants
.PROJECT
)) {
309 return myEditor
.getFileEditorManager().getProject();
315 protected static class TCompForTablessMode
extends TComp
{
316 private final EditorWindow myWindow
;
318 TCompForTablessMode(final EditorWindow window
, final EditorWithProviderComposite editor
) {
323 public Object
getData(String dataId
) {
324 if (dataId
.equals(DataConstantsEx
.EDITOR_WINDOW
)){
325 // this is essintial for ability to close opened file
328 return super.getData(dataId
);
332 private void checkConsistency() {
333 LOG
.assertTrue(getWindows().contains(this), "EditorWindow not in collection");
336 public EditorWithProviderComposite
getSelectedEditor() {
338 if (myTabbedPane
!= null) {
339 comp
= (TComp
)myTabbedPane
.getSelectedComponent();
341 else if (myPanel
.getComponentCount() != 0) {
342 final Component component
= myPanel
.getComponent(0);
343 comp
= component
instanceof TComp ?
(TComp
)component
: null;
350 return comp
.myEditor
;
355 public EditorWithProviderComposite
[] getEditors() {
356 final int tabCount
= getTabCount();
357 final EditorWithProviderComposite
[] res
= new EditorWithProviderComposite
[tabCount
];
358 for (int i
= 0; i
!= tabCount
; ++i
) {
359 res
[i
] = getEditorAt(i
);
364 public VirtualFile
[] getFiles() {
365 final int tabCount
= getTabCount();
366 final VirtualFile
[] res
= new VirtualFile
[tabCount
];
367 for (int i
= 0; i
!= tabCount
; ++i
) {
368 res
[i
] = getEditorAt(i
).getFile();
373 public void setSelectedEditor(final EditorComposite editor
, final boolean focusEditor
) {
374 if (myTabbedPane
== null) {
377 if (editor
!= null) {
378 final int index
= findFileIndex(editor
.getFile());
380 myTabbedPane
.setSelectedIndex(index
, focusEditor
);
385 public void setEditor(final EditorWithProviderComposite editor
, final boolean focusEditor
) {
386 if (editor
!= null) {
387 if (myTabbedPane
== null) {
388 myPanel
.removeAll ();
389 myPanel
.add (new TCompForTablessMode(this, editor
), BorderLayout
.CENTER
);
390 myPanel
.revalidate ();
394 final int index
= findEditorIndex(editor
);
396 setSelectedEditor(editor
, focusEditor
);
399 final int indexToInsert
= myTabbedPane
.getSelectedIndex() + 1;
400 final VirtualFile file
= editor
.getFile();
401 final Icon template
= IconLoader
.getIcon("/fileTypes/text.png");
402 myTabbedPane
.insertTab(file
, new EmptyIcon(template
.getIconWidth(), template
.getIconHeight()), new TComp(editor
), null, indexToInsert
);
403 trimToSize(UISettings
.getInstance().EDITOR_TAB_LIMIT
, file
, false);
404 setSelectedEditor(editor
, focusEditor
);
405 myOwner
.updateFileIcon(file
);
406 myOwner
.updateFileColor(file
);
408 myOwner
.setCurrentWindow(this, false);
410 myPanel
.revalidate();
413 private boolean splitAvailable() {
414 return getTabCount() >= 1;
417 public void split(final int orientation
) {
419 final FileEditorManagerImpl fileEditorManager
= myOwner
.getManager();
420 if (splitAvailable()) {
421 final JPanel panel
= myPanel
;
422 final int tabCount
= getTabCount();
424 final EditorWithProviderComposite firstEC
= getEditorAt(0);
425 myPanel
= new JPanel(new BorderLayout());
426 final Splitter splitter
= new Splitter(orientation
== JSplitPane
.VERTICAL_SPLIT
, 0.5f
, 0.1f
, 0.9f
);
427 final EditorWindow res
= new EditorWindow(myOwner
);
428 if (myTabbedPane
!= null) {
429 final EditorWithProviderComposite selectedEditor
= getSelectedEditor();
430 panel
.remove(myTabbedPane
.getComponent());
431 panel
.add(splitter
, BorderLayout
.CENTER
);
432 splitter
.setFirstComponent(myPanel
);
433 myPanel
.add(myTabbedPane
.getComponent(), BorderLayout
.CENTER
);
434 splitter
.setSecondComponent(res
.myPanel
);
436 for (int i = 0; i != tabCount; ++i) {
437 final EditorWithProviderComposite eC = getEditorAt(i);
438 final VirtualFile file = eC.getFile();
439 fileEditorManager.openFileImpl3(res, file, false, null);
440 res.setFilePinned (file, isFilePinned (file));
443 // open only selected file in the new splitter instead of opening all tabs
444 final VirtualFile file
= selectedEditor
.getFile();
445 fileEditorManager
.openFileImpl3(res
, file
, false, null, true);
446 res
.setFilePinned (file
, isFilePinned (file
));
448 res
.setSelectedEditor(selectedEditor
, true);
449 selectedEditor
.getComponent().requestFocus();
455 panel
.add(splitter
, BorderLayout
.CENTER
);
456 splitter
.setFirstComponent(myPanel
);
457 splitter
.setSecondComponent(res
.myPanel
);
459 final VirtualFile file
= firstEC
.getFile();
460 fileEditorManager
.openFileImpl3(this, file
, true, null, true);
461 fileEditorManager
.openFileImpl3(res
, file
, false, null, true);
468 public EditorWindow
[] findSiblings() {
470 final ArrayList
<EditorWindow
> res
= new ArrayList
<EditorWindow
>();
471 if (myPanel
.getParent() instanceof Splitter
) {
472 final Splitter splitter
= (Splitter
)myPanel
.getParent();
473 for (final EditorWindow win
: getWindows()) {
474 if (win
!= this && SwingUtilities
.isDescendingFrom(win
.myPanel
, splitter
)) {
479 return res
.toArray(new EditorWindow
[res
.size()]);
482 public void changeOrientation() {
484 final Container parent
= myPanel
.getParent();
485 if (parent
instanceof Splitter
) {
486 final Splitter splitter
= (Splitter
)parent
;
487 splitter
.setOrientation(!splitter
.getOrientation());
491 protected void updateFileIcon(VirtualFile file
) {
492 final int index
= findEditorIndex(findFileComposite(file
));
493 LOG
.assertTrue(index
!= -1);
494 setIconAt(index
, getFileIcon(file
));
497 protected void updateFileName(VirtualFile file
) {
498 final int index
= findEditorIndex(findFileComposite(file
));
500 setTitleAt(index
, EditorTabbedContainer
.calcTabTitle(getManager().getProject(), file
));
501 setToolTipTextAt(index
, getManager().getFileTooltipText(file
));
506 * @return icon which represents file's type and modification status
508 private Icon
getFileIcon(@NotNull final VirtualFile file
) {
509 if (!file
.isValid()) {
510 Icon fakeIcon
= FileTypes
.UNKNOWN
.getIcon();
511 assert fakeIcon
!= null : "Can't find the icon for unknown file type";
515 final Icon baseIcon
= IconUtil
.getIcon(file
, Iconable
.ICON_FLAG_READ_STATUS
, getManager().getProject());
520 final EditorComposite composite
= findFileComposite(file
);
521 if (composite
!= null && composite
.isPinned()) {
529 final Icon modifiedIcon
;
530 if (UISettings
.getInstance().MARK_MODIFIED_TABS_WITH_ASTERISK
) {
531 modifiedIcon
= composite
!= null && composite
.isModified() ? MODIFIED_ICON
: GAP_ICON
;
538 if (count
== 1) return baseIcon
;
541 final LayeredIcon result
= new LayeredIcon(count
);
542 result
.setIcon(baseIcon
, i
++);
543 if (pinIcon
!= null) result
.setIcon(pinIcon
, i
++);
544 if (modifiedIcon
!= null) result
.setIcon(modifiedIcon
, i
++);
549 public void unsplit(boolean setCurrent
) {
551 final Container splitter
= myPanel
.getParent();
553 if (!(splitter
instanceof Splitter
)) return;
555 EditorWithProviderComposite editorToSelect
= getSelectedEditor();
556 final EditorWindow
[] siblings
= findSiblings();
557 final JPanel parent
= (JPanel
)splitter
.getParent();
559 for (EditorWindow eachSibling
: siblings
) {
560 // selected editors will be added first
561 final EditorWithProviderComposite selected
= eachSibling
.getSelectedEditor();
562 if (editorToSelect
== null) {
563 editorToSelect
= selected
;
567 for (final EditorWindow sibling
: siblings
) {
568 final EditorWithProviderComposite
[] siblingEditors
= sibling
.getEditors();
569 for (final EditorWithProviderComposite siblingEditor
: siblingEditors
) {
570 if (editorToSelect
== null) {
571 editorToSelect
= siblingEditor
;
573 processSiblingEditor(siblingEditor
);
575 LOG
.assertTrue(sibling
!= this);
578 parent
.remove(splitter
);
579 if (myTabbedPane
!= null) {
580 parent
.add(myTabbedPane
.getComponent(), BorderLayout
.CENTER
);
583 parent
.add(myPanel
.getComponent(0), BorderLayout
.CENTER
);
587 if (editorToSelect
!= null) {
588 setSelectedEditor(editorToSelect
, true);
591 myOwner
.setCurrentWindow(this, false);
595 private void processSiblingEditor(final EditorWithProviderComposite siblingEditor
) {
596 if (myTabbedPane
!= null && getTabCount() < UISettings
.getInstance().EDITOR_TAB_LIMIT
&& findFileComposite(siblingEditor
.getFile()) == null) {
597 setEditor(siblingEditor
, true);
599 else if (myTabbedPane
== null && getTabCount() == 0) { // tabless mode and no file opened
600 setEditor(siblingEditor
, true);
603 getManager().disposeComposite(siblingEditor
);
607 public void unsplitAll() {
609 while (inSplitter()) {
614 public boolean inSplitter() {
616 return myPanel
.getParent() instanceof Splitter
;
619 public VirtualFile
getSelectedFile() {
621 final EditorWithProviderComposite editor
= getSelectedEditor();
622 return editor
== null ?
null : editor
.getFile();
625 public EditorWithProviderComposite
findFileComposite(final VirtualFile file
) {
626 for (int i
= 0; i
!= getTabCount(); ++i
) {
627 final EditorWithProviderComposite editor
= getEditorAt(i
);
628 if (editor
.getFile ().equals (file
)) {
636 public int findComponentIndex(final Component component
) {
637 for (int i
= 0; i
!= getTabCount(); ++i
) {
638 final EditorWithProviderComposite editor
= getEditorAt(i
);
639 if (editor
.getComponent ().equals (component
)) {
646 public int findEditorIndex(final EditorComposite editorToFind
) {
647 for (int i
= 0; i
!= getTabCount(); ++i
) {
648 final EditorWithProviderComposite editor
= getEditorAt(i
);
649 if (editor
.equals (editorToFind
)) {
656 private int findFileIndex(final VirtualFile fileToFind
) {
657 for (int i
= 0; i
!= getTabCount(); ++i
) {
658 final VirtualFile file
= getFileAt(i
);
659 if (file
.equals (fileToFind
)) {
666 private EditorWithProviderComposite
getEditorAt(final int i
) {
668 if (myTabbedPane
!= null) {
669 comp
= (TComp
)myTabbedPane
.getComponentAt(i
);
672 LOG
.assertTrue(i
<= 1);
673 comp
= (TComp
)myPanel
.getComponent(i
);
675 return comp
.myEditor
;
678 public boolean isFileOpen(final VirtualFile file
) {
679 return findFileComposite(file
) != null;
682 public boolean isFilePinned(final VirtualFile file
) {
683 ApplicationManager
.getApplication().assertIsDispatchThread();
684 if(!isFileOpen(file
)){
685 throw new IllegalArgumentException("file is not open: " + file
.getPath());
687 final EditorComposite editorComposite
= findFileComposite(file
);
688 return editorComposite
.isPinned();
691 public void setFilePinned(final VirtualFile file
, final boolean pinned
) {
692 ApplicationManager
.getApplication().assertIsDispatchThread();
693 if(!isFileOpen(file
)){
694 throw new IllegalArgumentException("file is not open: " + file
.getPath());
696 final EditorComposite editorComposite
= findFileComposite(file
);
697 editorComposite
.setPinned(pinned
);
698 updateFileIcon(file
);
701 void trimToSize(final int limit
, final VirtualFile fileToIgnore
, boolean transferFocus
) {
702 if (myTabbedPane
== null) {
705 final boolean closeNonModifiedFilesFirst
= UISettings
.getInstance().CLOSE_NON_MODIFIED_FILES_FIRST
;
706 final EditorComposite selectedComposite
= getSelectedEditor();
708 doTrimSize(limit
, fileToIgnore
, closeNonModifiedFilesFirst
, transferFocus
);
711 setSelectedEditor(selectedComposite
, false);
715 private void doTrimSize(int limit
, VirtualFile fileToIgnore
, boolean closeNonModifiedFilesFirst
, boolean transferFocus
) {
717 while (myTabbedPane
.getTabCount() > limit
&& myTabbedPane
.getTabCount() > 0) {
718 // If all tabs are pinned then do nothings. Othrwise we will get infinitive loop
719 boolean allTabsArePinned
= true;
720 for (int i
= myTabbedPane
.getTabCount() - 1; i
>= 0; i
--) {
721 final VirtualFile file
= getFileAt(i
);
722 if (fileCanBeClosed(file
, fileToIgnore
)) {
723 allTabsArePinned
= false;
727 if (allTabsArePinned
) {
731 // Try to close non-modified files first (is specified in option)
732 if (closeNonModifiedFilesFirst
) {
734 final VirtualFile
[] allFiles
= getFiles();
735 final VirtualFile
[] histFiles
= EditorHistoryManager
.getInstance(getManager ().getProject()).getFiles();
737 // first, we search for files not in history
738 for (int i
= 0; i
!= allFiles
.length
; ++ i
) {
739 final VirtualFile file
= allFiles
[i
];
740 if (fileCanBeClosed(file
, fileToIgnore
)) {
741 boolean found
= false;
742 for (int j
= 0; j
!= histFiles
.length
; j
++) {
743 if (histFiles
[j
] == file
) {
749 defaultCloseFile(file
, transferFocus
);
750 continue while_label
;
755 for (final VirtualFile file
: histFiles
) {
756 if (!fileCanBeClosed(file
, fileToIgnore
)) {
760 final EditorComposite composite
= findFileComposite(file
);
761 //LOG.assertTrue(composite != null);
762 if (composite
!= null && composite
.getInitialFileTimeStamp() == file
.getTimeStamp()) {
763 // we found non modified file
764 defaultCloseFile(file
, transferFocus
);
765 continue while_label
;
769 // Search in tabbed pane
770 final VirtualFile selectedFile
= getSelectedFile();
771 for (int i
= 0; i
< myTabbedPane
.getTabCount(); i
++) {
772 final VirtualFile file
= getFileAt(i
);
773 final EditorComposite composite
= getEditorAt(i
);
774 if (!fileCanBeClosed(file
, fileToIgnore
)) {
777 if (!selectedFile
.equals(file
)) {
778 if (composite
.getInitialFileTimeStamp() == file
.getTimeStamp()) {
779 // we found non modified file
780 defaultCloseFile(file
, transferFocus
);
781 continue while_label
;
787 // It's non enough to close non-modified files only. Try all other files.
788 // Search in history from less frequently used.
790 final VirtualFile
[] allFiles
= getFiles();
791 final VirtualFile
[] histFiles
= EditorHistoryManager
.getInstance(getManager ().getProject()).getFiles();
793 // first, we search for files not in history
794 for (int i
= 0; i
!= allFiles
.length
; ++ i
) {
795 final VirtualFile file
= allFiles
[i
];
796 if (fileCanBeClosed(file
, fileToIgnore
)) {
797 boolean found
= false;
798 for (int j
= 0; j
!= histFiles
.length
; j
++) {
799 if (histFiles
[j
] == file
) {
805 defaultCloseFile(file
, transferFocus
);
806 continue while_label
;
812 for (final VirtualFile file
: histFiles
) {
813 if (fileCanBeClosed(file
, fileToIgnore
)) {
814 defaultCloseFile(file
, transferFocus
);
815 continue while_label
;
820 // Close first opened file in tabbed pane that isn't a selected one
822 final VirtualFile selectedFile
= getSelectedFile();
823 for (int i
= 0; i
< myTabbedPane
.getTabCount(); i
++) {
824 final VirtualFile file
= getFileAt(i
);
825 if (!fileCanBeClosed(file
, fileToIgnore
)) {
828 if (!selectedFile
.equals(file
)) {
829 defaultCloseFile(file
, transferFocus
);
830 continue while_label
;
832 else if (i
== myTabbedPane
.getTabCount() - 1) {
833 // if file is selected one and it's last file that we have no choice as close it
834 defaultCloseFile(file
, transferFocus
);
835 continue while_label
;
842 private void defaultCloseFile(VirtualFile file
, boolean transferFocus
) {
843 closeFile(file
, true, transferFocus
);
846 private boolean fileCanBeClosed(final VirtualFile file
, final VirtualFile fileToIgnore
) {
847 return isFileOpen (file
) && !file
.equals(fileToIgnore
) && !isFilePinned(file
);
850 protected VirtualFile
getFileAt(int i
) {
851 return getEditorAt(i
).getFile();