diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorProvider.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorProvider.java index 2f6d2f611fe6..140de948a336 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorProvider.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorProvider.java @@ -16,6 +16,7 @@ package com.intellij.openapi.fileEditor; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; @@ -24,16 +25,18 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; /** - * Should be registered via {@link #EP_FILE_EDITOR_PROVIDER} + * Should be registered via {@link #EP_FILE_EDITOR_PROVIDER}. * * @author Anton Katilin * @author Vladimir Kondratyev + * @see DumbAware */ public interface FileEditorProvider { ExtensionPointName EP_FILE_EDITOR_PROVIDER = new ExtensionPointName("com.intellij.fileEditorProvider"); Key KEY = Key.create("com.intellij.fileEditorProvider"); /** + * If provider is not dumb-aware, and it is the only * @param file file to be tested for acceptance. This * parameter is never null. * diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java index c4ea579a1b46..ce5b90c91285 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java @@ -41,6 +41,7 @@ import com.intellij.ui.PrevNextActionsDescriptor; import com.intellij.ui.SideBorder; import com.intellij.ui.TabbedPaneWrapper; import com.intellij.ui.tabs.UiDecorator; +import com.intellij.util.ArrayUtil; import com.intellij.util.SmartList; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -75,13 +76,13 @@ public abstract class EditorComposite implements Disposable { /** * Editors which are opened in the composite */ - protected final FileEditor[] myEditors; + protected FileEditor[] myEditors; /** * This is initial timestamp of the file. It uses to implement * "close non modified editors first" feature. */ private final long myInitialFileTimeStamp; - protected final TabbedPaneWrapper myTabbedPaneWrapper; + protected TabbedPaneWrapper myTabbedPaneWrapper; private final MyComponent myComponent; private final FocusWatcher myFocusWatcher; /** @@ -112,69 +113,14 @@ public abstract class EditorComposite implements Disposable { Disposer.register(fileEditorManager.getProject(), this); if(editors.length > 1){ - PrevNextActionsDescriptor descriptor = new PrevNextActionsDescriptor(IdeActions.ACTION_NEXT_EDITOR_TAB, IdeActions.ACTION_PREVIOUS_EDITOR_TAB); - final TabbedPaneWrapper.AsJBTabs wrapper = new TabbedPaneWrapper.AsJBTabs(fileEditorManager.getProject(), SwingConstants.BOTTOM, descriptor, this); - wrapper.getTabs().getPresentation().setPaintBorder(0, 0, 0, 0).setTabSidePaintBorder(1).setGhostsAlwaysVisible(true).setUiDecorator(new UiDecorator() { - @Override - @NotNull - public UiDecoration getDecoration() { - return new UiDecoration(null, new Insets(0, 8, 0, 8)); - } - }); - wrapper.getTabs().getComponent().setBorder(new EmptyBorder(0, 0, 1, 0)); - - myTabbedPaneWrapper=wrapper; - myComponent=new MyComponent(wrapper.getComponent()){ - @Override - public boolean requestFocusInWindow() { - return wrapper.getComponent().requestFocusInWindow(); - } - - @Override - public void requestFocus() { - wrapper.getComponent().requestFocus(); - } - - @Override - public boolean requestDefaultFocus() { - return wrapper.getComponent().requestDefaultFocus(); - } - }; - for (FileEditor editor : editors) { - wrapper.addTab(editor.getName(), createEditorComponent(editor)); - } - myTabbedPaneWrapper.addChangeListener(new MyChangeListener()); + myTabbedPaneWrapper = createTabbedPaneWrapper(editors); + JComponent component = myTabbedPaneWrapper.getComponent(); + myComponent = new MyComponent(component, component); } else if(editors.length==1){ myTabbedPaneWrapper=null; - myComponent = new MyComponent(createEditorComponent(editors[0])){ - @Override - public void requestFocus() { - JComponent component = editors[0].getPreferredFocusedComponent(); - if (component != null) { - component.requestFocus(); - } - } - - @Override - public boolean requestFocusInWindow() { - JComponent component = editors[0].getPreferredFocusedComponent(); - if (component != null) { - return component.requestFocusInWindow(); - } - - return false; - } - - @Override - public boolean requestDefaultFocus() { - JComponent component = editors[0].getPreferredFocusedComponent(); - if (component != null) { - return component.requestDefaultFocus(); - } - return false; - } - }; + FileEditor editor = editors[0]; + myComponent = new MyComponent(createEditorComponent(editor), editor.getPreferredFocusedComponent()); } else{ throw new IllegalArgumentException("editors array cannot be empty"); @@ -212,6 +158,28 @@ public abstract class EditorComposite implements Disposable { }, this); } + @NotNull + private TabbedPaneWrapper.AsJBTabs createTabbedPaneWrapper(FileEditor[] editors) { + PrevNextActionsDescriptor descriptor = new PrevNextActionsDescriptor(IdeActions.ACTION_NEXT_EDITOR_TAB, IdeActions.ACTION_PREVIOUS_EDITOR_TAB); + final TabbedPaneWrapper.AsJBTabs wrapper = new TabbedPaneWrapper.AsJBTabs(myFileEditorManager.getProject(), SwingConstants.BOTTOM, descriptor, this); + wrapper.getTabs().getPresentation().setPaintBorder(0, 0, 0, 0).setTabSidePaintBorder(1).setGhostsAlwaysVisible(true).setUiDecorator(new UiDecorator() { + @Override + @NotNull + public UiDecoration getDecoration() { + return new UiDecoration(null, new Insets(0, 8, 0, 8)); + } + }); + wrapper.getTabs().getComponent().setBorder(new EmptyBorder(0, 0, 1, 0)); + + for (FileEditor editor : editors) { + JComponent component = myEditors.length == 1 && editor == myEditors[0] ? (JComponent)myComponent.getComponent(0) : createEditorComponent(editor); + wrapper.addTab(editor.getName(), component); + } + wrapper.addChangeListener(new MyChangeListener()); + + return wrapper; + } + private JComponent createEditorComponent(final FileEditor editor) { JPanel component = new JPanel(new BorderLayout()); JComponent comp = editor.getComponent(); @@ -423,12 +391,38 @@ public abstract class EditorComposite implements Disposable { } } - private abstract class MyComponent extends JPanel implements DataProvider{ - public MyComponent(JComponent realComponent){ + private class MyComponent extends JPanel implements DataProvider{ + @Nullable + private JComponent myFocusComponent; + + public MyComponent(@NotNull JComponent realComponent, @Nullable JComponent focusComponent){ super(new BorderLayout()); + myFocusComponent = focusComponent; add(realComponent, BorderLayout.CENTER); } + void setComponent(JComponent newComponent) { + add(newComponent, BorderLayout.CENTER); + myFocusComponent = newComponent; + } + + @Override + public boolean requestFocusInWindow() { + return myFocusComponent == null ? false : myFocusComponent.requestFocusInWindow(); + } + + @Override + public void requestFocus() { + if (myFocusComponent != null) { + myFocusComponent.requestFocus(); + } + } + + @Override + public boolean requestDefaultFocus() { + return myFocusComponent == null ? false : myFocusComponent.requestDefaultFocus(); + } + @Override public final Object getData(String dataId){ if (PlatformDataKeys.FILE_EDITOR.is(dataId)) { @@ -462,6 +456,18 @@ public abstract class EditorComposite implements Disposable { myFocusWatcher.deinstall(myFocusWatcher.getTopComponent()); } + void addEditor(FileEditor editor) { + FileEditor[] editors = ArrayUtil.append(myEditors, editor); + if (myTabbedPaneWrapper == null) { + myTabbedPaneWrapper = createTabbedPaneWrapper(editors); + myComponent.setComponent(myTabbedPaneWrapper.getComponent()); + } + else { + myTabbedPaneWrapper.addTab(editor.getName(), editor.getComponent()); + } + myEditors = editors; + } + private static class TopBottomPanel extends JPanel { private TopBottomPanel() { setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWithProviderComposite.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWithProviderComposite.java index aef6dc7f370a..4e97445817ec 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWithProviderComposite.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWithProviderComposite.java @@ -31,7 +31,7 @@ import org.jetbrains.annotations.NotNull; */ public class EditorWithProviderComposite extends EditorComposite { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite"); - private final FileEditorProvider[] myProviders; + private FileEditorProvider[] myProviders; EditorWithProviderComposite(@NotNull VirtualFile file, @NotNull FileEditor[] editors, @@ -90,4 +90,9 @@ public class EditorWithProviderComposite extends EditorComposite { final FileEditorProvider[] providers = getProviders(); return new HistoryEntry(getFile(), providers, states, providers[selectedProviderIndex]); } + + void addEditor(FileEditor editor, FileEditorProvider provider) { + addEditor(editor); + myProviders = ArrayUtil.append(myProviders, provider); + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index 4a88b77dfc22..5409d69a30d0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -145,6 +145,35 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec } myQueue.setTrackUiActivity(true); + + project.getMessageBus().connect().subscribe(DumbService.DUMB_MODE, new DumbService.DumbModeListener() { + + public void enteredDumbMode() { + } + + public void exitDumbMode() { + VirtualFile[] files = getOpenFiles(); + for (VirtualFile file : files) { + Set providers = new HashSet(); + List composites = getEditorComposites(file); + for (EditorWithProviderComposite composite : composites) { + providers.addAll(Arrays.asList(composite.getProviders())); + } + FileEditorProvider[] newProviders = FileEditorProviderManager.getInstance().getProviders(project, file); + if (newProviders.length > providers.size()) { + List toOpen = new ArrayList(Arrays.asList(newProviders)); + toOpen.removeAll(providers); + // need to open additional non dumb-aware editors + for (EditorWithProviderComposite composite : composites) { + for (FileEditorProvider provider : toOpen) { + FileEditor editor = provider.createEditor(myProject, file); + composite.addEditor(editor, provider); + } + } + } + } + } + }); } public void initDockableContentFactory() { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.java index aba649be7115..647f88952e96 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.java @@ -81,7 +81,7 @@ public final class FileEditorProviderManagerImpl extends FileEditorProviderManag @NotNull public synchronized FileEditorProvider[] getProviders(@NotNull final Project project, @NotNull final VirtualFile file) { // Collect all possible editors - List mySharedProviderList = new ArrayList(); + List sharedProviders = new ArrayList(); boolean doNotShowTextEditor = false; for (final FileEditorProvider provider : myProviders) { if (ApplicationManager.getApplication().runReadAction(new Computable() { @@ -93,14 +93,14 @@ public final class FileEditorProviderManagerImpl extends FileEditorProviderManag return provider.accept(project, file); } })) { - mySharedProviderList.add(provider); + sharedProviders.add(provider); doNotShowTextEditor |= provider.getPolicy() == FileEditorPolicy.HIDE_DEFAULT_EDITOR; } } // Throw out default editors provider if necessary if (doNotShowTextEditor) { - ContainerUtil.retainAll(mySharedProviderList, new Condition() { + ContainerUtil.retainAll(sharedProviders, new Condition() { @Override public boolean value(FileEditorProvider provider) { return !(provider instanceof TextEditorProvider); @@ -109,12 +109,9 @@ public final class FileEditorProviderManagerImpl extends FileEditorProviderManag } // Sort editors according policies - Collections.sort(mySharedProviderList, MyComparator.ourInstance); + Collections.sort(sharedProviders, MyComparator.ourInstance); - if (mySharedProviderList.isEmpty()) { - return EMPTY_ARRAY; - } - return mySharedProviderList.toArray(new FileEditorProvider[mySharedProviderList.size()]); + return sharedProviders.toArray(new FileEditorProvider[sharedProviders.size()]); } @Override diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTest.java index 021873b89697..11f84ca4daf9 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTest.java @@ -22,7 +22,7 @@ import com.intellij.openapi.editor.FoldRegion; import com.intellij.openapi.editor.FoldingModel; import com.intellij.openapi.fileEditor.impl.EditorWindow; import com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite; -import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; +import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbServiceImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; @@ -43,6 +43,7 @@ import java.util.List; * @author Dmitry Avdeev * Date: 4/16/13 */ +@SuppressWarnings("ConstantConditions") public class FileEditorManagerTest extends FileEditorManagerTestCase { @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors") @@ -161,13 +162,16 @@ public class FileEditorManagerTest extends FileEditorManagerTestCase { } } - public void _testOpenInDumbMode() throws Exception { + public void testOpenInDumbMode() throws Exception { PlatformTestUtil.registerExtension(FileEditorProvider.EP_FILE_EDITOR_PROVIDER, new MyFileEditorProvider(), getTestRootDisposable()); + PlatformTestUtil.registerExtension(FileEditorProvider.EP_FILE_EDITOR_PROVIDER, new DumbAwareProvider(), getTestRootDisposable()); try { DumbServiceImpl.getInstance(getProject()).setDumb(true); - FileEditor[] editors = myManager.openFile(getFile("/src/foo.bar"), false); - assertEquals(1, editors.length); - assertFalse(FileEditorManagerImpl.isDumbAware(editors[0])); + VirtualFile file = getFile("/src/foo.bar"); + assertEquals(1, myManager.openFile(file, false).length); + DumbServiceImpl.getInstance(getProject()).setDumb(false); + assertEquals(2, myManager.getAllEditors(file).length); + //assertFalse(FileEditorManagerImpl.isDumbAware(editors[0])); } finally { DumbServiceImpl.getInstance(getProject()).setDumb(false); @@ -282,4 +286,13 @@ public class FileEditorManagerTest extends FileEditorManagerTestCase { return FileEditorPolicy.PLACE_AFTER_DEFAULT_EDITOR; } } + + private static class DumbAwareProvider extends MyFileEditorProvider implements DumbAware { + @NotNull + @Override + public String getEditorTypeId() { + return "dumbAware"; + } + } } +