fe232519c6065b702cf98428ad589a0bfed0aaff
[fedora-idea.git] / platform / lang-impl / src / com / intellij / find / actions / ShowUsagesAction.java
blobfe232519c6065b702cf98428ad589a0bfed0aaff
1 /*
2 * Copyright 2000-2010 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.
17 package com.intellij.find.actions;
19 import com.intellij.codeInsight.hint.HintManager;
20 import com.intellij.codeInsight.hint.HintUtil;
21 import com.intellij.featureStatistics.FeatureUsageTracker;
22 import com.intellij.find.FindManager;
23 import com.intellij.find.findUsages.AbstractFindUsagesDialog;
24 import com.intellij.find.findUsages.FindUsagesHandler;
25 import com.intellij.find.findUsages.FindUsagesManager;
26 import com.intellij.find.impl.FindManagerImpl;
27 import com.intellij.openapi.Disposable;
28 import com.intellij.openapi.actionSystem.*;
29 import com.intellij.openapi.editor.Editor;
30 import com.intellij.openapi.fileEditor.FileEditor;
31 import com.intellij.openapi.fileEditor.FileEditorLocation;
32 import com.intellij.openapi.fileEditor.TextEditor;
33 import com.intellij.openapi.keymap.KeymapUtil;
34 import com.intellij.openapi.project.Project;
35 import com.intellij.openapi.ui.popup.JBPopup;
36 import com.intellij.openapi.ui.popup.JBPopupFactory;
37 import com.intellij.openapi.ui.popup.PopupChooserBuilder;
38 import com.intellij.openapi.util.Comparing;
39 import com.intellij.openapi.util.Disposer;
40 import com.intellij.openapi.util.IconLoader;
41 import com.intellij.openapi.vfs.VirtualFile;
42 import com.intellij.openapi.wm.IdeFocusManager;
43 import com.intellij.psi.PsiDocumentManager;
44 import com.intellij.psi.PsiElement;
45 import com.intellij.psi.SmartPointerManager;
46 import com.intellij.psi.SmartPsiElementPointer;
47 import com.intellij.psi.search.ProjectScope;
48 import com.intellij.psi.search.PsiElementProcessor;
49 import com.intellij.psi.search.SearchScope;
50 import com.intellij.ui.InplaceButton;
51 import com.intellij.ui.SpeedSearchBase;
52 import com.intellij.ui.TableScrollingUtil;
53 import com.intellij.ui.awt.RelativePoint;
54 import com.intellij.usageView.UsageViewBundle;
55 import com.intellij.usages.*;
56 import com.intellij.usages.impl.GroupNode;
57 import com.intellij.usages.impl.NullUsage;
58 import com.intellij.usages.impl.UsageNode;
59 import com.intellij.usages.impl.UsageViewImpl;
60 import com.intellij.usages.rules.UsageFilteringRuleProvider;
61 import com.intellij.util.Icons;
62 import com.intellij.util.Processor;
63 import com.intellij.util.messages.MessageBusConnection;
64 import com.intellij.util.ui.Table;
65 import org.jetbrains.annotations.NonNls;
66 import org.jetbrains.annotations.NotNull;
68 import javax.swing.*;
69 import javax.swing.table.AbstractTableModel;
70 import javax.swing.table.TableColumn;
71 import java.awt.*;
72 import java.awt.event.ActionEvent;
73 import java.awt.event.ActionListener;
74 import java.util.*;
75 import java.util.List;
77 public class ShowUsagesAction extends AnAction {
78 private final boolean showSettingsDialogBefore;
80 private static final int USAGES_PAGE_SIZE = 100;
81 private static final Comparator<Object> USAGE_COMPARATOR = new Comparator<Object>() {
82 public int compare(Object c1, Object c2) {
83 Usage o1 = ((UsageNode)c1).getUsage();
84 Usage o2 = ((UsageNode)c2).getUsage();
85 if (o1 == NullUsage.INSTANCE) return 1;
86 if (o2 == NullUsage.INSTANCE) return -1;
88 VirtualFile v1 = UsageListCellRenderer.getVirtualFile(o1);
89 VirtualFile v2 = UsageListCellRenderer.getVirtualFile(o2);
90 String name1 = v1 == null ? null : v1.getName();
91 String name2 = v2 == null ? null : v2.getName();
92 int i = Comparing.compare(name1, name2);
93 if (i!=0) return i;
95 if (o1 instanceof Comparable && o2 instanceof Comparable) {
96 return ((Comparable)o1).compareTo(o2);
99 FileEditorLocation loc1 = o1.getLocation();
100 FileEditorLocation loc2 = o2.getLocation();
101 return Comparing.compare(loc1, loc2);
104 private static final Runnable HIDE_HINTS_ACTION = new Runnable() {
105 public void run() {
106 hideHints();
110 public ShowUsagesAction() {
111 setInjectedContext(true);
112 showSettingsDialogBefore = false;
115 public static class ShowSettings extends ShowUsagesAction {
116 public ShowSettings() {
117 super(true);
121 private ShowUsagesAction(boolean showDialogBefore) {
122 setInjectedContext(true);
123 showSettingsDialogBefore = showDialogBefore;
126 public void actionPerformed(AnActionEvent e) {
127 final Project project = e.getData(PlatformDataKeys.PROJECT);
128 if (project == null) return;
129 hideHints();
130 myWidth = -1;
131 final RelativePoint popupPosition = JBPopupFactory.getInstance().guessBestPopupLocation(e.getDataContext());
132 PsiDocumentManager.getInstance(project).commitAllDocuments();
133 FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.goto.usages");
135 UsageTarget[] usageTargets = e.getData(UsageView.USAGE_TARGETS_KEY);
136 final Editor editor = e.getData(PlatformDataKeys.EDITOR);
137 if (usageTargets == null) {
138 FindUsagesAction.chooseAmbiguousTargetAndPerform(project, editor, new PsiElementProcessor<PsiElement>() {
139 public boolean execute(final PsiElement element) {
140 startFindUsages(element, popupPosition, editor, USAGES_PAGE_SIZE);
141 return false;
145 else {
146 PsiElement element = ((PsiElementUsageTarget)usageTargets[0]).getElement();
147 if (element != null) {
148 startFindUsages(element, popupPosition, editor, USAGES_PAGE_SIZE);
153 private static void hideHints() {
154 HintManager.getInstance().hideHints(HintManager.HIDE_BY_ANY_KEY, false, false);
157 private void startFindUsages(@NotNull PsiElement element, RelativePoint popupPosition, Editor editor, int maxUsages) {
158 Project project = element.getProject();
159 FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager();
160 FindUsagesHandler handler = findUsagesManager.getFindUsagesHandler(element, false);
161 if (handler == null) return;
162 if (showSettingsDialogBefore) {
163 showDialogAndFindUsages(handler, popupPosition, editor, maxUsages);
164 return;
166 showElementUsages(handler, editor, popupPosition, maxUsages);
169 private void showElementUsages(@NotNull FindUsagesHandler handler, final Editor editor, final RelativePoint popupPosition, final int maxUsages) {
170 UsageViewPresentation presentation = new UsageViewPresentation();
171 presentation.setDetachedMode(true);
173 final UsageViewSettings usageViewSettings = UsageViewSettings.getInstance();
174 final UsageViewSettings save = new UsageViewSettings();
176 save.loadState(usageViewSettings);
177 usageViewSettings.GROUP_BY_FILE_STRUCTURE = false;
178 usageViewSettings.GROUP_BY_MODULE = false;
179 usageViewSettings.GROUP_BY_PACKAGE = false;
180 usageViewSettings.GROUP_BY_USAGE_TYPE = false;
182 UsageViewManager manager = UsageViewManager.getInstance(handler.getProject());
183 final UsageViewImpl usageView = (UsageViewImpl)manager.createUsageView(UsageTarget.EMPTY_ARRAY, Usage.EMPTY_ARRAY, presentation, null);
185 Disposer.register(usageView, new Disposable() {
186 public void dispose() {
187 usageViewSettings.GROUP_BY_FILE_STRUCTURE = save.GROUP_BY_FILE_STRUCTURE;
188 usageViewSettings.GROUP_BY_MODULE = save.GROUP_BY_MODULE;
189 usageViewSettings.GROUP_BY_PACKAGE = save.GROUP_BY_PACKAGE;
190 usageViewSettings.GROUP_BY_USAGE_TYPE = save.GROUP_BY_USAGE_TYPE;
194 final List<Usage> usages = new ArrayList<Usage>();
195 final Set<UsageNode> visibleNodes = new LinkedHashSet<UsageNode>();
196 Processor<Usage> collect = new Processor<Usage>() {
197 public boolean process(@NotNull Usage usage) {
198 synchronized (usages) {
199 if (visibleNodes.size() > maxUsages) return false;
200 UsageNode node = usageView.doAppendUsage(usage);
201 if (node != null) {
202 if (visibleNodes.size() == maxUsages) {
203 usageView.removeUsage(usage);
204 visibleNodes.add(UsageViewImpl.NULL_NODE);
205 return false;
207 visibleNodes.add(node);
209 usages.add(usage);
211 return true;
214 FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(handler.getProject())).getFindUsagesManager();
215 presentation = findUsagesManager.processUsages(handler, collect);
216 if (presentation == null) {
217 Disposer.dispose(usageView);
218 return;
220 final String title = presentation.getTabText();
222 JBPopup popup = createUsagePopup(usages, visibleNodes, title, handler, editor, popupPosition, maxUsages, usageView);
223 if (popup != null) {
224 popup.show(popupPosition);
228 private void showHint(String text, final Editor editor, final RelativePoint popupPosition, FindUsagesHandler handler, int maxUsages) {
229 JComponent label = createHintComponent(text, handler, popupPosition, editor, HIDE_HINTS_ACTION, maxUsages);
230 if (editor == null) {
231 HintManager.getInstance().showHint(label, popupPosition, HintManager.HIDE_BY_ANY_KEY |
232 HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING, 0);
234 else {
235 HintManager.getInstance().showInformationHint(editor, label);
239 private JComponent createHintComponent(String text, final FindUsagesHandler handler, final RelativePoint popupPosition, final Editor editor,
240 final Runnable cancelAction,
241 int maxUsages) {
242 JLabel label = HintUtil.createInformationLabel(text);
243 InplaceButton button = createSettingsButton(handler, popupPosition, editor, maxUsages, cancelAction);
244 JPanel panel = new JPanel(new BorderLayout());
245 button.setBackground(label.getBackground());
246 panel.setBackground(label.getBackground());
247 label.setOpaque(false);
248 label.setBorder(null);
249 panel.setBorder(HintUtil.createHintBorder());
250 panel.add(label, BorderLayout.CENTER);
251 panel.add(button, BorderLayout.EAST);
252 return panel;
255 private InplaceButton createSettingsButton(final FindUsagesHandler handler, final RelativePoint popupPosition,
256 final Editor editor,
257 final int maxUsages,
258 final Runnable cancelAction) {
259 String shortcutText = "";
260 KeyboardShortcut shortcut = getSettingsShortcut();
261 if (shortcut != null) {
262 shortcutText = "(" + KeymapUtil.getShortcutText(shortcut) + ")";
264 return new InplaceButton("Options..." + shortcutText, IconLoader.getIcon("/general/ideOptions.png"), new ActionListener() {
265 public void actionPerformed(ActionEvent e) {
266 SwingUtilities.invokeLater(new Runnable() {
267 public void run() {
268 showDialogAndFindUsages(handler, popupPosition, editor, maxUsages);
271 cancelAction.run();
276 private void showDialogAndFindUsages(FindUsagesHandler handler, RelativePoint popupPosition, Editor editor, int maxUsages) {
277 AbstractFindUsagesDialog dialog = handler.getFindUsagesDialog(false, false, false);
278 dialog.show();
279 if (dialog.isOK()) {
280 dialog.calcFindUsagesOptions();
281 showElementUsages(handler, editor, popupPosition, maxUsages);
285 private static String searchScopePresentableName(final FindUsagesHandler handler) {
286 SearchScope searchScope = FindUsagesManager.getCurrentSearchScope(handler);
287 if (searchScope == null) searchScope = ProjectScope.getAllScope(handler.getProject());
288 return searchScope.getDisplayName();
291 private JBPopup createUsagePopup(final List<Usage> usages,
292 Set<UsageNode> visibleNodes,
293 final String title,
294 final FindUsagesHandler handler,
295 final Editor editor,
296 final RelativePoint popupPosition,
297 final int maxUsages,
298 final UsageViewImpl usageView) {
299 boolean hasMore = visibleNodes.remove(UsageViewImpl.NULL_NODE);
301 final Project project = handler.getProject();
303 if (visibleNodes.isEmpty()) {
304 if (usages.isEmpty()) {
305 String text = UsageViewBundle.message("no.usages.found.in", searchScopePresentableName(handler));
306 showHint(text, editor, popupPosition, handler, maxUsages);
307 Disposer.dispose(usageView);
308 return null;
310 else {
311 // all usages filtered out
314 if (visibleNodes.size() == 1 && usages.size() == 1) {
315 //the only usage
316 Usage usage = visibleNodes.iterator().next().getUsage();
317 navigateAndHint(usage, UsageViewBundle.message("show.usages.only.usage", searchScopePresentableName(handler)), handler, popupPosition,
318 maxUsages);
319 Disposer.dispose(usageView);
320 return null;
322 if (visibleNodes.size() == 1 && usages.size() >= 1) {
323 // usage view can filter usages down to one
324 Usage usage = visibleNodes.iterator().next().getUsage();
325 navigateAndHint(usage, UsageViewBundle.message("all.usages.are.in.this.line", usages.size(), searchScopePresentableName(handler)),
326 handler, popupPosition, maxUsages);
327 Disposer.dispose(usageView);
328 return null;
331 if (hasMore) {
332 usages.add(NullUsage.INSTANCE);
333 visibleNodes.add(UsageViewImpl.NULL_NODE);
335 addUsageNodes(usageView.getRoot(), usageView, new ArrayList<UsageNode>());
338 final JTable table = new MyTable();
339 TableScrollingUtil.installActions(table);
340 final Vector<Object> data = new Vector<Object>();
341 setModel(table, usages, visibleNodes, usageView, data);
343 final Runnable navigateRunnable = new Runnable() {
344 public void run() {
345 int[] selected = table.getSelectedRows();
346 for (int i : selected) {
347 Object value = table.getValueAt(i,0);
348 if (value instanceof UsageNode) {
349 Usage usage = ((UsageNode)value).getUsage();
350 if (usage == NullUsage.INSTANCE) {
351 appendMoreUsages(editor, popupPosition, handler, maxUsages);
352 return;
354 navigateAndHint(usage, null, handler, popupPosition, maxUsages);
360 SpeedSearchBase<JTable> speedSearch = new SpeedSearchBase<JTable>(table) {
361 protected int getSelectedIndex() {
362 return table.getSelectedRow();
365 protected Object[] getAllElements() {
366 return data.toArray(new Object[data.size()]);
369 protected String getElementText(Object element) {
370 if (!(element instanceof UsageNode)) return element.toString();
371 UsageNode node = (UsageNode)element;
372 GroupNode group = (GroupNode)node.getParent();
373 return node.getUsage().getPresentation().getPlainText() + group.toString();
376 protected void selectElement(Object element, String selectedText) {
377 int i = data.indexOf(element);
378 if (i == -1) return;
379 table.getSelectionModel().setSelectionInterval(i, i);
382 speedSearch.setComparator(new SpeedSearchBase.SpeedSearchComparator(false));
384 PopupChooserBuilder builder = new PopupChooserBuilder(table);
385 if (title != null) {
386 String s;
387 if (hasMore) {
388 s = "<html><body><b>Some</b> " + title + " " + "<b>(Only " + (visibleNodes.size() - 1) + " usages shown)</b></body></html>";
390 else {
391 s = title + " (" + usages.size() + " usages found)";
393 builder.setTitle(s);
396 builder.setMovable(true).setResizable(true);
397 builder.setItemChoosenCallback(navigateRunnable);
398 final JBPopup[] popup = new JBPopup[1];
399 ActionListener editSettings = new ActionListener() {
400 public void actionPerformed(ActionEvent e) {
401 popup[0].cancel();
402 SwingUtilities.invokeLater(new Runnable() {
403 public void run() {
404 showDialogAndFindUsages(handler, popupPosition, editor, maxUsages);
412 KeyboardShortcut shortcut = getSettingsShortcut();
413 if (shortcut != null) {
414 builder.registerKeyboardAction(shortcut.getFirstKeyStroke(), editSettings);
417 InplaceButton button = createSettingsButton(handler, popupPosition, editor, maxUsages, new Runnable() {
418 public void run() {
419 popup[0].cancel();
422 builder.setCommandButton(button);
424 DefaultActionGroup filters = new DefaultActionGroup();
425 usageView.addFilteringActions(filters);
427 filters.add(new AnAction("Open Find Usages Toolwindow", "Show all usages in a separate toolwindow", IconLoader.getIcon("/general/toolWindowFind.png")) {
429 AnAction action = ActionManager.getInstance().getAction(IdeActions.ACTION_FIND_USAGES);
430 setShortcutSet(action.getShortcutSet());
432 @Override
433 public void actionPerformed(AnActionEvent e) {
434 hideHints();
435 popup[0].cancel();
436 FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager();
437 FindUsagesManager.SearchData data = new FindUsagesManager.SearchData();
438 data.myOptions = handler.getFindUsagesOptions();
439 SmartPsiElementPointer<PsiElement> pointer =
440 SmartPointerManager.getInstance(project).createSmartPsiElementPointer(handler.getPsiElement());
441 data.myElements = new SmartPsiElementPointer[]{pointer};
442 findUsagesManager.rerunAndRecallFromHistory(data);
446 ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.USAGE_VIEW_TOOLBAR, filters, true);
447 actionToolbar.setReservePlaceAutoPopupIcon(false);
448 final JComponent toolBar = actionToolbar.getComponent();
449 toolBar.setOpaque(false);
450 builder.setSettingButton(toolBar);
452 popup[0] = builder.createPopup();
453 Disposer.register(popup[0], usageView);
454 for (AnAction action : filters.getChildren(null)) {
455 action.unregisterCustomShortcutSet(usageView.getComponent());
456 action.registerCustomShortcutSet(action.getShortcutSet(), popup[0].getContent());
459 final MessageBusConnection messageBusConnection = project.getMessageBus().connect(usageView);
460 messageBusConnection.subscribe(UsageFilteringRuleProvider.RULES_CHANGED, new Runnable() {
461 public void run() {
462 rebuildPopup(usageView, usages, table, popup[0]);
466 return popup[0];
469 private static int setModel(JTable table, List<Usage> usages, Collection<UsageNode> visibleNodes, UsageViewImpl usageView,
470 final Vector<Object> data) {
471 if (visibleNodes.isEmpty()) {
472 data.add(UsageViewBundle.message("usages.were.filtered.out", usages.size()));
474 else {
475 data.addAll(visibleNodes);
477 Collections.sort(data, USAGE_COMPARATOR);
478 AbstractTableModel model = new AbstractTableModel() {
479 public int getRowCount() {
480 return data.size();
483 public int getColumnCount() {
484 return data.get(0) instanceof UsageNode ? 3 : 1;
487 public Object getValueAt(int rowIndex, int columnIndex) {
488 return data.get(rowIndex);
491 table.setModel(model);
493 table.setRowHeight(Icons.CLASS_ICON.getIconHeight()+2);
494 table.setShowGrid(false);
495 table.setShowVerticalLines(false);
496 table.setShowHorizontalLines(false);
497 table.setTableHeader(null);
498 table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
499 ShowUsagesTableCellRenderer renderer = new ShowUsagesTableCellRenderer(usageView);
500 for (int i=0;i<table.getColumnModel().getColumnCount();i++) {
501 TableColumn column = table.getColumnModel().getColumn(i);
502 column.setCellRenderer(renderer);
504 table.setIntercellSpacing(new Dimension(0, 0));
506 int colsNum = table.getColumnModel().getColumnCount();
508 int totalWidth = 0;
509 for (int col = 0; col < colsNum -1; col++) {
510 TableColumn column = table.getColumnModel().getColumn(col);
511 int preferred = column.getPreferredWidth();
512 int width = Math.max(preferred, calcMaxWidth(table, col));
513 totalWidth += width;
514 column.setMinWidth(width);
515 column.setMaxWidth(width);
516 column.setWidth(width);
517 column.setPreferredWidth(width);
520 totalWidth += calcMaxWidth(table, colsNum - 1);
522 Dimension dimension = new Dimension(totalWidth, table.getRowHeight() * data.size());
523 table.setMinimumSize(dimension);
524 table.setSize(dimension);
525 table.setPreferredSize(dimension);
526 table.setMaximumSize(dimension);
527 table.setPreferredScrollableViewportSize(dimension);
529 return totalWidth;
532 private static int calcMaxWidth(JTable table, int col) {
533 TableColumn column = table.getColumnModel().getColumn(col);
534 int width = 0;
535 for (int row = 0; row < table.getRowCount(); row++) {
536 Component component = table.prepareRenderer(column.getCellRenderer(), row, col);
538 int rendererWidth = component.getPreferredSize().width;
539 width = Math.max(width, rendererWidth + table.getIntercellSpacing().width);
541 return width;
544 private int myWidth;
545 private void rebuildPopup(final UsageViewImpl usageView, final List<Usage> usages, final JTable table, final JBPopup popup) {
546 SwingUtilities.invokeLater(new Runnable() {
547 public void run() {
548 JComponent content = popup.getContent();
549 Window window = SwingUtilities.windowForComponent(content);
550 Dimension d = window.getSize();
552 final List<UsageNode> nodes = new ArrayList<UsageNode>();
553 addUsageNodes(usageView.getRoot(), usageView, nodes);
555 int old = table.getModel().getRowCount();
556 Vector<Object> data = new Vector<Object>();
557 int width = setModel(table, usages, nodes, usageView, data);
560 if (myWidth == -1) myWidth = width;
561 Dimension newDim = new Dimension(Math.max(width, d.width + width - myWidth), d.height + (data.size() - old) * table.getRowHeight());
562 myWidth = width;
563 window.setSize(newDim);
564 window.validate();
565 window.repaint();
566 table.revalidate();
567 table.repaint();
572 private void appendMoreUsages(Editor editor, RelativePoint popupPosition, FindUsagesHandler handler, int maxUsages) {
573 showElementUsages(handler, editor, popupPosition, maxUsages+USAGES_PAGE_SIZE);
576 private static KeyboardShortcut getSettingsShortcut() {
577 AnAction action = ActionManager.getInstance().getAction("ShowUsagesSettings");
578 final ShortcutSet shortcutSet = action.getShortcutSet();
579 final Shortcut[] shortcuts = shortcutSet.getShortcuts();
580 for (final Shortcut shortcut : shortcuts) {
581 KeyboardShortcut kb = (KeyboardShortcut)shortcut;
582 if (kb.getSecondKeyStroke() == null) {
583 return (KeyboardShortcut)shortcut;
587 return null;
591 private static void addUsageNodes(GroupNode root, final UsageViewImpl usageView, List<UsageNode> outNodes) {
592 for (UsageNode node : root.getUsageNodes()) {
593 Usage usage = node.getUsage();
594 if (usageView.isVisible(usage)) {
595 node.setParent(root);
596 outNodes.add(node);
599 for (GroupNode groupNode : root.getSubGroups()) {
600 groupNode.setParent(root);
601 addUsageNodes(groupNode, usageView, outNodes);
605 public void update(AnActionEvent e){
606 FindUsagesInFileAction.updateFindUsagesAction(e);
609 private void navigateAndHint(Usage usage, final String hint, final FindUsagesHandler handler,
610 final RelativePoint popupPosition,
611 final int maxUsages) {
612 usage.navigate(true);
613 if (hint == null) return;
614 FileEditorLocation location = usage.getLocation();
615 FileEditor newFileEditor = location == null ? null : location.getEditor();
616 final Editor newEditor = newFileEditor instanceof TextEditor ? ((TextEditor)newFileEditor).getEditor() : null;
617 if (newEditor != null) {
618 final Project project = handler.getProject();
619 //opening editor is performing in invokeLater
620 IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() {
621 public void run() {
622 newEditor.getScrollingModel().runActionOnScrollingFinished(new Runnable() {
623 public void run() {
624 // after new editor created, some editor resizing events are still bubbling. To prevent hiding hint, invokeLater this
625 IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() {
626 public void run() {
627 showHint(hint, newEditor, popupPosition, handler, maxUsages);
637 static class MyTable extends Table implements DataProvider {
638 @Override
639 public boolean getScrollableTracksViewportWidth() {
640 return true;
643 public Object getData(@NonNls String dataId) {
644 if (LangDataKeys.PSI_ELEMENT.is(dataId)) {
645 final int[] selected = getSelectedRows();
646 if (selected.length == 1) {
647 final Object at = getValueAt(selected[0], 0);
648 if (at instanceof UsageNode) {
649 final Usage usage = ((UsageNode)at).getUsage();
650 if (usage instanceof UsageInfo2UsageAdapter) {
651 final PsiElement element = ((UsageInfo2UsageAdapter)usage).getElement();
652 if (element != null) {
653 final PsiElement view = UsageToPsiElementProvider.findAppropriateParentFrom(element);
654 return view == null ? element : view;
660 return null;