IDEA-127739 Navigation Tab
authorVassiliy.Kudryashov <Vassiliy.Kudryashov@jetbrains.com>
Sun, 19 Oct 2014 12:15:01 +0000 (16:15 +0400)
committerVassiliy.Kudryashov <Vassiliy.Kudryashov@jetbrains.com>
Sun, 19 Oct 2014 12:15:15 +0000 (16:15 +0400)
Stage 7: "Usages" provider, fix for 'tabless' editor requestFocus(), persistance for PreviewManager

14 files changed:
platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationPreviewPanelProvider.java
platform/lang-impl/src/com/intellij/find/UsagesPreviewPanelProvider.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java
platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FilePreviewPanelProvider.java
platform/platform-impl/src/com/intellij/openapi/preview/PreviewInfo.java
platform/platform-impl/src/com/intellij/openapi/preview/PreviewManager.java
platform/platform-impl/src/com/intellij/openapi/preview/PreviewPanelProvider.java
platform/platform-impl/src/com/intellij/openapi/preview/impl/PreviewManagerImpl.java
platform/platform-impl/src/com/intellij/openapi/preview/impl/PreviewManagerState.java [new file with mode: 0644]
platform/platform-resources/src/META-INF/LangExtensions.xml
platform/usageView/src/com/intellij/usages/UsageViewPresentation.java

index 99900deda5974d766f4789c0061635bc1c096563..aa7f2bf6485f7b9123daf5e035f4e5e1a0316d8a 100644 (file)
@@ -386,9 +386,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
     myPreviouslyFocused = WindowManagerEx.getInstanceEx().getFocusedComponent(project);
 
     JBPopup _oldHint = getDocInfoHint();
-    PreviewManager previewManager = PreviewManager.SERVICE.getInstance(myProject);
-    if (previewManager != null &&
-        previewManager.preview(DocumentationPreviewPanelProvider.ID, Couple.of(element, originalElement), requestFocus) != null) {
+    if (PreviewManager.SERVICE.preview(myProject, DocumentationPreviewPanelProvider.ID, Couple.of(element, originalElement), requestFocus) != null) {
       return;
     }
 
index 60149683b9874906fceddfc5f7a0c3768c4636a8..a4617ff337a1f819ebecddcabf0dbd36899c7cf4 100644 (file)
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.documentation;
 import com.intellij.openapi.preview.PreviewPanelProvider;
 import com.intellij.openapi.preview.PreviewProviderId;
 import com.intellij.openapi.util.Couple;
+import com.intellij.openapi.util.Disposer;
 import com.intellij.psi.PsiElement;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -28,7 +29,6 @@ public class DocumentationPreviewPanelProvider extends PreviewPanelProvider<Coup
   public static final PreviewProviderId<Couple<PsiElement>, DocumentationComponent> ID = PreviewProviderId.create("Documentation");
   private final DocumentationComponent myDocumentationComponent;
   private final DocumentationManager myDocumentationManager;
-  private boolean myBlocked = false;
 
   public DocumentationPreviewPanelProvider(DocumentationManager documentationManager) {
     super(ID);
@@ -42,8 +42,8 @@ public class DocumentationPreviewPanelProvider extends PreviewPanelProvider<Coup
   }
 
   @Override
-  public boolean shouldBeEnabledByDefault() {
-    return true;
+  public void dispose() {
+    Disposer.dispose(myDocumentationComponent);
   }
 
   @NotNull
@@ -70,20 +70,26 @@ public class DocumentationPreviewPanelProvider extends PreviewPanelProvider<Coup
   }
 
   @Override
-  public boolean moveContentToStandardView(@NotNull Couple<PsiElement> content) {
-    myBlocked = true;
-    try {
-      myDocumentationManager.showJavaDocInfo(content.getFirst(), content.getSecond());
-    }
-    finally {
-      myBlocked = false;
-    }
-    return true;
+  public void showInStandardPlace(@NotNull Couple<PsiElement> content) {
+    myDocumentationManager.showJavaDocInfo(content.getFirst(), content.getSecond());
+  }
+
+  @Override
+  public void release(@NotNull Couple<PsiElement> content) {
+  }
+
+  @Override
+  public boolean contentsAreEqual(@NotNull Couple<PsiElement> content1, @NotNull Couple<PsiElement> content2) {
+    return content1.getFirst().getManager().areElementsEquivalent(content1.getFirst(), content2.getFirst());
+  }
+
+  @Override
+  public boolean isModified(Couple<PsiElement> content, boolean beforeReuse) {
+    return beforeReuse;
   }
 
   @Override
   protected DocumentationComponent initComponent(Couple<PsiElement> content, boolean requestFocus) {
-    if (myBlocked) return null;
     if (!content.getFirst().getManager().areElementsEquivalent(myDocumentationComponent.getElement(), content.getFirst())) {
       myDocumentationManager.fetchDocInfo(content.getFirst(), myDocumentationComponent);
     }
diff --git a/platform/lang-impl/src/com/intellij/find/UsagesPreviewPanelProvider.java b/platform/lang-impl/src/com/intellij/find/UsagesPreviewPanelProvider.java
new file mode 100644 (file)
index 0000000..c199f64
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.find;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.preview.PreviewPanelProvider;
+import com.intellij.openapi.preview.PreviewProviderId;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Pair;
+import com.intellij.usages.impl.UsageViewImpl;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class UsagesPreviewPanelProvider extends PreviewPanelProvider<Pair<UsageViewImpl, ? extends JTable>, Boolean> {
+  public static final PreviewProviderId<Pair<UsageViewImpl, ? extends JTable>, Boolean> ID = PreviewProviderId.create("Usages");
+
+  private JComponent myComponent;
+  private Collection<UsageViewImpl> myViews = new ArrayList<UsageViewImpl>();
+
+  public UsagesPreviewPanelProvider(Project project) {
+    super(ID);
+    myComponent = new JPanel(new BorderLayout()) {
+      @Override
+      public String toString() {
+        return "UsagesPreviewPanel";
+      }
+    };
+  }
+
+  @Override
+  public void dispose() {
+    //myPresentation = null;
+    myComponent.removeAll();
+    for (UsageViewImpl view : myViews) {
+      Disposer.dispose(view);
+    }
+  }
+
+  @NotNull
+  @Override
+  protected JComponent getComponent() {
+    return myComponent;
+  }
+
+  @NotNull
+  @Override
+  protected String getTitle(@NotNull Pair<UsageViewImpl, ? extends JTable> content) {
+    return content.first.getPresentation().getTabText();
+  }
+
+  @Nullable
+  @Override
+  protected Icon getIcon(@NotNull Pair<UsageViewImpl, ? extends JTable> content) {
+    return AllIcons.Actions.Find;
+  }
+
+  @Override
+  public float getMenuOrder() {
+    return 2;
+  }
+
+  @Override
+  public void showInStandardPlace(@NotNull Pair<UsageViewImpl, ? extends JTable> content) {
+  }
+
+  @Override
+  public boolean supportsStandardPlace() {
+    return false;
+  }
+
+  @Override
+  public boolean isModified(Pair<UsageViewImpl, ? extends JTable> content, boolean beforeReuse) {
+    return beforeReuse;
+  }
+
+  @Override
+  public void release(@NotNull Pair<UsageViewImpl, ? extends JTable> content) {
+    myViews.remove(content.first);
+    Disposer.dispose(content.first);
+    myComponent.remove(content.second);
+  }
+
+  @Override
+  public boolean contentsAreEqual(@NotNull Pair<UsageViewImpl, ? extends JTable> content1, @NotNull Pair<UsageViewImpl, ? extends JTable> content2) {
+    return content1.getFirst().getPresentation().equals(content2.getFirst().getPresentation());
+  }
+
+  @Override
+  protected Boolean initComponent(final Pair<UsageViewImpl, ? extends JTable> content, boolean requestFocus) {
+    myComponent.removeAll();
+    myComponent.add(content.second);
+    myViews.add(content.first);
+    return Boolean.TRUE;
+  }
+}
index 90d7d30853098a90fdbc6de1e5f0b92aafc7fad3..c7ad66868e35f1309fbfa457288ee72604dd295e 100644 (file)
@@ -21,6 +21,7 @@ import com.intellij.codeInsight.hint.HintUtil;
 import com.intellij.featureStatistics.FeatureUsageTracker;
 import com.intellij.find.FindManager;
 import com.intellij.find.FindSettings;
+import com.intellij.find.UsagesPreviewPanelProvider;
 import com.intellij.find.findUsages.*;
 import com.intellij.find.impl.FindManagerImpl;
 import com.intellij.icons.AllIcons;
@@ -34,6 +35,7 @@ import com.intellij.openapi.fileEditor.FileEditor;
 import com.intellij.openapi.fileEditor.FileEditorLocation;
 import com.intellij.openapi.fileEditor.TextEditor;
 import com.intellij.openapi.keymap.KeymapUtil;
+import com.intellij.openapi.preview.PreviewManager;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.Project;
@@ -41,10 +43,7 @@ import com.intellij.openapi.ui.MessageType;
 import com.intellij.openapi.ui.popup.JBPopup;
 import com.intellij.openapi.ui.popup.JBPopupFactory;
 import com.intellij.openapi.ui.popup.PopupChooserBuilder;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.*;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.wm.IdeFocusManager;
@@ -70,6 +69,7 @@ import com.intellij.util.messages.MessageBusConnection;
 import com.intellij.util.ui.AsyncProcessIcon;
 import com.intellij.util.ui.ColumnInfo;
 import com.intellij.util.ui.ListTableModel;
+import com.intellij.util.ui.UIUtil;
 import com.intellij.xml.util.XmlStringUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -80,8 +80,7 @@ import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 import javax.swing.table.TableColumn;
 import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
+import java.awt.event.*;
 import java.util.*;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -248,45 +247,47 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
     final List<UsageNode> data = collectData(usages, visibleNodes, usageView, presentation);
     setTableModel(table, usageView, data, outOfScopeUsages, options.searchScope);
 
-    SpeedSearchBase<JTable> speedSearch = new MySpeedSearch(table);
-    speedSearch.setComparator(new SpeedSearchComparator(false));
 
-    final JBPopup popup = createUsagePopup(usages, visibleNodes, handler, editor, popupPosition,
-                                           maxUsages, usageView, options, table, presentation, processIcon);
+    boolean isPreviewMode = (Boolean.TRUE == PreviewManager.SERVICE.preview(handler.getProject(), UsagesPreviewPanelProvider.ID, Pair.create(usageView, table), false) );
+    Runnable itemChosenCallback = prepareTable(table, editor, popupPosition, handler, maxUsages, options, isPreviewMode);
 
-    Disposer.register(popup, usageView);
+    @Nullable final JBPopup popup = isPreviewMode ? null : createUsagePopup(usages, visibleNodes, handler, editor, popupPosition,
+                                           maxUsages, usageView, options, table, itemChosenCallback, presentation, processIcon);
+    if (popup != null) {
+      Disposer.register(popup, usageView);
 
-    // show popup only if find usages takes more than 300ms, otherwise it would flicker needlessly
-    Alarm alarm = new Alarm(usageView);
-    alarm.addRequest(new Runnable() {
-      @Override
-      public void run() {
-        showPopupIfNeedTo(popup, popupPosition);
-      }
-    }, 300);
+      // show popup only if find usages takes more than 300ms, otherwise it would flicker needlessly
+      Alarm alarm = new Alarm(usageView);
+      alarm.addRequest(new Runnable() {
+        @Override
+        public void run() {
+          showPopupIfNeedTo(popup, popupPosition);
+        }
+      }, 300);
+    }
 
     final PingEDT pingEDT = new PingEDT("Rebuild popup in EDT", new Condition<Object>() {
       @Override
       public boolean value(Object o) {
-        return popup.isDisposed();
+        return popup != null && popup.isDisposed();
       }
     }, 100, new Runnable() {
       @Override
       public void run() {
-        if (popup.isDisposed()) return;
+        if (popup != null && popup.isDisposed()) return;
 
         final List<UsageNode> nodes = new ArrayList<UsageNode>();
         List<Usage> copy;
         synchronized (usages) {
           // open up popup as soon as several usages 've been found
-          if (!popup.isVisible() && (usages.size() <= 1 || !showPopupIfNeedTo(popup, popupPosition))) {
+          if (popup != null && (!popup.isVisible() && (usages.size() <= 1 || !showPopupIfNeedTo(popup, popupPosition)))) {
             return;
           }
           addUsageNodes(usageView.getRoot(), usageView, nodes);
           copy = new ArrayList<Usage>(usages);
         }
 
-        rebuildPopup(usageView, copy, nodes, table, popup, presentation, popupPosition, !processIcon.isDisposed(), outOfScopeUsages,
+        rebuildTable(usageView, copy, nodes, table, popup, presentation, popupPosition, !processIcon.isDisposed(), outOfScopeUsages,
                      options.searchScope);
       }
     });
@@ -346,15 +347,17 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
           public void run() {
             Disposer.dispose(processIcon);
             Container parent = processIcon.getParent();
-            parent.remove(processIcon);
-            parent.repaint();
+            if (parent != null) {
+              parent.remove(processIcon);
+              parent.repaint();
+            }
             pingEDT.ping(); // repaint title
             synchronized (usages) {
               if (visibleNodes.isEmpty()) {
                 if (usages.isEmpty()) {
                   String text = UsageViewBundle.message("no.usages.found.in", searchScopePresentableName(options));
                   hint(editor, text, handler, popupPosition, maxUsages, options, false);
-                  popup.cancel();
+                  cancel(popup);
                 }
                 else {
                   // all usages filtered out
@@ -371,7 +374,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
                     String message = UsageViewBundle.message("show.usages.only.usage", searchScopePresentableName(options));
                     navigateAndHint(usage, message, handler, popupPosition, maxUsages, options);
                   }
-                  popup.cancel();
+                  cancel(popup);
                 }
                 else {
                   assert usages.size() > 1 : usages;
@@ -380,27 +383,32 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
                   if (areAllUsagesInOneLine(visibleUsage, usages)) {
                     String hint = UsageViewBundle.message("all.usages.are.in.this.line", usages.size(), searchScopePresentableName(options));
                     navigateAndHint(visibleUsage, hint, handler, popupPosition, maxUsages, options);
-                    popup.cancel();
+                    cancel(popup);
                   }
                 }
               }
               else {
-                String title = presentation.getTabText();
-                boolean shouldShowMoreSeparator = visibleNodes.contains(MORE_USAGES_SEPARATOR_NODE);
-                String fullTitle = getFullTitle(usages, title, shouldShowMoreSeparator, visibleNodes.size() - (shouldShowMoreSeparator ? 1 : 0), false);
-                ((AbstractPopup)popup).setCaption(fullTitle);
+                if (popup != null) {
+                  String title = presentation.getTabText();
+                  boolean shouldShowMoreSeparator = visibleNodes.contains(MORE_USAGES_SEPARATOR_NODE);
+                  String fullTitle =
+                    getFullTitle(usages, title, shouldShowMoreSeparator, visibleNodes.size() - (shouldShowMoreSeparator ? 1 : 0), false);
+                  ((AbstractPopup)popup).setCaption(fullTitle);
+                }
               }
             }
           }
         }, project.getDisposed());
       }
     });
-    Disposer.register(popup, new Disposable() {
-      @Override
-      public void dispose() {
-        indicator.cancel();
-      }
-    });
+    if (popup != null) {
+      Disposer.register(popup, new Disposable() {
+        @Override
+        public void dispose() {
+          indicator.cancel();
+        }
+      });
+    }
   }
 
   @NotNull
@@ -543,18 +551,17 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
     return options.searchScope.getDisplayName();
   }
 
-  @NotNull
-  private JBPopup createUsagePopup(@NotNull final List<Usage> usages,
-                                   @NotNull Set<UsageNode> visibleNodes,
-                                   @NotNull final FindUsagesHandler handler,
-                                   final Editor editor,
-                                   @NotNull final RelativePoint popupPosition,
-                                   final int maxUsages,
-                                   @NotNull final UsageViewImpl usageView,
-                                   @NotNull final FindUsagesOptions options,
-                                   @NotNull final JTable table,
-                                   @NotNull final UsageViewPresentation presentation,
-                                   @NotNull final AsyncProcessIcon processIcon) {
+  private Runnable prepareTable(final MyTable table,
+                                final Editor editor,
+                                final RelativePoint popupPosition,
+                                final FindUsagesHandler handler,
+                                final int maxUsages,
+                                final @NotNull FindUsagesOptions options,
+                                final boolean previewMode) {
+
+    SpeedSearchBase<JTable> speedSearch = new MySpeedSearch(table);
+    speedSearch.setComparator(new SpeedSearchComparator(false));
+
     table.setRowHeight(PlatformIcons.CLASS_ICON.getIconHeight()+2);
     table.setShowGrid(false);
     table.setShowVerticalLines(false);
@@ -562,19 +569,30 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
     table.setTableHeader(null);
     table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
     table.setIntercellSpacing(new Dimension(0, 0));
-
-    PopupChooserBuilder builder = new PopupChooserBuilder(table);
-    final String title = presentation.getTabText();
-    if (title != null) {
-      String result = getFullTitle(usages, title, false, visibleNodes.size() - 1, true);
-      builder.setTitle(result);
-      builder.setAdText(getSecondInvocationTitle(options, handler));
-    }
-
-    builder.setMovable(true).setResizable(true);
     final AtomicReference<Object> selectedUsage = new AtomicReference<Object>();
     final AtomicBoolean moreUsagesSelected = new AtomicBoolean();
     final AtomicBoolean outsideScopeUsagesSelected = new AtomicBoolean();
+    final Runnable itemChosenCallback = new Runnable() {
+      @Override
+      public void run() {
+        if (moreUsagesSelected.get()) {
+          appendMoreUsages(editor, popupPosition, handler, maxUsages, options);
+          return;
+        }
+        if (outsideScopeUsagesSelected.get()) {
+          options.searchScope = GlobalSearchScope.projectScope(handler.getProject());
+          showElementUsages(editor, popupPosition, handler, maxUsages, options);
+          return;
+        }
+        Object usage = selectedUsage.get();
+        if (usage instanceof UsageInfo) {
+          UsageViewUtil.navigateTo((UsageInfo)usage, true);
+        }
+        else if (usage instanceof Navigatable) {
+          ((Navigatable)usage).navigate(true);
+        }
+      }
+    };
     table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
       @Override
       public void valueChanged(ListSelectionEvent e) {
@@ -602,28 +620,52 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
         }
       }
     });
-    builder.setMovable(true).setResizable(true);
-    builder.setItemChoosenCallback(new Runnable() {
-      @Override
-      public void run() {
-        if (moreUsagesSelected.get()) {
-          appendMoreUsages(editor, popupPosition, handler, maxUsages, options);
-          return;
-        }
-        if (outsideScopeUsagesSelected.get()) {
-          options.searchScope = GlobalSearchScope.projectScope(handler.getProject());
-          showElementUsages(editor, popupPosition, handler, maxUsages, options);
-          return;
-        }
-        Object usage = selectedUsage.get();
-        if (usage instanceof UsageInfo) {
-          UsageViewUtil.navigateTo((UsageInfo)usage, true);
+    if (previewMode) {
+      table.addMouseListener(new MouseAdapter() {
+        @Override
+        public void mouseReleased(MouseEvent e) {
+          if (UIUtil.isActionClick(e, MouseEvent.MOUSE_RELEASED) && !UIUtil.isSelectionButtonDown(e) && !e.isConsumed()) {
+            itemChosenCallback.run();
+          }
         }
-        else if (usage instanceof Navigatable) {
-          ((Navigatable)usage).navigate(true);
+      });
+      table.addKeyListener(new KeyAdapter() {
+        @Override
+        public void keyPressed(KeyEvent e) {
+          if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+            itemChosenCallback.run();
+          }
         }
-      }
-    });
+      });
+    }
+    return itemChosenCallback;
+  }
+
+  @NotNull
+  private JBPopup createUsagePopup(@NotNull final List<Usage> usages,
+                                   @NotNull Set<UsageNode> visibleNodes,
+                                   @NotNull final FindUsagesHandler handler,
+                                   final Editor editor,
+                                   @NotNull final RelativePoint popupPosition,
+                                   final int maxUsages,
+                                   @NotNull final UsageViewImpl usageView,
+                                   @NotNull final FindUsagesOptions options,
+                                   @NotNull final JTable table,
+                                   @NotNull final Runnable itemChoseCallback,
+                                   @NotNull final UsageViewPresentation presentation,
+                                   @NotNull final AsyncProcessIcon processIcon) {
+
+    PopupChooserBuilder builder = new PopupChooserBuilder(table);
+    final String title = presentation.getTabText();
+    if (title != null) {
+      String result = getFullTitle(usages, title, false, visibleNodes.size() - 1, true);
+      builder.setTitle(result);
+      builder.setAdText(getSecondInvocationTitle(options, handler));
+    }
+
+    builder.setMovable(true).setResizable(true);
+    builder.setMovable(true).setResizable(true);
+    builder.setItemChoosenCallback(itemChoseCallback);
     final JBPopup[] popup = new JBPopup[1];
 
     KeyboardShortcut shortcut = UsageViewImpl.getShowUsagesWithSettingsShortcut();
@@ -631,7 +673,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
       new DumbAwareAction() {
         @Override
         public void actionPerformed(AnActionEvent e) {
-          popup[0].cancel();
+          cancel(popup);
           showDialogAndFindUsages(handler, popupPosition, editor, maxUsages);
         }
       }.registerCustomShortcutSet(new CustomShortcutSet(shortcut.getFirstKeyStroke()), table);
@@ -641,7 +683,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
       new DumbAwareAction() {
         @Override
         public void actionPerformed(AnActionEvent e) {
-          popup[0].cancel();
+          cancel(popup);
           searchEverywhere(options, handler, editor, popupPosition, maxUsages);
         }
       }.registerCustomShortcutSet(new CustomShortcutSet(shortcut.getFirstKeyStroke()), table);
@@ -650,7 +692,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
     InplaceButton settingsButton = createSettingsButton(handler, popupPosition, editor, maxUsages, new Runnable() {
       @Override
       public void run() {
-        popup[0].cancel();
+        cancel(popup);
       }
     });
 
@@ -713,7 +755,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
         @Override
         public void actionPerformed(AnActionEvent e) {
           hideHints();
-          popup[0].cancel();
+          cancel(popup);
           FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(usageView.getProject())).getFindUsagesManager();
           findUsagesManager.findUsages(handler.getPrimaryElements(), handler.getSecondaryElements(), handler, options,
                                        FindSettings.getInstance().isSkipResultsWithOneUsage());
@@ -738,6 +780,12 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
     };
   }
 
+  private static void cancel(@Nullable JBPopup... popup) {
+    if (popup != null && popup.length>0 && popup[0] != null) {
+      popup[0].cancel();
+    }
+  }
+
   @NotNull
   private static String getFullTitle(@NotNull List<Usage> usages,
                                      @NotNull String title,
@@ -901,11 +949,11 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
 
   private int myWidth;
 
-  private void rebuildPopup(@NotNull final UsageViewImpl usageView,
+  private void rebuildTable(@NotNull final UsageViewImpl usageView,
                             @NotNull final List<Usage> usages,
                             @NotNull List<UsageNode> nodes,
                             @NotNull final JTable table,
-                            @NotNull final JBPopup popup,
+                            @Nullable final JBPopup popup,
                             @NotNull final UsageViewPresentation presentation,
                             @NotNull final RelativePoint popupPosition,
                             boolean findUsagesInProgress,
@@ -924,8 +972,9 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
 
     String title = presentation.getTabText();
     String fullTitle = getFullTitle(usages, title, shouldShowMoreSeparator || hasOutsideScopeUsages, nodes.size() - (shouldShowMoreSeparator || hasOutsideScopeUsages ? 1 : 0), findUsagesInProgress);
-
-    ((AbstractPopup)popup).setCaption(fullTitle);
+    if (popup != null) {
+      ((AbstractPopup)popup).setCaption(fullTitle);
+    }
 
     List<UsageNode> data = collectData(usages, nodes, usageView, presentation);
     MyModel tableModel = setTableModel(table, usageView, data, outOfScopeUsages, searchScope);
@@ -943,7 +992,9 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
     }
     TableScrollingUtil.ensureIndexIsVisible(table, newSelection, 0);
 
-    setSizeAndDimensions(table, popup, popupPosition, data);
+    if (popup != null) {
+      setSizeAndDimensions(table, popup, popupPosition, data);
+    }
   }
 
   // returns new selection
@@ -1100,7 +1151,8 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
             });
           }
         };
-        if (editor == null) runnable.run(); else editor.getScrollingModel().runActionOnScrollingFinished(runnable);
+        if (editor == null) runnable.run();
+        else editor.getScrollingModel().runActionOnScrollingFinished(runnable);
       }
     });
   }
index 047684ace72a0578a23fd8fe5caffd20b9bcea15..91dfb648e49b40069e3013bcea860f7a9b318ec6 100644 (file)
@@ -555,7 +555,13 @@ public class EditorWindow {
     if (myTabbedPane != null) {
       myTabbedPane.requestFocus(forced);
     } else {
-      IdeFocusManager.findInstanceByComponent(myPanel).requestFocus(myPanel, forced);
+      EditorWithProviderComposite editor = getSelectedEditor();
+      if (editor != null) {
+        JComponent toFocus = editor.getPreferredFocusedComponent();
+        IdeFocusManager.findInstanceByComponent(toFocus).requestFocus(toFocus, forced);
+      } else {
+        IdeFocusManager.findInstanceByComponent(myPanel).requestFocus(myPanel, forced);
+      }
     }
   }
 
index f77527023ad6d6e65cae13d7d0df6f573748967f..c4ac427f89b511c7f7b533d6a16c58002511a04a 100644 (file)
@@ -635,14 +635,12 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
     }
 
     if (wndToOpenIn == null || !wndToOpenIn.isFileOpen(file)) {
-      PreviewManager previewManager = PreviewManager.SERVICE.getInstance(myProject);
-      if (previewManager != null) {
-        Pair<FileEditor[], FileEditorProvider[]> previewResult = previewManager.preview(FilePreviewPanelProvider.ID, file, focusEditor);
+      Pair<FileEditor[], FileEditorProvider[]> previewResult =
+        PreviewManager.SERVICE.preview(myProject, FilePreviewPanelProvider.ID, file, focusEditor);
         if (previewResult != null) {
           return previewResult;
         }
       }
-    }
 
     EditorsSplitters splitters = getSplitters();
 
index dcf2638ec06dccb9812dec3fff61bf2c134bf144..b5990fdddfdae0e91feec8a2af2e9d8e88ff446e 100644 (file)
@@ -22,16 +22,16 @@ import com.intellij.openapi.preview.PreviewManager;
 import com.intellij.openapi.preview.PreviewPanelProvider;
 import com.intellij.openapi.preview.PreviewProviderId;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.IdeFocusManager;
 import com.intellij.ui.docking.DockManager;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import java.util.ArrayList;
-import java.util.List;
 
 public class FilePreviewPanelProvider extends PreviewPanelProvider<VirtualFile, Pair<FileEditor[], FileEditorProvider[]>> {
   public static final PreviewProviderId<VirtualFile, Pair<FileEditor[], FileEditorProvider[]>> ID = PreviewProviderId.create("Files");
@@ -52,20 +52,27 @@ public class FilePreviewPanelProvider extends PreviewPanelProvider<VirtualFile,
     myWindow.setTabsPlacement(UISettings.TABS_NONE);
   }
 
-  @NotNull
   @Override
-  protected JComponent getComponent() {
-    return myEditorsSplitters;
+  public void dispose() {
+    myEditorsSplitters.dispose();
   }
 
+  @NotNull
   @Override
-  public boolean shouldBeEnabledByDefault() {
-    return true;
+  protected JComponent getComponent() {
+    return myEditorsSplitters;
   }
 
   @Override
   protected Pair<FileEditor[], FileEditorProvider[]> initComponent(VirtualFile file, boolean requestFocus) {
-    return myManager.openFileWithProviders(file, requestFocus, myWindow);
+    Pair<FileEditor[], FileEditorProvider[]> result = myManager.openFileWithProviders(file, requestFocus, myWindow);
+    IdeFocusManager.findInstance().doWhenFocusSettlesDown(new Runnable() {
+      @Override
+      public void run() {
+        myWindow.requestFocus(true);
+      }
+    });
+    return result;
   }
 
   @NotNull
@@ -86,14 +93,31 @@ public class FilePreviewPanelProvider extends PreviewPanelProvider<VirtualFile,
   }
 
   @Override
-  public boolean moveContentToStandardView(@NotNull VirtualFile file) {
+  public void showInStandardPlace(@NotNull VirtualFile file) {
     EditorWindow window = myManager.getCurrentWindow();
     if (window == null) { //main tab set is still not created, rare situation
       myManager.getMainSplitters().createCurrentWindow();
       window = myManager.getCurrentWindow();
     }
     myManager.openFileWithProviders(file, true, window);
-    return true;
+  }
+
+  @Override
+  public boolean isModified(VirtualFile content, boolean beforeReuse) {
+    for (EditorWithProviderComposite composite : myEditorsSplitters.getEditorsComposites()) {
+      if (composite.isModified() && Comparing.equal(composite.getFile(), content)) return true;
+    }
+    return false;
+  }
+
+  @Override
+  public void release(@NotNull VirtualFile content) {
+    myEditorsSplitters.closeFile(content, false);
+  }
+
+  @Override
+  public boolean contentsAreEqual(@NotNull VirtualFile content1, @NotNull VirtualFile content2) {
+    return Comparing.equal(content1, content2);
   }
 
   private class MyEditorsSplitters extends EditorsSplitters {
@@ -103,10 +127,7 @@ public class FilePreviewPanelProvider extends PreviewPanelProvider<VirtualFile,
 
     @Override
     protected void afterFileClosed(VirtualFile file) {
-      PreviewManager previewManager = PreviewManager.SERVICE.getInstance(myProject);
-      if (previewManager != null) {
-        previewManager.close(getId(), file);
-      }
+      PreviewManager.SERVICE.close(myProject, getId(), file);
     }
 
     @Override
@@ -114,16 +135,11 @@ public class FilePreviewPanelProvider extends PreviewPanelProvider<VirtualFile,
       return new EditorWindow(this) {
         @Override
         protected void onBeforeSetEditor(VirtualFile file) {
-          List<VirtualFile> toMove = new ArrayList<VirtualFile>();
           for (EditorWithProviderComposite composite : getEditorsComposites()) {
             if (composite.isModified()) {
-              toMove.add(composite.getFile());
-            }
-          }
-          PreviewManager previewManager = PreviewManager.SERVICE.getInstance(myProject);
-          if (previewManager != null) {
-            for (VirtualFile virtualFile : toMove) {
-              previewManager.moveToStandardPlace(getId(), virtualFile);
+              //Estimation: no more than one file is modified at the same time
+              PreviewManager.SERVICE.moveToStandardPlaceImpl(myProject, getId(), composite.getFile());
+              return;
             }
           }
         }
index 2d096f9b63885fe6d78bc3612f83860159462e0b..12c55f91257c6bac70002ce0e297522baea464a5 100644 (file)
@@ -17,6 +17,7 @@ package com.intellij.openapi.preview;
 
 import com.intellij.util.ui.EmptyIcon;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 
@@ -67,18 +68,33 @@ public class PreviewInfo<V, C> {
     return myData;
   }
 
+  @Nullable
   public C initComponent(boolean requestFocus) {
     return myProvider.initComponent(myData, requestFocus);
   }
 
+  public boolean isModified(boolean beforeReuse) {
+    return myProvider.isModified(myData, beforeReuse);
+  }
+
   @Override
   public int hashCode() {
-    return myProvider.hashCode() * 31 + myData.hashCode();
+    return myProvider.hashCode();
   }
 
   @Override
   public boolean equals(Object obj) {
-    return obj == this ||
-           (obj instanceof PreviewInfo && ((PreviewInfo)obj).myProvider.equals(myProvider) && ((PreviewInfo)obj).myData.equals(myData));
+    if (obj == this) return true;
+    if (!(obj instanceof PreviewInfo)) return false;
+    //noinspection unchecked
+    return ((PreviewInfo)obj).getId() == getId() && myProvider.contentsAreEqual( (V)((PreviewInfo)obj).myData, myData);
+  }
+
+  public void release() {
+    myProvider.release(myData);
+  }
+
+  public boolean supportsStandardPlace() {
+    return myProvider.supportsStandardPlace();
   }
 }
index 810563ca6f8ad68641b0caaaabfcb5b94b10684d..0c948a42865618c17fb45ddf5348d8e8f4b3b417 100644 (file)
@@ -28,10 +28,34 @@ public interface PreviewManager {
     }
 
     @Nullable
-    public static PreviewManager getInstance(@NotNull Project project) {
+    private static PreviewManager getInstance(@NotNull Project project) {
       if (!UISettings.getInstance().NAVIGATE_TO_PREVIEW) return null;
       return ServiceManager.getService(project, PreviewManager.class);
     }
+
+    /**
+     * @return null if preview cannot be performed
+     */
+    @Nullable
+    public static <V, C> C preview(@NotNull Project project, @NotNull PreviewProviderId<V, C> id, V data, boolean requestFocus) {
+      PreviewManager instance = getInstance(project);
+      if (instance == null) return null;
+      return instance.preview(id, data, requestFocus);
+    }
+
+    public static <V, C> void close(@NotNull Project project, @NotNull PreviewProviderId<V, C> id, V data) {
+      PreviewManager instance = getInstance(project);
+      if (instance != null) {
+        instance.close(id, data);
+      }
+    }
+
+    public static <V, C> void moveToStandardPlaceImpl(@NotNull Project project, @NotNull PreviewProviderId<V, C> id, V data) {
+      PreviewManager instance = getInstance(project);
+      if (instance != null) {
+        instance.moveToStandardPlaceImpl(id, data);
+      }
+    }
   }
 
   /**
@@ -40,7 +64,7 @@ public interface PreviewManager {
   @Nullable
   <V, C> C preview(@NotNull PreviewProviderId<V, C> id, V data, boolean requestFocus);
 
-  <V, C> boolean moveToStandardPlace(@NotNull PreviewProviderId<V, C> id, V data);
+  <V, C> void moveToStandardPlaceImpl(@NotNull PreviewProviderId<V, C> id, V data);
 
   <V, C> void close(@NotNull PreviewProviderId<V, C> id, V data);
 }
index b38145ceed6b3eb1ba300bec035b8f58e27dfa7d..f84cefcefcc79092fa47932a5a72a6ec3cd85268 100644 (file)
  */
 package com.intellij.openapi.preview;
 
+import com.intellij.openapi.Disposable;
 import com.intellij.openapi.extensions.ExtensionPointName;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 
-public abstract class PreviewPanelProvider<V, C> {
-  public static final ExtensionPointName<PreviewPanelProvider> EP_NAME =
-    new ExtensionPointName<PreviewPanelProvider>("com.intellij.previewPanelProvider");
+public abstract class PreviewPanelProvider<V, C> implements Disposable {
+  public static final ExtensionPointName<PreviewPanelProvider> EP_NAME = new ExtensionPointName<PreviewPanelProvider>("com.intellij.previewPanelProvider");
   private final PreviewProviderId<V, C> myId;
 
   public PreviewPanelProvider(PreviewProviderId<V, C> id) {
@@ -35,8 +35,6 @@ public abstract class PreviewPanelProvider<V, C> {
     return myId;
   }
 
-  public abstract boolean shouldBeEnabledByDefault();
-
   //Let's share single specific component for all provided previews (if possible)
   @NotNull
   protected abstract JComponent getComponent();
@@ -49,7 +47,22 @@ public abstract class PreviewPanelProvider<V, C> {
 
   public abstract float getMenuOrder();
 
-  public abstract boolean moveContentToStandardView(@NotNull V content);
+  public abstract void showInStandardPlace(@NotNull V content);
+
+  @Nullable protected abstract C initComponent(V content, boolean requestFocus);
+
+  public abstract boolean isModified(V content, boolean beforeReuse);
+
+  public abstract void release(@NotNull V content);
 
-  protected abstract C initComponent(V content, boolean requestFocus);
+  public abstract boolean contentsAreEqual(@NotNull V content1, @NotNull V content2);
+
+  @Override
+  public final String toString() {
+    return myId.getVisualName();
+  }
+
+  public boolean supportsStandardPlace() {
+    return true;
+  }
 }
index a7ba87c843aef26db4a59a1643cc81d61cb768b4..207445e19f4126e94805adc633dfe279822da716 100644 (file)
@@ -19,7 +19,10 @@ import com.intellij.icons.AllIcons;
 import com.intellij.ide.ui.UISettings;
 import com.intellij.ide.ui.UISettingsListener;
 import com.intellij.openapi.actionSystem.*;
-import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.State;
+import com.intellij.openapi.components.Storage;
+import com.intellij.openapi.components.StoragePathMacros;
 import com.intellij.openapi.keymap.Keymap;
 import com.intellij.openapi.keymap.KeymapManager;
 import com.intellij.openapi.preview.PreviewInfo;
@@ -28,6 +31,7 @@ import com.intellij.openapi.preview.PreviewPanelProvider;
 import com.intellij.openapi.preview.PreviewProviderId;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Couple;
+import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.wm.*;
 import com.intellij.openapi.wm.impl.ToolWindowImpl;
@@ -49,8 +53,14 @@ import org.jetbrains.annotations.Nullable;
 import javax.swing.*;
 import java.awt.*;
 import java.util.*;
-
-public class PreviewManagerImpl implements PreviewManager {
+@State(
+  name = "PreviewManager",
+  storages = {
+  @Storage(
+    file = StoragePathMacros.WORKSPACE_FILE
+  )}
+)
+public class PreviewManagerImpl implements PreviewManager, PersistentStateComponent<PreviewManagerState> {
   private static final Key<PreviewInfo> INFO_KEY = Key.create("preview_info");
   private static final int HISTORY_LIMIT = 10;
 
@@ -69,10 +79,12 @@ public class PreviewManagerImpl implements PreviewManager {
   private TreeSet<PreviewPanelProvider> myProviders = new TreeSet<PreviewPanelProvider>(new Comparator<PreviewPanelProvider>() {
     @Override
     public int compare(PreviewPanelProvider o1, PreviewPanelProvider o2) {
-      return Float.compare(o1.getMenuOrder(), o2.getMenuOrder());
+      int result = Float.compare(o1.getMenuOrder(), o2.getMenuOrder());
+      return result != 0 ? result : o1.toString().compareTo(o2.toString());
     }
   });
   private Set<PreviewProviderId> myActiveProviderIds = new HashSet<PreviewProviderId>();
+  private Set<PreviewProviderId> myLockedProviderIds = new HashSet<PreviewProviderId>();
   private boolean myInnerSelectionChange;
 
   private static boolean isAvailable() {
@@ -86,10 +98,8 @@ public class PreviewManagerImpl implements PreviewManager {
     PreviewPanelProvider[] providers = PreviewPanelProvider.EP_NAME.getExtensions(project);
     for (PreviewPanelProvider provider : providers) {
       myProviders.add(provider);
-      if (provider.shouldBeEnabledByDefault()) {
-        myActiveProviderIds.add(provider.getId());
-      }
-      //todo make it all externalizable to store/restore enabled/disabled state
+      myActiveProviderIds.add(provider.getId());
+      Disposer.register(project, provider);
     }
 
     UISettings.getInstance().addUISettingsListener(new UISettingsListener() {
@@ -103,7 +113,34 @@ public class PreviewManagerImpl implements PreviewManager {
   }
 
   @Nullable
-  public <V, C> PreviewPanelProvider<V, C> findProvider(@NotNull PreviewProviderId<V, C> id) {
+  @Override
+  public PreviewManagerState getState() {
+    PreviewManagerState state = new PreviewManagerState();
+    state.myArtifactFilesMap = new HashMap<String, Boolean>();
+    for (PreviewPanelProvider provider : myProviders) {
+      state.myArtifactFilesMap.put(provider.toString(), myActiveProviderIds.contains(provider.getId()));
+    }
+    return state;
+  }
+
+  @Override
+  public void loadState(PreviewManagerState state) {
+    if (state == null) return;
+    for (Map.Entry<String, Boolean> entry : state.myArtifactFilesMap.entrySet()) {
+      if (!entry.getValue()) {
+        for (Iterator<PreviewProviderId> iterator = myActiveProviderIds.iterator(); iterator.hasNext(); ) {
+          PreviewProviderId id = iterator.next();
+          if (id.getVisualName().equals(entry.getKey())) {
+            iterator.remove();
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  @Nullable
+  private <V, C> PreviewPanelProvider<V, C> findProvider(@NotNull PreviewProviderId<V, C> id) {
     for (PreviewPanelProvider provider : myProviders) {
       if (id == provider.getId()) return provider;
     }
@@ -123,21 +160,22 @@ public class PreviewManagerImpl implements PreviewManager {
       myToolWindow = (ToolWindowImpl)toolWindowManager
         .registerToolWindow(ToolWindowId.PREVIEW, myEmptyStatePanel, ToolWindowAnchor.RIGHT, myProject, false);
       myContentManager = myToolWindow.getContentManager();
-      myToolWindow.setIcon(AllIcons.Actions.PreviewDetails);
+      myToolWindow.setIcon(AllIcons.Toolwindows.ToolWindowPreview);
       myToolWindow.setContentUiType(ToolWindowContentUiType.COMBO, null);
       myToolWindow.setAutoHide(true);
       myEmptyStateContent = myContentManager.getContent(0);
+      final MoveToStandardViewAction moveToStandardViewAction = new MoveToStandardViewAction();
       myContentManager.addContentManagerListener(new ContentManagerAdapter() {
         @Override
         public void selectionChanged(ContentManagerEvent event) {
           if (myInnerSelectionChange || event.getOperation() != ContentManagerEvent.ContentOperation.add) return;
           PreviewInfo previewInfo = event.getContent().getUserData(INFO_KEY);
           if (previewInfo != null) {
-            preview(previewInfo, true);
+            preview(previewInfo, false);
+            myToolWindow.setTitleActions(previewInfo.supportsStandardPlace() ? moveToStandardViewAction : null);
           }
         }
       });
-      MoveToStandardViewAction moveToStandardViewAction = new MoveToStandardViewAction();
 
       moveToStandardViewAction.registerCustomShortcutSet(new ShortcutSet() {
         @NotNull
@@ -154,7 +192,12 @@ public class PreviewManagerImpl implements PreviewManager {
         myGearActions.add(new ContentTypeToggleAction(provider));
       }
       myToolWindow.setAdditionalGearActions(new DefaultActionGroup("Preview", myGearActions));
-      //myToolWindow.hide(null);
+      myToolWindow.activate(new Runnable() {
+        @Override
+        public void run() {
+          myToolWindow.activate(null);
+        }
+      });
     }
   }
 
@@ -162,14 +205,6 @@ public class PreviewManagerImpl implements PreviewManager {
     if (myContentManager.getContents().length == 0) {
       myToolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "false");
       myContentManager.addContent(myEmptyStateContent);
-      //ApplicationManager.getApplication().invokeLater(new Runnable() {
-      //  @Override
-      //  public void run() {
-      //    if (myContentManager.getIndexOfContent(myEmptyStateContent) != -1) {
-      //      toggleToolWindow(false);
-      //    }
-      //  }
-      //});
     }
     else if (myContentManager.getContents().length > 1) {
       myToolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "true");
@@ -180,9 +215,8 @@ public class PreviewManagerImpl implements PreviewManager {
   @Nullable
   private Content getContent(@NotNull PreviewInfo info) {
     for (Content content : myContentManager.getContents()) {
-      if (info.equals(content.getUserData(INFO_KEY))) {
-        return content;
-      }
+      PreviewInfo eachInfo = content.getUserData(INFO_KEY);
+      if (info.equals(eachInfo)) return content;
     }
     return null;
   }
@@ -191,27 +225,30 @@ public class PreviewManagerImpl implements PreviewManager {
   private Content addContent(PreviewInfo info) {
     myHistory.add(info);
     while (myHistory.size() > HISTORY_LIMIT) {
-      PreviewInfo previewInfo = myHistory.remove(0);
-      close(previewInfo);
+      close(myHistory.remove(0));
     }
 
     Content content = myContentManager.getFactory().createContent(info.getComponent(), info.getTitle(), false);
-    content.putUserData(ToolWindow.SHOW_CONTENT_ICON, Boolean.TRUE);
-    content.putUserData(INFO_KEY, info);
-    content.setIcon(info.getIcon());
-    content.setPopupIcon(info.getIcon());
 
     myContentManager.addContent(content, 0);
     checkEmptyState();
     return content;
   }
 
+  private static void updateContentWithInfo(Content content, PreviewInfo info) {
+    content.putUserData(ToolWindow.SHOW_CONTENT_ICON, Boolean.TRUE);
+    content.putUserData(INFO_KEY, info);
+    content.setIcon(info.getIcon());
+    content.setPopupIcon(info.getIcon());
+  }
+
   private void close(@NotNull PreviewInfo info) {
     Content content = getContent(info);
     if (content != null) {
       myContentManager.removeContent(content, false);
+      info.release();
       if (myContentManager.getContents().length == 0) {
-        toggleToolWindow(false);
+        toggleToolWindow(false, null);
       }
       checkEmptyState();
     }
@@ -219,37 +256,56 @@ public class PreviewManagerImpl implements PreviewManager {
 
   @Override
   public <V, C> C preview(@NotNull PreviewProviderId<V, C> id, V data, boolean requestFocus) {
+    if (!myActiveProviderIds.contains(id) || myLockedProviderIds.contains(id)) {
+      return null;
+    }
     PreviewPanelProvider<V, C> provider = findProvider(id);
-    if (provider == null || !myActiveProviderIds.contains(id)) return null;
+    if (provider == null) {
+      return null;
+    }
     return preview(PreviewInfo.create(provider, data), requestFocus);
   }
 
-  public <V, C> C preview(@NotNull PreviewInfo<V, C> info, boolean requestFocus) {
-    toggleToolWindow(true);
+  private <V, C> C preview(@NotNull final PreviewInfo<V, C> info, boolean requestFocus) {
+    toggleToolWindow(true, null);
     Content content = getContent(info);
-    if (myContentManager.getSelectedContent() != content) {
+    Content selectedContent = myContentManager.getSelectedContent();
+    if (selectedContent != content) {
       myInnerSelectionChange = true;
       try {
+        PreviewInfo selectedInfo = selectedContent != null ? selectedContent.getUserData(INFO_KEY) : null;
+        if (selectedInfo != null && selectedInfo.isModified(selectedInfo.getId() == info.getId())) {
+          moveToStandardPlaceImpl(selectedInfo.getId(), selectedInfo.getData());
+        }
         if (content == null) {
           content = addContent(info);
         }
-        myContentManager.setSelectedContent(content);
       }
       finally {
         myInnerSelectionChange = false;
       }
     }
     if (content != null) {
-      myContentManager.addContent(content, 0);
+      myContentManager.addContent(content, 0);//Adjust usage order
+    }
+    myInnerSelectionChange = true;
+    try {
+      if (content != null) {
+        updateContentWithInfo(content, info);
+        myContentManager.setSelectedContent(content, requestFocus);
+      }
+      return info.initComponent(requestFocus);
+    }
+    finally {
+      myInnerSelectionChange = false;
     }
-    return info.initComponent(requestFocus);
   }
 
   @Override
   public <V, C> void close(@NotNull PreviewProviderId<V, C> id, V data) {
     for (Content content : myContentManager.getContents()) {
       PreviewInfo info = content.getUserData(INFO_KEY);
-      if (info != null && info.getId() == id && info.getData() == data) {
+      if (info != null && info.getId() == id && info.getProvider().contentsAreEqual(info.getData(),data)) {
         close(info);
         break;
       }
@@ -257,25 +313,23 @@ public class PreviewManagerImpl implements PreviewManager {
   }
 
   @Override
-  public <V, C> boolean moveToStandardPlace(@NotNull PreviewProviderId<V, C> id, V data) {
+  public <V, C> void moveToStandardPlaceImpl(@NotNull PreviewProviderId<V, C> id, V data) {
     PreviewPanelProvider<V, C> provider = findProvider(id);
-    if (provider != null && provider.moveContentToStandardView(data)) {
-      close(id, data);
-      return true;
+    if (provider == null) return;
+    myLockedProviderIds.add(id);
+    try {
+      provider.showInStandardPlace(data);
+    } finally {
+      myLockedProviderIds.remove(id);
     }
-    return false;
+    close(id, data);
   }
 
-  private void toggleToolWindow(boolean activate) {
+  private void toggleToolWindow(boolean activate, Runnable runnable) {
     final ToolWindow toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW);
     if (toolWindow != null && activate != toolWindow.isActive()) {
       if (activate) {
-        myAlarm.addRequest(new Runnable() {
-          @Override
-          public void run() {
-            toolWindow.activate(null, false);
-          }
-        }, 75, ModalityState.stateForComponent(myEmptyStatePanel));
+        toolWindow.activate(runnable, true);
       }
       else {
         if (!myAlarm.isEmpty()) {
@@ -288,7 +342,7 @@ public class PreviewManagerImpl implements PreviewManager {
   private class MoveToStandardViewAction extends AnAction {
 
     public MoveToStandardViewAction() {
-      super("Move to standard view", "Move to standard view", AllIcons.Duplicates.SendToTheLeftGrayed);
+      super("Move to standard view", "Move to standard view", AllIcons.Actions.MoveToStandardPlace);
     }
 
     @Override
@@ -297,8 +351,8 @@ public class PreviewManagerImpl implements PreviewManager {
       if (selectedContent == null) return;
       PreviewInfo previewInfo = selectedContent.getUserData(INFO_KEY);
       if (previewInfo != null) {
-        moveToStandardPlace(previewInfo.getId(), previewInfo.getData());
-        toggleToolWindow(false);
+        moveToStandardPlaceImpl(previewInfo.getId(), previewInfo.getData());
+        toggleToolWindow(false, null);
       }
     }
   }
diff --git a/platform/platform-impl/src/com/intellij/openapi/preview/impl/PreviewManagerState.java b/platform/platform-impl/src/com/intellij/openapi/preview/impl/PreviewManagerState.java
new file mode 100644 (file)
index 0000000..a3bda83
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.preview.impl;
+
+import com.intellij.util.containers.hash.LinkedHashMap;
+import com.intellij.util.xmlb.annotations.MapAnnotation;
+import com.intellij.util.xmlb.annotations.Property;
+
+import java.util.Map;
+
+public class PreviewManagerState {
+  //@Tag("providers")
+  @Property(surroundWithTag = false)
+  @MapAnnotation(surroundWithTag = false)
+  public Map<String, Boolean> myArtifactFilesMap = new LinkedHashMap<String, Boolean>();
+}
index b4df75cd547b69387ec9351af0cc555a5dbbc1b5..70cf33e8d8d78cdde4e61f4b2fdccc56c802e151 100644 (file)
     <projectService serviceInterface="com.intellij.execution.ExecutionTargetManager" serviceImplementation="com.intellij.execution.ExecutionTargetManagerImpl"/>
     <previewPanelProvider implementation="com.intellij.openapi.fileEditor.impl.FilePreviewPanelProvider"/>
     <previewPanelProvider implementation="com.intellij.codeInsight.documentation.DocumentationPreviewPanelProvider"/>
+    <previewPanelProvider implementation="com.intellij.find.UsagesPreviewPanelProvider"/>
     <projectService serviceInterface="com.intellij.openapi.preview.PreviewManager"
                     serviceImplementation="com.intellij.openapi.preview.impl.PreviewManagerImpl"/>
 
index ee4f0b63cc8a3457b180b7ae52583a4af59a16af..5c0100e7bbe799e00de229384160541faaf1460a 100644 (file)
@@ -207,5 +207,69 @@ public class UsageViewPresentation {
   public void setUsageTypeFilteringAvailable(boolean usageTypeFilteringAvailable) {
     myUsageTypeFilteringAvailable = usageTypeFilteringAvailable;
   }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof UsageViewPresentation)) return false;
+
+    UsageViewPresentation that = (UsageViewPresentation)o;
+
+    if (myCodeUsages != that.myCodeUsages) return false;
+    if (myDetachedMode != that.myDetachedMode) return false;
+    if (myMergeDupLinesAvailable != that.myMergeDupLinesAvailable) return false;
+    if (myOpenInNewTab != that.myOpenInNewTab) return false;
+    if (myShowCancelButton != that.myShowCancelButton) return false;
+    if (myShowReadOnlyStatusAsRed != that.myShowReadOnlyStatusAsRed) return false;
+    if (myUsageTypeFilteringAvailable != that.myUsageTypeFilteringAvailable) return false;
+    if (myCodeUsagesString != null ? !myCodeUsagesString.equals(that.myCodeUsagesString) : that.myCodeUsagesString != null) return false;
+    if (myDynamicCodeUsagesString != null
+        ? !myDynamicCodeUsagesString.equals(that.myDynamicCodeUsagesString)
+        : that.myDynamicCodeUsagesString != null) {
+      return false;
+    }
+    if (myNonCodeUsagesString != null ? !myNonCodeUsagesString.equals(that.myNonCodeUsagesString) : that.myNonCodeUsagesString != null) {
+      return false;
+    }
+    if (myNotFoundActions != null ? !myNotFoundActions.equals(that.myNotFoundActions) : that.myNotFoundActions != null) return false;
+    if (myScopeText != null ? !myScopeText.equals(that.myScopeText) : that.myScopeText != null) return false;
+    if (myTabName != null ? !myTabName.equals(that.myTabName) : that.myTabName != null) return false;
+    if (myTabText != null ? !myTabText.equals(that.myTabText) : that.myTabText != null) return false;
+    if (myTargetsNodeText != null ? !myTargetsNodeText.equals(that.myTargetsNodeText) : that.myTargetsNodeText != null) return false;
+    if (myToolwindowTitle != null ? !myToolwindowTitle.equals(that.myToolwindowTitle) : that.myToolwindowTitle != null) return false;
+    if (myUsagesInGeneratedCodeString != null
+        ? !myUsagesInGeneratedCodeString.equals(that.myUsagesInGeneratedCodeString)
+        : that.myUsagesInGeneratedCodeString != null) {
+      return false;
+    }
+    if (myUsagesString != null ? !myUsagesString.equals(that.myUsagesString) : that.myUsagesString != null) return false;
+    if (myUsagesWord != null ? !myUsagesWord.equals(that.myUsagesWord) : that.myUsagesWord != null) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myTabText != null ? myTabText.hashCode() : 0;
+    result = 31 * result + (myScopeText != null ? myScopeText.hashCode() : 0);
+    result = 31 * result + (myUsagesString != null ? myUsagesString.hashCode() : 0);
+    result = 31 * result + (myTargetsNodeText != null ? myTargetsNodeText.hashCode() : 0);
+    result = 31 * result + (myNonCodeUsagesString != null ? myNonCodeUsagesString.hashCode() : 0);
+    result = 31 * result + (myCodeUsagesString != null ? myCodeUsagesString.hashCode() : 0);
+    result = 31 * result + (myUsagesInGeneratedCodeString != null ? myUsagesInGeneratedCodeString.hashCode() : 0);
+    result = 31 * result + (myShowReadOnlyStatusAsRed ? 1 : 0);
+    result = 31 * result + (myShowCancelButton ? 1 : 0);
+    result = 31 * result + (myOpenInNewTab ? 1 : 0);
+    result = 31 * result + (myCodeUsages ? 1 : 0);
+    result = 31 * result + (myUsageTypeFilteringAvailable ? 1 : 0);
+    result = 31 * result + (myUsagesWord != null ? myUsagesWord.hashCode() : 0);
+    result = 31 * result + (myTabName != null ? myTabName.hashCode() : 0);
+    result = 31 * result + (myToolwindowTitle != null ? myToolwindowTitle.hashCode() : 0);
+    result = 31 * result + (myNotFoundActions != null ? myNotFoundActions.hashCode() : 0);
+    result = 31 * result + (myDetachedMode ? 1 : 0);
+    result = 31 * result + (myDynamicCodeUsagesString != null ? myDynamicCodeUsagesString.hashCode() : 0);
+    result = 31 * result + (myMergeDupLinesAvailable ? 1 : 0);
+    return result;
+  }
 }