diff --git a/resources/src/idea/ActionManager.xml b/resources/src/idea/ActionManager.xml
index af7cd24ded5f..57e33f0ef99a 100644
--- a/resources/src/idea/ActionManager.xml
+++ b/resources/src/idea/ActionManager.xml
@@ -243,6 +243,8 @@
+
+
diff --git a/resources/src/idea/DefaultKeymap.xml b/resources/src/idea/DefaultKeymap.xml
index 8bb15d966d93..95ebd0118a12 100644
--- a/resources/src/idea/DefaultKeymap.xml
+++ b/resources/src/idea/DefaultKeymap.xml
@@ -457,6 +457,12 @@
+
+
+
+
+
+
diff --git a/source/com/intellij/ide/actions/CopyReferenceAction.java b/source/com/intellij/ide/actions/CopyReferenceAction.java
new file mode 100644
index 000000000000..0476d146beda
--- /dev/null
+++ b/source/com/intellij/ide/actions/CopyReferenceAction.java
@@ -0,0 +1,94 @@
+/**
+ * @author Alexey
+ */
+package com.intellij.ide.actions;
+
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.DataConstants;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.colors.EditorColors;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.ex.StatusBarEx;
+import com.intellij.openapi.wm.WindowManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.codeInsight.highlighting.HighlightManager;
+
+public class CopyReferenceAction extends AnAction {
+ public void update(AnActionEvent e) {
+ DataContext dataContext = e.getDataContext();
+ Editor editor = (Editor)dataContext.getData(DataConstants.EDITOR);
+ boolean enabled = editor != null;
+ e.getPresentation().setEnabled(enabled);
+ }
+
+ public void actionPerformed(AnActionEvent e) {
+ DataContext dataContext = e.getDataContext();
+ Editor editor = (Editor)dataContext.getData(DataConstants.EDITOR);
+ Project project = (Project)dataContext.getData(DataConstants.PROJECT);
+ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+ PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
+
+ PsiMember member = PsiTreeUtil.getParentOfType(element, PsiMember.class);
+ String fqn;
+ fqn = elementToFqn(member);
+ PropertiesComponent.getInstance(project).setValue("REFERENCE_FQN",fqn);
+
+ final StatusBarEx statusBar = (StatusBarEx)WindowManager.getInstance().getStatusBar(project);
+ statusBar.setInfo("Reference to '"+fqn+"' has been copied.");
+
+ HighlightManager highlightManager = HighlightManager.getInstance(project);
+ EditorColorsManager manager = EditorColorsManager.getInstance();
+ TextAttributes attributes = manager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
+ PsiIdentifier nameIdentifier = member instanceof PsiClass ? ((PsiClass)member).getNameIdentifier() :
+ member instanceof PsiVariable ? ((PsiVariable)member).getNameIdentifier() :
+ ((PsiMethod)member).getNameIdentifier();
+ highlightManager.addOccurrenceHighlights(editor, new PsiElement[]{nameIdentifier}, attributes, true, null);
+ }
+
+ public static String elementToFqn(final PsiElement element) {
+ final String fqn;
+ if (element instanceof PsiClass) {
+ fqn = ((PsiClass)element).getQualifiedName();
+ }
+ else if (element instanceof PsiMember) {
+ final PsiMember member = (PsiMember)element;
+ fqn = member.getContainingClass().getQualifiedName() + "#" + member.getName();
+ }
+ else if (element instanceof PsiFile) {
+ final PsiFile file = (PsiFile)element;
+ final VirtualFile virtualFile = file.getVirtualFile();
+ fqn = virtualFile == null ? file.getName() : FileUtil.toSystemDependentName(virtualFile.getPath());
+ }
+ else {
+ fqn = element.getClass().getName();
+ }
+ return fqn;
+ }
+
+ static PsiMember fqnToMember(final Project project, final String fqn) {
+ PsiClass aClass = PsiManager.getInstance(project).findClass(fqn, GlobalSearchScope.allScope(project));
+ PsiMember member;
+ if (aClass != null) {
+ member = aClass;
+ }
+ else {
+ String className = fqn.substring(0, fqn.indexOf("#"));
+ aClass = PsiManager.getInstance(project).findClass(className, GlobalSearchScope.allScope(project));
+ String memberName = fqn.substring(fqn.indexOf("#") + 1);
+ member = aClass.findFieldByName(memberName, false);
+ if (member == null) {
+ member = aClass.findMethodsByName(memberName, false)[0];
+ }
+ }
+ return member;
+ }
+}
diff --git a/source/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/source/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
index c82a49e77ae7..42ffbf344040 100644
--- a/source/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
+++ b/source/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
@@ -1,9 +1,13 @@
package com.intellij.ide.util.gotoByName;
+import com.intellij.ide.DataManager;
+import com.intellij.ide.actions.CopyReferenceAction;
+import com.intellij.ide.actions.PasteReferenceAction;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.keymap.KeymapManager;
@@ -52,8 +56,8 @@ public abstract class ChooseByNameBase{
protected JScrollPane myListScrollPane; // Located in the layered pane
protected JList myList;
private DefaultListModel myListModel;
- private ArrayList> myHistory;
- private ArrayList> myFuture;
+ private List> myHistory;
+ private List> myFuture;
protected ChooseByNamePopupComponent.Callback myActionListener;
@@ -70,6 +74,7 @@ public abstract class ChooseByNameBase{
private static final String NOT_FOUND_CARD = "nfound";
private static final String CHECK_BOX_CARD = "chkbox";
static final int REBUILD_DELAY = 100;
+ private Editor myEditor;
private static class IgnoreCaseComparator implements Comparator {
public int compare(String a, String b) {
@@ -79,8 +84,6 @@ public abstract class ChooseByNameBase{
private static final Comparator UCS_COMPARATOR = new IgnoreCaseComparator();
-
-
/**
* @param initialText initial text which will be in the lookup text field
*/
@@ -114,7 +117,6 @@ public abstract class ChooseByNameBase{
return element;
}
}
-
return null;
}
@@ -161,8 +163,9 @@ public abstract class ChooseByNameBase{
* @param allowMultipleSelection
*/
protected void initUI(final ChooseByNamePopupComponent.Callback callback, final ModalityState modalityState, boolean allowMultipleSelection) {
+ myPreviouslyFocusedComponent = WindowManagerEx.getInstanceEx().getFocusedComponent(myProject);
+
myActionListener = callback;
- //myTextFieldPanel = new JPanelProvider(new GridBagLayout());
myTextFieldPanel = new JPanelProvider();
myTextFieldPanel.setLayout(new BoxLayout(myTextFieldPanel, BoxLayout.Y_AXIS));
final JPanel hBox = new JPanel();
@@ -181,11 +184,11 @@ public abstract class ChooseByNameBase{
checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel, BoxLayout.X_AXIS));
checkBoxPanel.add (new JLabel (" ("));
- myCheckBox = new JCheckBox(myModel.getCheckBoxName() + " )");
+ myCheckBox = new JCheckBox(myModel.getCheckBoxName());
myCheckBox.setMnemonic(myModel.getCheckBoxMnemonic());
myCheckBox.setSelected(myModel.loadInitialCheckBoxState());
checkBoxPanel.add (myCheckBox);
-
+ checkBoxPanel.add (new JLabel (")"));
myCardContainer.add(checkBoxPanel, CHECK_BOX_CARD);
myCardContainer.add(new JLabel(" (" + myModel.getNotInMessage() + ")"), NOT_FOUND_MESSAGE_CARD);
@@ -213,12 +216,20 @@ public abstract class ChooseByNameBase{
myTextField = new MyTextField();
myTextField.setText(myInitialText);
+ myEditor = (Editor)DataManager.getInstance().getDataContext(myPreviouslyFocusedComponent).getData(DataConstants.EDITOR);
+ if (myEditor != null) {
+ myTextField.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.EMPTY_SET);
+ final JPanel p = new JPanel(new BorderLayout());
+ final JLabel label = new JLabel("Press TAB to paste the reference into editor.");
+ label.setHorizontalAlignment(SwingConstants.CENTER);
+ p.add(label, BorderLayout.CENTER);
+ myTextFieldPanel.add(p);
+ }
+
+ myTextFieldPanel.add(myTextField);
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
Font editorFont = new Font(scheme.getEditorFontName(), Font.PLAIN, scheme.getEditorFontSize());
myTextField.setFont(editorFont);
- myTextFieldPanel.add(myTextField,
- new GridBagConstraints(0, 1, 3, 1, 1, 0, GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL,
- new Insets(0, 0, 0, 0), 0, 0));
if (isCloseByFocusLost()) {
myTextField.addFocusListener(new FocusAdapter() {
@@ -248,26 +259,33 @@ public abstract class ChooseByNameBase{
myTextField.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
- if (myListScrollPane.isVisible()) {
- if (e.getKeyCode() == KeyEvent.VK_DOWN) {
+ if (!myListScrollPane.isVisible()) {
+ return;
+ }
+ final int keyCode = e.getKeyCode();
+ switch (keyCode) {
+ case KeyEvent.VK_TAB:
+ insertElement();
+ break;
+ case KeyEvent.VK_DOWN:
ListScrollingUtilEx.moveDown(myList, e.getModifiersEx());
- }
- else if (e.getKeyCode() == KeyEvent.VK_UP) {
+ break;
+ case KeyEvent.VK_UP:
ListScrollingUtilEx.moveUp(myList, e.getModifiersEx());
- }
- else if (e.getKeyCode() == KeyEvent.VK_PAGE_UP) {
+ break;
+ case KeyEvent.VK_PAGE_UP:
ListScrollingUtil.movePageUp(myList);
- }
- else if (e.getKeyCode() == KeyEvent.VK_PAGE_DOWN) {
+ break;
+ case KeyEvent.VK_PAGE_DOWN:
ListScrollingUtil.movePageDown(myList);
- }
- else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
- if (myList.getSelectedValue() instanceof ExtraElem) {
+ break;
+ case KeyEvent.VK_ENTER:
+ if (myList.getSelectedValue() == OUR_EXTRA_ELEMENT) {
myMaximumListSizeLimit += MAXIMUM_LIST_SIZE_LIMIT;
rebuildList(myList.getSelectedIndex(), REBUILD_DELAY, null, ModalityState.current());
e.consume();
}
- }
+ break;
}
}
});
@@ -290,13 +308,14 @@ public abstract class ChooseByNameBase{
}
if (e.getClickCount() == 2) {
- if (myList.getSelectedValue() instanceof ExtraElem) {
+ if (myList.getSelectedValue() == OUR_EXTRA_ELEMENT) {
myMaximumListSizeLimit += MAXIMUM_LIST_SIZE_LIMIT;
rebuildList(myList.getSelectedIndex(), REBUILD_DELAY, null, ModalityState.current());
e.consume();
}
- else
+ else {
close(true);
+ }
}
}
});
@@ -326,6 +345,16 @@ public abstract class ChooseByNameBase{
}
}
+ private void insertElement() {
+ final Object chosenElement = getChosenElement();
+ if (!(chosenElement instanceof PsiElement)) return;
+ if (myEditor == null) return;
+ final PsiElement element = (PsiElement)chosenElement;
+ final String fqn = CopyReferenceAction.elementToFqn(element);
+ PasteReferenceAction.doInsert(fqn, element, myEditor);
+ close(false);
+ }
+
private synchronized void ensureNamesLoaded(boolean checkboxState) {
int index = checkboxState ? 1 : 0;
if (myNames[index] != null) return;
@@ -389,7 +418,6 @@ public abstract class ChooseByNameBase{
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
- myPreviouslyFocusedComponent = WindowManagerEx.getInstanceEx().getFocusedComponent(myProject);
if (myTextField.requestFocusInWindow()) {
myTextField.requestFocus();
}
@@ -435,7 +463,7 @@ public abstract class ChooseByNameBase{
final Runnable request = this;
LOG.info ("Rebuild " + hashCode() + " started");
final CalcElementsCallback callback = new CalcElementsCallback() {
- public void run(final ArrayList> elements) {
+ public void run(final List> elements) {
synchronized (myRebuildMutex) {
LOG.info ("Rebuild callback " + hashCode() + " of " + request.hashCode() + " started");
ApplicationManager.getApplication().assertIsDispatchThread();
@@ -484,7 +512,7 @@ public abstract class ChooseByNameBase{
}
}
- private void setElementsToList(int pos, ArrayList> elements) {
+ private void setElementsToList(int pos, List> elements) {
if (myDisposedFlag) return;
myListModel.clear();
if (elements.size() == 0) {
@@ -513,7 +541,7 @@ public abstract class ChooseByNameBase{
public Object getChosenElement() {
final Object[] elements = getChosenElements();
- return (elements != null && elements.length == 1) ? elements[0] : null;
+ return elements != null && elements.length == 1 ? elements[0] : null;
}
protected Object[] getChosenElements() {
@@ -574,11 +602,9 @@ public abstract class ChooseByNameBase{
}
protected void processKeyEvent(KeyEvent e) {
- {
- final int caretPosition = getCaretPosition();
- if (getCaretPosition() < myExactPrefixLen) {
- myExactPrefixLen = caretPosition;
- }
+ final int caretPosition = getCaretPosition();
+ if (getCaretPosition() < myExactPrefixLen) {
+ myExactPrefixLen = caretPosition;
}
final KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e);
@@ -601,13 +627,10 @@ public abstract class ChooseByNameBase{
if (myHistory.size() != 0) {
final String oldText = myTextField.getText();
final int oldPos = myList.getSelectedIndex();
- //final String pattern = myTextField.getText();
- //final Object current = myList.getSelectedValue();
final Pair last = myHistory.remove(myHistory.size() - 1);
myTextField.setText(last.first);
myFuture.add(Pair.create(oldText, new Integer(oldPos)));
rebuildList(0, 0, null, ModalityState.current());
- //myList.setSelectedIndex(last.second.intValue());
}
return;
}
@@ -620,7 +643,6 @@ public abstract class ChooseByNameBase{
myTextField.setText(next.first);
myHistory.add(Pair.create(oldText, new Integer(oldPos)));
rebuildList(0, 0, null, ModalityState.current());
- //myList.setSelectedIndex(next.second.intValue());
}
return;
}
@@ -636,36 +658,35 @@ public abstract class ChooseByNameBase{
final int oldPos = myList.getSelectedIndex();
final String newPattern;
- {
- String commonPrefix = null;
- if (list.size() != 0) {
- for (int i = 0; i < list.size(); i++) {
- final String string = list.get(i).toLowerCase();
- if (commonPrefix == null) {
- commonPrefix = string;
- }
- else {
- while (commonPrefix.length() > 0) {
- if (string.startsWith(commonPrefix)) {
- break;
- }
- commonPrefix = commonPrefix.substring(0, commonPrefix.length() - 1);
- }
- if (commonPrefix.length() == 0) break;
- }
+ String commonPrefix = null;
+ if (list.size() != 0) {
+ for (int i = 0; i < list.size(); i++) {
+ final String string = list.get(i).toLowerCase();
+ if (commonPrefix == null) {
+ commonPrefix = string;
}
- commonPrefix = list.get(0).substring(0, commonPrefix.length());
- for (int i = 1; i < list.size(); i++) {
- final String string = list.get(i).substring(0, commonPrefix.length());
- if (!string.equals(commonPrefix)) {
- commonPrefix = commonPrefix.toLowerCase();
- break;
+ else {
+ while (commonPrefix.length() > 0) {
+ if (string.startsWith(commonPrefix)) {
+ break;
+ }
+ commonPrefix = commonPrefix.substring(0, commonPrefix.length() - 1);
}
+ if (commonPrefix.length() == 0) break;
+ }
+ }
+ commonPrefix = list.get(0).substring(0, commonPrefix.length());
+ for (int i = 1; i < list.size(); i++) {
+ final String string = list.get(i).substring(0, commonPrefix.length());
+ if (!string.equals(commonPrefix)) {
+ commonPrefix = commonPrefix.toLowerCase();
+ break;
}
}
- if (commonPrefix == null) commonPrefix = "";
- newPattern = commonPrefix;
}
+ if (commonPrefix == null) commonPrefix = "";
+ newPattern = commonPrefix;
+
myHistory.add(Pair.create(oldText, new Integer(oldPos)));
myTextField.setText(newPattern);
myTextField.setCaretPosition(newPattern.length());
@@ -685,13 +706,10 @@ public abstract class ChooseByNameBase{
private final CalcElementsCallback myCallback;
private final ModalityState myModalityState;
- //private boolean myIsTooLong;
- private ArrayList> myElements = null;
+ private List