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
.actionSystem
.ex
.ActionManagerEx
;
30 import com
.intellij
.openapi
.editor
.Editor
;
31 import com
.intellij
.openapi
.fileEditor
.FileEditor
;
32 import com
.intellij
.openapi
.fileEditor
.FileEditorLocation
;
33 import com
.intellij
.openapi
.fileEditor
.TextEditor
;
34 import com
.intellij
.openapi
.keymap
.KeymapUtil
;
35 import com
.intellij
.openapi
.project
.Project
;
36 import com
.intellij
.openapi
.ui
.popup
.JBPopup
;
37 import com
.intellij
.openapi
.ui
.popup
.JBPopupFactory
;
38 import com
.intellij
.openapi
.ui
.popup
.PopupChooserBuilder
;
39 import com
.intellij
.openapi
.util
.Comparing
;
40 import com
.intellij
.openapi
.util
.Disposer
;
41 import com
.intellij
.openapi
.util
.IconLoader
;
42 import com
.intellij
.openapi
.vfs
.VirtualFile
;
43 import com
.intellij
.openapi
.wm
.IdeFocusManager
;
44 import com
.intellij
.psi
.PsiDocumentManager
;
45 import com
.intellij
.psi
.PsiElement
;
46 import com
.intellij
.psi
.SmartPointerManager
;
47 import com
.intellij
.psi
.SmartPsiElementPointer
;
48 import com
.intellij
.psi
.search
.ProjectScope
;
49 import com
.intellij
.psi
.search
.PsiElementProcessor
;
50 import com
.intellij
.psi
.search
.SearchScope
;
51 import com
.intellij
.ui
.InplaceButton
;
52 import com
.intellij
.ui
.SpeedSearchBase
;
53 import com
.intellij
.ui
.TableScrollingUtil
;
54 import com
.intellij
.ui
.awt
.RelativePoint
;
55 import com
.intellij
.usageView
.UsageViewBundle
;
56 import com
.intellij
.usages
.*;
57 import com
.intellij
.usages
.impl
.GroupNode
;
58 import com
.intellij
.usages
.impl
.NullUsage
;
59 import com
.intellij
.usages
.impl
.UsageNode
;
60 import com
.intellij
.usages
.impl
.UsageViewImpl
;
61 import com
.intellij
.usages
.rules
.UsageFilteringRuleProvider
;
62 import com
.intellij
.util
.Icons
;
63 import com
.intellij
.util
.Processor
;
64 import com
.intellij
.util
.messages
.MessageBusConnection
;
65 import com
.intellij
.util
.ui
.Table
;
66 import org
.jetbrains
.annotations
.NonNls
;
67 import org
.jetbrains
.annotations
.NotNull
;
70 import javax
.swing
.table
.AbstractTableModel
;
71 import javax
.swing
.table
.TableColumn
;
73 import java
.awt
.event
.ActionEvent
;
74 import java
.awt
.event
.ActionListener
;
76 import java
.util
.List
;
78 public class ShowUsagesAction
extends AnAction
{
79 private final boolean showSettingsDialogBefore
;
81 private static final int USAGES_PAGE_SIZE
= 100;
82 private static final Comparator
<Object
> USAGE_COMPARATOR
= new Comparator
<Object
>() {
83 public int compare(Object c1
, Object c2
) {
84 Usage o1
= ((UsageNode
)c1
).getUsage();
85 Usage o2
= ((UsageNode
)c2
).getUsage();
86 if (o1
== NullUsage
.INSTANCE
) return 1;
87 if (o2
== NullUsage
.INSTANCE
) return -1;
89 VirtualFile v1
= UsageListCellRenderer
.getVirtualFile(o1
);
90 VirtualFile v2
= UsageListCellRenderer
.getVirtualFile(o2
);
91 String name1
= v1
== null ?
null : v1
.getName();
92 String name2
= v2
== null ?
null : v2
.getName();
93 int i
= Comparing
.compare(name1
, name2
);
96 if (o1
instanceof Comparable
&& o2
instanceof Comparable
) {
97 return ((Comparable
)o1
).compareTo(o2
);
100 FileEditorLocation loc1
= o1
.getLocation();
101 FileEditorLocation loc2
= o2
.getLocation();
102 return Comparing
.compare(loc1
, loc2
);
105 private static final Runnable HIDE_HINTS_ACTION
= new Runnable() {
111 public ShowUsagesAction() {
112 setInjectedContext(true);
113 showSettingsDialogBefore
= false;
116 public static class ShowSettings
extends ShowUsagesAction
{
117 public ShowSettings() {
122 private ShowUsagesAction(boolean showDialogBefore
) {
123 setInjectedContext(true);
124 showSettingsDialogBefore
= showDialogBefore
;
127 public void actionPerformed(AnActionEvent e
) {
128 final Project project
= e
.getData(PlatformDataKeys
.PROJECT
);
129 if (project
== null) return;
132 final RelativePoint popupPosition
= JBPopupFactory
.getInstance().guessBestPopupLocation(e
.getDataContext());
133 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
134 FeatureUsageTracker
.getInstance().triggerFeatureUsed("navigation.goto.usages");
136 UsageTarget
[] usageTargets
= e
.getData(UsageView
.USAGE_TARGETS_KEY
);
137 final Editor editor
= e
.getData(PlatformDataKeys
.EDITOR
);
138 if (usageTargets
== null) {
139 FindUsagesAction
.chooseAmbiguousTargetAndPerform(project
, editor
, new PsiElementProcessor
<PsiElement
>() {
140 public boolean execute(final PsiElement element
) {
141 startFindUsages(element
, popupPosition
, editor
, USAGES_PAGE_SIZE
);
147 PsiElement element
= ((PsiElementUsageTarget
)usageTargets
[0]).getElement();
148 if (element
!= null) {
149 startFindUsages(element
, popupPosition
, editor
, USAGES_PAGE_SIZE
);
154 private static void hideHints() {
155 HintManager
.getInstance().hideHints(HintManager
.HIDE_BY_ANY_KEY
, false, false);
158 private void startFindUsages(@NotNull PsiElement element
, RelativePoint popupPosition
, Editor editor
, int maxUsages
) {
159 Project project
= element
.getProject();
160 FindUsagesManager findUsagesManager
= ((FindManagerImpl
)FindManager
.getInstance(project
)).getFindUsagesManager();
161 FindUsagesHandler handler
= findUsagesManager
.getFindUsagesHandler(element
, false);
162 if (handler
== null) return;
163 if (showSettingsDialogBefore
) {
164 showDialogAndFindUsages(handler
, popupPosition
, editor
, maxUsages
);
167 showElementUsages(handler
, editor
, popupPosition
, maxUsages
);
170 private void showElementUsages(@NotNull FindUsagesHandler handler
, final Editor editor
, final RelativePoint popupPosition
, final int maxUsages
) {
171 UsageViewPresentation presentation
= new UsageViewPresentation();
172 presentation
.setDetachedMode(true);
174 final UsageViewSettings usageViewSettings
= UsageViewSettings
.getInstance();
175 final UsageViewSettings save
= new UsageViewSettings();
177 save
.loadState(usageViewSettings
);
178 usageViewSettings
.GROUP_BY_FILE_STRUCTURE
= false;
179 usageViewSettings
.GROUP_BY_MODULE
= false;
180 usageViewSettings
.GROUP_BY_PACKAGE
= false;
181 usageViewSettings
.GROUP_BY_USAGE_TYPE
= false;
183 UsageViewManager manager
= UsageViewManager
.getInstance(handler
.getProject());
184 final UsageViewImpl usageView
= (UsageViewImpl
)manager
.createUsageView(UsageTarget
.EMPTY_ARRAY
, Usage
.EMPTY_ARRAY
, presentation
, null);
186 Disposer
.register(usageView
, new Disposable() {
187 public void dispose() {
188 usageViewSettings
.GROUP_BY_FILE_STRUCTURE
= save
.GROUP_BY_FILE_STRUCTURE
;
189 usageViewSettings
.GROUP_BY_MODULE
= save
.GROUP_BY_MODULE
;
190 usageViewSettings
.GROUP_BY_PACKAGE
= save
.GROUP_BY_PACKAGE
;
191 usageViewSettings
.GROUP_BY_USAGE_TYPE
= save
.GROUP_BY_USAGE_TYPE
;
195 final List
<Usage
> usages
= new ArrayList
<Usage
>();
196 final Set
<UsageNode
> visibleNodes
= new LinkedHashSet
<UsageNode
>();
197 Processor
<Usage
> collect
= new Processor
<Usage
>() {
198 public boolean process(@NotNull Usage usage
) {
199 synchronized (usages
) {
200 if (visibleNodes
.size() > maxUsages
) return false;
201 UsageNode node
= usageView
.doAppendUsage(usage
);
203 if (visibleNodes
.size() == maxUsages
) {
204 usageView
.removeUsage(usage
);
205 visibleNodes
.add(UsageViewImpl
.NULL_NODE
);
208 visibleNodes
.add(node
);
215 FindUsagesManager findUsagesManager
= ((FindManagerImpl
)FindManager
.getInstance(handler
.getProject())).getFindUsagesManager();
216 presentation
= findUsagesManager
.processUsages(handler
, collect
);
217 if (presentation
== null) {
218 Disposer
.dispose(usageView
);
221 final String title
= presentation
.getTabText();
223 JBPopup popup
= createUsagePopup(usages
, visibleNodes
, title
, handler
, editor
, popupPosition
, maxUsages
, usageView
);
225 popup
.show(popupPosition
);
229 private void showHint(String text
, final Editor editor
, final RelativePoint popupPosition
, FindUsagesHandler handler
, int maxUsages
) {
230 JComponent label
= createHintComponent(text
, handler
, popupPosition
, editor
, HIDE_HINTS_ACTION
, maxUsages
);
231 if (editor
== null) {
232 HintManager
.getInstance().showHint(label
, popupPosition
, HintManager
.HIDE_BY_ANY_KEY
|
233 HintManager
.HIDE_BY_TEXT_CHANGE
| HintManager
.HIDE_BY_SCROLLING
, 0);
236 HintManager
.getInstance().showInformationHint(editor
, label
);
240 private JComponent
createHintComponent(String text
, final FindUsagesHandler handler
, final RelativePoint popupPosition
, final Editor editor
,
241 final Runnable cancelAction
,
243 JLabel label
= HintUtil
.createInformationLabel(text
);
244 InplaceButton button
= createSettingsButton(handler
, popupPosition
, editor
, maxUsages
, cancelAction
);
245 JPanel panel
= new JPanel(new BorderLayout());
246 button
.setBackground(label
.getBackground());
247 panel
.setBackground(label
.getBackground());
248 label
.setOpaque(false);
249 label
.setBorder(null);
250 panel
.setBorder(HintUtil
.createHintBorder());
251 panel
.add(label
, BorderLayout
.CENTER
);
252 panel
.add(button
, BorderLayout
.EAST
);
256 private InplaceButton
createSettingsButton(final FindUsagesHandler handler
, final RelativePoint popupPosition
,
259 final Runnable cancelAction
) {
260 String shortcutText
= "";
261 KeyboardShortcut shortcut
= getSettingsShortcut();
262 if (shortcut
!= null) {
263 shortcutText
= "(" + KeymapUtil
.getShortcutText(shortcut
) + ")";
265 return new InplaceButton("Options..." + shortcutText
, IconLoader
.getIcon("/general/ideOptions.png"), new ActionListener() {
266 public void actionPerformed(ActionEvent e
) {
267 SwingUtilities
.invokeLater(new Runnable() {
269 showDialogAndFindUsages(handler
, popupPosition
, editor
, maxUsages
);
277 private void showDialogAndFindUsages(FindUsagesHandler handler
, RelativePoint popupPosition
, Editor editor
, int maxUsages
) {
278 AbstractFindUsagesDialog dialog
= handler
.getFindUsagesDialog(false, false, false);
281 dialog
.calcFindUsagesOptions();
282 showElementUsages(handler
, editor
, popupPosition
, maxUsages
);
286 private static String
searchScopePresentableName(final FindUsagesHandler handler
) {
287 SearchScope searchScope
= FindUsagesManager
.getCurrentSearchScope(handler
);
288 if (searchScope
== null) searchScope
= ProjectScope
.getAllScope(handler
.getProject());
289 return searchScope
.getDisplayName();
292 private JBPopup
createUsagePopup(final List
<Usage
> usages
,
293 Set
<UsageNode
> visibleNodes
,
295 final FindUsagesHandler handler
,
297 final RelativePoint popupPosition
,
299 final UsageViewImpl usageView
) {
300 boolean hasMore
= visibleNodes
.remove(UsageViewImpl
.NULL_NODE
);
302 final Project project
= handler
.getProject();
304 if (visibleNodes
.isEmpty()) {
305 if (usages
.isEmpty()) {
306 String text
= UsageViewBundle
.message("no.usages.found.in", searchScopePresentableName(handler
));
307 showHint(text
, editor
, popupPosition
, handler
, maxUsages
);
308 Disposer
.dispose(usageView
);
312 // all usages filtered out
315 if (visibleNodes
.size() == 1 && usages
.size() == 1) {
317 Usage usage
= visibleNodes
.iterator().next().getUsage();
318 navigateAndHint(usage
, UsageViewBundle
.message("show.usages.only.usage", searchScopePresentableName(handler
)), handler
, popupPosition
,
320 Disposer
.dispose(usageView
);
323 if (visibleNodes
.size() == 1 && usages
.size() >= 1) {
324 // usage view can filter usages down to one
325 Usage usage
= visibleNodes
.iterator().next().getUsage();
326 navigateAndHint(usage
, UsageViewBundle
.message("all.usages.are.in.this.line", usages
.size(), searchScopePresentableName(handler
)),
327 handler
, popupPosition
, maxUsages
);
328 Disposer
.dispose(usageView
);
333 usages
.add(NullUsage
.INSTANCE
);
334 visibleNodes
.add(UsageViewImpl
.NULL_NODE
);
336 addUsageNodes(usageView
.getRoot(), usageView
, new ArrayList
<UsageNode
>());
339 final JTable table
= new MyTable();
340 TableScrollingUtil
.installActions(table
);
341 final Vector
<Object
> data
= new Vector
<Object
>();
342 setModel(table
, usages
, visibleNodes
, usageView
, data
);
344 final Runnable navigateRunnable
= new Runnable() {
346 int[] selected
= table
.getSelectedRows();
347 for (int i
: selected
) {
348 Object value
= table
.getValueAt(i
,0);
349 if (value
instanceof UsageNode
) {
350 Usage usage
= ((UsageNode
)value
).getUsage();
351 if (usage
== NullUsage
.INSTANCE
) {
352 appendMoreUsages(editor
, popupPosition
, handler
, maxUsages
);
355 navigateAndHint(usage
, null, handler
, popupPosition
, maxUsages
);
361 SpeedSearchBase
<JTable
> speedSearch
= new SpeedSearchBase
<JTable
>(table
) {
362 protected int getSelectedIndex() {
363 return table
.getSelectedRow();
366 protected Object
[] getAllElements() {
367 return data
.toArray(new Object
[data
.size()]);
370 protected String
getElementText(Object element
) {
371 if (!(element
instanceof UsageNode
)) return element
.toString();
372 UsageNode node
= (UsageNode
)element
;
373 GroupNode group
= (GroupNode
)node
.getParent();
374 return node
.getUsage().getPresentation().getPlainText() + group
.toString();
377 protected void selectElement(Object element
, String selectedText
) {
378 int i
= data
.indexOf(element
);
380 table
.getSelectionModel().setSelectionInterval(i
, i
);
383 speedSearch
.setComparator(new SpeedSearchBase
.SpeedSearchComparator(false));
385 PopupChooserBuilder builder
= new PopupChooserBuilder(table
);
389 s
= "<html><body><b>Some</b> " + title
+ " " + "<b>(Only " + (visibleNodes
.size() - 1) + " usages shown)</b></body></html>";
392 s
= title
+ " (" + usages
.size() + " usages found)";
397 builder
.setMovable(true).setResizable(true);
398 builder
.setItemChoosenCallback(navigateRunnable
);
399 final JBPopup
[] popup
= new JBPopup
[1];
400 ActionListener editSettings
= new ActionListener() {
401 public void actionPerformed(ActionEvent e
) {
403 SwingUtilities
.invokeLater(new Runnable() {
405 showDialogAndFindUsages(handler
, popupPosition
, editor
, maxUsages
);
413 KeyboardShortcut shortcut
= getSettingsShortcut();
414 if (shortcut
!= null) {
415 builder
.registerKeyboardAction(shortcut
.getFirstKeyStroke(), editSettings
);
418 InplaceButton button
= createSettingsButton(handler
, popupPosition
, editor
, maxUsages
, new Runnable() {
423 builder
.setCommandButton(button
);
425 DefaultActionGroup filters
= new DefaultActionGroup();
426 usageView
.addFilteringActions(filters
);
428 filters
.add(new AnAction("Open Find Usages Toolwindow", "Show all usages in a separate toolwindow", IconLoader
.getIcon("/general/toolWindowFind.png")) {
430 AnAction action
= ActionManager
.getInstance().getAction(IdeActions
.ACTION_FIND_USAGES
);
431 setShortcutSet(action
.getShortcutSet());
434 public void actionPerformed(AnActionEvent e
) {
437 FindUsagesManager findUsagesManager
= ((FindManagerImpl
)FindManager
.getInstance(project
)).getFindUsagesManager();
438 FindUsagesManager
.SearchData data
= new FindUsagesManager
.SearchData();
439 data
.myOptions
= handler
.getFindUsagesOptions();
440 SmartPsiElementPointer
<PsiElement
> pointer
=
441 SmartPointerManager
.getInstance(project
).createSmartPsiElementPointer(handler
.getPsiElement());
442 data
.myElements
= new SmartPsiElementPointer
[]{pointer
};
443 findUsagesManager
.rerunAndRecallFromHistory(data
);
447 ActionToolbar actionToolbar
= ActionManager
.getInstance().createActionToolbar(ActionPlaces
.USAGE_VIEW_TOOLBAR
, filters
, true);
448 actionToolbar
.setReservePlaceAutoPopupIcon(false);
449 final JComponent toolBar
= actionToolbar
.getComponent();
450 toolBar
.setOpaque(false);
451 builder
.setSettingButton(toolBar
);
453 popup
[0] = builder
.createPopup();
454 Disposer
.register(popup
[0], usageView
);
455 for (AnAction action
: filters
.getChildren(null)) {
456 action
.unregisterCustomShortcutSet(usageView
.getComponent());
457 action
.registerCustomShortcutSet(action
.getShortcutSet(), popup
[0].getContent());
460 final MessageBusConnection messageBusConnection
= project
.getMessageBus().connect(usageView
);
461 messageBusConnection
.subscribe(UsageFilteringRuleProvider
.RULES_CHANGED
, new Runnable() {
463 rebuildPopup(usageView
, usages
, table
, popup
[0]);
470 private static int setModel(JTable table
, List
<Usage
> usages
, Collection
<UsageNode
> visibleNodes
, UsageViewImpl usageView
,
471 final Vector
<Object
> data
) {
472 if (visibleNodes
.isEmpty()) {
473 data
.add(UsageViewBundle
.message("usages.were.filtered.out", usages
.size()));
476 data
.addAll(visibleNodes
);
478 Collections
.sort(data
, USAGE_COMPARATOR
);
479 AbstractTableModel model
= new AbstractTableModel() {
480 public int getRowCount() {
484 public int getColumnCount() {
485 return data
.get(0) instanceof UsageNode ?
3 : 1;
488 public Object
getValueAt(int rowIndex
, int columnIndex
) {
489 return data
.get(rowIndex
);
492 table
.setModel(model
);
494 table
.setRowHeight(Icons
.CLASS_ICON
.getIconHeight()+2);
495 table
.setShowGrid(false);
496 table
.setShowVerticalLines(false);
497 table
.setShowHorizontalLines(false);
498 table
.setTableHeader(null);
499 table
.setAutoResizeMode(JTable
.AUTO_RESIZE_LAST_COLUMN
);
500 ShowUsagesTableCellRenderer renderer
= new ShowUsagesTableCellRenderer(usageView
);
501 for (int i
=0;i
<table
.getColumnModel().getColumnCount();i
++) {
502 TableColumn column
= table
.getColumnModel().getColumn(i
);
503 column
.setCellRenderer(renderer
);
505 table
.setIntercellSpacing(new Dimension(0, 0));
507 int colsNum
= table
.getColumnModel().getColumnCount();
510 for (int col
= 0; col
< colsNum
-1; col
++) {
511 TableColumn column
= table
.getColumnModel().getColumn(col
);
512 int preferred
= column
.getPreferredWidth();
513 int width
= Math
.max(preferred
, calcMaxWidth(table
, col
));
515 column
.setMinWidth(width
);
516 column
.setMaxWidth(width
);
517 column
.setWidth(width
);
518 column
.setPreferredWidth(width
);
521 totalWidth
+= calcMaxWidth(table
, colsNum
- 1);
523 Dimension dimension
= new Dimension(totalWidth
, table
.getRowHeight() * data
.size());
524 table
.setMinimumSize(dimension
);
525 table
.setSize(dimension
);
526 table
.setPreferredSize(dimension
);
527 table
.setMaximumSize(dimension
);
528 table
.setPreferredScrollableViewportSize(dimension
);
533 private static int calcMaxWidth(JTable table
, int col
) {
534 TableColumn column
= table
.getColumnModel().getColumn(col
);
536 for (int row
= 0; row
< table
.getRowCount(); row
++) {
537 Component component
= table
.prepareRenderer(column
.getCellRenderer(), row
, col
);
539 int rendererWidth
= component
.getPreferredSize().width
;
540 width
= Math
.max(width
, rendererWidth
+ table
.getIntercellSpacing().width
);
546 private void rebuildPopup(final UsageViewImpl usageView
, final List
<Usage
> usages
, final JTable table
, final JBPopup popup
) {
547 SwingUtilities
.invokeLater(new Runnable() {
549 JComponent content
= popup
.getContent();
550 Window window
= SwingUtilities
.windowForComponent(content
);
551 Dimension d
= window
.getSize();
553 final List
<UsageNode
> nodes
= new ArrayList
<UsageNode
>();
554 addUsageNodes(usageView
.getRoot(), usageView
, nodes
);
556 int old
= table
.getModel().getRowCount();
557 Vector
<Object
> data
= new Vector
<Object
>();
558 int width
= setModel(table
, usages
, nodes
, usageView
, data
);
561 if (myWidth
== -1) myWidth
= width
;
562 Dimension newDim
= new Dimension(Math
.max(width
, d
.width
+ width
- myWidth
), d
.height
+ (data
.size() - old
) * table
.getRowHeight());
564 window
.setSize(newDim
);
573 private void appendMoreUsages(Editor editor
, RelativePoint popupPosition
, FindUsagesHandler handler
, int maxUsages
) {
574 showElementUsages(handler
, editor
, popupPosition
, maxUsages
+USAGES_PAGE_SIZE
);
577 private static KeyboardShortcut
getSettingsShortcut() {
578 return ActionManagerEx
.getInstanceEx().getKeyboardShortcut("ShowUsagesSettings");
581 private static void addUsageNodes(GroupNode root
, final UsageViewImpl usageView
, List
<UsageNode
> outNodes
) {
582 for (UsageNode node
: root
.getUsageNodes()) {
583 Usage usage
= node
.getUsage();
584 if (usageView
.isVisible(usage
)) {
585 node
.setParent(root
);
589 for (GroupNode groupNode
: root
.getSubGroups()) {
590 groupNode
.setParent(root
);
591 addUsageNodes(groupNode
, usageView
, outNodes
);
595 public void update(AnActionEvent e
){
596 FindUsagesInFileAction
.updateFindUsagesAction(e
);
599 private void navigateAndHint(Usage usage
, final String hint
, final FindUsagesHandler handler
,
600 final RelativePoint popupPosition
,
601 final int maxUsages
) {
602 usage
.navigate(true);
603 if (hint
== null) return;
604 FileEditorLocation location
= usage
.getLocation();
605 FileEditor newFileEditor
= location
== null ?
null : location
.getEditor();
606 final Editor newEditor
= newFileEditor
instanceof TextEditor ?
((TextEditor
)newFileEditor
).getEditor() : null;
607 if (newEditor
!= null) {
608 final Project project
= handler
.getProject();
609 //opening editor is performing in invokeLater
610 IdeFocusManager
.getInstance(project
).doWhenFocusSettlesDown(new Runnable() {
612 newEditor
.getScrollingModel().runActionOnScrollingFinished(new Runnable() {
614 // after new editor created, some editor resizing events are still bubbling. To prevent hiding hint, invokeLater this
615 IdeFocusManager
.getInstance(project
).doWhenFocusSettlesDown(new Runnable() {
617 showHint(hint
, newEditor
, popupPosition
, handler
, maxUsages
);
627 static class MyTable
extends Table
implements DataProvider
{
629 public boolean getScrollableTracksViewportWidth() {
633 public Object
getData(@NonNls String dataId
) {
634 if (LangDataKeys
.PSI_ELEMENT
.is(dataId
)) {
635 final int[] selected
= getSelectedRows();
636 if (selected
.length
== 1) {
637 final Object at
= getValueAt(selected
[0], 0);
638 if (at
instanceof UsageNode
) {
639 final Usage usage
= ((UsageNode
)at
).getUsage();
640 if (usage
instanceof UsageInfo2UsageAdapter
) {
641 final PsiElement element
= ((UsageInfo2UsageAdapter
)usage
).getElement();
642 if (element
!= null) {
643 final PsiElement view
= UsageToPsiElementProvider
.findAppropriateParentFrom(element
);
644 return view
== null ? element
: view
;