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
.AppTopics
;
19 import com
.intellij
.ide
.IdeBundle
;
20 import com
.intellij
.ide
.plugins
.PluginManager
;
21 import com
.intellij
.ide
.ui
.UISettings
;
22 import com
.intellij
.ide
.ui
.UISettingsListener
;
23 import com
.intellij
.injected
.editor
.VirtualFileWindow
;
24 import com
.intellij
.openapi
.Disposable
;
25 import com
.intellij
.openapi
.application
.ApplicationManager
;
26 import com
.intellij
.openapi
.application
.ModalityState
;
27 import com
.intellij
.openapi
.application
.ex
.ApplicationManagerEx
;
28 import com
.intellij
.openapi
.application
.impl
.LaterInvocator
;
29 import com
.intellij
.openapi
.command
.CommandProcessor
;
30 import com
.intellij
.openapi
.components
.ProjectComponent
;
31 import com
.intellij
.openapi
.diagnostic
.Logger
;
32 import com
.intellij
.openapi
.editor
.Editor
;
33 import com
.intellij
.openapi
.editor
.ex
.EditorEx
;
34 import com
.intellij
.openapi
.fileEditor
.*;
35 import com
.intellij
.openapi
.fileEditor
.ex
.FileEditorManagerEx
;
36 import com
.intellij
.openapi
.fileEditor
.ex
.FileEditorProviderManager
;
37 import com
.intellij
.openapi
.fileEditor
.ex
.IdeDocumentHistory
;
38 import com
.intellij
.openapi
.fileEditor
.impl
.text
.TextEditorImpl
;
39 import com
.intellij
.openapi
.fileEditor
.impl
.text
.TextEditorProvider
;
40 import com
.intellij
.openapi
.fileTypes
.FileTypeEvent
;
41 import com
.intellij
.openapi
.fileTypes
.FileTypeListener
;
42 import com
.intellij
.openapi
.project
.DumbAware
;
43 import com
.intellij
.openapi
.project
.DumbAwareRunnable
;
44 import com
.intellij
.openapi
.project
.DumbService
;
45 import com
.intellij
.openapi
.project
.Project
;
46 import com
.intellij
.openapi
.project
.impl
.ProjectImpl
;
47 import com
.intellij
.openapi
.startup
.StartupManager
;
48 import com
.intellij
.openapi
.util
.*;
49 import com
.intellij
.openapi
.vcs
.FileStatus
;
50 import com
.intellij
.openapi
.vcs
.FileStatusListener
;
51 import com
.intellij
.openapi
.vcs
.FileStatusManager
;
52 import com
.intellij
.openapi
.vfs
.*;
53 import com
.intellij
.openapi
.wm
.ToolWindowManager
;
54 import com
.intellij
.openapi
.wm
.WindowManager
;
55 import com
.intellij
.openapi
.wm
.ex
.StatusBarEx
;
56 import com
.intellij
.openapi
.wm
.ex
.WindowManagerEx
;
57 import com
.intellij
.openapi
.wm
.impl
.FrameTitleBuilder
;
58 import com
.intellij
.openapi
.wm
.impl
.IdeFrameImpl
;
59 import com
.intellij
.util
.containers
.ContainerUtil
;
60 import com
.intellij
.util
.messages
.MessageBusConnection
;
61 import com
.intellij
.util
.messages
.impl
.MessageListenerList
;
62 import com
.intellij
.util
.ui
.update
.MergingUpdateQueue
;
63 import com
.intellij
.util
.ui
.update
.Update
;
64 import org
.jdom
.Element
;
65 import org
.jetbrains
.annotations
.NotNull
;
66 import org
.jetbrains
.annotations
.Nullable
;
70 import java
.beans
.PropertyChangeEvent
;
71 import java
.beans
.PropertyChangeListener
;
73 import java
.util
.ArrayList
;
74 import java
.util
.Arrays
;
75 import java
.util
.Collection
;
76 import java
.util
.List
;
79 * @author Anton Katilin
80 * @author Eugene Belyaev
81 * @author Vladimir Kondratyev
83 public class FileEditorManagerImpl
extends FileEditorManagerEx
implements ProjectComponent
, JDOMExternalizable
{
84 private static final Logger LOG
= Logger
.getInstance("#com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl");
85 private static final Key
<LocalFileSystem
.WatchRequest
> WATCH_REQUEST_KEY
= Key
.create("WATCH_REQUEST_KEY");
86 private static final Key
<Boolean
> DUMB_AWARE
= Key
.create("DUMB_AWARE");
88 private static final FileEditor
[] EMPTY_EDITOR_ARRAY
= {};
89 private static final FileEditorProvider
[] EMPTY_PROVIDER_ARRAY
= {};
91 private volatile JPanel myPanels
;
92 private EditorsSplitters mySplitters
;
93 private final Project myProject
;
95 private final MergingUpdateQueue myQueue
= new MergingUpdateQueue("FileEditorManagerUpdateQueue", 50, true, null);
98 * Removes invalid myEditor and updates "modified" status.
100 private final MyEditorPropertyChangeListener myEditorPropertyChangeListener
= new MyEditorPropertyChangeListener();
102 private final List
<EditorDataProvider
> myDataProviders
= new ArrayList
<EditorDataProvider
>();
104 public FileEditorManagerImpl(final Project project
) {
105 /* ApplicationManager.getApplication().assertIsDispatchThread(); */
107 myListenerList
= new MessageListenerList
<FileEditorManagerListener
>(myProject
.getMessageBus(), FileEditorManagerListener
.FILE_EDITOR_MANAGER
);
110 public static boolean isDumbAware(FileEditor editor
) {
111 return Boolean
.TRUE
.equals(editor
.getUserData(DUMB_AWARE
));
114 //-------------------------------------------------------------------------------
116 public JComponent
getComponent() {
121 public EditorsSplitters
getSplitters() {
126 private final Object myInitLock
= new Object();
127 private void initUI() {
128 if (myPanels
== null) {
129 synchronized (myInitLock
) {
130 if (myPanels
== null) {
131 myPanels
= new JPanel(new BorderLayout());
132 mySplitters
= new EditorsSplitters(this);
133 myPanels
.add(mySplitters
, BorderLayout
.CENTER
);
139 public JComponent
getPreferredFocusedComponent() {
141 final EditorWindow window
= getSplitters().getCurrentWindow();
142 if (window
!= null) {
143 final EditorWithProviderComposite editor
= window
.getSelectedEditor();
144 if (editor
!= null) {
145 return editor
.getPreferredFocusedComponent();
151 //-------------------------------------------------------
154 * @return color of the <code>file</code> which corresponds to the
157 public Color
getFileColor(@NotNull final VirtualFile file
) {
158 final FileStatusManager fileStatusManager
= FileStatusManager
.getInstance(myProject
);
159 Color statusColor
= fileStatusManager
!= null ? fileStatusManager
.getStatus(file
).getColor() : Color
.BLACK
;
160 if (statusColor
== null) statusColor
= Color
.BLACK
;
164 public boolean isProblem(@NotNull final VirtualFile file
) {
168 public String
getFileTooltipText(VirtualFile file
) {
169 return file
.getPresentableUrl();
172 public void updateFilePresentation(VirtualFile file
) {
173 if (!isFileOpen(file
)) return;
175 updateFileColor(file
);
176 updateFileIcon(file
);
177 updateFileName(file
);
178 updateFileBackgroundColor(file
);
182 * Updates tab color for the specified <code>file</code>. The <code>file</code>
183 * should be opened in the myEditor, otherwise the method throws an assertion.
185 private void updateFileColor(final VirtualFile file
) {
186 getSplitters().updateFileColor(file
);
189 private void updateFileBackgroundColor(final VirtualFile file
) {
190 getSplitters().updateFileBackgroundColor(file
);
194 * Updates tab icon for the specified <code>file</code>. The <code>file</code>
195 * should be opened in the myEditor, otherwise the method throws an assertion.
197 protected void updateFileIcon(final VirtualFile file
) {
198 getSplitters().updateFileIcon(file
);
202 * Updates tab title and tab tool tip for the specified <code>file</code>
204 void updateFileName(@Nullable final VirtualFile file
) {
205 // Queue here is to prevent title flickering when tab is being closed and two events arriving: with component==null and component==next focused tab
206 // only the last event makes sense to handle
207 myQueue
.queue(new Update("UpdateFileName "+(file
==null?
"":file
.getPath())) {
208 public boolean isExpired() {
209 return myProject
.isDisposed() || !myProject
.isOpen() || (file
== null ?
super.isExpired() : !file
.isValid());
213 final WindowManagerEx windowManagerEx
= WindowManagerEx
.getInstanceEx();
214 final IdeFrameImpl frame
= windowManagerEx
.getFrame(myProject
);
215 LOG
.assertTrue(frame
!= null);
216 getSplitters().updateFileName(file
);
217 File ioFile
= file
== null ?
null : new File(file
.getPresentableUrl());
218 frame
.setFileTitle(file
== null ?
null : FrameTitleBuilder
.getInstance().getFileTitle(myProject
, file
), ioFile
);
223 //-------------------------------------------------------
226 public VirtualFile
getFile(@NotNull final FileEditor editor
) {
227 final EditorComposite editorComposite
= getEditorComposite(editor
);
228 if (editorComposite
!= null) {
229 return editorComposite
.getFile();
234 public void unsplitWindow() {
235 final EditorWindow currentWindow
= getSplitters().getCurrentWindow();
236 if (currentWindow
!= null) {
237 currentWindow
.unsplit(true);
241 public void unsplitAllWindow() {
242 final EditorWindow currentWindow
= getSplitters().getCurrentWindow();
243 if (currentWindow
!= null) {
244 currentWindow
.unsplitAll();
249 public EditorWindow
[] getWindows() {
250 return getSplitters().getWindows();
253 public EditorWindow
getNextWindow(@NotNull final EditorWindow window
) {
254 final EditorWindow
[] windows
= getSplitters().getOrderedWindows();
255 for (int i
= 0; i
!= windows
.length
; ++i
) {
256 if (windows
[i
].equals(window
)) {
257 return windows
[(i
+ 1) % windows
.length
];
260 LOG
.error("Not window found");
264 public EditorWindow
getPrevWindow(@NotNull final EditorWindow window
) {
265 final EditorWindow
[] windows
= getSplitters().getOrderedWindows();
266 for (int i
= 0; i
!= windows
.length
; ++i
) {
267 if (windows
[i
].equals(window
)) {
268 return windows
[(i
+ windows
.length
- 1) % windows
.length
];
271 LOG
.error("Not window found");
275 public void createSplitter(final int orientation
) {
276 final EditorWindow currentWindow
= getSplitters().getCurrentWindow();
277 if (currentWindow
!= null) {
278 currentWindow
.split(orientation
);
282 public void changeSplitterOrientation() {
283 final EditorWindow currentWindow
= getSplitters().getCurrentWindow();
284 if (currentWindow
!= null) {
285 currentWindow
.changeOrientation();
290 public void flipTabs() {
292 if (myTabs == null) {
293 myTabs = new EditorTabs (this, UISettings.getInstance().EDITOR_TAB_PLACEMENT);
294 remove (mySplitters);
295 add (myTabs, BorderLayout.CENTER);
299 add (mySplitters, BorderLayout.CENTER);
304 myPanels
.revalidate();
307 public boolean tabsMode() {
311 private void setTabsMode(final boolean mode
) {
312 if (tabsMode() != mode
) {
315 //LOG.assertTrue (tabsMode () == mode);
319 public boolean isInSplitter() {
320 final EditorWindow currentWindow
= getSplitters().getCurrentWindow();
321 return currentWindow
!= null && currentWindow
.inSplitter();
324 public boolean hasOpenedFile() {
325 final EditorWindow currentWindow
= getSplitters().getCurrentWindow();
326 return currentWindow
!= null && currentWindow
.getSelectedEditor() != null;
329 public VirtualFile
getCurrentFile() {
330 return getSplitters().getCurrentFile();
333 public EditorWindow
getCurrentWindow() {
334 return getSplitters().getCurrentWindow();
337 public void setCurrentWindow(final EditorWindow window
) {
338 getSplitters().setCurrentWindow(window
, true);
341 public void closeFile(@NotNull final VirtualFile file
, @NotNull final EditorWindow window
) {
342 assertDispatchThread();
344 CommandProcessor
.getInstance().executeCommand(myProject
, new Runnable() {
346 if (window
.isFileOpen(file
)) {
347 window
.closeFile(file
);
348 final List
<EditorWindow
> windows
= getSplitters().findWindows(file
);
349 if (windows
.isEmpty()) { // no more windows containing this file left
350 final LocalFileSystem
.WatchRequest request
= file
.getUserData(WATCH_REQUEST_KEY
);
351 if (request
!= null) {
352 LocalFileSystem
.getInstance().removeWatchedRoot(request
);
357 }, IdeBundle
.message("command.close.active.editor"), null);
360 //============================= EditorManager methods ================================
362 public void closeFile(@NotNull final VirtualFile file
) {
363 closeFile(file
, true);
366 public void closeFile(@NotNull final VirtualFile file
, final boolean moveFocus
) {
367 assertDispatchThread();
369 final LocalFileSystem
.WatchRequest request
= file
.getUserData(WATCH_REQUEST_KEY
);
370 if (request
!= null) {
371 LocalFileSystem
.getInstance().removeWatchedRoot(request
);
374 CommandProcessor
.getInstance().executeCommand(myProject
, new Runnable() {
376 closeFileImpl(file
, moveFocus
);
382 private VirtualFile
findNextFile(final VirtualFile file
) {
383 final EditorWindow
[] windows
= getWindows(); // TODO: use current file as base
384 for (int i
= 0; i
!= windows
.length
; ++ i
) {
385 final VirtualFile
[] files
= windows
[i
].getFiles();
386 for (final VirtualFile fileAt
: files
) {
387 if (fileAt
!= file
) {
395 private void closeFileImpl(@NotNull final VirtualFile file
, final boolean moveFocus
) {
396 assertDispatchThread();
397 getSplitters().runChange(new Runnable() {
399 final List
<EditorWindow
> windows
= getSplitters().findWindows(file
);
400 if (!windows
.isEmpty()) {
401 final VirtualFile nextFile
= findNextFile(file
);
402 for (final EditorWindow window
: windows
) {
403 LOG
.assertTrue(window
.getSelectedEditor() != null);
404 window
.closeFile(file
, false, moveFocus
);
405 if (window
.getTabCount() == 0 && nextFile
!= null) {
406 EditorWithProviderComposite newComposite
= newEditorComposite(nextFile
);
407 window
.setEditor(newComposite
, moveFocus
); // newComposite can be null
410 // cleanup windows with no tabs
411 for (final EditorWindow window
: windows
) {
412 if (window
.isDisposed()) {
413 // call to window.unsplit() which might make its sibling disposed
416 if (window
.getTabCount() == 0) {
417 window
.unsplit(false);
425 //-------------------------------------- Open File ----------------------------------------
427 @NotNull public Pair
<FileEditor
[], FileEditorProvider
[]> openFileWithProviders(@NotNull final VirtualFile file
, final boolean focusEditor
) {
428 if (!file
.isValid()) {
429 throw new IllegalArgumentException("file is not valid: " + file
);
431 assertDispatchThread();
432 return openFileImpl2(getSplitters().getOrCreateCurrentWindow(file
), file
, focusEditor
, null);
435 @NotNull Pair
<FileEditor
[], FileEditorProvider
[]> openFileImpl2(final EditorWindow window
, final VirtualFile file
, final boolean focusEditor
,
436 final HistoryEntry entry
) {
437 final Ref
<Pair
<FileEditor
[], FileEditorProvider
[]>> resHolder
= new Ref
<Pair
<FileEditor
[], FileEditorProvider
[]>>();
438 CommandProcessor
.getInstance().executeCommand(myProject
, new Runnable() {
440 resHolder
.set(openFileImpl3(window
, file
, focusEditor
, entry
, true));
443 return resHolder
.get();
447 * @param file to be opened. Unlike openFile method, file can be
448 * invalid. For example, all file were invalidate and they are being
449 * removed one by one. If we have removed one invalid file, then another
450 * invalid file become selected. That's why we do not require that
451 * passed file is valid.
452 * @param entry map between FileEditorProvider and FileEditorState. If this parameter
455 @NotNull Pair
<FileEditor
[], FileEditorProvider
[]> openFileImpl3(final EditorWindow window
,
456 @NotNull final VirtualFile file
,
457 final boolean focusEditor
,
458 final HistoryEntry entry
,
461 FileEditor
[] editors
;
462 FileEditorProvider
[] providers
;
463 final EditorWithProviderComposite newSelectedComposite
;
464 boolean newEditorCreated
= false;
466 final boolean open
= window
.isFileOpen(file
);
468 // File is already opened. In this case we have to just select existing EditorComposite
469 newSelectedComposite
= window
.findFileComposite(file
);
470 LOG
.assertTrue(newSelectedComposite
!= null);
472 editors
= newSelectedComposite
.getEditors();
473 providers
= newSelectedComposite
.getProviders();
476 // File is not opened yet. In this case we have to create editors
477 // and select the created EditorComposite.
478 final FileEditorProviderManager editorProviderManager
= FileEditorProviderManager
.getInstance();
479 providers
= editorProviderManager
.getProviders(myProject
, file
);
480 if (DumbService
.getInstance(myProject
).isDumb()) {
481 final List
<FileEditorProvider
> dumbAware
= ContainerUtil
.findAll(providers
, new Condition
<FileEditorProvider
>() {
482 public boolean value(FileEditorProvider fileEditorProvider
) {
483 return fileEditorProvider
instanceof DumbAware
;
486 providers
= dumbAware
.toArray(new FileEditorProvider
[dumbAware
.size()]);
489 if (providers
.length
== 0) {
490 return Pair
.create(EMPTY_EDITOR_ARRAY
, EMPTY_PROVIDER_ARRAY
);
492 newEditorCreated
= true;
494 editors
= new FileEditor
[providers
.length
];
495 for (int i
= 0; i
< providers
.length
; i
++) {
497 final FileEditorProvider provider
= providers
[i
];
498 LOG
.assertTrue(provider
!= null);
499 LOG
.assertTrue(provider
.accept(myProject
, file
));
500 final FileEditor editor
= provider
.createEditor(myProject
, file
);
501 if (current
&& editor
instanceof TextEditorImpl
) {
502 ((TextEditorImpl
)editor
).initFolding();
505 LOG
.assertTrue(editor
!= null);
506 LOG
.assertTrue(editor
.isValid());
508 // Register PropertyChangeListener into editor
509 editor
.addPropertyChangeListener(myEditorPropertyChangeListener
);
510 editor
.putUserData(DUMB_AWARE
, provider
instanceof DumbAware
);
512 catch (Exception e
) {
515 catch (AssertionError e
) {
520 // Now we have to create EditorComposite and insert it into the TabbedEditorComponent.
521 // After that we have to select opened editor.
522 newSelectedComposite
= new EditorWithProviderComposite(file
, editors
, providers
, this);
525 window
.setEditor(newSelectedComposite
, focusEditor
);
527 final EditorHistoryManager editorHistoryManager
= EditorHistoryManager
.getInstance(myProject
);
528 for (int i
= 0; i
< editors
.length
; i
++) {
529 final FileEditor editor
= editors
[i
];
530 if (editor
instanceof TextEditor
) {
532 // This code prevents "jumping" on next repaint.
533 ((EditorEx
)((TextEditor
)editor
).getEditor()).stopOptimizedScrolling();
536 final FileEditorProvider provider
= providers
[i
];//getProvider(editor);
538 // Restore editor state
539 FileEditorState state
= null;
541 state
= entry
.getState(provider
);
543 if (state
== null && !open
) {
544 // We have to try to get state from the history only in case
545 // if editor is not opened. Otherwise history enty might have a state
546 // out of sync with the current editor state.
547 state
= editorHistoryManager
.getState(file
, provider
);
550 editor
.setState(state
);
554 // Restore selected editor
555 final FileEditorProvider selectedProvider
= editorHistoryManager
.getSelectedProvider(file
);
556 if (selectedProvider
!= null) {
557 final FileEditor
[] _editors
= newSelectedComposite
.getEditors();
558 final FileEditorProvider
[] _providers
= newSelectedComposite
.getProviders();
559 for (int i
= _editors
.length
- 1; i
>= 0; i
--) {
560 final FileEditorProvider provider
= _providers
[i
];//getProvider(_editors[i]);
561 if (provider
.equals(selectedProvider
)) {
562 newSelectedComposite
.setSelectedEditor(i
);
568 // Notify editors about selection changes
569 getSplitters().setCurrentWindow(window
, false);
570 newSelectedComposite
.getSelectedEditor().selectNotify();
572 if (newEditorCreated
) {
573 getProject().getMessageBus().syncPublisher(FileEditorManagerListener
.FILE_EDITOR_MANAGER
).fileOpened(this, file
);
575 //Add request to watch this editor's virtual file
576 final VirtualFile parentDir
= file
.getParent();
577 if (parentDir
!= null) {
578 final LocalFileSystem
.WatchRequest request
= LocalFileSystem
.getInstance().addRootToWatch(parentDir
.getPath(), false);
579 file
.putUserData(WATCH_REQUEST_KEY
, request
);
583 //[jeka] this is a hack to support back-forward navigation
584 // previously here was incorrect call to fireSelectionChanged() with a side-effect
585 ((IdeDocumentHistoryImpl
)IdeDocumentHistory
.getInstance(myProject
)).onSelectionChanged();
587 // Transfer focus into editor
588 if (!ApplicationManagerEx
.getApplicationEx().isUnitTestMode()) {
590 //myFirstIsActive = myTabbedContainer1.equals(tabbedContainer);
591 window
.setAsCurrentWindow(false);
592 ToolWindowManager
.getInstance(myProject
).activateEditorComponent();
596 // Update frame and tab title
597 updateFileName(file
);
599 // Make back/forward work
600 IdeDocumentHistory
.getInstance(myProject
).includeCurrentCommandAsNavigation();
602 return Pair
.create(editors
, providers
);
605 private void setSelectedEditor(VirtualFile file
, String fileEditorProviderId
) {
606 EditorWithProviderComposite composite
= getCurrentEditorWithProviderComposite(file
);
607 if (composite
== null) {
608 final List
<EditorWithProviderComposite
> composites
= getEditorComposites(file
);
610 if (composites
.isEmpty()) return;
611 composite
= composites
.get(0);
614 final FileEditorProvider
[] editorProviders
= composite
.getProviders();
615 final FileEditorProvider selectedProvider
= composite
.getSelectedEditorWithProvider().getSecond();
617 for (int i
= 0; i
< editorProviders
.length
; i
++) {
618 if (editorProviders
[i
].getEditorTypeId().equals(fileEditorProviderId
) && !selectedProvider
.equals(editorProviders
[i
])) {
619 composite
.setSelectedEditor(i
);
620 composite
.getSelectedEditor().selectNotify();
626 private EditorWithProviderComposite
newEditorComposite(final VirtualFile file
) {
631 final FileEditorProviderManager editorProviderManager
= FileEditorProviderManager
.getInstance();
632 final FileEditorProvider
[] providers
= editorProviderManager
.getProviders(myProject
, file
);
633 final FileEditor
[] editors
= new FileEditor
[providers
.length
];
634 for (int i
= 0; i
< providers
.length
; i
++) {
635 final FileEditorProvider provider
= providers
[i
];
636 LOG
.assertTrue(provider
!= null);
637 LOG
.assertTrue(provider
.accept(myProject
, file
));
638 final FileEditor editor
= provider
.createEditor(myProject
, file
);
640 LOG
.assertTrue(editor
.isValid());
641 editor
.addPropertyChangeListener(myEditorPropertyChangeListener
);
644 final EditorWithProviderComposite newComposite
= new EditorWithProviderComposite(file
, editors
, providers
, this);
645 final EditorHistoryManager editorHistoryManager
= EditorHistoryManager
.getInstance(myProject
);
646 for (int i
= 0; i
< editors
.length
; i
++) {
647 final FileEditor editor
= editors
[i
];
648 if (editor
instanceof TextEditor
) {
650 // This code prevents "jumping" on next repaint.
651 //((EditorEx)((TextEditor)editor).getEditor()).stopOptimizedScrolling();
654 final FileEditorProvider provider
= providers
[i
];
656 // Restore myEditor state
657 FileEditorState state
= editorHistoryManager
.getState(file
, provider
);
659 editor
.setState(state
);
666 public List
<FileEditor
> openEditor(@NotNull final OpenFileDescriptor descriptor
, final boolean focusEditor
) {
667 assertDispatchThread();
668 if (descriptor
.getFile() instanceof VirtualFileWindow
) {
669 VirtualFileWindow delegate
= (VirtualFileWindow
)descriptor
.getFile();
670 int hostOffset
= delegate
.getDocumentWindow().injectedToHost(descriptor
.getOffset());
671 OpenFileDescriptor realDescriptor
= new OpenFileDescriptor(descriptor
.getProject(), delegate
.getDelegate(), hostOffset
);
672 return openEditor(realDescriptor
, focusEditor
);
675 final List
<FileEditor
> result
= new ArrayList
<FileEditor
>();
676 CommandProcessor
.getInstance().executeCommand(myProject
, new Runnable() {
678 VirtualFile file
= descriptor
.getFile();
679 final FileEditor
[] editors
= openFile(file
, focusEditor
);
680 result
.addAll(Arrays
.asList(editors
));
682 boolean navigated
= false;
683 for (final FileEditor editor
: editors
) {
684 if (editor
instanceof NavigatableFileEditor
&& getSelectedEditor(descriptor
.getFile()) == editor
) { // try to navigate opened editor
685 navigated
= navigateAndSelectEditor((NavigatableFileEditor
) editor
, descriptor
);
686 if (navigated
) break;
691 for (final FileEditor editor
: editors
) {
692 if (editor
instanceof NavigatableFileEditor
&& getSelectedEditor(descriptor
.getFile()) != editor
) { // try other editors
693 if (navigateAndSelectEditor((NavigatableFileEditor
) editor
, descriptor
)) {
705 private boolean navigateAndSelectEditor(final NavigatableFileEditor editor
, final OpenFileDescriptor descriptor
) {
706 if (editor
.canNavigateTo(descriptor
)) {
707 setSelectedEditor(editor
);
708 editor
.navigateTo(descriptor
);
715 private void setSelectedEditor(final FileEditor editor
) {
716 final EditorWithProviderComposite composite
= getEditorComposite(editor
);
717 if (composite
== null) return;
719 final FileEditor
[] editors
= composite
.getEditors();
720 for (int i
= 0; i
< editors
.length
; i
++) {
721 final FileEditor each
= editors
[i
];
722 if (editor
== each
) {
723 composite
.setSelectedEditor(i
);
724 composite
.getSelectedEditor().selectNotify();
731 public Project
getProject() {
735 public void registerExtraEditorDataProvider(@NotNull final EditorDataProvider provider
, Disposable parentDisposable
) {
736 myDataProviders
.add(provider
);
737 if (parentDisposable
!= null) {
738 Disposer
.register(parentDisposable
, new Disposable() {
739 public void dispose() {
740 myDataProviders
.remove(provider
);
747 public final Object
getData(String dataId
, Editor editor
, final VirtualFile file
) {
748 for (final EditorDataProvider dataProvider
: myDataProviders
) {
749 final Object o
= dataProvider
.getData(dataId
, editor
, file
);
750 if (o
!= null) return o
;
756 public Editor
openTextEditor(final OpenFileDescriptor descriptor
, final boolean focusEditor
) {
757 final Collection
<FileEditor
> fileEditors
= openEditor(descriptor
, focusEditor
);
758 for (FileEditor fileEditor
: fileEditors
) {
759 if (fileEditor
instanceof TextEditor
) {
760 setSelectedEditor(descriptor
.getFile(), TextEditorProvider
.getInstance().getEditorTypeId());
761 Editor editor
= ((TextEditor
)fileEditor
).getEditor();
762 return getOpenedEditor(editor
, focusEditor
);
769 protected Editor
getOpenedEditor(final Editor editor
, final boolean focusEditor
) {
773 public Editor
getSelectedTextEditor() {
776 final EditorWindow currentWindow
= getSplitters().getCurrentWindow();
777 if (currentWindow
!= null) {
778 final EditorWithProviderComposite selectedEditor
= currentWindow
.getSelectedEditor();
779 if (selectedEditor
!= null && selectedEditor
.getSelectedEditor() instanceof TextEditor
) {
780 return ((TextEditor
)selectedEditor
.getSelectedEditor()).getEditor();
788 public boolean isFileOpen(@NotNull final VirtualFile file
) {
789 return getEditors(file
).length
!= 0;
793 public VirtualFile
[] getOpenFiles() {
794 return getSplitters().getOpenFiles();
798 public VirtualFile
[] getSelectedFiles() {
799 return getSplitters().getSelectedFiles();
803 public FileEditor
[] getSelectedEditors() {
804 return getSplitters().getSelectedEditors();
807 public FileEditor
getSelectedEditor(@NotNull final VirtualFile file
) {
808 final Pair
<FileEditor
, FileEditorProvider
> selectedEditorWithProvider
= getSelectedEditorWithProvider(file
);
809 return selectedEditorWithProvider
== null ?
null : selectedEditorWithProvider
.getFirst();
813 public Pair
<FileEditor
, FileEditorProvider
> getSelectedEditorWithProvider(@NotNull VirtualFile file
) {
814 if (file
instanceof VirtualFileWindow
) file
= ((VirtualFileWindow
)file
).getDelegate();
815 final EditorWithProviderComposite composite
= getCurrentEditorWithProviderComposite(file
);
816 if (composite
!= null) {
817 return composite
.getSelectedEditorWithProvider();
820 final List
<EditorWithProviderComposite
> composites
= getEditorComposites(file
);
821 return composites
.isEmpty() ?
null : composites
.get(0).getSelectedEditorWithProvider();
825 public Pair
<FileEditor
[], FileEditorProvider
[]> getEditorsWithProviders(@NotNull final VirtualFile file
) {
828 final EditorWithProviderComposite composite
= getCurrentEditorWithProviderComposite(file
);
829 if (composite
!= null) {
830 return Pair
.create(composite
.getEditors(), composite
.getProviders());
833 final List
<EditorWithProviderComposite
> composites
= getEditorComposites(file
);
834 if (!composites
.isEmpty()) {
835 return Pair
.create(composites
.get(0).getEditors(), composites
.get(0).getProviders());
838 return Pair
.create(EMPTY_EDITOR_ARRAY
, EMPTY_PROVIDER_ARRAY
);
843 public FileEditor
[] getEditors(@NotNull VirtualFile file
) {
845 if (file
instanceof VirtualFileWindow
) file
= ((VirtualFileWindow
)file
).getDelegate();
847 final EditorWithProviderComposite composite
= getCurrentEditorWithProviderComposite(file
);
848 if (composite
!= null) {
849 return composite
.getEditors();
852 final List
<EditorWithProviderComposite
> composites
= getEditorComposites(file
);
853 if (!composites
.isEmpty()) {
854 return composites
.get(0).getEditors();
857 return EMPTY_EDITOR_ARRAY
;
862 private EditorWithProviderComposite
getCurrentEditorWithProviderComposite(@NotNull final VirtualFile virtualFile
) {
863 final EditorWindow editorWindow
= getSplitters().getCurrentWindow();
864 if (editorWindow
!= null) {
865 return editorWindow
.findFileComposite(virtualFile
);
871 public List
<EditorWithProviderComposite
> getEditorComposites(final VirtualFile file
) {
872 return getSplitters().findEditorComposites(file
);
876 public FileEditor
[] getAllEditors() {
878 final ArrayList
<FileEditor
> result
= new ArrayList
<FileEditor
>();
879 final EditorWithProviderComposite
[] editorsComposites
= getSplitters().getEditorsComposites();
880 for (EditorWithProviderComposite editorsComposite
: editorsComposites
) {
881 final FileEditor
[] editors
= editorsComposite
.getEditors();
882 result
.addAll(Arrays
.asList(editors
));
884 return result
.toArray(new FileEditor
[result
.size()]);
887 public void showEditorAnnotation(@NotNull FileEditor editor
, @NotNull JComponent annotationComponent
) {
888 final EditorComposite composite
= getEditorComposite(editor
);
889 if (composite
!= null) {
890 composite
.getPane(editor
).addInfo(annotationComponent
);
894 public void removeEditorAnnotation(@NotNull FileEditor editor
, @NotNull JComponent annotationComponent
) {
895 final EditorComposite composite
= getEditorComposite(editor
);
896 if (composite
!= null) {
897 composite
.getPane(editor
).removeInfo(annotationComponent
);
901 public void addTopComponent(@NotNull final FileEditor editor
, @NotNull final JComponent component
) {
902 final EditorComposite composite
= getEditorComposite(editor
);
903 if (composite
!= null) {
904 composite
.addTopComponent(editor
, component
);
908 public void removeTopComponent(@NotNull final FileEditor editor
, @NotNull final JComponent component
) {
909 final EditorComposite composite
= getEditorComposite(editor
);
910 if (composite
!= null) {
911 composite
.removeTopComponent(editor
, component
);
915 public void addBottomComponent(@NotNull final FileEditor editor
, @NotNull final JComponent component
) {
916 final EditorComposite composite
= getEditorComposite(editor
);
917 if (composite
!= null) {
918 composite
.addBottomComponent(editor
, component
);
922 public void removeBottomComponent(@NotNull final FileEditor editor
, @NotNull final JComponent component
) {
923 final EditorComposite composite
= getEditorComposite(editor
);
924 if (composite
!= null) {
925 composite
.removeBottomComponent(editor
, component
);
929 private final MessageListenerList
<FileEditorManagerListener
> myListenerList
;
931 public void addFileEditorManagerListener(@NotNull final FileEditorManagerListener listener
) {
932 myListenerList
.add(listener
);
935 public void addFileEditorManagerListener(@NotNull final FileEditorManagerListener listener
, final Disposable parentDisposable
) {
936 myListenerList
.add(listener
, parentDisposable
);
939 public void removeFileEditorManagerListener(@NotNull final FileEditorManagerListener listener
) {
940 myListenerList
.remove(listener
);
943 // ProjectComponent methods
945 public void projectOpened() {
946 //myFocusWatcher.install(myWindows.getComponent ());
947 getSplitters().startListeningFocus();
949 MessageBusConnection connection
= myProject
.getMessageBus().connect(myProject
);
951 final FileStatusManager fileStatusManager
= FileStatusManager
.getInstance(myProject
);
952 if (fileStatusManager
!= null) {
954 * Updates tabs colors
956 final MyFileStatusListener myFileStatusListener
= new MyFileStatusListener();
957 fileStatusManager
.addFileStatusListener(myFileStatusListener
, myProject
);
959 connection
.subscribe(AppTopics
.FILE_TYPES
, new MyFileTypeListener());
963 final MyVirtualFileListener myVirtualFileListener
= new MyVirtualFileListener();
964 VirtualFileManager
.getInstance().addVirtualFileListener(myVirtualFileListener
, myProject
);
966 * Extends/cuts number of opened tabs. Also updates location of tabs.
968 final MyUISettingsListener myUISettingsListener
= new MyUISettingsListener();
969 UISettings
.getInstance().addUISettingsListener(myUISettingsListener
);
970 Disposer
.register(myProject
, new Disposable() {
971 public void dispose() {
972 UISettings
.getInstance().removeUISettingsListener(myUISettingsListener
);
976 StartupManager
.getInstance(myProject
).registerPostStartupActivity(new DumbAwareRunnable() {
978 ToolWindowManager
.getInstance(myProject
).invokeLater(new Runnable() {
980 CommandProcessor
.getInstance().executeCommand(myProject
, new Runnable() {
982 setTabsMode(UISettings
.getInstance().EDITOR_TAB_PLACEMENT
!= UISettings
.TABS_NONE
);
983 getSplitters().openFiles();
984 LaterInvocator
.invokeLater(new Runnable() {
986 long currentTime
= System
.nanoTime();
987 Long startTime
= myProject
.getUserData(ProjectImpl
.CREATION_TIME
);
988 if (startTime
!= null) {
989 LOG
.info("Project opening took " + (currentTime
- startTime
.longValue()) / 1000000 + " ms");
990 PluginManager
.dumpPluginClassStatistics();
1003 public void projectClosed() {
1004 //myFocusWatcher.deinstall(myWindows.getComponent ());
1005 getSplitters().dispose();
1007 // Dispose created editors. We do not use use closeEditor method because
1008 // it fires event and changes history.
1012 // BaseCompomemnt methods
1015 public String
getComponentName() {
1016 return "FileEditorManager";
1019 public void initComponent() { /* really do nothing */ }
1021 public void disposeComponent() { /* really do nothing */ }
1023 //JDOMExternalizable methods
1025 public void writeExternal(final Element element
) {
1026 getSplitters().writeExternal(element
);
1029 public void readExternal(final Element element
) {
1030 getSplitters().readExternal(element
);
1033 private EditorWithProviderComposite
getEditorComposite(@NotNull final FileEditor editor
) {
1034 final EditorWithProviderComposite
[] editorsComposites
= getSplitters().getEditorsComposites();
1035 for (int i
= editorsComposites
.length
- 1; i
>= 0; i
--) {
1036 final EditorWithProviderComposite composite
= editorsComposites
[i
];
1037 final FileEditor
[] editors
= composite
.getEditors();
1038 for (int j
= editors
.length
- 1; j
>= 0; j
--) {
1039 final FileEditor _editor
= editors
[j
];
1040 LOG
.assertTrue(_editor
!= null);
1041 if (editor
.equals(_editor
)) {
1049 //======================= Misc =====================
1051 private static void assertDispatchThread() {
1052 ApplicationManager
.getApplication().assertIsDispatchThread();
1054 private static void assertReadAccess() {
1055 ApplicationManager
.getApplication().assertReadAccessAllowed();
1058 public void fireSelectionChanged(final EditorComposite oldSelectedComposite
, final EditorComposite newSelectedComposite
) {
1059 final VirtualFile oldSelectedFile
= oldSelectedComposite
!= null ? oldSelectedComposite
.getFile() : null;
1060 final VirtualFile newSelectedFile
= newSelectedComposite
!= null ? newSelectedComposite
.getFile() : null;
1062 final FileEditor oldSelectedEditor
= oldSelectedComposite
!= null && !oldSelectedComposite
.isDisposed() ? oldSelectedComposite
.getSelectedEditor() : null;
1063 final FileEditor newSelectedEditor
= newSelectedComposite
!= null && !newSelectedComposite
.isDisposed() ? newSelectedComposite
.getSelectedEditor() : null;
1065 final boolean filesEqual
= oldSelectedFile
== null ? newSelectedFile
== null : oldSelectedFile
.equals(newSelectedFile
);
1066 final boolean editorsEqual
= oldSelectedEditor
== null ? newSelectedEditor
== null : oldSelectedEditor
.equals(newSelectedEditor
);
1067 if (!filesEqual
|| !editorsEqual
) {
1068 final FileEditorManagerEvent event
=
1069 new FileEditorManagerEvent(this, oldSelectedFile
, oldSelectedEditor
, newSelectedFile
, newSelectedEditor
);
1070 final FileEditorManagerListener publisher
= getProject().getMessageBus().syncPublisher(FileEditorManagerListener
.FILE_EDITOR_MANAGER
);
1071 publisher
.selectionChanged(event
);
1075 public boolean isChanged(@NotNull final EditorComposite editor
) {
1076 final FileStatusManager fileStatusManager
= FileStatusManager
.getInstance(myProject
);
1077 if (fileStatusManager
!= null) {
1078 if (!fileStatusManager
.getStatus(editor
.getFile()).equals(FileStatus
.NOT_CHANGED
)) {
1085 public void disposeComposite(EditorWithProviderComposite editor
) {
1086 if (getAllEditors().length
== 0) {
1087 setCurrentWindow(null);
1090 if (editor
.equals(getLastSelected())) {
1091 editor
.getSelectedEditor().deselectNotify();
1092 getSplitters().setCurrentWindow(null, false);
1095 final FileEditor
[] editors
= editor
.getEditors();
1096 final FileEditorProvider
[] providers
= editor
.getProviders();
1098 final FileEditor selectedEditor
= editor
.getSelectedEditor();
1099 for (int i
= editors
.length
- 1; i
>= 0; i
--) {
1100 final FileEditor editor1
= editors
[i
];
1101 final FileEditorProvider provider
= providers
[i
];
1102 if (!editor
.equals(selectedEditor
)) { // we already notified the myEditor (when fire event)
1103 if (selectedEditor
.equals(editor1
)) {
1104 editor1
.deselectNotify();
1107 editor1
.removePropertyChangeListener(myEditorPropertyChangeListener
);
1108 provider
.disposeEditor(editor1
);
1111 Disposer
.dispose(editor
);
1114 EditorComposite
getLastSelected() {
1115 final EditorWindow currentWindow
= getSplitters().getCurrentWindow();
1116 if (currentWindow
!= null) {
1117 return currentWindow
.getSelectedEditor();
1122 public void runChange(Runnable runnable
) {
1123 getSplitters().runChange(runnable
);
1126 //================== Listeners =====================
1129 * Closes deleted files. Closes file which are in the deleted directories.
1131 private final class MyVirtualFileListener
extends VirtualFileAdapter
{
1132 public void beforeFileDeletion(VirtualFileEvent e
) {
1133 assertDispatchThread();
1134 final VirtualFile file
= e
.getFile();
1135 final VirtualFile
[] openFiles
= getOpenFiles();
1136 for (int i
= openFiles
.length
- 1; i
>= 0; i
--) {
1137 if (VfsUtil
.isAncestor(file
, openFiles
[i
], false)) {
1138 closeFile(openFiles
[i
]);
1143 public void propertyChanged(VirtualFilePropertyEvent e
) {
1144 if (VirtualFile
.PROP_NAME
.equals(e
.getPropertyName())) {
1145 assertDispatchThread();
1146 final VirtualFile file
= e
.getFile();
1147 if (isFileOpen(file
)) {
1148 updateFileName(file
);
1149 updateFileIcon(file
); // file type can change after renaming
1150 updateFileBackgroundColor(file
);
1153 else if (VirtualFile
.PROP_WRITABLE
.equals(e
.getPropertyName()) || VirtualFile
.PROP_ENCODING
.equals(e
.getPropertyName())) {
1154 updateIconAndStatusbar(e
);
1158 private void updateIconAndStatusbar(final VirtualFilePropertyEvent e
) {
1159 assertDispatchThread();
1160 final VirtualFile file
= e
.getFile();
1161 if (isFileOpen(file
)) {
1162 updateFileIcon(file
);
1163 if (file
.equals(getSelectedFiles()[0])) { // update "write" status
1164 final StatusBarEx statusBar
= (StatusBarEx
)WindowManager
.getInstance().getStatusBar(myProject
);
1165 assert statusBar
!= null;
1166 statusBar
.update(getSelectedTextEditor());
1171 public void fileMoved(VirtualFileMoveEvent e
) {
1172 final VirtualFile file
= e
.getFile();
1173 final VirtualFile
[] openFiles
= getOpenFiles();
1174 for (final VirtualFile openFile
: openFiles
) {
1175 if (VfsUtil
.isAncestor(file
, openFile
, false)) {
1176 updateFileName(openFile
);
1177 updateFileBackgroundColor(openFile
);
1184 private final class MyVirtualFileListener extends VirtualFileAdapter {
1185 public void beforeFileDeletion(final VirtualFileEvent e) {
1186 assertDispatchThread();
1187 final VirtualFile file = e.getFile();
1188 final VirtualFile[] openFiles = getOpenFiles();
1189 for (int i = openFiles.length - 1; i >= 0; i--) {
1190 if (VfsUtil.isAncestor(file, openFiles[i], false)) {
1191 closeFile(openFiles[i]);
1196 public void propertyChanged(final VirtualFilePropertyEvent e) {
1197 if (VirtualFile.PROP_WRITABLE.equals(e.getPropertyName())) {
1198 assertDispatchThread();
1199 final VirtualFile file = e.getFile();
1200 if (isFileOpen(file)) {
1201 if (file.equals(getSelectedFiles()[0])) { // update "write" status
1202 final StatusBarEx statusBar = (StatusBarEx)WindowManager.getInstance().getStatusBar(myProject);
1203 LOG.assertTrue(statusBar != null);
1204 statusBar.setWriteStatus(!file.isWritable());
1210 //public void fileMoved(final VirtualFileMoveEvent e){ }
1214 public boolean isInsideChange() {
1215 return getSplitters().isInsideChange();
1218 private final class MyEditorPropertyChangeListener
implements PropertyChangeListener
{
1219 public void propertyChange(final PropertyChangeEvent e
) {
1220 assertDispatchThread();
1222 final String propertyName
= e
.getPropertyName();
1223 if (FileEditor
.PROP_MODIFIED
.equals(propertyName
)) {
1224 final FileEditor editor
= (FileEditor
)e
.getSource();
1225 final EditorComposite composite
= getEditorComposite(editor
);
1226 if (composite
!= null) {
1227 updateFileIcon(composite
.getFile());
1230 else if (FileEditor
.PROP_VALID
.equals(propertyName
)) {
1231 final boolean valid
= ((Boolean
)e
.getNewValue()).booleanValue();
1233 final FileEditor editor
= (FileEditor
)e
.getSource();
1234 LOG
.assertTrue(editor
!= null);
1235 final EditorComposite composite
= getEditorComposite(editor
);
1236 if (composite
!= null) {
1237 closeFile(composite
.getFile());
1246 * Gets events from VCS and updates color of myEditor tabs
1248 private final class MyFileStatusListener
implements FileStatusListener
{
1249 public void fileStatusesChanged() { // update color of all open files
1250 assertDispatchThread();
1251 LOG
.debug("FileEditorManagerImpl.MyFileStatusListener.fileStatusesChanged()");
1252 final VirtualFile
[] openFiles
= getOpenFiles();
1253 for (int i
= openFiles
.length
- 1; i
>= 0; i
--) {
1254 final VirtualFile file
= openFiles
[i
];
1255 LOG
.assertTrue(file
!= null);
1256 ApplicationManager
.getApplication().invokeLater(new Runnable() {
1258 if (LOG
.isDebugEnabled()) {
1259 LOG
.debug("updating file status in tab for " + file
.getPath());
1261 updateFileStatus(file
);
1263 }, ModalityState
.NON_MODAL
, myProject
.getDisposed());
1267 public void fileStatusChanged(@NotNull final VirtualFile file
) { // update color of the file (if necessary)
1268 assertDispatchThread();
1269 if (isFileOpen(file
)) {
1270 updateFileStatus(file
);
1274 private void updateFileStatus(final VirtualFile file
) {
1275 updateFileColor(file
);
1276 updateFileIcon(file
);
1281 * Gets events from FileTypeManager and updates icons on tabs
1283 private final class MyFileTypeListener
implements FileTypeListener
{
1284 public void beforeFileTypesChanged(FileTypeEvent event
) {
1287 public void fileTypesChanged(final FileTypeEvent event
) {
1288 assertDispatchThread();
1289 final VirtualFile
[] openFiles
= getOpenFiles();
1290 for (int i
= openFiles
.length
- 1; i
>= 0; i
--) {
1291 final VirtualFile file
= openFiles
[i
];
1292 LOG
.assertTrue(file
!= null);
1293 updateFileIcon(file
);
1299 * Gets notifications from UISetting component to track changes of RECENT_FILES_LIMIT
1300 * and EDITOR_TAB_LIMIT, etc values.
1302 private final class MyUISettingsListener
implements UISettingsListener
{
1303 public void uiSettingsChanged(final UISettings source
) {
1304 assertDispatchThread();
1305 setTabsMode(source
.EDITOR_TAB_PLACEMENT
!= UISettings
.TABS_NONE
);
1306 getSplitters().setTabsPlacement(source
.EDITOR_TAB_PLACEMENT
);
1307 getSplitters().trimToSize(source
.EDITOR_TAB_LIMIT
);
1309 // Tab layout policy
1310 if (source
.SCROLL_TAB_LAYOUT_IN_EDITOR
) {
1311 getSplitters().setTabLayoutPolicy(JTabbedPane
.SCROLL_TAB_LAYOUT
);
1314 getSplitters().setTabLayoutPolicy(JTabbedPane
.WRAP_TAB_LAYOUT
);
1317 // "Mark modified files with asterisk"
1318 final VirtualFile
[] openFiles
= getOpenFiles();
1319 for (int i
= openFiles
.length
- 1; i
>= 0; i
--) {
1320 final VirtualFile file
= openFiles
[i
];
1321 updateFileIcon(file
);
1322 updateFileName(file
);
1323 updateFileBackgroundColor(file
);
1328 public void closeAllFiles() {
1329 final VirtualFile
[] openFiles
= getSplitters().getOpenFiles();
1330 for (VirtualFile openFile
: openFiles
) {
1331 closeFile(openFile
);
1336 public VirtualFile
[] getSiblings(VirtualFile file
) {
1337 return getOpenFiles();
1340 protected void queueUpdateFile(final VirtualFile file
) {
1341 myQueue
.queue(new Update(file
) {
1343 if (isFileOpen(file
)) {
1344 updateFileIcon(file
);
1345 updateFileColor(file
);
1346 updateFileBackgroundColor(file
);