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
;
69 import javax
.swing
.table
.AbstractTableModel
;
70 import javax
.swing
.table
.TableColumn
;
72 import java
.awt
.event
.ActionEvent
;
73 import java
.awt
.event
.ActionListener
;
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
);
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() {
110 public ShowUsagesAction() {
111 setInjectedContext(true);
112 showSettingsDialogBefore
= false;
115 public static class ShowSettings
extends ShowUsagesAction
{
116 public ShowSettings() {
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;
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
);
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
);
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
);
202 if (visibleNodes
.size() == maxUsages
) {
203 usageView
.removeUsage(usage
);
204 visibleNodes
.add(UsageViewImpl
.NULL_NODE
);
207 visibleNodes
.add(node
);
214 FindUsagesManager findUsagesManager
= ((FindManagerImpl
)FindManager
.getInstance(handler
.getProject())).getFindUsagesManager();
215 presentation
= findUsagesManager
.processUsages(handler
, collect
);
216 if (presentation
== null) {
217 Disposer
.dispose(usageView
);
220 final String title
= presentation
.getTabText();
222 JBPopup popup
= createUsagePopup(usages
, visibleNodes
, title
, handler
, editor
, popupPosition
, maxUsages
, usageView
);
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);
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
,
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
);
255 private InplaceButton
createSettingsButton(final FindUsagesHandler handler
, final RelativePoint popupPosition
,
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() {
268 showDialogAndFindUsages(handler
, popupPosition
, editor
, maxUsages
);
276 private void showDialogAndFindUsages(FindUsagesHandler handler
, RelativePoint popupPosition
, Editor editor
, int maxUsages
) {
277 AbstractFindUsagesDialog dialog
= handler
.getFindUsagesDialog(false, false, false);
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
,
294 final FindUsagesHandler handler
,
296 final RelativePoint popupPosition
,
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
);
311 // all usages filtered out
314 if (visibleNodes
.size() == 1 && usages
.size() == 1) {
316 Usage usage
= visibleNodes
.iterator().next().getUsage();
317 navigateAndHint(usage
, UsageViewBundle
.message("show.usages.only.usage", searchScopePresentableName(handler
)), handler
, popupPosition
,
319 Disposer
.dispose(usageView
);
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
);
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() {
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
);
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
);
379 table
.getSelectionModel().setSelectionInterval(i
, i
);
382 speedSearch
.setComparator(new SpeedSearchBase
.SpeedSearchComparator(false));
384 PopupChooserBuilder builder
= new PopupChooserBuilder(table
);
388 s
= "<html><body><b>Some</b> " + title
+ " " + "<b>(Only " + (visibleNodes
.size() - 1) + " usages shown)</b></body></html>";
391 s
= title
+ " (" + usages
.size() + " usages found)";
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
) {
402 SwingUtilities
.invokeLater(new Runnable() {
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() {
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());
433 public void actionPerformed(AnActionEvent e
) {
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() {
462 rebuildPopup(usageView
, usages
, table
, 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()));
475 data
.addAll(visibleNodes
);
477 Collections
.sort(data
, USAGE_COMPARATOR
);
478 AbstractTableModel model
= new AbstractTableModel() {
479 public int getRowCount() {
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();
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
));
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
);
532 private static int calcMaxWidth(JTable table
, int col
) {
533 TableColumn column
= table
.getColumnModel().getColumn(col
);
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
);
545 private void rebuildPopup(final UsageViewImpl usageView
, final List
<Usage
> usages
, final JTable table
, final JBPopup popup
) {
546 SwingUtilities
.invokeLater(new Runnable() {
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());
563 window
.setSize(newDim
);
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
;
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
);
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() {
622 newEditor
.getScrollingModel().runActionOnScrollingFinished(new Runnable() {
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() {
627 showHint(hint
, newEditor
, popupPosition
, handler
, maxUsages
);
637 static class MyTable
extends Table
implements DataProvider
{
639 public boolean getScrollableTracksViewportWidth() {
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
;