opening non-dumb-aware editors on excit from dumb mode

This commit is contained in:
Dmitry Avdeev
2015-02-16 13:06:41 +03:00
parent f45b45d7bf
commit 0ed3a9ef82
6 changed files with 132 additions and 79 deletions
@@ -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<FileEditorProvider> EP_FILE_EDITOR_PROVIDER = new ExtensionPointName<FileEditorProvider>("com.intellij.fileEditorProvider");
Key<FileEditorProvider> 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 <code>null</code>.
*
@@ -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));
@@ -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);
}
}
@@ -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<FileEditorProvider> providers = new HashSet<FileEditorProvider>();
List<EditorWithProviderComposite> 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<FileEditorProvider> toOpen = new ArrayList<FileEditorProvider>(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() {
@@ -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<FileEditorProvider> mySharedProviderList = new ArrayList<FileEditorProvider>();
List<FileEditorProvider> sharedProviders = new ArrayList<FileEditorProvider>();
boolean doNotShowTextEditor = false;
for (final FileEditorProvider provider : myProviders) {
if (ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
@@ -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<FileEditorProvider>() {
ContainerUtil.retainAll(sharedProviders, new Condition<FileEditorProvider>() {
@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
@@ -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";
}
}
}