mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+1
-1
@@ -1173,7 +1173,7 @@ public class GenericsHighlightUtil {
|
||||
public static HighlightInfo checkEnumMustNotBeLocal(final PsiClass aClass) {
|
||||
if (!aClass.isEnum()) return null;
|
||||
PsiElement parent = aClass.getParent();
|
||||
if (!(parent instanceof PsiClass || parent instanceof PsiFile)) {
|
||||
if (!(parent instanceof PsiClass || parent instanceof PsiFile || parent instanceof PsiClassLevelDeclarationStatement)) {
|
||||
String description = JavaErrorMessages.message("local.enum");
|
||||
TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass);
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create();
|
||||
|
||||
+27
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.reference;
|
||||
|
||||
import com.intellij.codeInsight.ExceptionUtil;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
@@ -30,6 +31,9 @@ import com.intellij.util.VisibilityUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class RefJavaUtilImpl extends RefJavaUtil{
|
||||
|
||||
@Override
|
||||
@@ -114,6 +118,29 @@ public class RefJavaUtilImpl extends RefJavaUtil{
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(aClass);
|
||||
if (interfaceMethod != null) {
|
||||
refFrom.addReference(refFrom.getRefManager().getReference(interfaceMethod), interfaceMethod, psiFrom, false, true, null);
|
||||
|
||||
PsiElement body = null;
|
||||
PsiElement topElement = null;
|
||||
if (expression instanceof PsiLambdaExpression) {
|
||||
body = ((PsiLambdaExpression)expression).getBody();
|
||||
topElement = expression;
|
||||
}
|
||||
else {
|
||||
final PsiElement resolve = ((PsiMethodReferenceExpression)expression).resolve();
|
||||
if (resolve instanceof PsiMethod) {
|
||||
body = ((PsiMethod)resolve).getBody();
|
||||
topElement = resolve;
|
||||
}
|
||||
}
|
||||
|
||||
final Collection<PsiClassType> exceptionTypes = body != null ? ExceptionUtil.collectUnhandledExceptions(body, topElement, false)
|
||||
: Collections.<PsiClassType>emptyList();
|
||||
RefElement refResolved = refFrom.getRefManager().getReference(interfaceMethod);
|
||||
if (refResolved instanceof RefMethodImpl) {
|
||||
for (final PsiClassType exceptionType : exceptionTypes) {
|
||||
((RefMethodImpl)refResolved).updateThrowsList(exceptionType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-4
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion;
|
||||
import com.intellij.codeInsight.generation.*;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.codeInspection.ex.GlobalInspectionContextBase;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
@@ -30,10 +31,7 @@ import com.intellij.util.VisibilityUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
|
||||
@@ -137,6 +135,17 @@ public class JavaGenerateMemberCompletionContributor {
|
||||
List<PsiGenerationInfo<PsiMethod>> newInfos = GenerateMembersUtil
|
||||
.insertMembersAtOffset(context.getFile(), context.getStartOffset(), infos);
|
||||
if (!newInfos.isEmpty()) {
|
||||
final List<PsiElement> elements = new ArrayList<PsiElement>();
|
||||
for (GenerationInfo member : newInfos) {
|
||||
if (!(member instanceof TemplateGenerationInfo)) {
|
||||
final PsiMember psiMember = member.getPsiMember();
|
||||
if (psiMember != null) {
|
||||
elements.add(psiMember);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GlobalInspectionContextBase.cleanupElements(context.getProject(), null, elements.toArray(new PsiElement[elements.size()]));
|
||||
newInfos.get(0).positionCaret(context.getEditor(), true);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -171,8 +171,8 @@ public class AddExceptionToCatchFix extends BaseIntentionAction {
|
||||
if (element == null) return null;
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
final PsiElement parent = PsiTreeUtil.getParentOfType(element, PsiTryStatement.class, PsiMethod.class);
|
||||
if (parent == null || parent instanceof PsiMethod) return null;
|
||||
final PsiElement parent = PsiTreeUtil.getParentOfType(element, PsiTryStatement.class, PsiMethod.class, PsiFunctionalExpression.class);
|
||||
if (parent == null || parent instanceof PsiMethod || parent instanceof PsiFunctionalExpression) return null;
|
||||
final PsiTryStatement statement = (PsiTryStatement) parent;
|
||||
|
||||
final PsiCodeBlock tryBlock = statement.getTryBlock();
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ public class GeneralizeCatchFix implements IntentionAction {
|
||||
myTryStatement = (PsiTryStatement)element.getParent();
|
||||
break;
|
||||
}
|
||||
if (element instanceof PsiMethod || (element instanceof PsiClass && !(element instanceof PsiAnonymousClass))) break;
|
||||
if (element instanceof PsiMethod || element instanceof PsiFunctionalExpression || (element instanceof PsiClass && !(element instanceof PsiAnonymousClass))) break;
|
||||
element = element.getParent();
|
||||
}
|
||||
if (myTryStatement == null) return false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -314,6 +314,10 @@ public class UnscrambleDialog extends DialogWrapper {
|
||||
builder.append(trimSuffix(line)).append("\n");
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith("at breakpoint")) { // possible thread status mixed with "at ..."
|
||||
builder.append(" ").append(trimSuffix(line));
|
||||
continue;
|
||||
}
|
||||
if (!first && mustHaveNewLineBefore(line)) {
|
||||
builder.append("\n");
|
||||
if (line.startsWith("\"")) builder.append("\n"); // Additional line break for thread names
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// "Add 'catch' clause(s)" "true"
|
||||
import java.io.IOException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class C {
|
||||
static Object get() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
void method() {
|
||||
try {
|
||||
Supplier<Object> lambda1 = () -> {
|
||||
try {
|
||||
return C.get();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
};
|
||||
} catch( Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Add 'catch' clause(s)" "false"
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class C {
|
||||
static Object get() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
void method() {
|
||||
try {
|
||||
Supplier<Object> lambda1 = () -> C.ge<caret>t();
|
||||
} catch( Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// "Add 'catch' clause(s)" "true"
|
||||
import java.io.IOException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class C {
|
||||
static Object get() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
void method() {
|
||||
try {
|
||||
Supplier<Object> lambda1 = () -> {
|
||||
try {
|
||||
return C.ge<caret>t();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
};
|
||||
} catch( Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Add 'catch' clause(s)" "false"
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class C {
|
||||
static Object get() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
void method() {
|
||||
try {
|
||||
Supplier<Object> lambda1 = C::g<caret>et;
|
||||
} catch( Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Generalize catch for 'java.lang.Exception' to 'java.lang.Exception'" "false"
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class C {
|
||||
static Object get() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
void method() {
|
||||
try {
|
||||
Supplier<Object> lambda1 = () -> C.ge<caret>t();
|
||||
} catch( Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Generalize catch for 'java.lang.Exception' to 'java.lang.Exception'" "false"
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class C {
|
||||
static Object get() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
void method() {
|
||||
try {
|
||||
Supplier<Object> lambda1 = C::g<caret>et;
|
||||
} catch( Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Foo.java</file>
|
||||
<line>21</line>
|
||||
<description>ObjectStreamException</description>
|
||||
</problem>
|
||||
</problems>
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import java.io.*;
|
||||
|
||||
class ExceptionTest {
|
||||
|
||||
MyFunction method() {
|
||||
return () -> {
|
||||
throw new EOFException();
|
||||
};
|
||||
}
|
||||
|
||||
MyFunction method1() {
|
||||
return this::e;
|
||||
}
|
||||
|
||||
private void e() throws FileNotFoundException {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface MyFunction {
|
||||
void call() throws FileNotFoundException, EOFException, ObjectStreamException;
|
||||
}
|
||||
}
|
||||
+17
@@ -27,6 +27,7 @@ import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings
|
||||
import com.siyeh.ig.style.UnqualifiedFieldAccessInspection
|
||||
|
||||
public class NormalCompletionTest extends LightFixtureCompletionTestCase {
|
||||
@Override
|
||||
@@ -1484,5 +1485,21 @@ class Bar {
|
||||
myFixture.assertPreferredCompletionItems(0, "xcreateZoo", "xcreateElephant");
|
||||
}
|
||||
|
||||
public void "test code cleanup during completion generation"() {
|
||||
myFixture.configureByText "a.java", "class Foo {int i; ge<caret>}"
|
||||
def inspection = new UnqualifiedFieldAccessInspection()
|
||||
try {
|
||||
myFixture.enableInspections(inspection)
|
||||
myFixture.complete(CompletionType.BASIC)
|
||||
myFixture.checkResult '''class Foo {int i;
|
||||
|
||||
public int getI() {
|
||||
return this.i;
|
||||
}
|
||||
}'''
|
||||
}
|
||||
finally {
|
||||
myFixture.disableInspections(inspection)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -1,5 +1,8 @@
|
||||
package com.intellij.codeInsight.daemon.quickFix;
|
||||
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
|
||||
public class AddExceptionToCatchTest extends LightQuickFixParameterizedTestCase {
|
||||
public void test() throws Exception {
|
||||
doAllTests();
|
||||
@@ -9,4 +12,9 @@ public class AddExceptionToCatchTest extends LightQuickFixParameterizedTestCase
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return IdeaTestUtil.getMockJdk18();
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -1,5 +1,8 @@
|
||||
package com.intellij.codeInsight.daemon.quickFix;
|
||||
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
|
||||
public class GeneralizeCatchTest extends LightQuickFixParameterizedTestCase {
|
||||
public void test() throws Exception {
|
||||
doAllTests();
|
||||
@@ -9,4 +12,9 @@ public class GeneralizeCatchTest extends LightQuickFixParameterizedTestCase {
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/generalizeCatch";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return IdeaTestUtil.getMockJdk18();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@ package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInspection.unneededThrows.RedundantThrows;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.InspectionTestCase;
|
||||
|
||||
public class RedundantThrowTest extends InspectionTestCase {
|
||||
@@ -60,4 +64,15 @@ public class RedundantThrowTest extends InspectionTestCase {
|
||||
public void testSelfCall() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testThrownClausesInFunctionalExpressions() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getTestProjectSdk() {
|
||||
Sdk sdk = IdeaTestUtil.getMockJdk17();
|
||||
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_8);
|
||||
return sdk;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -438,7 +438,7 @@ public class GlobalInspectionContextBase extends UserDataHolderBase implements G
|
||||
};
|
||||
|
||||
Application application = ApplicationManager.getApplication();
|
||||
if (application.isWriteAccessAllowed()) {
|
||||
if (application.isWriteAccessAllowed() && !application.isUnitTestMode()) {
|
||||
application.invokeLater(cleanupRunnable);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Collections;
|
||||
@@ -40,6 +41,7 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
private final List<T> myElements = ContainerUtil.newArrayList();
|
||||
private final JPanel myPanel;
|
||||
private final TableView<T> myTableView;
|
||||
private final CommonActionsPanel myActionsPanel;
|
||||
private boolean myIsEnabled = true;
|
||||
|
||||
protected ListTableWithButtons() {
|
||||
@@ -55,6 +57,7 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
final int column = myTableView.getEditingColumn();
|
||||
final int row = myTableView.getEditingRow();
|
||||
if (e.getModifiers() == 0 && (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_TAB)) {
|
||||
e.consume();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -69,6 +72,7 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
nextRow = 0;
|
||||
}
|
||||
}
|
||||
myTableView.scrollRectToVisible(myTableView.getCellRect(nextRow, nextColumn, true));
|
||||
myTableView.editCellAt(nextRow, nextColumn);
|
||||
}
|
||||
});
|
||||
@@ -79,19 +83,24 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
}
|
||||
};
|
||||
myTableView.setRowHeight(new JTextField().getPreferredSize().height);
|
||||
myTableView.setIntercellSpacing(new Dimension(0, 0));
|
||||
myTableView.setStriped(true);
|
||||
|
||||
myTableView.getTableViewModel().setSortable(false);
|
||||
myPanel = ToolbarDecorator.createDecorator(myTableView)
|
||||
ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTableView);
|
||||
myPanel = decorator
|
||||
.setAddAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
if (!myElements.isEmpty() && isEmpty(myElements.get(myElements.size() - 1))) return;
|
||||
myTableView.stopEditing();
|
||||
setModified();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myElements.add(createElement());
|
||||
myTableView.getTableViewModel().setItems(myElements);
|
||||
if (myElements.isEmpty() || !isEmpty(myElements.get(myElements.size() - 1))) {
|
||||
myElements.add(createElement());
|
||||
myTableView.getTableViewModel().setItems(myElements);
|
||||
}
|
||||
myTableView.scrollRectToVisible(myTableView.getCellRect(myElements.size() - 1, 0, true));
|
||||
myTableView.getComponent().editCellAt(myElements.size() - 1, 0);
|
||||
}
|
||||
@@ -105,6 +114,7 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
T selected = getSelection();
|
||||
if (selected != null) {
|
||||
int selectedIndex = myElements.indexOf(selected);
|
||||
myTableView.scrollRectToVisible(myTableView.getCellRect(selectedIndex, 0, true));
|
||||
myElements.remove(selected);
|
||||
myTableView.getTableViewModel().setItems(myElements);
|
||||
|
||||
@@ -133,6 +143,7 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
}
|
||||
});
|
||||
|
||||
myActionsPanel = decorator.getActionsPanel();
|
||||
|
||||
myTableView.getComponent().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
}
|
||||
@@ -157,6 +168,10 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
public CommonActionsPanel getActionsPanel() {
|
||||
return myActionsPanel;
|
||||
}
|
||||
|
||||
public void setEnabled() {
|
||||
myTableView.getComponent().setEnabled(true);
|
||||
myIsEnabled = true;
|
||||
|
||||
@@ -450,6 +450,9 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
|
||||
else {
|
||||
nothingToSearchFor();
|
||||
}
|
||||
if (mySearchField instanceof JTextArea) {
|
||||
UIUtil.adjustRows((JTextArea)mySearchField, 2, 6);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRegexp() {
|
||||
@@ -637,6 +640,9 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
|
||||
private void replaceFieldDocumentChanged() {
|
||||
setMatchesLimit(LivePreviewController.MATCHES_LIMIT);
|
||||
myFindModel.setStringToReplace(myReplaceField.getText());
|
||||
if (myReplaceField instanceof JTextArea) {
|
||||
UIUtil.adjustRows((JTextArea)myReplaceField, 2, 6);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canReplaceCurrent() {
|
||||
@@ -697,12 +703,17 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
|
||||
super.paintBorder(g);
|
||||
paintBorderOfTextField(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return super.getPreferredSize();
|
||||
}
|
||||
};
|
||||
((JTextArea)editorTextField).setColumns(25);
|
||||
((JTextArea)editorTextField).setRows(3);
|
||||
((JTextArea)editorTextField).setRows(2);
|
||||
final JScrollPane scrollPane = new JBScrollPane(editorTextField,
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
myLeftComponent.add(scrollPane, constraint);
|
||||
componentRef.set(scrollPane);
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usages.*;
|
||||
import com.intellij.usages.impl.UsagePreviewPanel;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Processor;
|
||||
@@ -70,14 +71,14 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
@@ -123,7 +124,9 @@ public class FindDialog extends DialogWrapper {
|
||||
private static boolean myPreviewResultsTabWasSelected;
|
||||
private static final int RESULTS_PREVIEW_TAB_INDEX = 1;
|
||||
|
||||
private Splitter myPreviewSplitter;
|
||||
private JBTable myResultsPreviewTable;
|
||||
private UsagePreviewPanel myUsagePreviewPanel;
|
||||
private TabbedPane myContent;
|
||||
private volatile ProgressIndicatorBase myResultsPreviewSearchProgress;
|
||||
|
||||
@@ -173,6 +176,7 @@ public class FindDialog extends DialogWrapper {
|
||||
@Override
|
||||
protected void dispose() {
|
||||
finishPreviousPreviewSearch();
|
||||
if (myUsagePreviewPanel != null) Disposer.dispose(myUsagePreviewPanel);
|
||||
for(Map.Entry<EditorTextField, DocumentAdapter> e: myComboBoxListeners.entrySet()) {
|
||||
e.getKey().removeDocumentListener(e.getValue());
|
||||
}
|
||||
@@ -489,8 +493,29 @@ public class FindDialog extends DialogWrapper {
|
||||
}
|
||||
};
|
||||
table.setShowColumns(false);
|
||||
table.setShowGrid(false);
|
||||
new NavigateToSourceListener().installOn(table);
|
||||
|
||||
Splitter previewSplitter = new Splitter(true, 0.5f, 0.1f, 0.9f);
|
||||
myUsagePreviewPanel = new UsagePreviewPanel(myProject, new UsageViewPresentation());
|
||||
myResultsPreviewTable = table;
|
||||
myResultsPreviewTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
if (e.getValueIsAdjusting()) return;
|
||||
int index = myResultsPreviewTable.getSelectionModel().getLeadSelectionIndex();
|
||||
if (index != -1) {
|
||||
UsageInfo usageInfo = ((UsageInfo2UsageAdapter)myResultsPreviewTable.getModel().getValueAt(index, 0)).getUsageInfo();
|
||||
myUsagePreviewPanel.updateLayout(Collections.singletonList(usageInfo));
|
||||
}
|
||||
else {
|
||||
myUsagePreviewPanel.updateLayout(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
previewSplitter.setFirstComponent(new JBScrollPane(myResultsPreviewTable));
|
||||
previewSplitter.setSecondComponent(myUsagePreviewPanel.createComponent());
|
||||
myPreviewSplitter = previewSplitter;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -513,10 +538,10 @@ public class FindDialog extends DialogWrapper {
|
||||
resultsOptionPanel.add(myCbToOpenInNewTab);
|
||||
}
|
||||
|
||||
if (myResultsPreviewTable != null) {
|
||||
if (myPreviewSplitter != null) {
|
||||
TabbedPane pane = new TabbedPaneImpl(SwingConstants.TOP);
|
||||
pane.insertTab("Options", null, optionsPanel, null, 0);
|
||||
pane.insertTab("Preview", null, new JBScrollPane(myResultsPreviewTable), null, RESULTS_PREVIEW_TAB_INDEX);
|
||||
pane.insertTab("Preview", null, myPreviewSplitter, null, RESULTS_PREVIEW_TAB_INDEX);
|
||||
myContent = pane;
|
||||
if (myPreviewResultsTabWasSelected) myContent.setSelectedIndex(RESULTS_PREVIEW_TAB_INDEX);
|
||||
|
||||
@@ -1389,36 +1414,46 @@ public class FindDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
private static class UsageTableCellRenderer extends JPanel implements TableCellRenderer {
|
||||
private SimpleColoredComponent myUsageRenderer = new SimpleColoredComponent();
|
||||
private SimpleColoredComponent myFileAndLineNumber = new SimpleColoredComponent();
|
||||
private ColoredTableCellRenderer myUsageRenderer = new ColoredTableCellRenderer() {
|
||||
@Override
|
||||
protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) {
|
||||
if (value instanceof UsageInfo2UsageAdapter) {
|
||||
TextChunk[] text = ((UsageInfo2UsageAdapter)value).getPresentation().getText();
|
||||
|
||||
// skip line number / file info
|
||||
for (int i = 1; i < text.length; ++i) {
|
||||
TextChunk textChunk = text[i];
|
||||
myUsageRenderer.append(textChunk.getText(), textChunk.getSimpleAttributesIgnoreBackground());
|
||||
}
|
||||
}
|
||||
setBorder(null);
|
||||
}
|
||||
};
|
||||
private ColoredTableCellRenderer myFileAndLineNumber = new ColoredTableCellRenderer() {
|
||||
@Override
|
||||
protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) {
|
||||
if (value instanceof UsageInfo2UsageAdapter) {
|
||||
TextChunk[] text = ((UsageInfo2UsageAdapter)value).getPresentation().getText();
|
||||
// line number / file info
|
||||
append(((UsageInfo2UsageAdapter)value).getFile().getName() + " " + text[0].getText(), SimpleTextAttributes.GRAYED_ITALIC_ATTRIBUTES);
|
||||
}
|
||||
setBorder(null);
|
||||
}
|
||||
};
|
||||
|
||||
UsageTableCellRenderer() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
add(myUsageRenderer, BorderLayout.WEST);
|
||||
add(myFileAndLineNumber, BorderLayout.EAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
myUsageRenderer.clear();
|
||||
myFileAndLineNumber.clear();
|
||||
setBackground(isSelected && hasFocus ? UIUtil.getTableSelectionBackground() : UIUtil.getTableBackground());
|
||||
setBackground(UIUtil.getTableBackground(isSelected));
|
||||
myUsageRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
myFileAndLineNumber.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
|
||||
if (value instanceof UsageInfo2UsageAdapter) {
|
||||
UsageInfo2UsageAdapter usageAdapter = (UsageInfo2UsageAdapter)value;
|
||||
UsagePresentation presentation = usageAdapter.getPresentation();
|
||||
TextChunk[] text = presentation.getText();
|
||||
|
||||
// put line number / file info at the right
|
||||
for (int i = 1; i < text.length; ++i) {
|
||||
TextChunk textChunk = text[i];
|
||||
SimpleTextAttributes simples = textChunk.getSimpleAttributesIgnoreBackground();
|
||||
myUsageRenderer.append(textChunk.getText(), simples);
|
||||
}
|
||||
|
||||
myFileAndLineNumber.append(usageAdapter.getFile().getName() + " " + text[0].getText(),
|
||||
SimpleTextAttributes.GRAYED_ITALIC_ATTRIBUTES);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -158,6 +158,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
private JBList myList;
|
||||
private JCheckBox myNonProjectCheckBox;
|
||||
private AnActionEvent myActionEvent;
|
||||
private Set<AnAction> myDisabledActions = new HashSet<AnAction>();
|
||||
private Component myContextComponent;
|
||||
private CalcThread myCalcThread;
|
||||
private static AtomicBoolean ourShiftIsPressed = new AtomicBoolean(false);
|
||||
@@ -1040,6 +1041,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
};
|
||||
SearchEverywherePsiRenderer myFileRenderer = new SearchEverywherePsiRenderer(myList);
|
||||
ListCellRenderer myActionsRenderer = new GotoActionModel.GotoActionListCellRenderer(Function.TO_STRING);
|
||||
|
||||
private String myLocationString;
|
||||
private DefaultPsiElementCellRenderer myPsiRenderer = new DefaultPsiElementCellRenderer() {
|
||||
@@ -1080,6 +1082,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
} else if (value instanceof PsiElement) {
|
||||
myFileRenderer.setPatternMatcher(matcher);
|
||||
cmp = myFileRenderer.getListCellRendererComponent(list, value, index, isSelected, isSelected);
|
||||
} else if (value instanceof GotoActionModel.ActionWrapper) {
|
||||
cmp = myActionsRenderer.getListCellRendererComponent(list, new GotoActionModel.MatchedValue(((GotoActionModel.ActionWrapper)value), pattern), index, isSelected, isSelected);
|
||||
} else {
|
||||
cmp = super.getListCellRendererComponent(list, value, index, isSelected, isSelected);
|
||||
final JPanel p = new JPanel(new BorderLayout());
|
||||
@@ -1464,7 +1468,10 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
result.add(object);
|
||||
}
|
||||
} else if (actions && !isToolWindowAction(object) && isActionValue(object)) {
|
||||
result.add(object);
|
||||
AnAction action = object instanceof AnAction ? ((AnAction)object) : ((GotoActionModel.ActionWrapper)object).getAction();
|
||||
if (isEnabled(action)) {
|
||||
result.add(object);
|
||||
}
|
||||
}
|
||||
return result.size() <= max;
|
||||
}
|
||||
@@ -1905,19 +1912,9 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
public void run() {
|
||||
if (isCanceled()) return;
|
||||
|
||||
|
||||
for (Object element : new ArrayList(elements)) {
|
||||
if (element instanceof AnAction) {
|
||||
final AnAction action = (AnAction)element;
|
||||
final AnActionEvent e = new AnActionEvent(myActionEvent.getInputEvent(),
|
||||
myActionEvent.getDataContext(),
|
||||
myActionEvent.getPlace(),
|
||||
action.getTemplatePresentation(),
|
||||
myActionEvent.getActionManager(),
|
||||
myActionEvent.getModifiers());
|
||||
ActionUtil.performDumbAwareUpdate(action, e, false);
|
||||
final Presentation presentation = e.getPresentation();
|
||||
if (!presentation.isEnabled() || !presentation.isVisible() || StringUtil.isEmpty(presentation.getText())) {
|
||||
if (!isEnabled((AnAction)element)) {
|
||||
elements.remove(element);
|
||||
}
|
||||
if (isCanceled()) return;
|
||||
@@ -1933,6 +1930,29 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isEnabled(final AnAction action) {
|
||||
if (myDisabledActions.contains(action)) return false;
|
||||
final AnActionEvent e = new AnActionEvent(myActionEvent.getInputEvent(),
|
||||
myActionEvent.getDataContext(),
|
||||
myActionEvent.getPlace(),
|
||||
action.getTemplatePresentation(),
|
||||
myActionEvent.getActionManager(),
|
||||
myActionEvent.getModifiers());
|
||||
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ActionUtil.performDumbAwareUpdate(action, e, false);
|
||||
}
|
||||
});
|
||||
final Presentation presentation = e.getPresentation();
|
||||
final boolean enabled = presentation.isEnabled() && presentation.isVisible() && !StringUtil.isEmpty(presentation.getText());
|
||||
if (!enabled) {
|
||||
myDisabledActions.add(action);
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
|
||||
private synchronized void checkModelsUpToDate() {
|
||||
if (myClassModel == null) {
|
||||
myClassModel = new GotoClassModel2(project);
|
||||
@@ -2165,6 +2185,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
myEditor = null;
|
||||
myFileEditor = null;
|
||||
myStructureModel = null;
|
||||
myDisabledActions.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -41,6 +41,7 @@ import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.OnOffButton;
|
||||
import com.intellij.ui.speedSearch.SpeedSearchUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.ui.EmptyIcon;
|
||||
@@ -144,7 +145,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
@NotNull public final Comparable value;
|
||||
@NotNull final String pattern;
|
||||
|
||||
MatchedValue(@NotNull Comparable value, @NotNull String pattern) {
|
||||
public MatchedValue(@NotNull Comparable value, @NotNull String pattern) {
|
||||
this.value = value;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
@@ -208,121 +209,12 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
|
||||
@Override
|
||||
public ListCellRenderer getListCellRenderer() {
|
||||
return new DefaultListCellRenderer() {
|
||||
return new GotoActionListCellRenderer(new Function<OptionDescription, String>() {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(@NotNull final JList list,
|
||||
final Object matchedValue,
|
||||
final int index, final boolean isSelected, final boolean cellHasFocus) {
|
||||
final JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder(2));
|
||||
panel.setOpaque(true);
|
||||
Color bg = UIUtil.getListBackground(isSelected);
|
||||
panel.setBackground(bg);
|
||||
|
||||
if (matchedValue instanceof String) { //...
|
||||
final JBLabel label = new JBLabel((String)matchedValue);
|
||||
label.setIcon(EMPTY_ICON);
|
||||
panel.add(label, BorderLayout.WEST);
|
||||
return panel;
|
||||
}
|
||||
|
||||
Color groupFg = isSelected ? UIUtil.getListSelectionForeground() : UIUtil.getLabelDisabledForeground();
|
||||
|
||||
final Object value = ((MatchedValue) matchedValue).value;
|
||||
String pattern = ((MatchedValue)matchedValue).pattern;
|
||||
|
||||
SimpleColoredComponent nameComponent = new SimpleColoredComponent();
|
||||
nameComponent.setBackground(bg);
|
||||
panel.add(nameComponent, BorderLayout.CENTER);
|
||||
|
||||
if (value instanceof ActionWrapper) {
|
||||
final ActionWrapper actionWithParentGroup = (ActionWrapper)value;
|
||||
final AnAction anAction = actionWithParentGroup.getAction();
|
||||
final Presentation presentation = anAction.getTemplatePresentation();
|
||||
boolean toggle = anAction instanceof ToggleAction;
|
||||
String groupName = actionWithParentGroup.getAction() instanceof ApplyIntentionAction ? null : actionWithParentGroup.getGroupName();
|
||||
final Color fg = defaultActionForeground(isSelected, actionWithParentGroup.getPresentation());
|
||||
panel.add(createIconLabel(presentation.getIcon()), BorderLayout.WEST);
|
||||
appendWithColoredMatches(nameComponent, getName(presentation.getText(), groupName, toggle), pattern, fg, isSelected);
|
||||
|
||||
final Shortcut shortcut = preferKeyboardShortcut(KeymapManager.getInstance().getActiveKeymap().getShortcuts(getActionId(anAction)));
|
||||
if (shortcut != null) {
|
||||
nameComponent.append(" (" + KeymapUtil.getShortcutText(shortcut) + ")", new SimpleTextAttributes(STYLE_PLAIN, groupFg));
|
||||
}
|
||||
|
||||
if (toggle) {
|
||||
final OnOffButton button = new OnOffButton();
|
||||
AnActionEvent event = new AnActionEvent(null, ((ActionWrapper)value).myDataContext,
|
||||
ActionPlaces.UNKNOWN, new Presentation(), ActionManager.getInstance(),
|
||||
0);
|
||||
button.setSelected(((ToggleAction)anAction).isSelected(event));
|
||||
panel.add(button, BorderLayout.EAST);
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder());
|
||||
}
|
||||
else {
|
||||
if (groupName != null) {
|
||||
final JLabel groupLabel = new JLabel(groupName);
|
||||
groupLabel.setBackground(bg);
|
||||
groupLabel.setForeground(groupFg);
|
||||
panel.add(groupLabel, BorderLayout.EAST);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (value instanceof OptionDescription) {
|
||||
if (!isSelected && !(value instanceof BooleanOptionDescription)) {
|
||||
Color descriptorBg = UIUtil.isUnderDarcula() ? ColorUtil.brighter(UIUtil.getListBackground(), 1) : LightColors.SLIGHTLY_GRAY;
|
||||
panel.setBackground(descriptorBg);
|
||||
nameComponent.setBackground(descriptorBg);
|
||||
}
|
||||
String hit = ((OptionDescription)value).getHit();
|
||||
if (hit == null) {
|
||||
hit = ((OptionDescription)value).getOption();
|
||||
}
|
||||
hit = StringUtil.unescapeXml(hit);
|
||||
hit = hit.replace(" ", " "); // avoid extra spaces from mnemonics and xml conversion
|
||||
String fullHit = hit;
|
||||
hit = StringUtil.first(hit, 45, true);
|
||||
|
||||
final Color fg = UIUtil.getListForeground(isSelected);
|
||||
|
||||
appendWithColoredMatches(nameComponent, hit.trim(), pattern, fg, isSelected);
|
||||
|
||||
panel.add(new JLabel(EMPTY_ICON), BorderLayout.WEST);
|
||||
panel.setToolTipText(fullHit);
|
||||
|
||||
if (value instanceof BooleanOptionDescription) {
|
||||
final OnOffButton button = new OnOffButton();
|
||||
button.setSelected(((BooleanOptionDescription)value).isOptionEnabled());
|
||||
panel.add(button, BorderLayout.EAST);
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder());
|
||||
}
|
||||
else {
|
||||
final JLabel settingsLabel = new JLabel(getGroupName((OptionDescription)value));
|
||||
settingsLabel.setForeground(groupFg);
|
||||
settingsLabel.setBackground(bg);
|
||||
panel.add(settingsLabel, BorderLayout.EAST);
|
||||
}
|
||||
}
|
||||
return panel;
|
||||
public String fun(OptionDescription description) {
|
||||
return getGroupName(description);
|
||||
}
|
||||
|
||||
public String getName(String text, String groupName, boolean toggle) {
|
||||
return toggle && StringUtil.isNotEmpty(groupName)? groupName + ": "+ text : text;
|
||||
}
|
||||
|
||||
private void appendWithColoredMatches(SimpleColoredComponent nameComponent, String name, String pattern, Color fg, boolean selected) {
|
||||
final SimpleTextAttributes plain = new SimpleTextAttributes(STYLE_PLAIN, fg);
|
||||
final SimpleTextAttributes highlighted = new SimpleTextAttributes(null, fg, null, STYLE_SEARCH_MATCH);
|
||||
List<TextRange> fragments = ContainerUtil.newArrayList();
|
||||
if (selected) {
|
||||
int matchStart = StringUtil.indexOfIgnoreCase(name, pattern, 0);
|
||||
if (matchStart >= 0) {
|
||||
fragments.add(TextRange.from(matchStart, pattern.length()));
|
||||
}
|
||||
}
|
||||
SpeedSearchUtil.appendColoredFragments(nameComponent, name, fragments, plain, highlighted);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
protected String getActionId(@NotNull final AnAction anAction) {
|
||||
@@ -721,4 +613,130 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
return myAction.getTemplatePresentation().getText().hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static class GotoActionListCellRenderer extends DefaultListCellRenderer {
|
||||
private final Function<OptionDescription, String> myGroupNamer;
|
||||
|
||||
public GotoActionListCellRenderer(Function<OptionDescription, String> groupNamer) {
|
||||
myGroupNamer = groupNamer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(@NotNull final JList list,
|
||||
final Object matchedValue,
|
||||
final int index, final boolean isSelected, final boolean cellHasFocus) {
|
||||
final JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder(2));
|
||||
panel.setOpaque(true);
|
||||
Color bg = UIUtil.getListBackground(isSelected);
|
||||
panel.setBackground(bg);
|
||||
|
||||
if (matchedValue instanceof String) { //...
|
||||
final JBLabel label = new JBLabel((String)matchedValue);
|
||||
label.setIcon(EMPTY_ICON);
|
||||
panel.add(label, BorderLayout.WEST);
|
||||
return panel;
|
||||
}
|
||||
|
||||
Color groupFg = isSelected ? UIUtil.getListSelectionForeground() : UIUtil.getLabelDisabledForeground();
|
||||
|
||||
final Object value = ((MatchedValue) matchedValue).value;
|
||||
String pattern = ((MatchedValue)matchedValue).pattern;
|
||||
|
||||
SimpleColoredComponent nameComponent = new SimpleColoredComponent();
|
||||
nameComponent.setBackground(bg);
|
||||
panel.add(nameComponent, BorderLayout.CENTER);
|
||||
|
||||
if (value instanceof ActionWrapper) {
|
||||
final ActionWrapper actionWithParentGroup = (ActionWrapper)value;
|
||||
final AnAction anAction = actionWithParentGroup.getAction();
|
||||
final Presentation presentation = anAction.getTemplatePresentation();
|
||||
boolean toggle = anAction instanceof ToggleAction;
|
||||
String groupName = actionWithParentGroup.getAction() instanceof ApplyIntentionAction ? null : actionWithParentGroup.getGroupName();
|
||||
final Color fg = defaultActionForeground(isSelected, actionWithParentGroup.getPresentation());
|
||||
panel.add(createIconLabel(presentation.getIcon()), BorderLayout.WEST);
|
||||
appendWithColoredMatches(nameComponent, getName(presentation.getText(), groupName, toggle), pattern, fg, isSelected);
|
||||
|
||||
final Shortcut shortcut = preferKeyboardShortcut(KeymapManager.getInstance().getActiveKeymap().getShortcuts(ActionManager.getInstance().getId(anAction)));
|
||||
if (shortcut != null) {
|
||||
nameComponent.append(" (" + KeymapUtil.getShortcutText(shortcut) + ")", new SimpleTextAttributes(STYLE_PLAIN, groupFg));
|
||||
}
|
||||
|
||||
if (toggle) {
|
||||
final OnOffButton button = new OnOffButton();
|
||||
AnActionEvent event = new AnActionEvent(null, ((ActionWrapper)value).myDataContext,
|
||||
ActionPlaces.UNKNOWN, new Presentation(), ActionManager.getInstance(),
|
||||
0);
|
||||
button.setSelected(((ToggleAction)anAction).isSelected(event));
|
||||
panel.add(button, BorderLayout.EAST);
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder());
|
||||
}
|
||||
else {
|
||||
if (groupName != null) {
|
||||
final JLabel groupLabel = new JLabel(groupName);
|
||||
groupLabel.setBackground(bg);
|
||||
groupLabel.setForeground(groupFg);
|
||||
panel.add(groupLabel, BorderLayout.EAST);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (value instanceof OptionDescription) {
|
||||
if (!isSelected && !(value instanceof BooleanOptionDescription)) {
|
||||
Color descriptorBg = UIUtil.isUnderDarcula() ? ColorUtil.brighter(UIUtil.getListBackground(), 1) : LightColors.SLIGHTLY_GRAY;
|
||||
panel.setBackground(descriptorBg);
|
||||
nameComponent.setBackground(descriptorBg);
|
||||
}
|
||||
String hit = ((OptionDescription)value).getHit();
|
||||
if (hit == null) {
|
||||
hit = ((OptionDescription)value).getOption();
|
||||
}
|
||||
hit = StringUtil.unescapeXml(hit);
|
||||
hit = hit.replace(" ", " "); // avoid extra spaces from mnemonics and xml conversion
|
||||
String fullHit = hit;
|
||||
hit = StringUtil.first(hit, 45, true);
|
||||
|
||||
final Color fg = UIUtil.getListForeground(isSelected);
|
||||
|
||||
appendWithColoredMatches(nameComponent, hit.trim(), pattern, fg, isSelected);
|
||||
|
||||
panel.add(new JLabel(EMPTY_ICON), BorderLayout.WEST);
|
||||
panel.setToolTipText(fullHit);
|
||||
|
||||
if (value instanceof BooleanOptionDescription) {
|
||||
final OnOffButton button = new OnOffButton();
|
||||
button.setSelected(((BooleanOptionDescription)value).isOptionEnabled());
|
||||
panel.add(button, BorderLayout.EAST);
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder());
|
||||
}
|
||||
else {
|
||||
final JLabel settingsLabel = new JLabel(myGroupNamer.fun((OptionDescription)value));
|
||||
settingsLabel.setForeground(groupFg);
|
||||
settingsLabel.setBackground(bg);
|
||||
panel.add(settingsLabel, BorderLayout.EAST);
|
||||
}
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
public String getName(String text, String groupName, boolean toggle) {
|
||||
return toggle && StringUtil.isNotEmpty(groupName)? groupName + ": "+ text : text;
|
||||
}
|
||||
|
||||
private static void appendWithColoredMatches(SimpleColoredComponent nameComponent,
|
||||
String name,
|
||||
String pattern,
|
||||
Color fg,
|
||||
boolean selected) {
|
||||
final SimpleTextAttributes plain = new SimpleTextAttributes(STYLE_PLAIN, fg);
|
||||
final SimpleTextAttributes highlighted = new SimpleTextAttributes(null, fg, null, STYLE_SEARCH_MATCH);
|
||||
List<TextRange> fragments = ContainerUtil.newArrayList();
|
||||
if (selected) {
|
||||
int matchStart = StringUtil.indexOfIgnoreCase(name, pattern, 0);
|
||||
if (matchStart >= 0) {
|
||||
fragments.add(TextRange.from(matchStart, pattern.length()));
|
||||
}
|
||||
}
|
||||
SpeedSearchUtil.appendColoredFragments(nameComponent, name, fragments, plain, highlighted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ public interface IdeActions {
|
||||
@NonNls String ACTION_EDITOR_BACKSPACE = "EditorBackSpace";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION = "EditorLeftWithSelection";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION = "EditorRightWithSelection";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_UP_WITH_SELECTION = "EditorUpWithSelection";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_DOWN_WITH_SELECTION = "EditorDownWithSelection";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_UP = "EditorUp";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_LEFT = "EditorLeft";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_DOWN = "EditorDown";
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ public class DarculaRadioButtonUI extends MetalRadioButtonUI {
|
||||
if (b.isSelected()) {
|
||||
final boolean enabled = b.isEnabled();
|
||||
g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledShadowColor" : "RadioButton.darcula.selectionDisabledShadowColor"));// ? Gray._30 : Gray._60);
|
||||
final int yOff = UIUtil.isUnderDarcula() ? 2 : JBUI.scale(1);
|
||||
final int yOff = 2;
|
||||
g.fillOval(w/2 - rad/2, h/2 - rad/2 + yOff , rad, rad);
|
||||
g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledColor" : "RadioButton.darcula.selectionDisabledColor")); //Gray._170 : Gray._120);
|
||||
g.fillOval(w/2 - rad/2, h/2 - rad/2 -1 + yOff, rad, rad);
|
||||
|
||||
@@ -248,6 +248,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int oldOffset = myOffset;
|
||||
final int leadSelectionOffset = getLeadSelectionOffset();
|
||||
final VisualPosition leadSelectionPosition = getLeadSelectionPosition();
|
||||
EditorSettings editorSettings = myEditor.getSettings();
|
||||
@@ -370,7 +371,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
else {
|
||||
int selectionStartToUse = leadSelectionOffset;
|
||||
VisualPosition selectionStartPositionToUse = leadSelectionPosition;
|
||||
if (isUnknownDirection()) {
|
||||
if (isUnknownDirection() || oldOffset > getSelectionStart() && oldOffset < getSelectionEnd()) {
|
||||
if (getOffset() > leadSelectionOffset ^ getSelectionStart() < getSelectionEnd()) {
|
||||
selectionStartToUse = getSelectionEnd();
|
||||
selectionStartPositionToUse = getSelectionEndPosition();
|
||||
|
||||
+20
@@ -167,4 +167,24 @@ public class EditorActionTest extends AbstractEditorTest {
|
||||
executeAction(IdeActions.ACTION_EDITOR_DELETE_TO_WORD_END);
|
||||
checkResultByText("class Foo { String s = \"a\\<caret>b\"; }");
|
||||
}
|
||||
|
||||
public void testUpWithSelectionOnCaretInsideSelection() throws Exception {
|
||||
initText("blah blah\n" +
|
||||
"blah <selection>bl<caret>ah</selection>\n" +
|
||||
"blah blah");
|
||||
executeAction(IdeActions.ACTION_EDITOR_MOVE_CARET_UP_WITH_SELECTION);
|
||||
checkResultByText("blah bl<selection><caret>ah\n" +
|
||||
"blah blah</selection>\n" +
|
||||
"blah blah");
|
||||
}
|
||||
|
||||
public void testDownWithSelectionOnCaretInsideSelection() throws Exception {
|
||||
initText("blah blah\n" +
|
||||
"blah <selection>bl<caret>ah</selection>\n" +
|
||||
"blah blah");
|
||||
executeAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN_WITH_SELECTION);
|
||||
checkResultByText("blah blah\n" +
|
||||
"blah <selection>blah\n" +
|
||||
"blah bl<caret></selection>ah");
|
||||
}
|
||||
}
|
||||
@@ -116,6 +116,7 @@ public class ListTableModel<Item> extends TableViewModel<Item> implements Editab
|
||||
if (rowIndex < myItems.size()) {
|
||||
myColumnInfos[columnIndex].setValue(getItem(rowIndex), aValue);
|
||||
}
|
||||
fireTableCellUpdated(rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3215,6 +3215,10 @@ public class UIUtil {
|
||||
textComponent.getActionMap().put("redoKeystroke", REDO_ACTION);
|
||||
}
|
||||
|
||||
public static void adjustRows(JTextArea area, int minRows, int maxRows) {
|
||||
area.setRows(Math.max(minRows, Math.min(maxRows, area.getText().split("\n").length)));
|
||||
}
|
||||
|
||||
public static void playSoundFromResource(final String resourceName) {
|
||||
final Class callerClass = ReflectionUtil.getGrandCallerClass();
|
||||
if (callerClass == null) return;
|
||||
|
||||
+2
-2
@@ -947,12 +947,12 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper {
|
||||
if (myPatches.isEmpty() || (! myContainBasedChanges)) return;
|
||||
final List<FilePatchInProgress.PatchChange> changes = getAllChanges();
|
||||
Collections.sort(changes, myMyChangeComparator);
|
||||
final List<FilePatchInProgress.PatchChange> selectedChanges = myChangesTreeList.getSelectedChanges();
|
||||
List<FilePatchInProgress.PatchChange> selectedChanges = myChangesTreeList.getSelectedChanges();
|
||||
|
||||
int selectedIdx = 0;
|
||||
final ArrayList<DiffRequestPresentable> diffRequestPresentables = new ArrayList<DiffRequestPresentable>(changes.size());
|
||||
if (selectedChanges.isEmpty()) {
|
||||
selectedChanges.addAll(changes);
|
||||
selectedChanges = changes;
|
||||
}
|
||||
if (! selectedChanges.isEmpty()) {
|
||||
final FilePatchInProgress.PatchChange c = selectedChanges.get(0);
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.awt.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* Use this interface to access information available in the VCS Log.
|
||||
@@ -55,7 +56,8 @@ public interface VcsLog {
|
||||
/**
|
||||
* Selects the commit node defined by the given reference (commit hash, branch or tag).
|
||||
*/
|
||||
void jumpToReference(String reference);
|
||||
@NotNull
|
||||
Future<Boolean> jumpToReference(String reference);
|
||||
|
||||
/**
|
||||
* Returns the VCS log toolbar component.
|
||||
@@ -68,5 +70,4 @@ public interface VcsLog {
|
||||
*/
|
||||
@NotNull
|
||||
Collection<VcsLogProvider> getLogProviders();
|
||||
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.awt.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -84,8 +85,9 @@ public class VcsLogImpl implements VcsLog {
|
||||
return myUi.getDataPack().getRefsModel().getAllRefs();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public void jumpToReference(final String reference) {
|
||||
public Future<Boolean> jumpToReference(final String reference) {
|
||||
Collection<VcsRef> references = getAllReferences();
|
||||
VcsRef ref = ContainerUtil.find(references, new Condition<VcsRef>() {
|
||||
@Override
|
||||
@@ -94,10 +96,10 @@ public class VcsLogImpl implements VcsLog {
|
||||
}
|
||||
});
|
||||
if (ref != null) {
|
||||
myUi.jumpToCommit(ref.getCommitHash());
|
||||
return myUi.jumpToCommit(ref.getCommitHash());
|
||||
}
|
||||
else {
|
||||
myUi.jumpToCommitByPartOfHash(reference);
|
||||
return myUi.jumpToCommitByPartOfHash(reference);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.vcs.log.ui;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.JBPopupListener;
|
||||
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
|
||||
import com.intellij.ui.components.JBTextField;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class FindPopupWithProgress {
|
||||
private static final Logger LOG = Logger.getInstance(FindPopupWithProgress.class);
|
||||
|
||||
@NotNull private final TextFieldWithProgress myTextField;
|
||||
@NotNull private final Function<String, Future> myFunction;
|
||||
@NotNull private final JBPopup myPopup;
|
||||
@Nullable private Future myFuture;
|
||||
|
||||
public FindPopupWithProgress(@NotNull final Project project,
|
||||
@NotNull Collection<String> variants,
|
||||
@NotNull Function<String, Future> function) {
|
||||
myFunction = function;
|
||||
myTextField = new TextFieldWithProgress(project, variants) {
|
||||
@Override
|
||||
public void onOk() {
|
||||
if (myFuture == null) {
|
||||
final Future future = myFunction.fun(getText().trim());
|
||||
myFuture = future;
|
||||
showProgress();
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
future.get();
|
||||
ok();
|
||||
}
|
||||
catch (CancellationException ex) {
|
||||
cancel();
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
cancel();
|
||||
}
|
||||
catch (ExecutionException ex) {
|
||||
LOG.error(ex);
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(myTextField, myTextField.getPreferableFocusComponent())
|
||||
.setCancelOnClickOutside(true).setCancelOnWindowDeactivation(true).setCancelKeyEnabled(true).setRequestFocus(true).createPopup();
|
||||
myPopup.addListener(new JBPopupListener.Adapter() {
|
||||
@Override
|
||||
public void onClosed(LightweightWindowEvent event) {
|
||||
if (!event.isOk()) {
|
||||
if (myFuture != null) {
|
||||
myFuture.cancel(false);
|
||||
myFuture = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final JBTextField field = new JBTextField(20);
|
||||
final Dimension size = field.getPreferredSize();
|
||||
final Insets insets = myTextField.getBorder().getBorderInsets(myTextField);
|
||||
size.height += 6 + insets.top + insets.bottom;
|
||||
size.width += 4 + insets.left + insets.right;
|
||||
myPopup.setSize(size);
|
||||
}
|
||||
|
||||
private void cancel() {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myFuture != null) myFuture = null;
|
||||
myTextField.hideProgress();
|
||||
myPopup.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void ok() {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myFuture != null) myFuture = null;
|
||||
myTextField.hideProgress();
|
||||
myPopup.closeOk(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showUnderneathOf(@NotNull Component anchor) {
|
||||
myPopup.showUnderneathOf(anchor);
|
||||
}
|
||||
}
|
||||
@@ -18,9 +18,6 @@ package com.intellij.vcs.log.ui;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupListener;
|
||||
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcs.log.VcsLog;
|
||||
@@ -28,6 +25,7 @@ import com.intellij.vcs.log.VcsLogDataKeys;
|
||||
import com.intellij.vcs.log.VcsRef;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class GoToRefAction extends DumbAwareAction {
|
||||
|
||||
@@ -45,16 +43,12 @@ public class GoToRefAction extends DumbAwareAction {
|
||||
return ref.getName();
|
||||
}
|
||||
});
|
||||
final PopupWithTextFieldWithAutoCompletion textField = new PopupWithTextFieldWithAutoCompletion(project, refs);
|
||||
JBPopup popup = textField.createPopup();
|
||||
popup.addListener(new JBPopupListener.Adapter() {
|
||||
@Override
|
||||
public void onClosed(LightweightWindowEvent event) {
|
||||
if (event.isOk()) {
|
||||
log.jumpToReference(textField.getText().trim());
|
||||
}
|
||||
}
|
||||
});
|
||||
FindPopupWithProgress popup = new FindPopupWithProgress(project, refs, new Function<String, Future>() {
|
||||
@Override
|
||||
public Future fun(String text) {
|
||||
return log.jumpToReference(text);
|
||||
}
|
||||
});
|
||||
popup.showUnderneathOf(log.getToolbar());
|
||||
}
|
||||
|
||||
|
||||
-85
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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.vcs.log.ui;
|
||||
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.spellchecker.ui.SpellCheckingEditorCustomization;
|
||||
import com.intellij.ui.TextFieldWithAutoCompletion;
|
||||
import com.intellij.ui.components.JBTextField;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Collection;
|
||||
|
||||
public class PopupWithTextFieldWithAutoCompletion extends TextFieldWithAutoCompletion<String> {
|
||||
|
||||
@Nullable private JBPopup myPopup;
|
||||
|
||||
public PopupWithTextFieldWithAutoCompletion(@NotNull Project project, @NotNull Collection<String> variants) {
|
||||
super(project, new StringsCompletionProvider(variants, null), false, null);
|
||||
setBorder(new EmptyBorder(3, 3, 3, 3));
|
||||
}
|
||||
|
||||
public JBPopup createPopup() {
|
||||
myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(this, this)
|
||||
.setCancelOnClickOutside(true)
|
||||
.setCancelOnWindowDeactivation(true)
|
||||
.setCancelKeyEnabled(true)
|
||||
.setRequestFocus(true)
|
||||
.createPopup();
|
||||
|
||||
final JBTextField field = new JBTextField(20);
|
||||
final Dimension size = field.getPreferredSize();
|
||||
final Insets insets = getBorder().getBorderInsets(this);
|
||||
size.height+=6 + insets.top + insets.bottom;
|
||||
size.width +=4 + insets.left + insets.right;
|
||||
myPopup.setSize(size);
|
||||
|
||||
return myPopup;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
if (myPopup != null) {
|
||||
myPopup.closeOk(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
|
||||
if (myPopup != null) {
|
||||
myPopup.cancel(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EditorEx createEditor() {
|
||||
// spell check is not needed
|
||||
EditorEx editor = super.createEditor();
|
||||
SpellCheckingEditorCustomization.getInstance(false).customize(editor);
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.vcs.log.ui;
|
||||
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.progress.PerformInBackgroundOption;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.spellchecker.ui.SpellCheckingEditorCustomization;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.TextFieldWithAutoCompletion;
|
||||
import com.intellij.util.ui.AsyncProcessIcon;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public abstract class TextFieldWithProgress extends JPanel {
|
||||
@NotNull private final TextFieldWithAutoCompletion<String> myTextField;
|
||||
@NotNull private final AsyncProcessIcon myProgressIcon;
|
||||
|
||||
public TextFieldWithProgress(@NotNull Project project, @NotNull Collection<String> variants) {
|
||||
super(new BorderLayout());
|
||||
setBorder(IdeBorderFactory.createEmptyBorder(3));
|
||||
|
||||
myProgressIcon = new AsyncProcessIcon("Loading commits");
|
||||
myTextField =
|
||||
new TextFieldWithAutoCompletion<String>(project, new TextFieldWithAutoCompletion.StringsCompletionProvider(variants, null), false,
|
||||
null) {
|
||||
@Override
|
||||
public void setBackground(Color bg) {
|
||||
super.setBackground(bg);
|
||||
myProgressIcon.setBackground(bg);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EditorEx createEditor() {
|
||||
// spell check is not needed
|
||||
EditorEx editor = super.createEditor();
|
||||
SpellCheckingEditorCustomization.getInstance(false).customize(editor);
|
||||
return editor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean processKeyBinding(KeyStroke ks, final KeyEvent e, int condition, boolean pressed) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
onOk();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
myTextField.setBorder(IdeBorderFactory.createEmptyBorder());
|
||||
|
||||
myProgressIcon.setOpaque(true);
|
||||
myProgressIcon.setBackground(myTextField.getBackground());
|
||||
|
||||
add(myTextField, BorderLayout.CENTER);
|
||||
add(myProgressIcon, BorderLayout.EAST);
|
||||
|
||||
hideProgress();
|
||||
}
|
||||
|
||||
public JComponent getPreferableFocusComponent() {
|
||||
return myTextField;
|
||||
}
|
||||
|
||||
public void showProgress() {
|
||||
myTextField.setEnabled(false);
|
||||
myProgressIcon.setVisible(true);
|
||||
}
|
||||
|
||||
public void hideProgress() {
|
||||
myTextField.setEnabled(true);
|
||||
myProgressIcon.setVisible(false);
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return myTextField.getText();
|
||||
}
|
||||
|
||||
public abstract void onOk();
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.intellij.vcs.log.ui;
|
||||
|
||||
import com.google.common.util.concurrent.SettableFuture;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -32,6 +33,7 @@ import javax.swing.table.TableModel;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class VcsLogUiImpl implements VcsLogUi, Disposable {
|
||||
|
||||
@@ -192,22 +194,28 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable {
|
||||
return myUiProperties.isShowRootNames();
|
||||
}
|
||||
|
||||
public void jumpToCommit(@NotNull Hash commitHash) {
|
||||
@NotNull
|
||||
public Future<Boolean> jumpToCommit(@NotNull Hash commitHash) {
|
||||
SettableFuture<Boolean> future = SettableFuture.create();
|
||||
jumpTo(commitHash, new PairFunction<GraphTableModel, Hash, Integer>() {
|
||||
@Override
|
||||
public Integer fun(GraphTableModel model, Hash hash) {
|
||||
return model.getRowOfCommit(hash);
|
||||
}
|
||||
});
|
||||
}, future);
|
||||
return future;
|
||||
}
|
||||
|
||||
public void jumpToCommitByPartOfHash(@NotNull String commitHash) {
|
||||
@NotNull
|
||||
public Future<Boolean> jumpToCommitByPartOfHash(@NotNull String commitHash) {
|
||||
SettableFuture<Boolean> future = SettableFuture.create();
|
||||
jumpTo(commitHash, new PairFunction<GraphTableModel, String, Integer>() {
|
||||
@Override
|
||||
public Integer fun(GraphTableModel model, String hash) {
|
||||
return model.getRowOfCommitByPartOfHash(hash);
|
||||
}
|
||||
});
|
||||
}, future);
|
||||
return future;
|
||||
}
|
||||
|
||||
public void handleAnswer(@Nullable GraphAnswer<Integer> answer, boolean dataCouldChange) {
|
||||
@@ -235,13 +243,15 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void jumpTo(@NotNull final T commitId, @NotNull final PairFunction<GraphTableModel, T, Integer> rowGetter) {
|
||||
private <T> void jumpTo(@NotNull final T commitId, @NotNull final PairFunction<GraphTableModel, T, Integer> rowGetter, @NotNull final SettableFuture<Boolean> future) {
|
||||
if (future.isCancelled()) return;
|
||||
|
||||
GraphTableModel model = getModel();
|
||||
if (model == null) {
|
||||
invokeOnChange(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
jumpTo(commitId, rowGetter);
|
||||
jumpTo(commitId, rowGetter, future);
|
||||
}
|
||||
});
|
||||
return;
|
||||
@@ -250,12 +260,13 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable {
|
||||
int row = rowGetter.fun(model, commitId);
|
||||
if (row >= 0) {
|
||||
myMainFrame.getGraphTable().jumpToRow(row);
|
||||
future.set(true);
|
||||
}
|
||||
else if (model.canRequestMore()) {
|
||||
model.requestToLoadMore(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
jumpTo(commitId, rowGetter);
|
||||
jumpTo(commitId, rowGetter, future);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -263,12 +274,13 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable {
|
||||
invokeOnChange(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
jumpTo(commitId, rowGetter);
|
||||
jumpTo(commitId, rowGetter, future);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
commitNotFound(commitId.toString());
|
||||
future.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,11 @@ package git4idea.history.wholeTree;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.PerformInBackgroundOption;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
@@ -22,7 +27,12 @@ import git4idea.i18n.GitBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class SelectRevisionInGitLogAction extends DumbAwareAction {
|
||||
private static final Logger LOG = Logger.getInstance(SelectRevisionInGitLogAction.class);
|
||||
|
||||
public SelectRevisionInGitLogAction() {
|
||||
super(GitBundle.getString("vcs.history.action.gitlog"), GitBundle.getString("vcs.history.action.gitlog"), null);
|
||||
@@ -30,7 +40,7 @@ public class SelectRevisionInGitLogAction extends DumbAwareAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent event) {
|
||||
Project project = event.getRequiredData(CommonDataKeys.PROJECT);
|
||||
final Project project = event.getRequiredData(CommonDataKeys.PROJECT);
|
||||
final VcsRevisionNumber revision = getRevisionNumber(event);
|
||||
if (revision == null) {
|
||||
return;
|
||||
@@ -60,7 +70,7 @@ public class SelectRevisionInGitLogAction extends DumbAwareAction {
|
||||
Runnable selectCommit = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
log.jumpToReference(revision.asString());
|
||||
jumpToRevisionUnderProgress(project, log, revision);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -128,5 +138,25 @@ public class SelectRevisionInGitLogAction extends DumbAwareAction {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static void jumpToRevisionUnderProgress(@NotNull Project project, @NotNull VcsLog log, @NotNull VcsRevisionNumber revision) {
|
||||
final Future<Boolean> future = log.jumpToReference(revision.asString());
|
||||
if (!future.isDone()) {
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Searching for revision " + revision.asString(), false/*can not cancel*/,
|
||||
PerformInBackgroundOption.ALWAYS_BACKGROUND) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
try {
|
||||
future.get();
|
||||
}
|
||||
catch (CancellationException ignored) {
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user