Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2014-12-04 11:19:40 +01:00
57 changed files with 1235 additions and 782 deletions
@@ -1304,11 +1304,14 @@ public class BuildManager implements ApplicationComponent{
// this will ensure that we'll be able to obtain VirtualFile for existing roots
CompilerUtil.refreshOutputDirectories(rootFiles, false);
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
final LocalFileSystem lfs = LocalFileSystem.getInstance();
final Set<VirtualFile> filesToRefresh = new HashSet<VirtualFile>();
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (project.isDisposed()) {
return;
}
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
for (File root : rootFiles) {
final VirtualFile rootFile = lfs.findFileByIoFile(root);
if (rootFile != null && fileIndex.isInSourceContent(rootFile)) {
@@ -27,19 +27,12 @@ import com.intellij.debugger.engine.evaluation.expression.Modifier;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.JdkVersionUtil;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.extractMethodObject.ExtractLightMethodObjectHandler;
import com.intellij.util.PathsList;
import com.sun.jdi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.org.objectweb.asm.ClassReader;
@@ -55,9 +48,9 @@ import java.util.*;
/**
* @author egor
*/
public class CompilingEvaluator implements ExpressionEvaluator {
@NotNull private final PsiElement myPsiContext;
@NotNull private final ExtractLightMethodObjectHandler.ExtractedData myData;
public abstract class CompilingEvaluator implements ExpressionEvaluator {
@NotNull protected final PsiElement myPsiContext;
@NotNull protected final ExtractLightMethodObjectHandler.ExtractedData myData;
public CompilingEvaluator(@NotNull PsiElement context, @NotNull ExtractLightMethodObjectHandler.ExtractedData data) {
myPsiContext = context;
@@ -203,25 +196,8 @@ public class CompilingEvaluator implements ExpressionEvaluator {
//private static final String GEN_CLASS_FULL_NAME = GEN_CLASS_PACKAGE + '.' + GEN_CLASS_NAME;
//private static final String GEN_METHOD_NAME = "invoke";
private String getClassCode() {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return myData.getGeneratedInnerClass().getContainingFile().getText();
}
});
}
private String getMainClassName() {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return FileUtil.getNameWithoutExtension(myData.getGeneratedInnerClass().getContainingFile().getName());
}
});
}
private String getGenClassQName() {
protected String getGenClassQName() {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
@@ -250,57 +226,13 @@ public class CompilingEvaluator implements ExpressionEvaluator {
///////////////// Compiler stuff
@NotNull
private Collection<OutputFileObject> compile(String target) throws EvaluateException {
if (!SystemInfo.isJavaVersionAtLeast(target)) {
throw new EvaluateException("Unable to compile for target level " + target + ". Need to run IDEA on java version at least " + target + ", currently running on " + SystemInfo.JAVA_RUNTIME_VERSION);
}
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
MemoryFileManager manager = new MemoryFileManager(compiler);
DiagnosticCollector<JavaFileObject> diagnostic = new DiagnosticCollector<JavaFileObject>();
Module module = ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
@Override
public Module compute() {
return ModuleUtilCore.findModuleForPsiElement(myPsiContext);
}
});
List<String> options = new ArrayList<String>();
if (module != null) {
options.add("-cp");
PathsList cp = ModuleRootManager.getInstance(module).orderEntries().compileOnly().recursively().exportedOnly().withoutSdk().getPathsList();
options.add(cp.getPathsString());
}
if (!StringUtil.isEmpty(target)) {
options.add("-source");
options.add(target);
options.add("-target");
options.add(target);
}
try {
if (!compiler.getTask(null,
manager,
diagnostic,
options,
null,
Collections.singletonList(new SourceFileObject(getMainClassName(), JavaFileObject.Kind.SOURCE, getClassCode()))
).call()) {
StringBuilder res = new StringBuilder("Compilation failed:\n");
for (Diagnostic<? extends JavaFileObject> d : diagnostic.getDiagnostics()) {
res.append(d);
}
throw new EvaluateException(res.toString());
}
}
catch (Exception e) {
throw new EvaluateException(e.getMessage());
}
return manager.classes;
}
protected abstract Collection<OutputFileObject> compile(String target) throws EvaluateException;
private static URI getUri(String name, JavaFileObject.Kind kind) {
return URI.create("memo:///" + name.replace('.', '/') + kind.extension);
}
private static class SourceFileObject extends SimpleJavaFileObject {
protected static class SourceFileObject extends SimpleJavaFileObject {
private final String myContent;
SourceFileObject(String name, Kind kind, String content) {
@@ -314,7 +246,7 @@ public class CompilingEvaluator implements ExpressionEvaluator {
}
}
private static class OutputFileObject extends SimpleJavaFileObject {
protected static class OutputFileObject extends SimpleJavaFileObject {
private final ByteArrayOutputStream myStream = new ByteArrayOutputStream();
private final String myOrigName;
@@ -333,8 +265,8 @@ public class CompilingEvaluator implements ExpressionEvaluator {
}
}
private static class MemoryFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
private final Collection<OutputFileObject> classes = new ArrayList<OutputFileObject>();
protected static class MemoryFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
protected final Collection<OutputFileObject> classes = new ArrayList<OutputFileObject>();
MemoryFileManager(JavaCompiler compiler) {
super(compiler.getStandardFileManager(null, null, null));
@@ -0,0 +1,109 @@
/*
* Copyright 2000-2014 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.debugger.ui.impl.watch;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.extractMethodObject.ExtractLightMethodObjectHandler;
import com.intellij.util.PathsList;
import org.jetbrains.annotations.NotNull;
import javax.tools.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class CompilingEvaluatorImpl extends CompilingEvaluator {
public CompilingEvaluatorImpl(@NotNull PsiElement context, @NotNull ExtractLightMethodObjectHandler.ExtractedData data) {
super(context, data);
}
@Override
@NotNull
protected Collection<OutputFileObject> compile(String target) throws EvaluateException {
if (!SystemInfo.isJavaVersionAtLeast(target)) {
throw new EvaluateException("Unable to compile for target level " + target + ". Need to run IDEA on java version at least " + target + ", currently running on " + SystemInfo.JAVA_RUNTIME_VERSION);
}
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
MemoryFileManager manager = new MemoryFileManager(compiler);
DiagnosticCollector<JavaFileObject> diagnostic = new DiagnosticCollector<JavaFileObject>();
Module module = ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
@Override
public Module compute() {
return ModuleUtilCore.findModuleForPsiElement(myPsiContext);
}
});
List<String> options = new ArrayList<String>();
if (module != null) {
options.add("-cp");
PathsList cp = ModuleRootManager.getInstance(module).orderEntries().compileOnly().recursively().exportedOnly().withoutSdk().getPathsList();
options.add(cp.getPathsString());
}
if (!StringUtil.isEmpty(target)) {
options.add("-source");
options.add(target);
options.add("-target");
options.add(target);
}
try {
if (!compiler.getTask(null,
manager,
diagnostic,
options,
null,
Collections.singletonList(new SourceFileObject(getMainClassName(), JavaFileObject.Kind.SOURCE, getClassCode()))
).call()) {
StringBuilder res = new StringBuilder("Compilation failed:\n");
for (Diagnostic<? extends JavaFileObject> d : diagnostic.getDiagnostics()) {
res.append(d);
}
throw new EvaluateException(res.toString());
}
}
catch (Exception e) {
throw new EvaluateException(e.getMessage());
}
return manager.classes;
}
protected String getClassCode() {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return myData.getGeneratedInnerClass().getContainingFile().getText();
}
});
}
protected String getMainClassName() {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return FileUtil.getNameWithoutExtension(myData.getGeneratedInnerClass().getContainingFile().getName());
}
});
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -101,7 +101,7 @@ public abstract class EvaluationDescriptor extends ValueDescriptorImpl{
ExtractLightMethodObjectHandler.ExtractedData data = ExtractLightMethodObjectHandler.extractLightMethodObject(myProject,
psiFile, fragment, CompilingEvaluator.getGeneratedClassName());
if (data != null) {
return new CompilingEvaluator(psiContext, data);
return new CompilingEvaluatorImpl(psiContext, data);
}
}
catch (PrepareFailedException e) {
@@ -22,7 +22,7 @@ import com.intellij.psi.*;
* Nikolay.Tropin
* 2014-11-25
*/
interface SimpleGetterProvider {
public interface SimpleGetterProvider {
ExtensionPointName<SimpleGetterProvider> EP_NAME = ExtensionPointName.create("com.intellij.debugger.simpleGetterProvider");
boolean isSimpleGetter(PsiMethod method);
@@ -109,6 +109,13 @@ public abstract class FrameworkSupportModelBase extends UserDataHolderBase imple
node.setChecked(enable);
// ensure configurable to be created and registered to disposer
node.getConfigurable();
if (myFrameworkVersions.get(providerId) == null) {
for (FrameworkVersion version : node.getUserObject().getFrameworkType().getVersions()) {
if (version.getAvailabilityCondition().isAvailableFor(this)) {
setSelectedVersion(providerId, version);
}
}
}
}
}
@@ -26,7 +26,7 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -68,7 +68,7 @@ public class NullityInference {
final AtomicBoolean hasNotNulls = new AtomicBoolean();
final AtomicBoolean hasNulls = new AtomicBoolean();
final AtomicBoolean hasUnknowns = new AtomicBoolean();
final List<PsiMethodCallExpression> calls = ContainerUtil.newArrayList();
final Set<PsiMethod> delegates = ContainerUtil.newLinkedHashSet();
body.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitReturnStatement(PsiReturnStatement statement) {
@@ -87,7 +87,12 @@ public class NullityInference {
hasNotNulls.set(true);
}
else if (value instanceof PsiMethodCallExpression) {
calls.add((PsiMethodCallExpression)value);
PsiMethod target = ((PsiMethodCallExpression)value).resolveMethod();
if (target == null) {
hasUnknowns.set(true);
} else {
delegates.add(target);
}
}
else {
hasUnknowns.set(true);
@@ -106,13 +111,12 @@ public class NullityInference {
return Nullness.NULLABLE;
}
if (calls.size() > 1) {
if (hasErrors.get() || delegates.size() > 1) {
return Nullness.UNKNOWN;
}
if (calls.size() == 1) {
PsiMethod target = calls.get(0).resolveMethod();
if (target != null && NullableNotNullManager.isNotNull(target)) {
if (delegates.size() == 1) {
if (NullableNotNullManager.isNotNull(delegates.iterator().next())) {
return Nullness.NOT_NULL;
}
return Nullness.UNKNOWN;
@@ -25,6 +25,7 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
@@ -56,9 +57,10 @@ import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.*;
import com.intellij.util.ui.DialogUtil;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.table.JBListTable;
import com.intellij.util.ui.table.EditorTextFieldJBTableRowRenderer;
import com.intellij.util.ui.table.JBTableRow;
import com.intellij.util.ui.table.JBTableRowEditor;
import com.intellij.util.ui.table.JBTableRowRenderer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -72,6 +74,7 @@ import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import static com.intellij.refactoring.changeSignature.ChangeSignatureHandler.REFACTORING_NAME;
@@ -220,32 +223,175 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase<Paramet
}
@Override
protected boolean isEmptyRow(ParameterTableModelItemBase<ParameterInfoImpl> row) {
if (!StringUtil.isEmpty(row.parameter.getName())) return false;
if (!StringUtil.isEmpty(row.parameter.getTypeText())) return false;
return true;
}
protected ParametersListTable createParametersListTable() {
return new ParametersListTable() {
private final EditorTextFieldJBTableRowRenderer myRowRenderer = new EditorTextFieldJBTableRowRenderer(getProject(), myDisposable) {
@Override
protected String getText(JTable table, int row) {
ParameterTableModelItemBase<ParameterInfoImpl> item = getRowItem(row);
final String typeText = item.typeCodeFragment.getText();
final String separator = StringUtil.repeatSymbol(' ', getTypesMaxLength() - typeText.length() + 1);
String text = typeText + separator + item.parameter.getName();
final String defaultValue = item.defaultValueCodeFragment.getText();
String tail = "";
if (StringUtil.isNotEmpty(defaultValue)) {
tail += " default value = " + defaultValue;
}
if (item.parameter.isUseAnySingleVariable()) {
if (StringUtil.isNotEmpty(defaultValue)) {
tail += ";";
}
tail += " Use any var.";
}
if (!StringUtil.isEmpty(tail)) {
text += " //" + tail;
}
return " " + text;
}
@Override
protected JComponent getRowPresentation(ParameterTableModelItemBase<ParameterInfoImpl> item, boolean selected, final boolean focused) {
final String typeText = item.typeCodeFragment.getText();
final String separator = StringUtil.repeatSymbol(' ', getTypesMaxLength() - typeText.length() + 1);
String text = typeText + separator + item.parameter.getName();
final String defaultValue = item.defaultValueCodeFragment.getText();
String tail = "";
if (StringUtil.isNotEmpty(defaultValue)) {
tail += " default value = " + defaultValue;
}
if (item.parameter.isUseAnySingleVariable()) {
if (StringUtil.isNotEmpty(defaultValue)) {
tail += ";";
@Nullable
@Override
protected FileType getFileType() {
return JavaChangeSignatureDialog.this.getFileType();
}
};
@Override
protected JBTableRowRenderer getRowRenderer(int row) {
return myRowRenderer;
}
tail += " Use any var.";
}
if (!StringUtil.isEmpty(tail)) {
text += " //" + tail;
}
return JBListTable.createEditorTextFieldPresentation(getProject(), getFileType(), " " + text, selected, focused);
@NotNull
@Override
protected JBTableRowEditor getRowEditor(final ParameterTableModelItemBase<ParameterInfoImpl> item) {
return new JBTableRowEditor() {
private EditorTextField myTypeEditor;
private EditorTextField myNameEditor;
private EditorTextField myDefaultValueEditor;
private JCheckBox myAnyVar;
@Override
public void prepareEditor(JTable table, int row) {
setLayout(new BorderLayout());
final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(item.typeCodeFragment);
myTypeEditor = new EditorTextField(document, getProject(), getFileType());
myTypeEditor.addDocumentListener(mySignatureUpdater);
myTypeEditor.setPreferredWidth(getTable().getWidth() / 2);
myTypeEditor.addDocumentListener(new RowEditorChangeListener(0));
add(createLabeledPanel("Type:", myTypeEditor), BorderLayout.WEST);
myNameEditor = new EditorTextField(item.parameter.getName(), getProject(), getFileType());
myNameEditor.addDocumentListener(mySignatureUpdater);
myNameEditor.addDocumentListener(new RowEditorChangeListener(1));
add(createLabeledPanel("Name:", myNameEditor), BorderLayout.CENTER);
new TextFieldCompletionProvider() {
@Override
protected void addCompletionVariants(@NotNull String text,
int offset,
@NotNull String prefix,
@NotNull CompletionResultSet result) {
final PsiCodeFragment fragment = item.typeCodeFragment;
if (fragment instanceof PsiTypeCodeFragment) {
final PsiType type;
try {
type = ((PsiTypeCodeFragment)fragment).getType();
}
catch (Exception e) {
return;
}
final SuggestedNameInfo info = JavaCodeStyleManager.getInstance(myProject)
.suggestVariableName(VariableKind.PARAMETER, null, null, type);
for (String completionVariant : info.names) {
final LookupElementBuilder element = LookupElementBuilder.create(completionVariant);
result.addElement(element.withLookupString(completionVariant.toLowerCase(Locale.ENGLISH)));
}
}
}
}.apply(myNameEditor, item.parameter.getName());
if (!item.isEllipsisType() && item.parameter.getOldIndex() == -1) {
final JPanel additionalPanel = new JPanel(new BorderLayout());
final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(item.defaultValueCodeFragment);
myDefaultValueEditor = new EditorTextField(doc, getProject(), getFileType());
((PsiExpressionCodeFragment)item.defaultValueCodeFragment).setExpectedType(getRowType(item));
myDefaultValueEditor.setPreferredWidth(getTable().getWidth() / 2);
myDefaultValueEditor.addDocumentListener(new RowEditorChangeListener(2));
additionalPanel.add(createLabeledPanel("Default value:", myDefaultValueEditor), BorderLayout.WEST);
if (!isGenerateDelegate()) {
myAnyVar = new JCheckBox("&Use Any Var");
UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, myAnyVar);
DialogUtil.registerMnemonic(myAnyVar, '&');
myAnyVar.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
item.parameter.setUseAnySingleVariable(myAnyVar.isSelected());
}
});
final JPanel anyVarPanel = new JPanel(new BorderLayout());
anyVarPanel.add(myAnyVar, BorderLayout.SOUTH);
UIUtil.addInsets(anyVarPanel, new Insets(0,0,8,0));
additionalPanel.add(anyVarPanel, BorderLayout.CENTER);
//additionalPanel.setPreferredSize(new Dimension(t.getWidth() / 3, -1));
}
add(additionalPanel, BorderLayout.SOUTH);
}
}
@Override
public JBTableRow getValue() {
return new JBTableRow() {
@Override
public Object getValueAt(int column) {
switch (column) {
case 0: return item.typeCodeFragment;
case 1: return myNameEditor.getText().trim();
case 2: return item.defaultValueCodeFragment;
case 3: return myAnyVar != null && myAnyVar.isSelected();
}
return null;
}
};
}
@Override
public JComponent getPreferredFocusedComponent() {
final MouseEvent me = getMouseEvent();
if (me == null) {
return myTypeEditor.getFocusTarget();
}
final double x = me.getPoint().getX();
return x <= getTypesColumnWidth()
? myTypeEditor.getFocusTarget()
: myDefaultValueEditor == null || x <= getNamesColumnWidth()
? myNameEditor.getFocusTarget()
: myDefaultValueEditor.getFocusTarget();
}
@Override
public JComponent[] getFocusableComponents() {
final List<JComponent> focusable = new ArrayList<JComponent>();
focusable.add(myTypeEditor.getFocusTarget());
focusable.add(myNameEditor.getFocusTarget());
if (myDefaultValueEditor != null) {
focusable.add(myDefaultValueEditor.getFocusTarget());
}
if (myAnyVar != null) {
focusable.add(myAnyVar);
}
return focusable.toArray(new JComponent[focusable.size()]);
}
};
}
@Override
protected boolean isRowEmpty(int row) {
ParameterInfoImpl parameter = getRowItem(row).parameter;
return StringUtil.isEmpty(parameter.getName()) && StringUtil.isEmpty(parameter.getTypeText());
}
};
}
private int getTypesMaxLength() {
@@ -281,130 +427,6 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase<Paramet
return getColumnWidth(1);
}
@Override
protected JBTableRowEditor getTableEditor(final JTable t, final ParameterTableModelItemBase<ParameterInfoImpl> item) {
return new JBTableRowEditor() {
private EditorTextField myTypeEditor;
private EditorTextField myNameEditor;
private EditorTextField myDefaultValueEditor;
private JCheckBox myAnyVar;
@Override
public void prepareEditor(JTable table, int row) {
setLayout(new BorderLayout());
final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(item.typeCodeFragment);
myTypeEditor = new EditorTextField(document, getProject(), getFileType());
myTypeEditor.addDocumentListener(mySignatureUpdater);
myTypeEditor.setPreferredWidth(t.getWidth() / 2);
myTypeEditor.addDocumentListener(new RowEditorChangeListener(0));
add(createLabeledPanel("Type:", myTypeEditor), BorderLayout.WEST);
myNameEditor = new EditorTextField(item.parameter.getName(), getProject(), getFileType());
myNameEditor.addDocumentListener(mySignatureUpdater);
myNameEditor.addDocumentListener(new RowEditorChangeListener(1));
add(createLabeledPanel("Name:", myNameEditor), BorderLayout.CENTER);
new TextFieldCompletionProvider() {
@Override
protected void addCompletionVariants(@NotNull String text,
int offset,
@NotNull String prefix,
@NotNull CompletionResultSet result) {
final PsiCodeFragment fragment = item.typeCodeFragment;
if (fragment instanceof PsiTypeCodeFragment) {
final PsiType type;
try {
type = ((PsiTypeCodeFragment)fragment).getType();
}
catch (Exception e) {
return;
}
final SuggestedNameInfo info = JavaCodeStyleManager.getInstance(myProject)
.suggestVariableName(VariableKind.PARAMETER, null, null, type);
for (String completionVariant : info.names) {
final LookupElementBuilder element = LookupElementBuilder.create(completionVariant);
result.addElement(element.withLookupString(completionVariant.toLowerCase()));
}
}
}
}.apply(myNameEditor, item.parameter.getName());
if (!item.isEllipsisType() && item.parameter.getOldIndex() == -1) {
final JPanel additionalPanel = new JPanel(new BorderLayout());
final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(item.defaultValueCodeFragment);
myDefaultValueEditor = new EditorTextField(doc, getProject(), getFileType());
((PsiExpressionCodeFragment)item.defaultValueCodeFragment).setExpectedType(getRowType(item));
myDefaultValueEditor.setPreferredWidth(t.getWidth() / 2);
myDefaultValueEditor.addDocumentListener(new RowEditorChangeListener(2));
additionalPanel.add(createLabeledPanel("Default value:", myDefaultValueEditor), BorderLayout.WEST);
if (!isGenerateDelegate()) {
myAnyVar = new JCheckBox("&Use Any Var");
UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, myAnyVar);
DialogUtil.registerMnemonic(myAnyVar, '&');
myAnyVar.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
item.parameter.setUseAnySingleVariable(myAnyVar.isSelected());
}
});
final JPanel anyVarPanel = new JPanel(new BorderLayout());
anyVarPanel.add(myAnyVar, BorderLayout.SOUTH);
UIUtil.addInsets(anyVarPanel, new Insets(0,0,8,0));
additionalPanel.add(anyVarPanel, BorderLayout.CENTER);
//additionalPanel.setPreferredSize(new Dimension(t.getWidth() / 3, -1));
}
add(additionalPanel, BorderLayout.SOUTH);
}
}
@Override
public JBTableRow getValue() {
return new JBTableRow() {
@Override
public Object getValueAt(int column) {
switch (column) {
case 0: return item.typeCodeFragment;
case 1: return myNameEditor.getText().trim();
case 2: return item.defaultValueCodeFragment;
case 3: return myAnyVar != null && myAnyVar.isSelected();
}
return null;
}
};
}
@Override
public JComponent getPreferredFocusedComponent() {
final MouseEvent me = getMouseEvent();
if (me == null) {
return myTypeEditor.getFocusTarget();
}
final double x = me.getPoint().getX();
return x <= getTypesColumnWidth()
? myTypeEditor.getFocusTarget()
: myDefaultValueEditor == null || x <= getNamesColumnWidth()
? myNameEditor.getFocusTarget()
: myDefaultValueEditor.getFocusTarget();
}
@Override
public JComponent[] getFocusableComponents() {
final List<JComponent> focusable = new ArrayList<JComponent>();
focusable.add(myTypeEditor.getFocusTarget());
focusable.add(myNameEditor.getFocusTarget());
if (myDefaultValueEditor != null) {
focusable.add(myDefaultValueEditor.getFocusTarget());
}
if (myAnyVar != null) {
focusable.add(myAnyVar);
}
return focusable.toArray(new JComponent[focusable.size()]);
}
};
}
@Nullable
private static PsiType getRowType(ParameterTableModelItemBase<ParameterInfoImpl> item) {
try {
@@ -28,6 +28,7 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.IntArrayList;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -142,10 +143,12 @@ public class ControlFlowWrapper {
public static class ExitStatementsNotSameException extends Exception {}
@NotNull
public PsiVariable[] getOutputVariables() {
return getOutputVariables(myGenerateConditionalExit);
}
@NotNull
public PsiVariable[] getOutputVariables(boolean collectVariablesAtExitPoints) {
PsiVariable[] myOutputVariables = ControlFlowUtil.getOutputVariables(myControlFlow, myFlowStart, myFlowEnd, myExitPoints.toArray());
if (collectVariablesAtExitPoints) {
@@ -41,6 +41,7 @@ import com.intellij.ui.EditorTextField;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.NonFocusableCheckBox;
import com.intellij.ui.SeparatorFactory;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.VisibilityUtil;
import com.intellij.util.containers.MultiMap;
@@ -240,14 +241,28 @@ public class ExtractMethodDialog extends DialogWrapper implements AbstractExtrac
return main;
}
protected boolean isVoidReturn() {
return false;
}
@Nullable
private JPanel createReturnTypePanel() {
if (TypeConversionUtil.isPrimitiveWrapper(myReturnType) && myNullness == Nullness.NULLABLE) {
return null;
}
mySelector = new TypeSelectorManagerImpl(myProject, myReturnType, findOccurrences(), areTypesDirected()).getTypeSelector();
final TypeSelectorManagerImpl manager = new TypeSelectorManagerImpl(myProject, myReturnType, findOccurrences(), areTypesDirected()) {
@Override
public PsiType[] getTypesForAll(boolean direct) {
final PsiType[] types = super.getTypesForAll(direct);
return !isVoidReturn() ? types : ArrayUtil.prepend(PsiType.VOID, types);
}
};
mySelector = manager.getTypeSelector();
final JComponent component = mySelector.getComponent();
if (component instanceof JComboBox) {
if (isVoidReturn()) {
mySelector.selectType(PsiType.VOID);
}
final JPanel returnTypePanel = new JPanel(new BorderLayout(2, 0));
final JLabel label = new JLabel(RefactoringBundle.message("changeSignature.return.type.prompt"));
returnTypePanel.add(label, BorderLayout.NORTH);
@@ -53,6 +53,8 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.controlFlow.ControlFlowUtil;
import com.intellij.psi.impl.source.codeStyle.JavaCodeStyleManagerImpl;
import com.intellij.psi.scope.processor.VariablesProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.PsiElementProcessor;
@@ -112,6 +114,7 @@ public class ExtractMethodProcessor implements MatchProvider {
protected InputVariables myInputVariables; // input variables
protected PsiVariable[] myOutputVariables; // output variables
protected PsiVariable myOutputVariable; // the only output variable
private PsiVariable myArtificialOutputVariable;
private Collection<PsiStatement> myExitStatements;
private boolean myHasReturnStatement; // there is a return statement
@@ -339,6 +342,23 @@ public class ExtractMethodProcessor implements MatchProvider {
: null;
}
@Nullable
private PsiVariable getArtificialOutputVariable() {
if (myOutputVariables.length == 0) {
final VariablesProcessor processor = new VariablesProcessor(true) {
@Override
protected boolean check(PsiVariable var, ResolveState state) {
return isDeclaredInside(var);
}
};
PsiScopesUtil.treeWalkUp(processor, myElements[myElements.length - 1], myCodeFragmentMember);
if (processor.size() == 1) {
return processor.getResult(0);
}
}
return null;
}
private boolean areAllExitPointsAreNotNull(PsiType returnStatementType) {
if (insertNotNullCheckIfPossible() && myControlFlowWrapper.getOutputVariables(false).length == 0) {
boolean isNotNull = returnStatementType != null && returnStatementType != PsiType.VOID;
@@ -508,7 +528,9 @@ public class ExtractMethodProcessor implements MatchProvider {
final List<VariableData> variables = myInputVariables.getInputVariables();
myVariableDatum = variables.toArray(new VariableData[variables.size()]);
myNullness = initNullness();
return new ExtractMethodDialog(myProject, myTargetClass, myInputVariables, myReturnType, getTypeParameterList(),
myArtificialOutputVariable = PsiType.VOID.equals(myReturnType) ? getArtificialOutputVariable() : null;
final PsiType returnType = myArtificialOutputVariable != null ? myArtificialOutputVariable.getType() : myReturnType;
return new ExtractMethodDialog(myProject, myTargetClass, myInputVariables, returnType, getTypeParameterList(),
getThrownExceptions(), isStatic(), isCanBeStatic(), myCanBeChainedConstructor,
suggestInitialMethodName(),
myRefactoringName, myHelpId, myNullness, myElements) {
@@ -526,6 +548,10 @@ public class ExtractMethodProcessor implements MatchProvider {
return ExtractMethodProcessor.this.isOutputVariable(var);
}
protected boolean isVoidReturn() {
return myArtificialOutputVariable != null;
}
@Override
protected void checkMethodConflicts(MultiMap<PsiElement, String> conflicts) {
super.checkMethodConflicts(conflicts);
@@ -669,6 +695,9 @@ public class ExtractMethodProcessor implements MatchProvider {
myInputVariables.setPassFields(true);
myStatic = true;
}
if (PsiType.VOID.equals(myReturnType)) {
myArtificialOutputVariable = getArtificialOutputVariable();
}
testPrepare();
if (returnType != null) {
myReturnType = returnType;
@@ -850,9 +879,14 @@ public class ExtractMethodProcessor implements MatchProvider {
myMethodCall = (PsiMethodCallExpression)((PsiReturnStatement)statement).getReturnValue().replace(myMethodCall);
}
else {
PsiStatement statement = myElementFactory.createStatementFromText("x();", null);
statement = (PsiStatement)addToMethodCallLocation(statement);
myMethodCall = (PsiMethodCallExpression)((PsiExpressionStatement)statement).getExpression().replace(myMethodCall);
if (myArtificialOutputVariable != null && myReturnType != PsiType.VOID) {
declareVariableAtMethodCallLocation(myArtificialOutputVariable.getName());
}
else {
PsiStatement statement = myElementFactory.createStatementFromText("x();", null);
statement = (PsiStatement)addToMethodCallLocation(statement);
myMethodCall = (PsiMethodCallExpression)((PsiExpressionStatement)statement).getExpression().replace(myMethodCall);
}
}
if (myHasReturnStatement && !myHasReturnStatementOutput && !hasNormalExit()) {
PsiStatement statement = myElementFactory.createStatementFromText("return;", null);
@@ -1012,6 +1046,9 @@ public class ExtractMethodProcessor implements MatchProvider {
}
}
}
else if (myArtificialOutputVariable != null && !PsiType.VOID.equals(myReturnType)) {
body.add(myElementFactory.createStatementFromText("return " + myArtificialOutputVariable.getName() + ";", null));
}
return exitStatementCopy;
}
@@ -118,7 +118,10 @@ public class ReassignVariableUtil {
};
PsiElement scope = declaration;
while (scope != null) {
if (scope instanceof PsiFile || scope instanceof PsiMethod || scope instanceof PsiClassInitializer) break;
if (scope instanceof PsiFile ||
scope instanceof PsiMethod ||
scope instanceof PsiLambdaExpression ||
scope instanceof PsiClassInitializer) break;
scope = scope.getParent();
}
if (scope == null) return proc;
@@ -205,7 +205,7 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
}
}
private PsiType[] getTypesForAll(final boolean areTypesDirected) {
protected PsiType[] getTypesForAll(final boolean areTypesDirected) {
final ArrayList<ExpectedTypeInfo[]> expectedTypesFromAll = new ArrayList<ExpectedTypeInfo[]>();
for (PsiExpression occurrence : myOccurrences) {
final ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes(occurrence, false, myOccurrenceClassProvider, isUsedAfter());
@@ -514,7 +514,8 @@ public final class PsiUtil extends PsiUtilCore {
PsiType lastParmType = getParameterType(lastParameter, languageLevel, substitutorForMethod);
if (!(lastParmType instanceof PsiArrayType)) return ApplicabilityLevel.NOT_APPLICABLE;
lastParmType = ((PsiArrayType)lastParmType).getComponentType();
if (lastParmType instanceof PsiCapturedWildcardType && !JavaVersionService.getInstance().isAtLeast(lastParameter, JavaSdkVersion.JDK_1_8)) {
if (lastParmType instanceof PsiCapturedWildcardType &&
!JavaVersionService.getInstance().isAtLeast(((PsiCapturedWildcardType)lastParmType).getContext(), JavaSdkVersion.JDK_1_8)) {
lastParmType = ((PsiCapturedWildcardType)lastParmType).getWildcard();
}
for (int i = parms.length - 1; i < args.length; i++) {
@@ -0,0 +1,5 @@
class X {
void foo() {
<selection>int x = 0;</selection>
}
}
@@ -0,0 +1,10 @@
class X {
void foo() {
int x = newMethod();
}
private int newMethod() {
int x = 0;
return x;
}
}
@@ -0,0 +1,7 @@
class X {
void foo() {
<selection>int x = 0;
int y = 42;
</selection>
}
}
@@ -0,0 +1,11 @@
class X {
void foo() {
newMethod();
}
private int newMethod() {
int x = 0;
int y = 42;
}
}
@@ -42,6 +42,17 @@ abstract class NullityInferenceFromSourceTestCase extends LightCodeInsightFixtur
assert inferNullity(parse('String foo() { return bar(); }; String bar() { return "z"; }; ')) == NOT_NULL
}
void "test same delegate method invoked twice"() {
assert inferNullity(parse('''
String foo() {
if (equals(2)) return bar();
if (equals(3)) return bar();
return "abc";
}
String bar() { return "z"; }
''')) == NOT_NULL
}
void "test if branch returns null"() {
assert inferNullity(parse('String bar() { if (equals(2)) return null; return "a"; }; ')) == NULLABLE
}
@@ -64,7 +75,7 @@ abstract class NullityInferenceFromSourceTestCase extends LightCodeInsightFixtur
protected abstract Nullness inferNullity(PsiMethod method)
private PsiMethod parse(String method) {
protected PsiMethod parse(String method) {
return myFixture.addClass("final class Foo { $method }").methods[0]
}
@@ -72,6 +83,10 @@ abstract class NullityInferenceFromSourceTestCase extends LightCodeInsightFixtur
Nullness inferNullity(PsiMethod method) {
return NullableNotNullManager.isNotNull(method) ? NOT_NULL : NullableNotNullManager.isNullable(method) ? NULLABLE : UNKNOWN
}
void "test skip when errors"() {
assert inferNullity(parse('String foo() { if(); return 2; } ')) == UNKNOWN
}
}
static class DfaInferenceTest extends NullityInferenceFromSourceTestCase {
@@ -252,7 +252,8 @@ public class IndexTest extends JavaCodeInsightFixtureTestCase {
((VirtualFileSystemEntry)vFile).setModificationStamp(0); // as unchanged file
final Document document = FileDocumentManager.getInstance().getDocument(vFile);
assertTrue(document != null && document.getModificationStamp() == 0);
assertTrue(document != null);
assert document.getModificationStamp() == 0;
assertNotNull(findClass("Foo"));
WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
@@ -629,6 +629,15 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
doTestReturnTypeChanged(PsiType.getJavaLangObject(getPsiManager(), GlobalSearchScope.allScope(getProject())));
}
public void testMakeVoidMethodReturnVariable() throws Exception {
doTestReturnTypeChanged(PsiType.INT);
}
public void testMultipleVarsInMethodNoReturnStatementAndAssignment() throws Exception {
//return type should not be suggested but still
doTestReturnTypeChanged(PsiType.INT);
}
public void testPassFieldAsParameterAndMakeStatic() throws Exception {
doTestPassFieldsAsParams();
}
@@ -115,11 +115,11 @@ public class HighlightDisplayLevel {
@NotNull
public static Icon createIconByMask(final Color renderColor) {
return new MyColorIcon(EMPTY_ICON_DIM, renderColor);
return new TheColorIcon(EMPTY_ICON_DIM, renderColor);
}
private static class MyColorIcon extends ColorIcon implements ColoredIcon {
public MyColorIcon(int size, @NotNull Color color) {
public static class TheColorIcon extends ColorIcon implements ColoredIcon {
public TheColorIcon(int size, @NotNull Color color) {
super(size, color);
}
@@ -93,7 +93,9 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator<Highlig
myRendererColors.put(severity.getName(), renderColor);
}
myOrderMap = null;
HighlightDisplayLevel.registerSeverity(severity, getHighlightInfoTypeBySeverity(severity).getAttributesKey());
Color color = info.getAttributes().getErrorStripeColor();
new HighlightDisplayLevel(severity, new HighlightDisplayLevel.TheColorIcon(HighlightDisplayLevel.EMPTY_ICON_DIM, color));
severitiesChanged();
}
@@ -324,6 +324,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
VirtualFile file = viewProvider.getVirtualFile();
msg += "; file stamp: " + file.getModificationStamp();
msg += "; file modCount: " + file.getModificationCount();
msg += "; file length: " + file.getLength();
Document document = FileDocumentManager.getInstance().getCachedDocument(file);
if (document != null) {
@@ -332,6 +333,8 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
msg += "; doc size: " + document.getTextLength();
msg += "; committed: " + PsiDocumentManager.getInstance(getProject()).isCommitted(document);
}
msg += "\nindexing info: " + StubTreeLoader.getInstance().getIndexingStampDebugInfo(file);
throw new AssertionError(msg + "\n------------\n");
}
@@ -87,4 +87,9 @@ public class CoreStubTreeLoader extends StubTreeLoader {
}
return false;
}
@Override
public String getIndexingStampDebugInfo(VirtualFile file) {
return "";
}
}
@@ -41,4 +41,6 @@ public abstract class StubTreeLoader {
public abstract long getStubTreeTimestamp(VirtualFile vFile);
public abstract boolean canHaveStub(VirtualFile file);
public abstract String getIndexingStampDebugInfo(VirtualFile file);
}
@@ -84,7 +84,7 @@ public class DocumentMarkupModel {
if (create && model == null) {
MarkupModelImpl newModel = new MarkupModelImpl((DocumentEx)document);
if ((model = ConcurrencyUtil.cacheOrGet(markupModelMap, project, newModel)) == newModel) {
documentMarkupModelManager.registerDocument((DocumentImpl)document);
documentMarkupModelManager.registerDocument(document);
}
else {
newModel.dispose();
@@ -18,6 +18,7 @@ package com.intellij.openapi.editor.impl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.containers.WeakList;
@@ -29,7 +30,7 @@ import org.jetbrains.annotations.NotNull;
public class DocumentMarkupModelManager extends AbstractProjectComponent {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.DocumentMarkupModelManager");
private final WeakList<DocumentImpl> myDocumentSet = new WeakList<DocumentImpl>();
private final WeakList<Document> myDocumentSet = new WeakList<Document>();
private volatile boolean myDisposed;
public static DocumentMarkupModelManager getInstance(Project project) {
@@ -46,7 +47,7 @@ public class DocumentMarkupModelManager extends AbstractProjectComponent {
});
}
public void registerDocument(DocumentImpl document) {
public void registerDocument(Document document) {
LOG.assertTrue(!myDisposed);
myDocumentSet.add(document);
}
@@ -58,7 +59,7 @@ public class DocumentMarkupModelManager extends AbstractProjectComponent {
private void cleanupProjectMarkups() {
if (!myDisposed) {
myDisposed = true;
for (DocumentImpl document : myDocumentSet.toStrongList()) {
for (Document document : myDocumentSet.toStrongList()) {
DocumentMarkupModel.removeMarkupModel(document, myProject);
}
}
@@ -167,4 +167,9 @@ public class StubTreeLoaderImpl extends StubTreeLoader {
public boolean canHaveStub(VirtualFile file) {
return StubUpdatingIndex.canHaveStub(file);
}
@Override
public String getIndexingStampDebugInfo(VirtualFile file) {
return StubUpdatingIndex.getIndexingStampInfo(file);
}
}
@@ -51,6 +51,7 @@ import com.intellij.util.PlatformIcons;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.table.JBListTable;
import com.intellij.util.ui.table.JBTableRowEditor;
import com.intellij.util.ui.table.JBTableRowRenderer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -458,37 +459,7 @@ public abstract class ChangeSignatureDialogBase<ParamInfo extends ParameterInfo,
myPropagateParamChangesButton.setShortcut(CustomShortcutSet.fromString("alt G"));
if (isListTableViewSupported() && Registry.is("change.signature.awesome.mode")) {
myParametersList = new JBListTable(myParametersTable) {
@Override
protected JComponent getRowRenderer(JTable table, int row, boolean selected, boolean focused) {
final List<ParameterTableModelItem> items = myParametersTable.getItems();
return getRowPresentation(items.get(row), selected, focused);
}
@Override
protected boolean isRowEmpty(int row) {
final List<ParameterTableModelItem> items = myParametersTable.getItems();
return isEmptyRow(items.get(row));
}
@Override
protected JBTableRowEditor getRowEditor(final int row) {
final List<ParameterTableModelItem> items = myParametersTable.getItems();
JBTableRowEditor editor = getTableEditor(myParametersList.getTable(), items.get(row));
LOG.assertTrue(editor != null);
editor.addDocumentListener(new JBTableRowEditor.RowDocumentListener() {
@Override
public void documentChanged(DocumentEvent e, int column) {
if (myParametersTableModel.getColumnClass(column).equals(String.class)) {
myParametersTableModel.setValueAtWithoutUpdate(e.getDocument().getText(), row, column);
}
updateSignature();
}
});
return editor;
}
};
myParametersList = createParametersListTable();
final JPanel buttonsPanel = ToolbarDecorator.createDecorator(myParametersList.getTable())
.addExtraAction(myPropagateParamChangesButton)
.createPanel();
@@ -512,15 +483,56 @@ public abstract class ChangeSignatureDialogBase<ParamInfo extends ParameterInfo,
}
}
protected ParametersListTable createParametersListTable() {
return new ParametersListTable() {
@Override
protected JBTableRowRenderer getRowRenderer(int row) {
return new JBTableRowRenderer() {
@Override
public JComponent getRowRendererComponent(JTable table, int row, boolean selected, boolean focused) {
JComponent presentation = getRowPresentation(getRowItem(row), selected, focused);
LOG.assertTrue(presentation != null);
return presentation;
}
};
}
@NotNull
@Override
protected JBTableRowEditor getRowEditor(ParameterTableModelItemBase<ParamInfo> item) {
JBTableRowEditor editor = ChangeSignatureDialogBase.this.getTableEditor(getTable(), item);
LOG.assertTrue(editor != null);
return editor;
}
@Override
protected boolean isRowEmpty(int row) {
return ChangeSignatureDialogBase.this.isEmptyRow(getRowItem(row));
}
};
}
/**
* @deprecated override {@link #createParametersListTable} instead.
*/
@Deprecated
@Nullable
protected JBTableRowEditor getTableEditor(JTable table, ParameterTableModelItemBase<ParamInfo> item) {
return null;
}
/**
* @deprecated override {@link #createParametersListTable} instead.
*/
@Deprecated
protected boolean isEmptyRow(ParameterTableModelItemBase<ParamInfo> row) {
return false;
}
/**
* @deprecated override {@link #createParametersListTable} instead.
*/
@Deprecated
@Nullable
protected JComponent getRowPresentation(ParameterTableModelItemBase<ParamInfo> item, boolean selected, boolean focused) {
return null;
@@ -673,4 +685,35 @@ public abstract class ChangeSignatureDialogBase<ParamInfo extends ParameterInfo,
public void beforeDocumentChange(DocumentEvent event) {
}
}
protected abstract class ParametersListTable extends JBListTable {
public ParametersListTable() {
super(myParametersTable);
}
@Override
protected final JBTableRowEditor getRowEditor(final int row) {
JBTableRowEditor editor = getRowEditor(getRowItem(row));
editor.addDocumentListener(new JBTableRowEditor.RowDocumentListener() {
@Override
public void documentChanged(DocumentEvent e, int column) {
if (String.class.equals(myParametersTableModel.getColumnClass(column))) {
myParametersTableModel.setValueAtWithoutUpdate(e.getDocument().getText(), row, column);
}
updateSignature();
}
});
return editor;
}
@NotNull
protected abstract JBTableRowEditor getRowEditor(ParameterTableModelItemBase<ParamInfo> item);
@Override
protected abstract boolean isRowEmpty(int row);
protected ParameterTableModelItem getRowItem(int row) {
return myParametersTable.getItems().get(row);
}
}
}
@@ -120,8 +120,7 @@ class TableToolbarDecorator extends ToolbarDecorator {
table.setColumnSelectionInterval(0, 0);
table.editCellAt(index, 0);
boolean temporaryHideVerticalScrollBar = table.getCellEditor() instanceof Animated;
TableUtil.updateScroller(table, temporaryHideVerticalScrollBar);
TableUtil.updateScroller(table);
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
@@ -145,7 +144,7 @@ class TableToolbarDecorator extends ToolbarDecorator {
if (TableUtil.doRemoveSelectedItems(table, tableModel, null)) {
updateButtons();
table.requestFocus();
TableUtil.updateScroller(table, false);
TableUtil.updateScroller(table);
}
}
};
@@ -17,10 +17,9 @@
package com.intellij.openapi.options.ex;
import com.intellij.ide.ui.search.SearchUtil;
import com.intellij.openapi.ui.GraphicsConfig;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBTabbedPane;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
@@ -30,7 +29,6 @@ import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.Kernel;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
@@ -60,19 +58,15 @@ public class GlassPanel extends JComponent {
public void paintSpotlight(final Graphics g, final JComponent surfaceComponent) {
Dimension size = surfaceComponent.getSize();
if (myLightComponents.size() > 0) {
int width = size.width - 1;
int height = size.height - 1;
int stroke = 2;
Rectangle2D screen = new Rectangle2D.Double(0, 0, width, height);
final Rectangle visibleRect = myPanel.getVisibleRect();
final Point leftPoint = SwingUtilities.convertPoint(myPanel, new Point(visibleRect.x, visibleRect.y), surfaceComponent);
Area innerPanel = new Area(new Rectangle2D.Double(leftPoint.x, leftPoint.y, visibleRect.width, visibleRect.height));
Area mask = new Area(screen);
ArrayList<JComponent> components = new ArrayList<JComponent>();
Area mask = new Area(new Rectangle(-stroke, -stroke, 2 * stroke + size.width, 2 * stroke + size.height));
for (JComponent lightComponent : myLightComponents) {
final Area area = getComponentArea(surfaceComponent, lightComponent, 1);
if (area == null) continue;
components.add(lightComponent);
if (lightComponent instanceof JLabel) {
final JLabel label = (JLabel)lightComponent;
@@ -80,7 +74,6 @@ public class GlassPanel extends JComponent {
if (labelFor instanceof JComponent) {
final Area labelForArea = getComponentArea(surfaceComponent, (JComponent)labelFor, 1);
if (labelForArea != null) {
components.add((JComponent)labelFor);
area.add(labelForArea);
}
}
@@ -89,35 +82,28 @@ public class GlassPanel extends JComponent {
area.intersect(innerPanel);
mask.subtract(area);
}
Graphics clip = g.create(0, 0, size.width, size.height);
try {
Graphics2D g2 = (Graphics2D)clip;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
Graphics2D g2 = (Graphics2D)g;
Color background = surfaceComponent.getBackground();
g2.setColor(ColorUtil.toAlpha(background == null ? null : background.darker(), 100));
g2.fill(mask);
Color shieldColor = new Color(0.0f, 0.0f, 0.0f, 0.20f);
Color boundsColor = Color.gray;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(shieldColor);
g2.fill(mask);
g2.setColor(ColorUtil.toAlpha(Color.orange, 25));
GraphicsConfig config = GraphicsUtil.setupAAPainting(g2);
for (int i = 2; i > 0; i--) {
g2.setStroke(new BasicStroke(i));
Area arrr = new Area();
for (JComponent component : components) {
Area area = getComponentArea(surfaceComponent, component, i-1);
if (area != null) {
arrr.add(area);
}
}
g2.draw(arrr);
g2.setStroke(new BasicStroke(stroke));
g2.setColor(ColorUtil.toAlpha(JBColor.ORANGE, 100));
g2.draw(mask);
}
finally {
clip.dispose();
}
config.restore();
}
}
@Nullable
private Area getComponentArea(final JComponent surfaceComponent, final JComponent lightComponent, int offset) {
private static Area getComponentArea(final JComponent surfaceComponent, final JComponent lightComponent, int offset) {
if (!lightComponent.isShowing()) return null;
final Point panelPoint = SwingUtilities.convertPoint(lightComponent, new Point(0, 0), surfaceComponent);
@@ -173,6 +159,9 @@ public class GlassPanel extends JComponent {
public void removeSpotlight(final JComponent component){
myLightComponents.remove(component);
if (myLightComponents.isEmpty()) {
setVisible(false);
}
}
public void clear() {
@@ -18,9 +18,10 @@ package com.intellij.platform;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComponentWithBrowseButton;
import com.intellij.openapi.ui.ComponentWithBrowseButton.BrowseFolderActionListener;
import com.intellij.openapi.ui.TextComponentAccessor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.DocumentAdapter;
@@ -35,9 +36,9 @@ import javax.swing.text.PlainDocument;
import java.io.File;
/**
* User: catherine
* <p/>
* Logic for updating 2 fields: name for new directory and it's base location
*
* @author catherine
*/
public class LocationNameFieldsBinding {
private boolean myModifyingLocation = false;
@@ -46,60 +47,59 @@ public class LocationNameFieldsBinding {
private String myBaseDir;
private String mySuggestedProjectName;
public LocationNameFieldsBinding(@Nullable Project project, final TextFieldWithBrowseButton locationTextField,
final JTextField nameTextField, String baseDir, final String browseFolderTitle) {
public LocationNameFieldsBinding(@Nullable Project project,
final TextFieldWithBrowseButton locationField,
final JTextField nameField,
String baseDir,
String title) {
myBaseDir = baseDir;
File suggestedProjectDirectory = FileUtil.findSequentNonexistentFile(new File(baseDir), "untitled", "");
locationTextField.setText(suggestedProjectDirectory.toString());
nameTextField.setDocument(new NameFieldDocument(nameTextField, locationTextField));
locationField.setText(suggestedProjectDirectory.toString());
nameField.setDocument(new NameFieldDocument(nameField, locationField));
mySuggestedProjectName = suggestedProjectDirectory.getName();
nameTextField.setText(mySuggestedProjectName);
nameTextField.selectAll();
nameField.setText(mySuggestedProjectName);
nameField.selectAll();
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
ComponentWithBrowseButton.BrowseFolderActionListener<JTextField> listener =
new ComponentWithBrowseButton.BrowseFolderActionListener<JTextField>(browseFolderTitle, "", locationTextField,
project,
descriptor,
TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) {
BrowseFolderActionListener<JTextField> listener =
new BrowseFolderActionListener<JTextField>(title, "", locationField, project, descriptor, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) {
@Override
protected void onFileChosen(@NotNull VirtualFile chosenFile) {
myBaseDir = chosenFile.getPath();
if (isProjectNameChanged(nameTextField.getText()) && !nameTextField.getText().equals(chosenFile.getName())) {
if (isProjectNameChanged(nameField.getText()) && !nameField.getText().equals(chosenFile.getName())) {
myExternalModify = true;
locationTextField.setText(new File(chosenFile.getPath(), nameTextField.getText()).toString());
locationField.setText(new File(chosenFile.getPath(), nameField.getText()).toString());
myExternalModify = false;
}
else {
myExternalModify = true;
locationTextField.setText(chosenFile.getPath());
nameTextField.setText(chosenFile.getName());
locationField.setText(chosenFile.getPath());
nameField.setText(chosenFile.getName());
myExternalModify = false;
}
}
};
locationTextField.addActionListener(listener);
locationTextField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
locationField.addActionListener(listener);
locationField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
if (myExternalModify) {
return;
}
myModifyingLocation = true;
String path = locationTextField.getText().trim();
String path = locationField.getText().trim();
if (path.endsWith(File.separator)) {
path = path.substring(0, path.length() - File.separator.length());
}
int ind = path.lastIndexOf(File.separator);
if (ind != -1) {
String projectName = path.substring(ind + 1, path.length());
if (!nameTextField.getText().trim().isEmpty()) {
if (!nameField.getText().trim().isEmpty()) {
myBaseDir = path.substring(0, ind);
}
if (!projectName.equals(nameTextField.getText())) {
if (!projectName.equals(nameField.getText())) {
if (!myModifyingProjectName) {
nameTextField.setText(projectName);
nameField.setText(projectName);
}
}
}
@@ -112,7 +112,6 @@ public class LocationNameFieldsBinding {
return !currentName.equals(mySuggestedProjectName);
}
private class NameFieldDocument extends PlainDocument {
public NameFieldDocument(final JTextField projectNameTextField, final TextFieldWithBrowseButton locationField) {
addDocumentListener(new DocumentAdapter() {
@@ -129,14 +128,25 @@ public class LocationNameFieldsBinding {
@Override
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
boolean ok = true;
for (int idx = 0; idx < str.length() && ok; idx++) {
char ch = str.charAt(idx);
ok = ch != File.separatorChar && ch != '\\' && ch != '/' && ch != '|' && ch != ':';
StringBuilder sb = null;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
boolean replace = c == '\\' || c == '/' || SystemInfo.isWindows && (c == '|' || c == ':');
if (replace) {
if (sb == null) {
sb = new StringBuilder(str.length());
sb.append(str.substring(0, i));
}
sb.append('_');
}
else if (sb != null) {
sb.append(c);
}
}
if (ok) {
super.insertString(offs, str, a);
if (sb != null) {
str = sb.toString();
}
super.insertString(offs, str, a);
}
}
}
@@ -47,6 +47,7 @@ import java.io.File;
public class NewDirectoryProjectAction extends AnAction implements DumbAware {
private static final Logger LOG = Logger.getInstance(NewDirectoryProjectAction.class);
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
Project project = e.getProject();
NewDirectoryProjectDialog dlg = new NewDirectoryProjectDialog(project);
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.platform.NewDirectoryProjectDialog">
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="575" height="400"/>
@@ -17,19 +17,6 @@
<text value="Project &amp;name:"/>
</properties>
</component>
<component id="89536" class="javax.swing.JLabel" binding="myLocationLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;Location:"/>
</properties>
</component>
<vspacer id="bf7cf">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="92c6d" class="javax.swing.JTextField" binding="myProjectNameTextField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
@@ -38,45 +25,40 @@
</constraints>
<properties/>
</component>
<component id="89536" class="javax.swing.JLabel" binding="myLocationLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;Location:"/>
</properties>
</component>
<component id="bf36b" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myLocationField">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<grid id="2663" binding="myProjectTypePanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<component id="dae2f" class="javax.swing.JLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="5c20f"/>
<text value="Project &amp;type:"/>
</properties>
</component>
<component id="5c20f" class="javax.swing.JComboBox" binding="myProjectTypeComboBox" default-binding="true">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="dae2f" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="5c20f"/>
<text value="Project &amp;type:"/>
</properties>
</component>
<component id="5c20f" class="javax.swing.JComboBox" binding="myProjectTypeComboBox" default-binding="true">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
</children>
</grid>
<grid id="eecc0" binding="myPlaceHolder" layout-manager="GridBagLayout">
</component>
<vspacer id="bf7cf">
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
</vspacer>
</children>
</grid>
</form>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -15,9 +15,8 @@
*/
package com.intellij.platform;
import com.intellij.facet.ui.FacetEditorValidator;
import com.intellij.facet.ui.FacetValidatorsManager;
import com.intellij.facet.ui.ValidationResult;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
@@ -31,7 +30,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
@@ -40,143 +38,93 @@ import java.util.List;
* @author yole
*/
public class NewDirectoryProjectDialog extends DialogWrapper {
private JTextField myProjectNameTextField;
private TextFieldWithBrowseButton myLocationField;
protected JPanel myRootPane;
protected JComboBox myProjectTypeComboBox;
private JPanel myProjectTypePanel;
private JLabel myLocationLabel;
protected JPanel getPlaceHolder() {
return myPlaceHolder;
}
private JPanel myPlaceHolder;
private static final Object EMPTY_PROJECT_GENERATOR = new Object();
private final DirectoryProjectGenerator myGeneratorBeforeSeparator;
protected NewDirectoryProjectDialog(Project project) {
private JPanel myRootPane;
private JTextField myProjectNameTextField;
private JLabel myLocationLabel;
private TextFieldWithBrowseButton myLocationField;
private JComboBox myProjectTypeComboBox;
@SuppressWarnings("unchecked")
protected NewDirectoryProjectDialog(@Nullable Project project) {
super(project, true);
setTitle("Create New Project");
setTitle(IdeBundle.message("new.dir.project.title"));
init();
myLocationLabel.setLabelFor(myLocationField.getChildComponent());
new LocationNameFieldsBinding(project, myLocationField, myProjectNameTextField, ProjectUtil.getBaseDir(), "Select Location for Project Directory");
String title = IdeBundle.message("new.dir.project.chooser.title");
new LocationNameFieldsBinding(project, myLocationField, myProjectNameTextField, ProjectUtil.getBaseDir(), title);
final DirectoryProjectGenerator[] generators = getGenerators();
if (generators.length == 0) {
myProjectTypePanel.setVisible(false);
myGeneratorBeforeSeparator = null;
}
else {
DefaultComboBoxModel model = new DefaultComboBoxModel();
model.addElement(getEmptyProjectGenerator());
DefaultComboBoxModel model = new DefaultComboBoxModel();
model.addElement(EMPTY_PROJECT_GENERATOR);
DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME);
if (generators.length > 0) {
List<DirectoryProjectGenerator> primaryGenerators = ContainerUtil.newArrayList();
List<DirectoryProjectGenerator> otherGenerators = ContainerUtil.newArrayList();
for (DirectoryProjectGenerator generator : generators) {
if (generator instanceof HideableProjectGenerator) {
if (((HideableProjectGenerator)generator).isHidden()) {
continue;
}
if (generator instanceof HideableProjectGenerator && ((HideableProjectGenerator)generator).isHidden()) {
continue;
}
boolean primary = true;
if (generator instanceof WebProjectGenerator) {
primary = ((WebProjectGenerator) generator).isPrimaryGenerator();
}
if (primary) {
if (generator instanceof WebProjectGenerator && ((WebProjectGenerator)generator).isPrimaryGenerator()) {
primaryGenerators.add(generator);
} else {
}
else {
otherGenerators.add(generator);
}
}
if (!primaryGenerators.isEmpty() && !otherGenerators.isEmpty()) {
myGeneratorBeforeSeparator = primaryGenerators.get(primaryGenerators.size() - 1);
}
else {
myGeneratorBeforeSeparator = null;
}
for (DirectoryProjectGenerator generator : primaryGenerators) {
model.addElement(generator);
}
for (DirectoryProjectGenerator generator : otherGenerators) {
model.addElement(generator);
}
myProjectTypeComboBox.setModel(model);
myProjectTypeComboBox.setRenderer(createProjectTypeListCellRenderer(myProjectTypeComboBox.getRenderer()));
for (DirectoryProjectGenerator generator : primaryGenerators) model.addElement(generator);
for (DirectoryProjectGenerator generator : otherGenerators) model.addElement(generator);
}
myProjectTypeComboBox.setModel(model);
myProjectTypeComboBox.setRenderer(createProjectTypeListCellRenderer());
registerValidators(new FacetValidatorsManager() {
public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) {
myLocationField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
checkValid();
}
public void validate() {
});
myProjectTypeComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(@NotNull ActionEvent e) {
checkValid();
}
});
}
@NotNull
private ListCellRenderer createProjectTypeListCellRenderer(@NotNull final ListCellRenderer originalRenderer) {
ListCellRenderer intermediate = myGeneratorBeforeSeparator == null ? originalRenderer : new ListCellRenderer() {
private final JSeparator mySeparator = new JSeparator(SwingConstants.HORIZONTAL);
private final JPanel myComponentWithSeparator = new JPanel(new BorderLayout(0, 0));
private static ListCellRendererWrapper<Object> createProjectTypeListCellRenderer() {
return new ListCellRendererWrapper<Object>() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component original = originalRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (index != -1 && value == myGeneratorBeforeSeparator
&& value instanceof DirectoryProjectGenerator && original instanceof JLabel) {
myComponentWithSeparator.removeAll();
JLabel label = (JLabel) original;
label.setText(((DirectoryProjectGenerator) value).getName());
myComponentWithSeparator.add(label, BorderLayout.CENTER);
myComponentWithSeparator.add(mySeparator, BorderLayout.SOUTH);
myComponentWithSeparator.revalidate();
myComponentWithSeparator.repaint();
return myComponentWithSeparator;
}
return original;
}
};
return new ListCellRendererWrapper() {
@Override
public void customize(final JList list, final Object value, final int index, final boolean selected, final boolean cellHasFocus) {
if (value == null) return;
public void customize(JList list, Object value, int index, boolean selected, boolean cellHasFocus) {
if (value == EMPTY_PROJECT_GENERATOR) {
setText("Empty project");
setText(IdeBundle.message("new.dir.project.default.generator"));
}
else {
else if (value != null) {
setText(((DirectoryProjectGenerator)value).getName());
}
}
};
}
protected Object getEmptyProjectGenerator() {
return EMPTY_PROJECT_GENERATOR;
}
protected DirectoryProjectGenerator[] getGenerators() {
return Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME);
}
protected void checkValid() {
private void checkValid() {
String projectName = myProjectNameTextField.getText();
if (projectName.trim().isEmpty()) {
setOKActionEnabled(false);
setErrorText("Project name can't be empty");
setErrorText(IdeBundle.message("new.dir.project.error.empty"));
return;
}
if (myLocationField.getText().indexOf('$') >= 0) {
setOKActionEnabled(false);
setErrorText("Project directory name must not contain the $ character");
setErrorText(IdeBundle.message("new.dir.project.error.buck"));
return;
}
DirectoryProjectGenerator generator = getProjectGenerator();
if (generator != null) {
String baseDirPath = myLocationField.getTextField().getText();
@@ -187,58 +135,33 @@ public class NewDirectoryProjectDialog extends DialogWrapper {
return;
}
}
setOKActionEnabled(true);
setErrorText(null);
}
private void registerValidators(final FacetValidatorsManager validatorsManager) {
validateOnTextChange(validatorsManager, myLocationField.getTextField());
validateOnSelectionChange(validatorsManager, myProjectTypeComboBox);
}
private static void validateOnSelectionChange(final FacetValidatorsManager validatorsManager, final JComboBox projectNameTextField) {
projectNameTextField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
validatorsManager.validate();
}
});
}
private static void validateOnTextChange(final FacetValidatorsManager validatorsManager, final JTextField textField) {
textField.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
validatorsManager.validate();
}
});
}
protected JComponent createCenterPanel() {
return myRootPane;
}
public String getNewProjectLocation() {
return myLocationField.getText();
}
public String getNewProjectName() {
return myProjectNameTextField.getText();
}
@Nullable
public DirectoryProjectGenerator getProjectGenerator() {
final Object selItem = myProjectTypeComboBox.getSelectedItem();
if (selItem == EMPTY_PROJECT_GENERATOR) return null;
return (DirectoryProjectGenerator)selItem;
}
@Override
public JComponent getPreferredFocusedComponent() {
return myProjectNameTextField;
}
@Override
protected JComponent createCenterPanel() {
return myRootPane;
}
@Override
protected String getHelpId() {
return "create_new_project_dialog";
}
public String getNewProjectLocation() {
return myLocationField.getText();
}
@Nullable
public DirectoryProjectGenerator getProjectGenerator() {
Object item = myProjectTypeComboBox.getSelectedItem();
return item == EMPTY_PROJECT_GENERATOR ? null : (DirectoryProjectGenerator)item;
}
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.impl.DelegateColorScheme;
import com.intellij.openapi.editor.event.DocumentListener;
@@ -30,7 +31,9 @@ import com.intellij.openapi.editor.impl.RangeMarkerTree;
import com.intellij.openapi.editor.markup.HighlighterLayer;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.LineTokenizer;
import com.intellij.openapi.util.text.StringUtil;
@@ -56,31 +59,54 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
private static final Key<MyPanel> MY_PANEL_PROPERTY = Key.create("EditorTextFieldCellRenderer.MyEditorPanel");
public EditorTextFieldCellRenderer(Disposable parent) {
private final Project myProject;
private final boolean myInheritFontFromLaF;
protected EditorTextFieldCellRenderer(@Nullable Project project, @NotNull Disposable parent) {
this(project, true, parent);
}
protected EditorTextFieldCellRenderer(@Nullable Project project, boolean inheritFontFromLaF, @NotNull Disposable parent) {
myProject = project;
myInheritFontFromLaF = inheritFontFromLaF;
Disposer.register(parent, this);
}
protected abstract EditorColorsScheme getColorScheme();
protected abstract String getText(FontMetrics fontMetrics, JTable table, Object value, int row, int column);
protected abstract String getText(JTable table, Object value, int row, int column);
@Nullable
protected abstract TextAttributes getTextAttributes(Object value, boolean selected, int row, int col);
protected TextAttributes getTextAttributes(JTable table, Object value, boolean selected, boolean focused, int row, int col) {
return null;
}
protected Color getCellBackground(JTable table, Object value, boolean selected, boolean focused, int row, int column) {
return UIUtil.getTableBackground(selected);
}
@Nullable
protected FileType getFileType() {
return null;
}
@NotNull
protected EditorColorsScheme getColorScheme() {
return EditorColorsManager.getInstance().getGlobalScheme();
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
public Component getTableCellRendererComponent(JTable table, Object value, boolean selected, boolean focused, int row, int column) {
MyPanel panel = getEditorPanel(table);
EditorEx editor = panel.myEditor;
editor.getColorsScheme().setEditorFontSize(table.getFont().getSize());
String text = getText(((EditorImpl)editor).getFontMetrics(Font.PLAIN), table, value, row, column);
TextAttributes textAttributes = getTextAttributes(value, isSelected, row, column);
String text = getText(table, value, row, column);
TextAttributes textAttributes = getTextAttributes(table, value, selected, focused, row, column);
panel.setText(text, textAttributes);
((EditorImpl)editor).setPaintSelection(isSelected);
editor.getSelectionModel().setSelection(0, isSelected ? editor.getDocument().getTextLength() : 0);
((EditorImpl)editor).setPaintSelection(selected);
editor.getSelectionModel().setSelection(0, selected ? editor.getDocument().getTextLength() : 0);
editor.getColorsScheme().setColor(EditorColors.SELECTION_BACKGROUND_COLOR, table.getSelectionBackground());
editor.getColorsScheme().setColor(EditorColors.SELECTION_FOREGROUND_COLOR, table.getSelectionForeground());
editor.setBackgroundColor(getCellBackgroundColor(getColorScheme(), table, isSelected, row));
editor.setBackgroundColor(getCellBackground(table, value, selected, focused, row, column));
panel.setOpaque(!Comparing.equal(editor.getBackgroundColor(), table.getBackground()));
panel.setBorder(null); // prevents double border painting when ExtendedItemRendererComponentWrapper is used
@@ -88,14 +114,8 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
return panel;
}
public static Color getCellBackgroundColor(EditorColorsScheme colorsScheme, JTable table, boolean isSelected, int row) {
return isSelected ? table.getSelectionBackground() :
table.getSelectionModel().getLeadSelectionIndex() == row ? colorsScheme.getColor(EditorColors.CARET_ROW_COLOR) :
table.getBackground();
}
@NotNull
private MyPanel getEditorPanel(JTable table) {
private MyPanel getEditorPanel(final JTable table) {
MyPanel panel = UIUtil.getClientProperty(table, MY_PANEL_PROPERTY);
if (panel != null) {
DelegateColorScheme scheme = (DelegateColorScheme)panel.myEditor.getColorsScheme();
@@ -103,10 +123,10 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
return panel;
}
// reuse EditorTextField initialization logic
EditorTextField field = new EditorTextField(new MyDocument(), null, FileTypes.PLAIN_TEXT, false, false);
FileType fileType = ObjectUtils.notNull(getFileType(), FileTypes.PLAIN_TEXT);
EditorTextField field = new EditorTextField(new MyDocument(), myProject, fileType, false, false);
field.setSupplementary(true);
field.setFontInheritedFromLAF(false);
field.setFontInheritedFromLAF(myInheritFontFromLaF);
field.addNotify(); // creates editor
EditorEx editor = (EditorEx)ObjectUtils.assertNotNull(field.getEditor());
@@ -119,6 +139,12 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
panel = new MyPanel(editor);
Disposer.register(this, panel);
Disposer.register(this, new Disposable() {
@Override
public void dispose() {
UIUtil.putClientProperty(table, MY_PANEL_PROPERTY, null);
}
});
table.putClientProperty(MY_PANEL_PROPERTY, panel);
return panel;
@@ -157,6 +183,15 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
recalculatePreferredSize();
}
@Override
public void setBackground(Color bg) {
// allows for striped tables
if (myEditor != null) {
myEditor.setBackgroundColor(bg);
}
super.setBackground(bg);
}
@Override
public Dimension getPreferredSize() {
return myPreferredSize;
@@ -525,8 +525,10 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
myPopupLayeredPane.validate();
myPopupLayeredPane.repaint();
myPopupLayeredPane = null;
Disposer.dispose(myListenerDisposable);
if (myListenerDisposable != null) {
Disposer.dispose(myListenerDisposable);
}
myListenerDisposable = null;
}
else if (searchPopup != null) {
@@ -0,0 +1,64 @@
/*
* Copyright 2000-2014 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.util.ui.table;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.ui.EditorTextFieldCellRenderer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
public abstract class EditorTextFieldJBTableRowRenderer extends EditorTextFieldCellRenderer implements JBTableRowRenderer {
protected EditorTextFieldJBTableRowRenderer(@Nullable Project project, @NotNull Disposable parent) {
super(project, parent);
}
@Override
public final JComponent getRowRendererComponent(JTable table, int row, boolean selected, boolean focused) {
return (JComponent)getTableCellRendererComponent(table, null, selected, focused, row, 0);
}
@Override
protected final String getText(JTable table, Object value, int row, int column) {
return getText(table, row);
}
@Override
protected final Color getCellBackground(JTable table, Object value, boolean selected, boolean focused, int row, int column) {
return getRowBackground(table, selected, focused, row);
}
@Nullable
@Override
protected final TextAttributes getTextAttributes(JTable table, Object value, boolean selected, boolean focused, int row, int col) {
return getTextAttributes(table, row);
}
protected abstract String getText(JTable table, int row);
@Nullable
protected TextAttributes getTextAttributes(JTable table, int row) {
return null;
}
protected Color getRowBackground(JTable table, boolean selected, boolean focused, int row) {
return super.getCellBackground(table, null, selected, focused, row, 0);
}
}
@@ -15,25 +15,33 @@
*/
package com.intellij.util.ui.table;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.ui.*;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.DottedBorder;
import com.intellij.ui.EditorSettingsProvider;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.TableUtil;
import com.intellij.ui.table.JBTable;
import com.intellij.util.ui.AbstractTableCellEditor;
import com.intellij.util.ui.UIUtil;
import gnu.trove.TIntArrayList;
import gnu.trove.TIntObjectHashMap;
import gnu.trove.TIntObjectProcedure;
import gnu.trove.TIntProcedure;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.*;
import java.util.List;
import static java.awt.event.KeyEvent.*;
@@ -41,16 +49,18 @@ import static java.awt.event.KeyEvent.*;
/**
* @author Konstantin Bulenkov
*/
public abstract class JBListTable extends JPanel {
public abstract class JBListTable {
protected final JTable myInternalTable;
private final JBTable mainTable;
private final Ref<Integer> myLastEditorIndex = Ref.create(null);
private final RowResizeAnimator myRowResizeAnimator;
private final Disposable myOnRemoveDisposable;
private MouseEvent myMouseEvent;
private MyCellEditor myCellEditor;
private int myLastFocusedEditorComponentIdx = -1;
public JBListTable(@NotNull final JTable t) {
super(new BorderLayout());
myInternalTable = t;
myOnRemoveDisposable = Disposer.newDisposable();
final JBListTableModel model = new JBListTableModel(t.getModel()) {
@Override
public JBTableRow getRow(int index) {
@@ -64,7 +74,7 @@ public abstract class JBListTable extends JPanel {
@Override
public void addRow() {
myLastEditorIndex.set(null);
myLastFocusedEditorComponentIdx = -1;
super.addRow();
}
};
@@ -114,10 +124,11 @@ public abstract class JBListTable extends JPanel {
@Override
public TableCellRenderer getCellRenderer(int row, int column) {
return new DefaultTableCellRenderer() {
final JBTableRowRenderer rowRenderer = getRowRenderer(row);
return new TableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean selected, boolean hasFocus, int row, int col) {
return getRowRenderer(t, row, selected, hasFocus);
public Component getTableCellRendererComponent(JTable table, Object value, boolean selected, boolean focused, int row, int col) {
return rowRenderer.getRowRendererComponent(t, row, selected, focused);
}
};
}
@@ -199,6 +210,16 @@ public abstract class JBListTable extends JPanel {
return super.processKeyBinding(ks, e, condition, pressed);
}
@Override
public void columnMarginChanged(ChangeEvent e) {
// we don't stop editing (it prevents editor removal when scrollbar is added)
TableColumn resizingColumn = tableHeader != null ? tableHeader.getResizingColumn() : null;
if (resizingColumn != null && autoResizeMode == AUTO_RESIZE_OFF) {
resizingColumn.setPreferredWidth(resizingColumn.getWidth());
}
resizeAndRepaint();
}
@Override
public TableCellEditor getCellEditor(final int row, int column) {
final JBTableRowEditor editor = getRowEditor(row);
@@ -224,14 +245,31 @@ public abstract class JBListTable extends JPanel {
boolean isSelected = isCellSelected(row, column);
return editor.getTableCellEditorComponent(this, value, isSelected, row, column);
}
@Override
public void addNotify() {
super.addNotify();
Disposer.register(myOnRemoveDisposable, myRowResizeAnimator);
}
@Override
public void removeNotify() {
super.removeNotify();
Disposer.dispose(myOnRemoveDisposable);
}
};
mainTable.setStriped(true);
myRowResizeAnimator = new RowResizeAnimator(mainTable);
}
public void stopEditing() {
TableUtil.stopEditing(mainTable);
}
public Disposable getOnRemoveDisposable() {
return myOnRemoveDisposable;
}
private static void installPaddingAndBordersForEditors(JBTableRowEditor editor) {
final List<EditorTextField> editors = UIUtil.findComponentsOfType(editor, EditorTextField.class);
for (EditorTextField textField : editors) {
@@ -244,7 +282,7 @@ public abstract class JBListTable extends JPanel {
return mainTable;
}
protected abstract JComponent getRowRenderer(JTable table, int row, boolean selected, boolean focused);
protected abstract JBTableRowRenderer getRowRenderer(int row);
protected abstract JBTableRowEditor getRowEditor(int row);
@@ -296,118 +334,49 @@ public abstract class JBListTable extends JPanel {
return panel;
}
private static class RowResizeAnimator extends Thread {
private final JTable myTable;
private final int myRow;
private final JScrollPane myScrollPane;
private int neededHeight;
private final JBTableRowEditor myEditor;
private final Ref<Integer> myIndex;
private int step = 5;
private int currentHeight;
private RowResizeAnimator(JTable table, int row, int height, JBTableRowEditor editor, @NotNull Ref<Integer> index) {
super("Row Animator");
myTable = table;
myRow = row;
neededHeight = height;
myEditor = editor;
myIndex = index;
currentHeight = myTable.getRowHeight(myRow);
myScrollPane = UIUtil.getParentOfType(JScrollPane.class, myTable);
}
@Override
public void run() {
final boolean exitEditing = currentHeight > neededHeight;
try {
sleep(50);
final JScrollBar bar = myScrollPane.getVerticalScrollBar();
if (bar == null || !bar.isVisible()) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
myScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
}
});
sleep(15);
}
while (currentHeight != neededHeight) {
if (Math.abs(currentHeight - neededHeight) < step) {
currentHeight = neededHeight;
}
else {
currentHeight += currentHeight < neededHeight ? step : -step;
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
myTable.setRowHeight(myRow, currentHeight);
}
});
sleep(15);
}
if (myEditor != null) {
JComponent[] components = myEditor.getFocusableComponents();
JComponent focus = null;
if (myIndex.get() != null) {
int index = myIndex.get().intValue();
if (0 <= index && index < components.length) {
focus = components[index];
}
}
if (focus == null) {
focus = myEditor.getPreferredFocusedComponent();
}
if (focus != null) {
focus.requestFocus();
}
}
}
catch (InterruptedException ignore) {
} finally {
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
TableUtil.scrollSelectionToVisible(myTable);
if (exitEditing && !myTable.isEditing()) {
myScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
}
}
});
}
}
}
private class MyCellEditor extends AbstractTableCellEditor implements Animated {
JTable curTable;
private class MyCellEditor extends AbstractTableCellEditor {
private final JBTableRowEditor myEditor;
public MyCellEditor(JBTableRowEditor editor) {
myEditor = editor;
curTable = null;
}
@Override
public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, final int row, int column) {
curTable = table;
final JPanel p = new JPanel(new BorderLayout()) {
@Override
public void addNotify() {
super.addNotify();
final int height = (int)getPreferredSize().getHeight();
int height = getPreferredSize().height;
if (height > table.getRowHeight(row)) {
new RowResizeAnimator(table, row, height, myEditor, myMouseEvent == null ? myLastEditorIndex : Ref.<Integer>create(null)).start();
myRowResizeAnimator.resize(row, height);
}
}
public void removeNotify() {
if (myCellEditor != null) myCellEditor.saveFocusIndex();
super.removeNotify();
new RowResizeAnimator(table, row, table.getRowHeight(), null, myMouseEvent == null ? myLastEditorIndex : Ref.<Integer>create(null)).start();
myRowResizeAnimator.resize(row, table.getRowHeight());
}
};
p.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
IdeFocusManager focusManager = IdeFocusManager.findInstanceByComponent(p);
focusManager.requestFocus(getComponentToFocus(), true);
}
private Component getComponentToFocus() {
if (myLastFocusedEditorComponentIdx >= 0) {
JComponent[] focusableComponents = myEditor.getFocusableComponents();
if (myLastFocusedEditorComponentIdx < focusableComponents.length) {
return focusableComponents[myLastFocusedEditorComponentIdx];
}
}
return myEditor.getPreferredFocusedComponent();
}
});
p.add(myEditor, BorderLayout.CENTER);
p.setFocusable(false);
return p;
}
@@ -422,31 +391,107 @@ public abstract class JBListTable extends JPanel {
return super.stopCellEditing();
}
private void removeEmptyRow() {
final int row = curTable.getSelectedRow();
if (row != -1 && isRowEmpty(row)) {
final JBListTableModel model = (JBListTableModel)curTable.getModel();
final int count = model.getRowCount();
model.removeRow(row);
int newRow = count == row + 1 ? row - 1 : row;
curTable.setRowSelectionInterval(newRow, newRow);
}
}
public void saveFocusIndex() {
JComponent[] components = myEditor.getFocusableComponents();
for (int i = 0; i < components.length; i++) {
if (components[i].hasFocus()) {
JBListTable.this.myLastEditorIndex.set(i);
break;
}
}
}
@Override
public void cancelCellEditing() {
saveFocusIndex();
super.cancelCellEditing();
}
private void saveFocusIndex() {
JComponent[] components = myEditor.getFocusableComponents();
for (int i = 0; i < components.length; i++) {
if (components[i].hasFocus()) {
myLastFocusedEditorComponentIdx = i;
break;
}
}
}
}
private static class RowResizeAnimator implements ActionListener, Disposable {
private static final int ANIMATION_STEP_MILLIS = 15;
private static final int RESIZE_AMOUNT_PER_STEP = 5;
private final TIntObjectHashMap<RowAnimationState> myRowAnimationStates = new TIntObjectHashMap<RowAnimationState>();
private final Timer myAnimationTimer = new Timer(ANIMATION_STEP_MILLIS, this);
private final JTable myTable;
public RowResizeAnimator(JTable table) {
myTable = table;
}
public void resize(int row, int targetHeight) {
myRowAnimationStates.put(row, new RowAnimationState(row, targetHeight));
startAnimation();
}
@Override
public void actionPerformed(final ActionEvent e) {
doAnimationStep(e.getWhen());
}
@Override
public void dispose() {
stopAnimation();
}
private void startAnimation() {
if (!myAnimationTimer.isRunning()) {
myAnimationTimer.start();
}
}
private void stopAnimation() {
myAnimationTimer.stop();
}
private void doAnimationStep(final long updateTime) {
final TIntArrayList completeRows = new TIntArrayList(myRowAnimationStates.size());
myRowAnimationStates.forEachEntry(new TIntObjectProcedure<RowAnimationState>() {
@Override
public boolean execute(int row, RowAnimationState animationState) {
if (animationState.doAnimationStep(updateTime)) {
completeRows.add(row);
}
return true;
}
});
completeRows.forEach(new TIntProcedure() {
@Override
public boolean execute(int row) {
myRowAnimationStates.remove(row);
return true;
}
});
if (myRowAnimationStates.isEmpty()) {
stopAnimation();
}
}
private class RowAnimationState {
private final int myRow;
private final int myTargetHeight;
private long myLastUpdateTime;
public RowAnimationState(int row, int targetHeight) {
myRow = row;
myTargetHeight = targetHeight;
myLastUpdateTime = System.currentTimeMillis();
}
/**
* @return whether this row animation is complete
*/
public boolean doAnimationStep(long currentTime) {
int currentRowHeight = myTable.getRowHeight(myRow);
int resizeAbs = (int) (RESIZE_AMOUNT_PER_STEP * ((currentTime - myLastUpdateTime) / (double)ANIMATION_STEP_MILLIS));
int leftToAnimate = myTargetHeight - currentRowHeight;
int newHeight = Math.abs(leftToAnimate) <= Math.abs(resizeAbs) ? myTargetHeight :
currentRowHeight + (leftToAnimate < 0 ? -resizeAbs : resizeAbs);
myTable.setRowHeight(myRow, newHeight);
myLastUpdateTime = currentTime;
return myTargetHeight == newHeight;
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -13,13 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ui;
package com.intellij.util.ui.table;
/**
* Indicates that component, or cell editor, or cell renderer performs
* some animations and side effects may occur because of changes of the bounds
*
* @author Konstantin Bulenkov
*/
public interface Animated {
import javax.swing.*;
public interface JBTableRowRenderer {
JComponent getRowRendererComponent(JTable table, int row, boolean selected, boolean focused);
}
@@ -371,7 +371,7 @@ public class TableModelEditor<T> implements ElementProducer<T> {
}
table.requestFocus();
TableUtil.updateScroller(table, false);
TableUtil.updateScroller(table);
}
}
).createPanel();
@@ -440,7 +440,7 @@ public class TableModelEditor<T> implements ElementProducer<T> {
public void run(AnActionButton button) {
if (TableUtil.doRemoveSelectedItems(table, model, this)) {
table.requestFocus();
TableUtil.updateScroller(table, false);
TableUtil.updateScroller(table);
}
}
@@ -1155,3 +1155,9 @@ presentation.mode.fon.size=Font size\:
update.available.group=Update Checker
loading.editors=Loading files...
new.dir.project.title=Create New Project
new.dir.project.chooser.title=Select Location for Project Directory
new.dir.project.default.generator=Empty project
new.dir.project.error.empty=Project name can't be empty
new.dir.project.error.buck=Project directory name must not contain the ''$'' character
@@ -28,6 +28,7 @@ public class _FirstInSuiteTest extends TestCase {
public static long suiteStarted = 0L;
public void testNothing() throws Exception {
suiteStarted = System.nanoTime();
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
@@ -48,7 +49,6 @@ public class _FirstInSuiteTest extends TestCase {
// performance tests
public void testNothingPerformance() throws Exception {
suiteStarted = System.nanoTime();
testNothing();
}
}
@@ -244,15 +244,9 @@ public class TableUtil {
column.setMinWidth(checkboxWidth);
}
public static void updateScroller(@NotNull JTable table, boolean temporaryHideVerticalScrollBar) {
public static void updateScroller(@NotNull JTable table) {
JScrollPane scrollPane = UIUtil.getParentOfType(JScrollPane.class, table);
if (scrollPane != null) {
if (temporaryHideVerticalScrollBar) {
final JScrollBar bar = scrollPane.getVerticalScrollBar();
if (bar == null || !bar.isVisible()) {
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
}
}
scrollPane.revalidate();
scrollPane.repaint();
}
@@ -55,7 +55,7 @@ public abstract class ColumnInfo <Item, Aspect> {
return myName;
}
public Class getColumnClass() {
public Class<?> getColumnClass() {
return String.class;
}
@@ -62,7 +62,7 @@ public class ListTableModel<Item> extends TableViewModel<Item> implements Editab
}
@Override
public Class getColumnClass(int columnIndex) {
public Class<?> getColumnClass(int columnIndex) {
return myColumnInfos[columnIndex].getColumnClass();
}
@@ -16,6 +16,7 @@
package com.intellij.lang.ant.config.actions;
import com.intellij.lang.ant.AntBundle;
import com.intellij.lang.ant.config.AntBuildFile;
import com.intellij.lang.ant.config.AntConfiguration;
import com.intellij.lang.ant.config.AntConfigurationBase;
import com.intellij.lang.ant.config.AntNoFileException;
@@ -30,35 +31,31 @@ import com.intellij.psi.PsiManager;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class AddAntBuildFile extends AnAction {
public void actionPerformed(AnActionEvent event) {
public void actionPerformed(@NotNull AnActionEvent event) {
final DataContext dataContext = event.getDataContext();
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project == null) {
return;
}
final Set<VirtualFile> files = new HashSet<VirtualFile>();
VirtualFile[] contextFiles = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
if (contextFiles != null) {
files.addAll(Arrays.asList(contextFiles));
}
final VirtualFile singleFile = CommonDataKeys.VIRTUAL_FILE.getData(dataContext);
if (singleFile != null) {
files.add(singleFile);
}
if (files.isEmpty()) {
final VirtualFile[] contextFiles = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
if (contextFiles == null || contextFiles.length == 0) {
return;
}
final AntConfiguration antConfiguration = AntConfiguration.getInstance(project);
final Set<VirtualFile> files = new HashSet<VirtualFile>();
files.addAll(Arrays.asList(contextFiles));
for (AntBuildFile buildFile : antConfiguration.getBuildFiles()) {
files.remove(buildFile.getVirtualFile());
}
int filesAdded = 0;
final StringBuilder errors = new StringBuilder();
@@ -87,51 +84,41 @@ public class AddAntBuildFile extends AnAction {
}
}
public void update(AnActionEvent e) {
public void update(@NotNull AnActionEvent e) {
final DataContext dataContext = e.getDataContext();
final Presentation presentation = e.getPresentation();
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project == null) {
disable(presentation);
return;
if (project != null) {
final VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
if (files != null && files.length > 0) {
for (VirtualFile file : files) {
final PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
if (!(psiFile instanceof XmlFile)) {
continue;
}
final XmlFile xmlFile = (XmlFile)psiFile;
final XmlDocument document = xmlFile.getDocument();
if (document == null) {
continue;
}
final XmlTag rootTag = document.getRootTag();
if (rootTag == null) {
continue;
}
if (!"project".equals(rootTag.getName())) {
continue;
}
if (AntConfigurationBase.getInstance(project).getAntBuildFile(psiFile) != null) {
continue;
}
// found at least one candidate file
enable(presentation);
return;
}
}
}
final VirtualFile file = CommonDataKeys.VIRTUAL_FILE.getData(dataContext);
if (file == null) {
disable(presentation);
return;
}
final PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
if (!(psiFile instanceof XmlFile)) {
disable(presentation);
return;
}
final XmlFile xmlFile = (XmlFile)psiFile;
final XmlDocument document = xmlFile.getDocument();
if (document == null) {
disable(presentation);
return;
}
final XmlTag rootTag = document.getRootTag();
if (rootTag == null) {
disable(presentation);
return;
}
if (!"project".equals(rootTag.getName())) {
disable(presentation);
return;
}
if (AntConfigurationBase.getInstance(project).getAntBuildFile(psiFile) != null) {
disable(presentation);
return;
}
enable(presentation);
disable(presentation);
}
private static void enable(Presentation presentation) {
@@ -208,6 +208,9 @@ public class AntBuildModelImpl implements AntBuildModelBase {
}
}.fillTargets(list, model, project, sourceFile);
}
if (dependencies.isEmpty()) {
dependencies.add(PsiModificationTracker.MODIFICATION_COUNT);
}
return new Pair<List<AntBuildTargetBase>, Collection<Object>>(list, dependencies);
}
@@ -1,5 +1,5 @@
<project name="n" default="main">
<p4counter property="p1"/>
<dirname property="p1"/>
<target name="main">
<echo message="p1=${<ref>p1}"/>
</target>
+15
View File
@@ -0,0 +1,15 @@
from PyQt5 import QtCore
import sys
class AThread(QtCore.QThread):
def run(self):
for i in range(3):
print("ping %d" % i)
app = QtCore.QCoreApplication([])
thread = AThread()
thread.finished.connect(app.exit)
thread.start()
sys.exit(app.exec_())
+23
View File
@@ -0,0 +1,23 @@
from PyQt5 import QtCore
import sys
class SomeObject(QtCore.QObject):
finished = QtCore.pyqtSignal()
def longRunning(self):
for i in range(3):
print("ping %d" % i)
self.finished.emit()
app = QtCore.QCoreApplication([])
objThread = QtCore.QThread()
obj = SomeObject()
obj.moveToThread(objThread)
obj.finished.connect(objThread.quit)
objThread.started.connect(obj.longRunning)
objThread.finished.connect(app.exit)
objThread.start()
sys.exit(app.exec_())
+19
View File
@@ -0,0 +1,19 @@
from PyQt5 import QtCore
import sys
class Runnable(QtCore.QRunnable):
def run(self):
app = QtCore.QCoreApplication.instance()
for i in range(3):
print("ping %d" % i)
app.quit()
app = QtCore.QCoreApplication([])
runnable = Runnable()
QtCore.QThreadPool.globalInstance().start(runnable)
sys.exit(app.exec_())
@@ -510,6 +510,112 @@ public class PythonDebuggerTest extends PyEnvTestCase {
});
}
public void testPyQtQThreadInheritor() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test_pyqt1.py") {
@Override
protected void init() {
setMultiprocessDebug(true);
}
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 8);
}
@Override
public void testing() throws Exception {
waitForPause();
eval("i").hasValue("0");
resume();
waitForPause();
eval("i").hasValue("1");
resume();
}
@Override
public Set<String> getTags() {
return Sets.newHashSet("pyqt5");
}
});
}
public void testPyQtMoveToThread() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test_pyqt2.py") {
@Override
protected void init() {
setMultiprocessDebug(true);
}
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 10);
}
@Override
public void testing() throws Exception {
waitForPause();
eval("i").hasValue("0");
resume();
waitForPause();
eval("i").hasValue("1");
resume();
}
@Override
public Set<String> getTags() {
return Sets.newHashSet("pyqt5");
}
});
}
public void testPyQtQRunnableInheritor() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test_pyqt3.py") {
@Override
protected void init() {
setMultiprocessDebug(true);
}
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 9);
}
@Override
public void testing() throws Exception {
waitForPause();
eval("i").hasValue("0");
resume();
waitForPause();
eval("i").hasValue("1");
resume();
}
@Override
public Set<String> getTags() {
return Sets.newHashSet("pyqt5");
}
});
}
//TODO: fix me as I don't work properly sometimes (something connected with process termination on agent)
//public void testResume() throws Exception {
+4
View File
@@ -52,6 +52,10 @@
<option name="PATTERN" value="sun.*" />
<option name="ENABLED" value="true" />
</filter>
<filter>
<option name="PATTERN" value="jdk.internal.*" />
<option name="ENABLED" value="true" />
</filter>
<filter>
<option name="PATTERN" value="junit.*" />
<option name="ENABLED" value="true" />
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -16,38 +16,38 @@
package com.intellij.spellchecker.inspector;
import com.intellij.spellchecker.SpellCheckerManager;
import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
import java.util.List;
public class SuggestionTest extends CodeInsightFixtureTestCase {
public class SuggestionTest extends LightPlatformCodeInsightFixtureTestCase {
private SpellCheckerManager spManager;
private SpellCheckerManager getManager(){
if (spManager==null){
private SpellCheckerManager getManager() {
if (spManager == null) {
spManager = SpellCheckerManager.getInstance(myFixture.getProject());
}
assert spManager!=null;
assert spManager != null;
return spManager;
}
public void testSuggestions(){
public void testSuggestions() {
List<String> result = getManager().getSuggestions("upgade");
assertEquals("upgrade",result.get(0));
assertEquals("upgrade", result.get(0));
}
public void testFirstLetterUppercaseSuggestions(){
public void testFirstLetterUppercaseSuggestions() {
List<String> result = getManager().getSuggestions("Upgade");
assertEquals("Upgrade",result.get(0));
assertEquals("Upgrade", result.get(0));
}
public void testCamelCaseSuggestions(){
public void testCamelCaseSuggestions() {
SpellCheckerManager manager = SpellCheckerManager.getInstance(myFixture.getProject());
assert manager!=null;
assert manager != null;
List<String> result = manager.getSuggestions("TestUpgade");
assertEquals("TestUpgrade",result.get(0));
assertEquals("TestUpgrade", result.get(0));
}
}
@@ -15,14 +15,14 @@
*/
package com.intellij.xml;
import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
import com.intellij.testFramework.fixtures.CodeInsightTestUtil;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import com.intellij.xml.refactoring.SchemaPrefixRenameHandler;
/**
* @author Konstantin Bulenkov
*/
public class XmlSchemaPrefixTest extends CodeInsightFixtureTestCase {
public class XmlSchemaPrefixTest extends LightCodeInsightFixtureTestCase {
public void testPrefixUsages() throws Exception {
doFindUsages("usages.xml", 16);
@@ -49,14 +49,8 @@ public class XmlSchemaPrefixTest extends CodeInsightFixtureTestCase {
return "/xml/tests/testData/schemaPrefix";
}
@Override
protected boolean isCommunity() {
return true;
}
protected void doFindUsages(String filename, int usages) {
final int size = myFixture.testFindUsages(filename).size();
assert size == usages : "Threre should be " + usages + " usages, but found " + size + ". File: " + filename;
assertSize(usages, myFixture.testFindUsages(filename));
}
}