build folding for current file only
[fedora-idea.git] / platform / platform-impl / src / com / intellij / openapi / fileEditor / impl / EditorWindow.java
blob898e93765db01a932a02d00d08335c0d95d5ca7f
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.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;
38 import javax.swing.*;
39 import java.awt.*;
40 import java.util.ArrayList;
41 import java.util.List;
42 import java.util.Set;
44 /**
45 * Author: msk
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) {
60 myOwner = owner;
61 myPanel = new JPanel(new BorderLayout());
62 myPanel.setOpaque(false);
64 myTabbedPane = null;
66 final int tabPlacement = UISettings.getInstance().EDITOR_TAB_PLACEMENT;
67 if (tabPlacement != UISettings.TABS_NONE) {
68 createTabs(tabPlacement);
71 // Tab layout policy
72 if (UISettings.getInstance().SCROLL_TAB_LAYOUT_IN_EDITOR) {
73 setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
74 } else {
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() {
95 try {
96 disposeTabs();
97 getWindows ().remove(this);
99 finally {
100 myIsDisposed = true;
104 public boolean isDisposed() {
105 return myIsDisposed;
108 private void disposeTabs() {
109 if (myTabbedPane != null) {
110 Disposer.dispose(myTabbedPane);
111 myTabbedPane = null;
113 myPanel.removeAll();
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() {
128 public void run() {
129 try {
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() {
139 public void run() {
140 editorManager.disposeComposite(editor);
145 else {
146 myPanel.removeAll ();
147 editorManager.disposeComposite(editor);
150 if (unsplit && getTabCount() == 0) {
151 unsplit (true);
153 myPanel.revalidate ();
154 if (myTabbedPane == null) {
155 // in tabless mode
156 myPanel.repaint();
159 finally {
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)) {
180 continue;
182 final EditorWithProviderComposite editor = findFileComposite(histFile);
183 if (editor == null) {
184 continue; // ????
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
194 if (fileIndex > 0) {
195 return fileIndex - 1;
197 // do nothing
198 return -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();
257 myPanel.removeAll();
258 createTabs(tabPlacement);
259 setEditor (editor, true);
261 else {
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);
272 disposeTabs();
273 if (currentFile != null) {
274 getManager().openFileImpl2(this, currentFile, focusEditor && myOwner.getCurrentWindow() == this, null);
276 else {
277 myPanel.repaint();
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));
288 if (index != -1) {
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());
299 myEditor = editor;
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();
311 return null;
315 protected static class TCompForTablessMode extends TComp{
316 private final EditorWindow myWindow;
318 TCompForTablessMode(final EditorWindow window, final EditorWithProviderComposite editor) {
319 super(editor);
320 myWindow = window;
323 public Object getData(String dataId) {
324 if (dataId.equals(DataConstantsEx.EDITOR_WINDOW)){
325 // this is essintial for ability to close opened file
326 return myWindow;
328 return super.getData(dataId);
332 private void checkConsistency() {
333 LOG.assertTrue(getWindows().contains(this), "EditorWindow not in collection");
336 public EditorWithProviderComposite getSelectedEditor() {
337 final TComp comp;
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;
345 else {
346 return null;
349 if (comp != null) {
350 return comp.myEditor;
352 return null;
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);
361 return res;
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();
370 return res;
373 public void setSelectedEditor(final EditorComposite editor, final boolean focusEditor) {
374 if (myTabbedPane == null) {
375 return;
377 if (editor != null) {
378 final int index = findFileIndex(editor.getFile());
379 if (index != -1) {
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 ();
391 return;
394 final int index = findEditorIndex(editor);
395 if (index != -1) {
396 setSelectedEditor(editor, focusEditor);
398 else {
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) {
418 checkConsistency();
419 final FileEditorManagerImpl fileEditorManager = myOwner.getManager();
420 if (splitAvailable()) {
421 final JPanel panel = myPanel;
422 final int tabCount = getTabCount();
423 if (tabCount != 0) {
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();
451 panel.revalidate();
453 else {
454 panel.removeAll();
455 panel.add(splitter, BorderLayout.CENTER);
456 splitter.setFirstComponent(myPanel);
457 splitter.setSecondComponent(res.myPanel);
458 panel.revalidate();
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() {
469 checkConsistency();
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)) {
475 res.add(win);
479 return res.toArray(new EditorWindow[res.size()]);
482 public void changeOrientation() {
483 checkConsistency();
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));
499 if (index != -1) {
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";
512 return fakeIcon;
515 final Icon baseIcon = IconUtil.getIcon(file, Iconable.ICON_FLAG_READ_STATUS, getManager().getProject());
517 int count = 1;
519 final Icon pinIcon;
520 final EditorComposite composite = findFileComposite(file);
521 if (composite != null && composite.isPinned()) {
522 count++;
523 pinIcon = PIN_ICON;
525 else {
526 pinIcon = null;
529 final Icon modifiedIcon;
530 if (UISettings.getInstance().MARK_MODIFIED_TABS_WITH_ASTERISK) {
531 modifiedIcon = composite != null && composite.isModified() ? MODIFIED_ICON : GAP_ICON;
532 count++;
534 else {
535 modifiedIcon = null;
538 if (count == 1) return baseIcon;
540 int i = 0;
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++);
546 return result;
549 public void unsplit(boolean setCurrent) {
550 checkConsistency();
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);
576 sibling.dispose();
578 parent.remove(splitter);
579 if (myTabbedPane != null) {
580 parent.add(myTabbedPane.getComponent(), BorderLayout.CENTER);
582 else {
583 parent.add(myPanel.getComponent(0), BorderLayout.CENTER);
585 parent.revalidate();
586 myPanel = parent;
587 if (editorToSelect != null) {
588 setSelectedEditor(editorToSelect, true);
590 if (setCurrent) {
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);
602 else {
603 getManager().disposeComposite(siblingEditor);
607 public void unsplitAll() {
608 checkConsistency();
609 while (inSplitter()) {
610 unsplit(true);
614 public boolean inSplitter() {
615 checkConsistency();
616 return myPanel.getParent() instanceof Splitter;
619 public VirtualFile getSelectedFile() {
620 checkConsistency();
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)) {
629 return editor;
632 return null;
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)) {
640 return i;
643 return -1;
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)) {
650 return i;
653 return -1;
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)) {
660 return i;
663 return -1;
666 private EditorWithProviderComposite getEditorAt(final int i) {
667 final TComp comp;
668 if (myTabbedPane != null) {
669 comp = (TComp)myTabbedPane.getComponentAt(i);
671 else {
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) {
703 return;
705 final boolean closeNonModifiedFilesFirst = UISettings.getInstance().CLOSE_NON_MODIFIED_FILES_FIRST;
706 final EditorComposite selectedComposite = getSelectedEditor();
707 try {
708 doTrimSize(limit, fileToIgnore, closeNonModifiedFilesFirst, transferFocus);
710 finally {
711 setSelectedEditor(selectedComposite, false);
715 private void doTrimSize(int limit, VirtualFile fileToIgnore, boolean closeNonModifiedFilesFirst, boolean transferFocus) {
716 while_label:
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;
724 break;
727 if (allTabsArePinned) {
728 return;
731 // Try to close non-modified files first (is specified in option)
732 if (closeNonModifiedFilesFirst) {
733 // Search in history
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) {
744 found = true;
745 break;
748 if (!found) {
749 defaultCloseFile(file, transferFocus);
750 continue while_label;
755 for (final VirtualFile file : histFiles) {
756 if (!fileCanBeClosed(file, fileToIgnore)) {
757 continue;
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)) {
775 continue;
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) {
800 found = true;
801 break;
804 if (!found) {
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)) {
826 continue;
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();