Merge remote branch 'origin/master'

This commit is contained in:
Dmitry Jemerov
2011-12-15 22:07:17 +01:00
87 changed files with 1068 additions and 1190 deletions
@@ -18,8 +18,8 @@ package org.intellij.images.editor;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileListener;
import org.intellij.images.ui.ImageComponentDecorator;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -28,13 +28,9 @@ import javax.swing.*;
*
* @author <a href="mailto:aefimov.box@gmail.com">Alexey Efimov</a>
*/
public interface ImageEditor extends Disposable, ImageComponentDecorator {
@Nullable
public interface ImageEditor extends Disposable, VirtualFileListener, ImageComponentDecorator {
VirtualFile getFile();
long getFileLength();
Project getProject();
ImageDocument getDocument();
@@ -17,15 +17,16 @@ package org.intellij.images.editor.impl;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.*;
import org.intellij.images.editor.ImageDocument;
import org.intellij.images.editor.ImageEditor;
import org.intellij.images.editor.ImageZoomModel;
import org.intellij.images.fileTypes.ImageFileTypeManager;
import org.intellij.images.options.*;
import org.intellij.images.thumbnail.actionSystem.ThumbnailViewActions;
import org.intellij.images.ui.ImageComponent;
import org.intellij.images.vfs.IfsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -38,69 +39,58 @@ import java.beans.PropertyChangeListener;
*
* @author <a href="mailto:aefimov.box@gmail.com">Alexey Efimov</a>
*/
class ImageEditorImpl implements ImageEditor {
private final PropertyChangeListener optionsChangeListener = new OptionsChangeListener();
private final Project project;
private final ImageContentProvider contentProvider;
private final ImageEditorUI editorUI;
private boolean disposed;
final class ImageEditorImpl extends VirtualFileAdapter implements ImageEditor {
private final PropertyChangeListener optionsChangeListener = new OptionsChangeListener();
private final Project project;
private final VirtualFile file;
private final ImageEditorUI editorUI;
private boolean disposed;
ImageEditorImpl(@NotNull Project project, @NotNull final ImageContentProvider contentProvider) {
this.project = project;
this.contentProvider = contentProvider;
ImageEditorImpl(@NotNull Project project, @NotNull VirtualFile file) {
this.project = project;
this.file = file;
// Options
Options options = OptionsManager.getInstance().getOptions();
editorUI = new ImageEditorUI(this, options.getEditorOptions());
options.addPropertyChangeListener(optionsChangeListener);
contentProvider.addContentChangeListener(new ImageContentProvider.ContentChangeListener() {
public void contentChanged() {
setValue(contentProvider.getContent());
}
});
setValue(contentProvider.getContent());
}
private void setValue(ImageContentProvider.ImageContent content) {
ImageDocument document = editorUI.getImageComponent().getDocument();
BufferedImage image = content.getImage();
String format = content.getFormat();
if (image != null && format != null) {
BufferedImage previousImage = document.getValue();
document.setFormat(format);
document.setValue(image);
ImageZoomModel zoomModel = getZoomModel();
if (previousImage == null || !zoomModel.isZoomLevelChanged()) {
// Set smart zooming behaviour on open
// Options
Options options = OptionsManager.getInstance().getOptions();
ZoomOptions zoomOptions = options.getEditorOptions().getZoomOptions();
// Open as actual size
zoomModel.setZoomFactor(1.0d);
editorUI = new ImageEditorUI(this, options.getEditorOptions());
options.addPropertyChangeListener(optionsChangeListener);
if (zoomOptions.isSmartZooming()) {
Dimension prefferedSize = zoomOptions.getPrefferedSize();
if (prefferedSize.width > image.getWidth() && prefferedSize.height > image.getHeight()) {
// Resize to preferred size
// Calculate zoom factor
VirtualFileManager.getInstance().addVirtualFileListener(this);
setValue(file);
}
private void setValue(VirtualFile file) {
ImageDocument document = editorUI.getImageComponent().getDocument();
try {
BufferedImage previousImage = document.getValue();
BufferedImage image = IfsUtil.getImage(file);
document.setValue(image);
document.setFormat(IfsUtil.getFormat(file));
ImageZoomModel zoomModel = getZoomModel();
if (image != null && (previousImage == null || !zoomModel.isZoomLevelChanged())) {
// Set smart zooming behaviour on open
Options options = OptionsManager.getInstance().getOptions();
ZoomOptions zoomOptions = options.getEditorOptions().getZoomOptions();
// Open as actual size
zoomModel.setZoomFactor(1.0d);
if (zoomOptions.isSmartZooming()) {
Dimension prefferedSize = zoomOptions.getPrefferedSize();
if (prefferedSize.width > image.getWidth() && prefferedSize.height > image.getHeight()) {
// Resize to preffered size
// Calculate zoom factor
double factor = (prefferedSize.getWidth() / (double) image.getWidth() + prefferedSize.getHeight() / (double) image.getHeight()) / 2.0d;
zoomModel.setZoomFactor(Math.ceil(factor));
}
zoomModel.setZoomFactor(Math.ceil(factor));
}
}
}
} catch (Exception e) {
// Error loading image file
document.setValue(null);
}
}
}
else {
document.setValue(null);
document.setFormat(null);
// Close editor
VirtualFile file = contentProvider.getVirtualFile();
if (file != null) {
FileEditorManager editorManager = FileEditorManager.getInstance(project);
editorManager.closeFile(file);
}
}
}
public boolean isValid() {
ImageDocument document = editorUI.getImageComponent().getDocument();
@@ -115,14 +105,10 @@ class ImageEditorImpl implements ImageEditor {
return editorUI.getImageComponent();
}
@Nullable
public VirtualFile getFile() {
return contentProvider.getVirtualFile();
}
public long getFileLength() {
return contentProvider.getFileLength();
}
@NotNull
public VirtualFile getFile() {
return file;
}
@NotNull
public Project getProject() {
@@ -168,9 +154,40 @@ class ImageEditorImpl implements ImageEditor {
Options options = OptionsManager.getInstance().getOptions();
options.removePropertyChangeListener(optionsChangeListener);
editorUI.dispose();
VirtualFileManager.getInstance().removeVirtualFileListener(this);
disposed = true;
}
public void propertyChanged(VirtualFilePropertyEvent event) {
super.propertyChanged(event);
if (file.equals(event.getFile())) {
// Change document
file.refresh(true, false, new Runnable() {
public void run() {
if (ImageFileTypeManager.getInstance().isImage(file)) {
setValue(file);
} else {
setValue(null);
// Close editor
FileEditorManager editorManager = FileEditorManager.getInstance(project);
editorManager.closeFile(file);
}
}
});
}
}
public void contentsChanged(VirtualFileEvent event) {
super.contentsChanged(event);
if (file.equals(event.getFile())) {
// Change document
file.refresh(true, false, new Runnable() {
public void run() {
setValue(file);
}
});
}
}
private class OptionsChangeListener implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent evt) {
@@ -37,8 +37,8 @@ final class ImageEditorManagerImpl {
* @return Image editor for file
*/
@NotNull
public static ImageEditor createImageEditor(@NotNull Project project, @NotNull ImageContentProvider contentProvider) {
return new ImageEditorImpl(project, contentProvider);
public static ImageEditor createImageEditor(@NotNull Project project, @NotNull VirtualFile file) {
return new ImageEditorImpl(project, file);
}
/**
@@ -152,10 +152,11 @@ final class ImageEditorUI extends JPanel implements DataProvider {
} else {
format = format.toUpperCase();
}
VirtualFile file = editor.getFile();
infoLabel.setText(
ImagesBundle.message("image.info",
image.getWidth(), image.getHeight(), format,
colorModel.getPixelSize(), StringUtil.formatFileSize(editor.getFileLength())));
colorModel.getPixelSize(), file != null ? StringUtil.formatFileSize(file.getLength()) : ""));
} else {
infoLabel.setText(null);
}
@@ -347,8 +348,7 @@ final class ImageEditorUI extends JPanel implements DataProvider {
} else if (PlatformDataKeys.VIRTUAL_FILE.is(dataId)) {
return editor.getFile();
} else if (PlatformDataKeys.VIRTUAL_FILE_ARRAY.is(dataId)) {
final VirtualFile file = editor.getFile();
return file != null ? new VirtualFile[]{file} : null;
return new VirtualFile[]{editor.getFile()};
} else if (LangDataKeys.PSI_FILE.is(dataId)) {
return getData(LangDataKeys.PSI_ELEMENT.getName());
} else if (LangDataKeys.PSI_ELEMENT.is(dataId)) {
@@ -22,6 +22,8 @@ import com.intellij.openapi.fileEditor.FileEditorState;
import com.intellij.openapi.fileEditor.FileEditorStateLevel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import org.intellij.images.editor.ImageEditor;
import org.intellij.images.editor.ImageFileEditor;
import org.intellij.images.editor.ImageZoomModel;
@@ -43,8 +45,11 @@ final class ImageFileEditorImpl extends UserDataHolderBase implements ImageFileE
private static final String NAME = "ImageFileEditor";
private final ImageEditor imageEditor;
ImageFileEditorImpl(@NotNull Project project, @NotNull ImageContentProvider contentProvider) {
imageEditor = ImageEditorManagerImpl.createImageEditor(project, contentProvider);
ImageFileEditorImpl(@NotNull Project project, @NotNull VirtualFile file) {
imageEditor = ImageEditorManagerImpl.createImageEditor(project, file);
// Append file listener
VirtualFileManager.getInstance().addVirtualFileListener(imageEditor);
// Set background and grid default options
Options options = OptionsManager.getInstance().getOptions();
@@ -121,6 +126,7 @@ final class ImageFileEditorImpl extends UserDataHolderBase implements ImageFileE
}
public void dispose() {
VirtualFileManager.getInstance().removeVirtualFileListener(imageEditor);
ImageEditorManagerImpl.releaseImageEditor(imageEditor);
}
@@ -30,7 +30,7 @@ import org.jetbrains.annotations.NotNull;
*
* @author <a href="mailto:aefimov.box@gmail.com">Alexey Efimov</a>
*/
public final class ImageFileEditorProvider implements FileEditorProvider, DumbAware {
final class ImageFileEditorProvider implements FileEditorProvider, DumbAware {
@NonNls private static final String EDITOR_TYPE_ID = "images";
private final ImageFileTypeManager typeManager;
@@ -45,14 +45,7 @@ public final class ImageFileEditorProvider implements FileEditorProvider, DumbAw
@NotNull
public FileEditor createEditor(@NotNull Project project, @NotNull VirtualFile file) {
return createImageEditor(project, new VirtualFileImageContentProvider(file));
}
@NotNull
public static FileEditor createImageEditor(@NotNull Project project, @NotNull ImageContentProvider contentProvider) {
ImageFileEditorImpl editor = new ImageFileEditorImpl(project, contentProvider);
Disposer.register(editor, contentProvider);
return editor;
return new ImageFileEditorImpl(project, file);
}
public void disposeEditor(@NotNull FileEditor editor) {
@@ -1,112 +0,0 @@
/*
* Copyright 2000-2011 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 org.intellij.images.editor.impl;
import com.intellij.openapi.vfs.*;
import com.intellij.util.EventDispatcher;
import org.intellij.images.fileTypes.ImageFileTypeManager;
import org.intellij.images.vfs.IfsUtil;
import org.jetbrains.annotations.Nullable;
import java.awt.image.BufferedImage;
import java.io.IOException;
/**
* User: ksafonov
*/
class VirtualFileImageContentProvider extends VirtualFileAdapter implements ImageContentProvider {
private final VirtualFile myFile;
private final EventDispatcher<ContentChangeListener> myEventDispatcher = EventDispatcher.create(ContentChangeListener.class);
private static final ImageContent NULL_CONTENT = new ImageContent() {
public BufferedImage getImage() {
return null;
}
public String getFormat() {
return null;
}
};
public VirtualFileImageContentProvider(final VirtualFile virtualFile) {
myFile = virtualFile;
VirtualFileManager.getInstance().addVirtualFileListener(this);
}
public ImageContent getContent() {
if (ImageFileTypeManager.getInstance().isImage(myFile)) {
return new ImageContent() {
@Nullable
public BufferedImage getImage() {
try {
return IfsUtil.getImage(myFile);
}
catch (IOException e) {
return null;
}
}
@Nullable
public String getFormat() {
try {
return IfsUtil.getFormat(myFile);
}
catch (IOException e) {
return null;
}
}
};
}
else {
return NULL_CONTENT;
}
}
public void addContentChangeListener(final ContentChangeListener listener) {
myEventDispatcher.addListener(listener, this);
}
public VirtualFile getVirtualFile() {
return myFile;
}
public long getFileLength() {
return myFile.getLength();
}
public void dispose() {
VirtualFileManager.getInstance().removeVirtualFileListener(this);
}
public void propertyChanged(VirtualFilePropertyEvent event) {
onFileChange(event);
}
public void contentsChanged(VirtualFileEvent event) {
onFileChange(event);
}
private void onFileChange(final VirtualFileEvent event) {
if (myFile.equals(event.getFile())) {
// Change document
myFile.refresh(true, false, new Runnable() {
public void run() {
myEventDispatcher.getMulticaster().contentChanged();
}
});
}
}
}
+22 -37
View File
@@ -27,7 +27,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.reference.SoftReference;
import com.intellij.util.LogicalRoot;
import com.intellij.util.LogicalRootsManager;
import com.intellij.util.PairConsumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -58,21 +57,34 @@ public final class IfsUtil {
* @return true if file image is loaded.
* @throws java.io.IOException if image can not be loaded
*/
private static boolean refresh(@NotNull final VirtualFile file) throws IOException {
private static boolean refresh(@NotNull VirtualFile file) throws IOException {
Long loadedTimeStamp = file.getUserData(TIMESTAMP_KEY);
SoftReference<BufferedImage> imageRef = file.getUserData(BUFFERED_IMAGE_REF_KEY);
if (loadedTimeStamp == null || loadedTimeStamp.longValue() != file.getTimeStamp() || imageRef == null || imageRef.get() == null) {
try {
final byte[] content = file.contentsToByteArray();
final boolean loaded = processBytes(content, new PairConsumer<String, BufferedImage>() {
public void consume(final String formatName, final BufferedImage image) {
file.putUserData(FORMAT_KEY, formatName);
file.putUserData(BUFFERED_IMAGE_REF_KEY, new SoftReference<BufferedImage>(image));
InputStream inputStream = new ByteArrayInputStream(content, 0, content.length);
ImageInputStream imageInputStream = ImageIO.createImageInputStream(inputStream);
try {
Iterator<ImageReader> imageReaders = ImageIO.getImageReaders(imageInputStream);
if (imageReaders.hasNext()) {
ImageReader imageReader = imageReaders.next();
try {
file.putUserData(FORMAT_KEY, imageReader.getFormatName());
ImageReadParam param = imageReader.getDefaultReadParam();
imageReader.setInput(imageInputStream, true, true);
int minIndex = imageReader.getMinIndex();
BufferedImage image = imageReader.read(minIndex, param);
file.putUserData(BUFFERED_IMAGE_REF_KEY, new SoftReference<BufferedImage>(image));
return true;
} finally {
imageReader.dispose();
}
}
});
if (loaded) return true;
}
finally {
} finally {
imageInputStream.close();
}
} finally {
// We perform loading no more needed
file.putUserData(TIMESTAMP_KEY, file.getTimeStamp());
}
@@ -80,33 +92,6 @@ public final class IfsUtil {
return false;
}
public static boolean processBytes(final byte[] content, PairConsumer<String, BufferedImage> consumer) throws IOException {
InputStream inputStream = new ByteArrayInputStream(content, 0, content.length);
ImageInputStream imageInputStream = ImageIO.createImageInputStream(inputStream);
try {
Iterator<ImageReader> imageReaders = ImageIO.getImageReaders(imageInputStream);
if (imageReaders.hasNext()) {
ImageReader imageReader = imageReaders.next();
try {
final String formatName = imageReader.getFormatName();
ImageReadParam param = imageReader.getDefaultReadParam();
imageReader.setInput(imageInputStream, true, true);
int minIndex = imageReader.getMinIndex();
BufferedImage image = imageReader.read(minIndex, param);
consumer.consume(formatName, image);
return true;
}
finally {
imageReader.dispose();
}
}
}
finally {
imageInputStream.close();
}
return false;
}
@Nullable
public static BufferedImage getImage(@NotNull VirtualFile file) throws IOException {
refresh(file);
@@ -16,9 +16,12 @@
package com.intellij.compiler.impl.javaCompiler.api;
import com.intellij.compiler.OutputParser;
import com.sun.source.util.*;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.api.JavacTool;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.tools.*;
import java.io.File;
@@ -49,8 +52,11 @@ class CompAPIDriver {
private volatile boolean compiling;
private static final PrintWriter COMPILER_ERRORS = new PrintWriter(System.err);
@Nullable
private final String mySourcesEncoding;
CompAPIDriver() {
CompAPIDriver(@Nullable String sourcesEncoding) {
mySourcesEncoding = sourcesEncoding;
}
public void compile(List<String> commandLine, List<File> paths, final String outputDir) {
@@ -60,7 +66,7 @@ class CompAPIDriver {
assert myCompilationResults.isEmpty();
JavaCompiler compiler = JavacTool.create(); //use current classloader
StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null);
MyFileManager manager = new MyFileManager(this, outputDir, standardFileManager);
MyFileManager manager = new MyFileManager(this, outputDir, standardFileManager, mySourcesEncoding);
Iterable<? extends JavaFileObject> input = manager.getJavaFileObjectsFromFiles(paths);
@@ -141,13 +141,27 @@ public class CompilerAPICompiler implements BackendCompiler {
private final ModuleChunk myChunk;
private final String myOutputDir;
private final CompileContext myCompileContext;
private final CompAPIDriver myCompAPIDriver = new CompAPIDriver();
private final CompAPIDriver myCompAPIDriver;
private MyProcess(List<String> commandLine, ModuleChunk chunk, String outputDir, CompileContext compileContext) {
myCommandLine = commandLine;
myChunk = chunk;
myOutputDir = outputDir;
myCompileContext = compileContext;
myCompAPIDriver = new CompAPIDriver(findEncodingValue(commandLine));
}
private static String findEncodingValue(List<String> commandLine) {
boolean found = false;
for (String param : commandLine) {
if (found) {
return param;
}
if ("-encoding".equalsIgnoreCase(param)) {
found = true;
}
}
return null;
}
public OutputStream getOutputStream() {
@@ -16,8 +16,10 @@
package com.intellij.compiler.impl.javaCompiler.api;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.Nullable;
import javax.tools.*;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import java.io.*;
/**
@@ -26,15 +28,18 @@ import java.io.*;
@SuppressWarnings({"Since15"})
class JavaIoFile extends SimpleJavaFileObject {
private final File myFile;
@Nullable
private final String myEncoding;
JavaIoFile(File file, Kind kind) {
JavaIoFile(File file, Kind kind, @Nullable String encoding) {
super(file.toURI(), kind);
myFile = file;
myEncoding = encoding;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return FileUtil.loadFile(myFile);
return FileUtil.loadFile(myFile, myEncoding);
}
@Override
@@ -26,7 +26,9 @@ import com.sun.tools.javac.util.ListBuffer;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import javax.tools.*;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import java.io.File;
import java.io.IOException;
import java.net.URI;
@@ -40,12 +42,14 @@ class MyFileManager implements StandardJavaFileManager {
private final String myOutputDir;
private final StandardJavaFileManager myStandardFileManager;
private final String myEncoding;
private final CompAPIDriver myCompAPIDriver;
MyFileManager(CompAPIDriver compAPIDriver, String outputDir, StandardJavaFileManager standardFileManager) {
MyFileManager(CompAPIDriver compAPIDriver, String outputDir, StandardJavaFileManager standardFileManager, String encoding) {
myCompAPIDriver = compAPIDriver;
myOutputDir = outputDir;
myStandardFileManager = standardFileManager;
myEncoding = encoding;
}
@Override
@@ -54,7 +58,7 @@ class MyFileManager implements StandardJavaFileManager {
List<JavaFileObject> result = new ArrayList<JavaFileObject>(size);
for (File file : files) {
JavaFileObject fileObject = new JavaIoFile(file, JavaFileObject.Kind.SOURCE);
JavaFileObject fileObject = new JavaIoFile(file, JavaFileObject.Kind.SOURCE, myEncoding);
result.add(fileObject);
}
@@ -119,7 +123,7 @@ class MyFileManager implements StandardJavaFileManager {
if (kind == JavaFileObject.Kind.SOURCE && child.getFileSystem() instanceof JarFileSystem) continue; //for some reasdon javac looks for java files inside jar
// use VFS to read content inside .jar
JavaFileObject fileObject = !child.getPath().contains("!/") ? new JavaIoFile(new File(child.getPath()), kind) : new JavaVirtualFile(child, kind);
JavaFileObject fileObject = !child.getPath().contains("!/") ? new JavaIoFile(new File(child.getPath()), kind, myEncoding) : new JavaVirtualFile(child, kind);
results.add(fileObject);
}
}
@@ -48,6 +48,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
private JCheckBox myCbHideNullArrayElements;
private JCheckBox myCbShowStatic;
private JCheckBox myCbShowDeclaredType;
private JCheckBox myCbShowFQNames;
private JCheckBox myCbShowObjectId;
private StateRestoringCheckBox myCbShowStaticFinalFields;
@@ -102,6 +103,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
}
});
myCbShowDeclaredType = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.declared.type"));
myCbShowFQNames = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.fq.names"));
myCbShowObjectId = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.object.id"));
myCbEnableToString = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.enable.tostring"));
@@ -149,7 +151,8 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
showPanel.add(myCbShowObjectId, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(4, 0, 0, 0), 0, 0));
showPanel.add(myCbShowSyntheticFields, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0));
showPanel.add(myCbShowStatic, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(4, 10, 0, 0), 0, 0));
showPanel.add(myCbShowStaticFinalFields, new GridBagConstraints(2, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(4, 10, 0, 0), 0, 0));
showPanel.add(myCbShowStaticFinalFields, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(4, 10, 0, 0), 0, 0));
showPanel.add(myCbShowFQNames, new GridBagConstraints(3, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0));
panel.add(showPanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(4, 0, 0, 0), 0, 0));
@@ -193,6 +196,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
classRenderer.SHOW_STATIC_FINAL = myCbShowStaticFinalFields.isSelectedWhenSelectable();
classRenderer.SHOW_SYNTHETICS = myCbShowSyntheticFields.isSelected();
classRenderer.SHOW_DECLARED_TYPE = myCbShowDeclaredType.isSelected();
classRenderer.SHOW_FQ_TYPE_NAMES = myCbShowFQNames.isSelected();
classRenderer.SHOW_OBJECT_ID = myCbShowObjectId.isSelected();
final ToStringRenderer toStringRenderer = rendererSettings.getToStringRenderer();
@@ -226,6 +230,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
myCbShowStaticFinalFields.makeUnselectable(false);
}
myCbShowDeclaredType.setSelected(classRenderer.SHOW_DECLARED_TYPE);
myCbShowFQNames.setSelected(classRenderer.SHOW_FQ_TYPE_NAMES);
myCbShowObjectId.setSelected(classRenderer.SHOW_OBJECT_ID);
final ToStringRenderer toStringRenderer = rendererSettings.getToStringRenderer();
@@ -275,6 +280,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
(classRenderer.SHOW_STATIC_FINAL != myCbShowStaticFinalFields.isSelectedWhenSelectable()) ||
(classRenderer.SHOW_SYNTHETICS != myCbShowSyntheticFields.isSelected()) ||
(classRenderer.SHOW_DECLARED_TYPE != myCbShowDeclaredType.isSelected()) ||
(classRenderer.SHOW_FQ_TYPE_NAMES != myCbShowFQNames.isSelected()) ||
(classRenderer.SHOW_OBJECT_ID != myCbShowObjectId.isSelected());
if (isClassRendererModified) {
return true;
@@ -158,7 +158,7 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes
buf.append(getName());
if (classRenderer.SHOW_DECLARED_TYPE) {
buf.append(": ");
buf.append(myField.typeName());
buf.append(classRenderer.renderTypeName(myField.typeName()));
}
return buf.toString();
}
@@ -121,7 +121,7 @@ public class LocalVariableDescriptorImpl extends ValueDescriptorImpl implements
buf.append(getName());
if (classRenderer.SHOW_DECLARED_TYPE) {
buf.append(": ");
buf.append(myTypeName);
buf.append(classRenderer.renderTypeName(myTypeName));
}
return buf.toString();
}
@@ -23,7 +23,9 @@ package com.intellij.debugger.ui.impl.watch;
import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.ui.tree.StaticDescriptor;
import com.intellij.debugger.ui.tree.render.ClassRenderer;
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
import com.sun.jdi.Field;
import com.sun.jdi.ReferenceType;
@@ -64,6 +66,7 @@ public class StaticDescriptorImpl extends NodeDescriptorImpl implements StaticDe
protected String calcRepresentation(EvaluationContextImpl context, DescriptorLabelListener descriptorLabelListener) throws EvaluateException {
DebuggerManagerThreadImpl.assertIsManagerThread();
return getName() + " = " + myType.name();
final ClassRenderer classRenderer = NodeRendererSettings.getInstance().getClassRenderer();
return getName() + " = " + classRenderer.renderTypeName(myType.name());
}
}
@@ -27,7 +27,9 @@ import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.ui.tree.UserExpressionDescriptor;
import com.intellij.debugger.ui.tree.render.ClassRenderer;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiCodeFragment;
@@ -57,8 +59,10 @@ public class UserExpressionDescriptorImpl extends EvaluationDescriptor implement
try {
buffer.append(getName());
buffer.append(": ");
if(getValue() != null) {
buffer.append(getValue().type().name());
final Value value = getValue();
if(value != null) {
final ClassRenderer classRenderer = NodeRendererSettings.getInstance().getClassRenderer();
buffer.append(classRenderer.renderTypeName(value.type().name()));
}
return buffer.toString();
@@ -378,7 +378,7 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
if (showConcreteType || classRenderer.SHOW_OBJECT_ID) {
buf.append('{');
if (showConcreteType) {
buf.append(objRef.type().name());
buf.append(classRenderer.renderTypeName(objRef.type().name()));
}
if (classRenderer.SHOW_OBJECT_ID) {
buf.append('@');
@@ -63,6 +63,7 @@ public class ClassRenderer extends NodeRendererImpl{
public boolean SHOW_STATIC = false;
public boolean SHOW_STATIC_FINAL = false;
public boolean SHOW_FQ_TYPE_NAMES = true;
public boolean SHOW_DECLARED_TYPE = false;
public boolean SHOW_OBJECT_ID = true;
@@ -70,6 +71,17 @@ public class ClassRenderer extends NodeRendererImpl{
myProperties.setEnabled(true);
}
public final String renderTypeName(final String typeName) {
if (SHOW_FQ_TYPE_NAMES) {
return typeName;
}
final int dotIndex = typeName.lastIndexOf('.');
if (dotIndex > 0) {
return typeName.substring(dotIndex + 1);
}
return typeName;
}
public String getUniqueId() {
return UNIQUE_ID;
}
@@ -36,6 +36,7 @@ import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStr
import com.intellij.openapi.ui.DetailsComponent;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.util.IconLoader;
import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -43,6 +44,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.*;
import java.util.List;
@@ -55,6 +58,7 @@ public class FacetStructureConfigurable extends BaseStructureConfigurable {
private final Map<FacetType<?, ?>, FacetTypeEditor> myFacetTypeEditors = new HashMap<FacetType<?,?>, FacetTypeEditor>();
private MultipleFacetSettingsEditor myCurrentMultipleSettingsEditor;
@NonNls private static final String NO_FRAMEWORKS_NODE = "No facets are configured";
private boolean myTreeWasInitialized;
public FacetStructureConfigurable(final Project project, ModuleManager moduleManager) {
super(project);
@@ -77,7 +81,30 @@ public class FacetStructureConfigurable extends BaseStructureConfigurable {
@Override
protected void initTree() {
super.initTree();
myTree.setCellRenderer(new FacetsTreeCellRenderer());
if (!myTreeWasInitialized) {
myTreeWasInitialized = true;
myTree.setCellRenderer(new FacetsTreeCellRenderer());
myTree.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
revalidateTree();
}
@Override
public void componentMoved(ComponentEvent e) {
revalidateTree();
}
@Override
public void componentShown(ComponentEvent e) {
revalidateTree();
}
});
}
}
private void revalidateTree() {
FilteringTreeBuilder.revalidateTree(myTree);
}
protected void loadTree() {
@@ -56,8 +56,8 @@ public class FacetsTreeCellRenderer extends GroupedElementsRenderer.Tree impleme
final Icon icon = configurable.getIcon(expanded);
final boolean showSeparator = configurable instanceof FrameworkDetectionConfigurable;
int width = -1;
if (showSeparator) {
final int treeWidth = tree.getSize().width;
if (showSeparator && tree.isVisible()) {
final int treeWidth = tree.getVisibleRect().width - 4;
if (treeWidth > 0) {
width = treeWidth;
}
@@ -634,6 +634,27 @@ public interface Test {
assert !lookup
}
public void testNoSingleTemplateLookup() {
myFixture.configureByText 'a.java', 'class Foo {{ ite<caret> }}'
type 'r'
assert !lookup
}
public void testTemplatesWithNonImportedClasses() {
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.NONE
myFixture.addClass("package foo.bar; public class LayoutStore {}")
try {
myFixture.configureByText 'a.java', 'class Foo {{ foo(<caret>) }}'
type 'lst'
assert lookup
assert 'lst' in myFixture.lookupElementStrings
assert 'LayoutStore' in myFixture.lookupElementStrings
}
finally {
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.FIRST_LETTER
}
}
public void testTemplateSelectionByComma() {
myFixture.configureByText("a.java", """
class Foo {
@@ -16,12 +16,10 @@
package com.intellij.codeInsight;
import com.intellij.openapi.application.ConfigImportHelper;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.hash.HashSet;
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
import com.intellij.util.xmlb.XmlSerializationException;
import com.intellij.util.xmlb.XmlSerializer;
@@ -33,9 +31,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@State(
@@ -148,32 +143,6 @@ public class CodeInsightSettings implements PersistentStateComponent<Element>, C
catch (XmlSerializationException e) {
LOG.info(e);
}
// TODO den remove when IJ v.11 is released.
// 1. Old default value for 'reformat on paste' setting was 'indent block';
// 2. 'Indent block' processing was corrected and it requires copied text to include first line indent in order for correct processing;
// 3. Many of our users don't include first line's indent to the copied text. That's why 'indent each line' was set as default;
// 4. We had a problem that code insight settings with default values were stored to a hdd. So, new default value will not
// be automatically applied;
// 5. That's why we explicitly set 'indent block's value to 'indent each line' if detect that this is the first line of IJ v.11;
if (Boolean.getBoolean(ConfigImportHelper.CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY)) {
REFORMAT_ON_PASTE = INDENT_EACH_LINE;
}
// TODO den remove this at 2012 (if we're still alive)
// There was a problem that 'exclude package' settings were written multiple times. The code below removes the duplicates.
// The problem is not included to the release version, so, we can have that filtering logic for a time that is enough for
// removing the duplicate across IJ team machines. It may be safely removed after that.
List<String> result = new ArrayList<String>();
Set<String> buffer = new HashSet<String>();
for (String s : EXCLUDED_PACKAGES) {
if (buffer.add(s)) {
result.add(s);
}
}
if (result.size() < EXCLUDED_PACKAGES.length) {
EXCLUDED_PACKAGES = result.toArray(new String[result.size()]);
}
}
public Element getState() {
@@ -25,6 +25,7 @@ import com.intellij.codeInsight.hint.EditorHintListener;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.codeInsight.template.impl.LiveTemplateLookupElement;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.injected.editor.DocumentWindow;
import com.intellij.injected.editor.EditorWindow;
@@ -511,7 +512,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
return false;
}
if (item.isValid()) {
if (item.isValid() && !(item instanceof LiveTemplateLookupElement)) {
final LookupElementPresentation presentation = new LookupElementPresentation();
item.renderElement(presentation);
if (StringUtil.isNotEmpty(presentation.getTailText())) {
@@ -29,6 +29,7 @@ import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
@@ -40,7 +41,9 @@ import java.util.Map;
public class ListTemplatesHandler implements CodeInsightActionHandler {
public void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
if (!file.isWritable()) return;
if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) {
return;
}
EditorUtil.fillVirtualSpaceUntilCaret(editor);
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -118,6 +118,11 @@ public class FoldingModelWindow implements FoldingModelEx{
myDelegate.runBatchFoldingOperation(operation);
}
@Override
public void runBatchFoldingOperation(@NotNull Runnable operation, boolean moveCaretFromCollapsedRegion) {
myDelegate.runBatchFoldingOperation(operation, moveCaretFromCollapsedRegion);
}
@Override
public void runBatchFoldingOperationDoNotCollapseCaret(@NotNull Runnable operation) {
myDelegate.runBatchFoldingOperationDoNotCollapseCaret(operation);
@@ -222,6 +222,8 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli
//todo use DefaultExternalizer
public void readExternal(Element parentNode) {
boolean safeWriteSettingRead = false;
List children = parentNode.getChildren(ELEMENT_OPTION);
for (final Object aChildren : children) {
Element element = (Element)aChildren;
@@ -295,6 +297,7 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli
}
if (OPTION_USE_SAFE_WRITE.equals(name) && value != null) {
myUseSafeWrite = Boolean.valueOf(value).booleanValue();
safeWriteSettingRead = true;
}
if (OPTION_CHARSET.equals(name)) {
@@ -361,6 +364,10 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli
}
}
}
if (!safeWriteSettingRead && "true".equals(System.getProperty("idea.no.safe.write"))) {
myUseSafeWrite = false;
}
}
public void writeExternal(Element parentNode) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -64,6 +64,7 @@ public interface FoldingModel {
*/
boolean isOffsetCollapsed(int offset);
@Nullable
FoldRegion getCollapsedRegionAtOffset(int offset);
/**
@@ -74,5 +75,15 @@ public interface FoldingModel {
*/
void runBatchFoldingOperation(@NotNull Runnable operation);
/**
* Runs an operation which is allowed to modify fold regions in the editor by calling
* {@link #addFoldRegion(int, int, String)} and {@link #removeFoldRegion(FoldRegion)}.
*
* @param operation the operation to execute.
* @param moveCaretFromCollapsedRegion flag that identifies whether caret position should be changed if it's located inside
* collapsed fold region after the operation
*/
void runBatchFoldingOperation(@NotNull Runnable operation, boolean moveCaretFromCollapsedRegion);
void runBatchFoldingOperationDoNotCollapseCaret(@NotNull Runnable operation);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -143,7 +143,10 @@ public class LogicalPosition implements Comparable<LogicalPosition> {
public String toString() {
return "LogicalPosition: (" + line + ", " + column + ")"
+ (visualPositionAware ? "; vp aware" : "")
+ (softWrapLinesBeforeCurrentLogicalLine + softWrapLinesOnCurrentLogicalLine == 0 ? "" : "; soft wrap: lines=" + (softWrapLinesBeforeCurrentLogicalLine + softWrapLinesOnCurrentLogicalLine) + " (before=" + softWrapLinesBeforeCurrentLogicalLine + "; current=" + softWrapLinesOnCurrentLogicalLine + ")")
+ (softWrapLinesBeforeCurrentLogicalLine + softWrapLinesOnCurrentLogicalLine == 0
? ""
: "; soft wrap: lines=" + (softWrapLinesBeforeCurrentLogicalLine + softWrapLinesOnCurrentLogicalLine)
+ " (before=" + softWrapLinesBeforeCurrentLogicalLine + "; current=" + softWrapLinesOnCurrentLogicalLine + ")")
+ (softWrapColumnDiff == 0 ? "" : "columns diff=" + softWrapColumnDiff + ";" )
+ (foldedLines == 0? "" : " folding: lines = " + foldedLines + ";")
+ (foldingColumnDiff == 0 ? "" : " columns diff=" + foldingColumnDiff);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,8 +41,7 @@ import java.util.List;
* @author Eugene Belyaev
*/
public class HyperlinkLabel extends HighlightableComponent {
private static final TextAttributes BOLD_ATTRIBUTES =
new TextAttributes(UIUtil.getLabelTextForeground(), UIUtil.getLabelBackground(), null, null, Font.BOLD);
private static final TextAttributes BOLD_ATTRIBUTES = new TextAttributes(UIUtil.getLabelTextForeground(), null, null, null, Font.BOLD);
private static final Logger LOG = Logger.getInstance(HyperlinkLabel.class.getName());
@@ -73,6 +73,34 @@ public abstract class OptionalChooserComponent<T> implements CheckBoxListListene
return myList.getSelectedIndex();
}
public void setSelectedIndex(final int index) {
myList.setSelectedIndex(index);
}
public boolean removeAt(final int index) {
getCurrentModel().remove(index);
refresh();
if (index < getCurrentModel().size()) {
setSelectedIndex(index);
return true;
}
else if (index > 0) {
setSelectedIndex(index - 1);
return true;
}
return false;
}
public boolean removeSelected() {
final int selectedIndex = getSelectedIndex();
// selected index
if (selectedIndex != -1) {
return removeAt(selectedIndex);
}
return false;
}
public boolean isModified() {
return !myWorkingList.equals(myInitialList);
}
@@ -18,14 +18,16 @@ package com.intellij.ui.components;
import com.intellij.ui.table.JBTable;
import com.intellij.util.ui.ComponentWithEmptyText;
import com.intellij.util.ui.StatusText;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
public class JBViewport extends JViewport {
public class JBViewport extends JViewport implements ZoomableViewport {
private StatusText myEmptyText;
private ZoomingDelegate myZoomer;
public JBViewport() {
addContainerListener(new ContainerListener() {
@@ -50,16 +52,40 @@ public class JBViewport extends JViewport {
}
@Override
public Dimension getPreferredSize() {
return super.getPreferredSize(); //To change body of overridden methods use File | Settings | File Templates.
public void paint(Graphics g) {
if (myZoomer != null && myZoomer.isActive()) {
myZoomer.paint(g);
}
else {
super.paint(g);
if (myEmptyText != null) {
myEmptyText.paint(this, g);
}
}
}
@Nullable
@Override
public Magnificator getMagnificator() {
JComponent view = (JComponent)getView();
return view != null ? (Magnificator)view.getClientProperty(Magnificator.CLIENT_PROPERTY_KEY) : null;
}
@Override
public void paint(Graphics g) {
super.paint(g);
public void magnificationStarted(Point at) {
myZoomer = new ZoomingDelegate((JComponent)getView(), this);
myZoomer.magnificationStarted(at);
}
if (myEmptyText != null) {
myEmptyText.paint(this, g);
}
@Override
public void magnificationFinished(double magnification) {
myZoomer.magnificationFinished(magnification);
myZoomer = null;
}
@Override
public void magnify(double magnification) {
myZoomer.magnify(magnification);
}
}
@@ -0,0 +1,29 @@
/*
* Copyright 2000-2011 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.
*/
/*
* @author max
*/
package com.intellij.ui.components;
import com.intellij.openapi.util.Key;
import java.awt.*;
public interface Magnificator {
Key CLIENT_PROPERTY_KEY = Key.create("MagnifiableComponent");
Point magnify(double scale, Point at);
}
@@ -13,39 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.intellij.images.editor.impl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.vfs.VirtualFile;
/*
* @author max
*/
package com.intellij.ui.components;
import org.jetbrains.annotations.Nullable;
import java.awt.image.BufferedImage;
import java.util.EventListener;
/**
* User: ksafonov
*/
public interface ImageContentProvider extends Disposable {
interface ImageContent {
@Nullable
BufferedImage getImage();
@Nullable
String getFormat();
}
interface ContentChangeListener extends EventListener {
void contentChanged();
}
ImageContent getContent();
void addContentChangeListener(ContentChangeListener listener);
import java.awt.*;
public interface ZoomableViewport {
@Nullable
VirtualFile getVirtualFile();
long getFileLength();
Magnificator getMagnificator();
void magnificationStarted(Point at);
void magnificationFinished(double magnification);
void magnify(double magnification);
}
@@ -0,0 +1,125 @@
/*
* Copyright 2000-2011 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.
*/
/*
* @author max
*/
package com.intellij.ui.components;
import com.intellij.ui.Gray;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class ZoomingDelegate {
private final JComponent myContentComponent;
private final JComponent myViewportComponent;
private BufferedImage myCachedImage;
private Point myMagnificationPoint;
private double myMagnification;
public ZoomingDelegate(JComponent contentComponent, JComponent viewportComponent) {
myContentComponent = contentComponent;
myViewportComponent = viewportComponent;
}
public void paint(Graphics g) {
if (myCachedImage != null && myMagnificationPoint != null && myMagnification != 0) {
double scale = magnificationToScale(myMagnification);
int xoffset = (int)(myMagnificationPoint.x - myMagnificationPoint.x * scale);
int yoffset = (int)(myMagnificationPoint.y - myMagnificationPoint.y * scale);
Rectangle clip = g.getClipBounds();
g.setColor(Gray._120);
g.fillRect(clip.x, clip.y, clip.width, clip.height);
Graphics2D translated = (Graphics2D)g.create();
translated.translate(xoffset, yoffset);
translated.scale(scale, scale);
translated.drawImage(myCachedImage, 0, 0, null);
}
}
public void magnificationStarted(Point at) {
myMagnificationPoint = at;
}
public void magnificationFinished(double magnification) {
if (myMagnification != 0) {
Magnificator magnificator = ((ZoomableViewport)myViewportComponent).getMagnificator();
if (magnificator != null) {
Point inContent = convertToContentCoordinates(myMagnificationPoint);
final Point inContentScaled = magnificator.magnify(magnificationToScale(magnification), inContent);
int voffset = inContentScaled.y - myMagnificationPoint.y;
int hoffset = inContentScaled.x - myMagnificationPoint.x;
myViewportComponent.repaint();
myViewportComponent.validate();
scrollTo(voffset, hoffset);
}
}
myMagnificationPoint = null;
myMagnification = 0;
myCachedImage = null;
}
protected void scrollTo(int voffset, int hoffset) {
JViewport viewport = (JViewport)myViewportComponent;
JScrollPane pane = (JScrollPane)viewport.getParent();
JScrollBar vsb = pane.getVerticalScrollBar();
vsb.setValue(voffset);
JScrollBar hsb = pane.getHorizontalScrollBar();
hsb.setValue(hoffset);
}
protected Point convertToContentCoordinates(Point point) {
return SwingUtilities.convertPoint(myViewportComponent, point, myContentComponent);
}
public boolean isActive() {
return myCachedImage != null;
}
private static double magnificationToScale(double magnification) {
return magnification < 0 ? 1f / (1 - magnification) : (1 + magnification);
}
public void magnify(double magnification) {
if (myMagnification != magnification) {
myMagnification = magnification;
if (myCachedImage == null) {
Rectangle bounds = myViewportComponent.getBounds();
BufferedImage image = new BufferedImage(bounds.width, bounds.height, BufferedImage.TYPE_INT_RGB);
Graphics graphics = image.getGraphics();
graphics.setClip(0, 0, bounds.width, bounds.height);
myViewportComponent.paint(graphics);
myCachedImage = image;
}
}
myViewportComponent.repaint();
}
}
@@ -86,7 +86,7 @@ public class TableView<Item> extends BaseTableView implements ItemsProvider, Sel
final TableColumn column = getColumnModel().getColumn(i);
// hack to get sort arrow included into the renderer component
if (sorter != null && columnInfo.isSortable()) {
sorter.setSortKeys(Collections.singletonList(new RowSorter.SortKey(0, SortOrder.ASCENDING)));
sorter.setSortKeys(Collections.singletonList(new RowSorter.SortKey(i, SortOrder.ASCENDING)));
}
final Component headerComponent = defaultRenderer == null? null :
@@ -187,10 +187,14 @@ public class FilteringTreeBuilder extends AbstractTreeBuilder {
}
public void revalidateTree() {
myTree.invalidate();
myTree.setRowHeight(myTree.getRowHeight() == -1 ? -2 : -1);
myTree.revalidate();
myTree.repaint();
revalidateTree(myTree);
}
public static void revalidateTree(Tree tree) {
tree.invalidate();
tree.setRowHeight(tree.getRowHeight() == -1 ? -2 : -1);
tree.revalidate();
tree.repaint();
}
@@ -18,6 +18,7 @@ package com.intellij.diagnostic;
import com.intellij.diagnostic.errordialog.Attachment;
import com.intellij.openapi.diagnostic.IdeaLoggingEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ExceptionUtil;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -137,7 +138,8 @@ public class LogMessageEx extends LogMessage {
if (details.length > 0 && detailsBuffer.length() > 0) {
detailsBuffer.setLength(detailsBuffer.length() - 1);
}
logger.error(createEvent(message, detailsBuffer.toString(), null, null, (Attachment)null));
Attachment attachment = detailsBuffer.length() > 0 ? new Attachment("current-context.txt", detailsBuffer.toString()) : null;
logger.error(createEvent(message, ExceptionUtil.getThrowableText(new Throwable()), null, null, attachment));
}
/**
@@ -16,9 +16,16 @@
package com.intellij.openapi.actionSystem.impl;
import com.apple.eawt.event.*;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.ui.components.Magnificator;
import com.intellij.ui.components.ZoomableViewport;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
/**
* User: anna
@@ -28,6 +35,7 @@ class MacGestureAdapter extends GestureAdapter {
double magnification;
private final IdeFrame myFrame;
private MouseGestureManager myManager;
private ZoomableViewport myMagnifyingViewport;
public MacGestureAdapter(MouseGestureManager manager, IdeFrame frame) {
myFrame = frame;
@@ -38,35 +46,63 @@ class MacGestureAdapter extends GestureAdapter {
@Override
public void gestureBegan(GesturePhaseEvent event) {
myManager.activateTrackpad();
magnification = 0;
Point mouse = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(mouse, myFrame.getComponent());
Component deepest = SwingUtilities.getDeepestComponentAt(myFrame.getComponent(), mouse.x, mouse.y);
ZoomableViewport viewport = (ZoomableViewport) SwingUtilities.getAncestorOfClass(ZoomableViewport.class, deepest);
if (viewport != null) {
Magnificator magnificator = viewport.getMagnificator();
if (magnificator != null) {
Point at = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(at, (JComponent)viewport);
viewport.magnificationStarted(at);
myMagnifyingViewport = viewport;
}
}
}
@Override
public void gestureEnded(GesturePhaseEvent event) {
myManager.activateTrackpad();
if (magnification != 0) {
MouseGestureManager.processMagnification(myFrame, magnification);
if (myMagnifyingViewport != null) {
myMagnifyingViewport.magnificationFinished(magnification);
myMagnifyingViewport = null;
magnification = 0;
}
}
@Override
public void swipedLeft(SwipeEvent event) {
myManager.activateTrackpad();
myManager.processLeftSwipe(myFrame);
ActionManager actionManager = ActionManager.getInstance();
AnAction forward = actionManager.getAction("Forward");
if (forward == null) return;
actionManager.tryToExecute(forward, createMouseEventWrapper(myFrame), null, null, false);
}
@Override
public void swipedRight(SwipeEvent event) {
myManager.activateTrackpad();
myManager.processRightSwipe(myFrame);
ActionManager actionManager = ActionManager.getInstance();
AnAction back = actionManager.getAction("Back");
if (back == null) return;
actionManager.tryToExecute(back, createMouseEventWrapper(myFrame), null, null, false);
}
private static MouseEvent createMouseEventWrapper(IdeFrame frame) {
return new MouseEvent(frame.getComponent(), ActionEvent.ACTION_PERFORMED, System.currentTimeMillis(), 0, 0, 0, 0, false, 0);
}
@Override
public void magnify(MagnificationEvent event) {
myManager.activateTrackpad();
magnification += event.getMagnification();
if (myMagnifyingViewport != null) {
myMagnifyingViewport.magnify(magnification);
}
}
public void remove(JComponent cmp) {
@@ -39,14 +39,11 @@ import java.util.Map;
public class MouseGestureManager implements ApplicationComponent {
private static final Logger LOG = Logger.getInstance("MouseGestureManager");
private ActionManagerImpl myActionManager;
private Map<IdeFrame, Object> myListeners = new HashMap<IdeFrame, Object>();
private boolean HAS_TRACKPAD = false;
public MouseGestureManager(ActionManagerImpl actionManager) {
myActionManager = actionManager;
public MouseGestureManager() {
}
public void add(final IdeFrame frame) {
@@ -76,38 +73,6 @@ public class MouseGestureManager implements ApplicationComponent {
return HAS_TRACKPAD;
}
protected static void processMagnification(IdeFrame frame, double magnification) {
Point mouse = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(mouse, frame.getComponent());
Component componentAt = SwingUtilities.getDeepestComponentAt(frame.getComponent(), mouse.x, mouse.y);
if (componentAt != null) {
Editor editor = PlatformDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext(componentAt));
if (editor != null) {
double currentSize = editor.getColorsScheme().getEditorFontSize();
int defaultFontSize = EditorColorsManager.getInstance().getGlobalScheme().getEditorFontSize();
((EditorEx)editor).setFontSize((int)(Math.max(currentSize + magnification * 3, defaultFontSize)));
}
}
}
protected void processLeftSwipe(IdeFrame frame) {
AnAction forward = myActionManager.getAction("Forward");
if (forward == null) return;
myActionManager.tryToExecute(forward, createMouseEventWrapper(frame), null, null, false);
}
protected void processRightSwipe(IdeFrame frame) {
AnAction back = myActionManager.getAction("Back");
if (back == null) return;
myActionManager.tryToExecute(back, createMouseEventWrapper(frame), null, null, false);
}
private static MouseEvent createMouseEventWrapper(IdeFrame frame) {
return new MouseEvent(frame.getComponent(), ActionEvent.ACTION_PERFORMED, System.currentTimeMillis(), 0, 0, 0, 0, false, 0);
}
public void remove(IdeFrame frame) {
if (!Registry.is("actionSystem.mouseGesturesEnabled")) return;
@@ -212,20 +212,22 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
validateCallContext();
final LogicalPosition logicalPosition = myEditor.offsetToLogicalPosition(offset);
moveToLogicalPosition(logicalPosition, locateBeforeSoftWrap, null);
if (!ignoreWrongMoves && !myEditor.offsetToLogicalPosition(myOffset).equals(logicalPosition)) {
final LogicalPosition positionByOffsetAfterMove = myEditor.offsetToLogicalPosition(myOffset);
if (!ignoreWrongMoves && !positionByOffsetAfterMove.equals(logicalPosition)) {
StringBuilder debugBuffer = new StringBuilder();
moveToLogicalPosition(logicalPosition, locateBeforeSoftWrap, debugBuffer);
int textStart = Math.max(0, Math.min(offset, myOffset) - 1);
final DocumentEx document = myEditor.getDocument();
int textEnd = Math.min(document.getTextLength() - 1, Math.max(offset, myOffset) + 1);
CharSequence text = document.getCharsSequence().subSequence(textStart, textEnd);
LOG.error(
"caret moved to wrong offset. Requested: offset=" + offset + ", logical position=" + logicalPosition
+ " but actual: offset=" + myOffset + ", logical position=" + myLogicalCaret + "(" + myEditor.offsetToLogicalPosition(myOffset)
+ "). " + myEditor.dumpState()
+ "\n interested text [" + textStart + "; " + textEnd + "): '" + text + "'"
+ "\n debug trace: " + debugBuffer
);
LogMessageEx.error(
LOG, "caret moved to wrong offset",
String.format(
"Requested: offset=%d, logical position='%s' but actual: offset=%d, logical position='%s' (%s). %s%n"
+ "interested text [%d;%d): '%s'%n debug trace: %s",
offset, logicalPosition, myOffset, myLogicalCaret, positionByOffsetAfterMove, myEditor.dumpState(),
textStart, textEnd, text, debugBuffer
));
}
}
@@ -408,7 +410,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
assertIsDispatchThread();
if (debugBuffer != null) {
debugBuffer.append(String.format(
"Start moveToLogicalPosition(). Locate before soft wrap: %b, position: %s", locateBeforeSoftWrap, pos
"Start moveToLogicalPosition(). Locate before soft wrap: %b, position: %s%n", locateBeforeSoftWrap, pos
));
}
myDesiredX = -1;
@@ -423,14 +425,14 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
if (column < 0) {
if (debugBuffer != null) {
debugBuffer.append("Resetting target logical column to zero as it is negative (" + column + ")");
debugBuffer.append("Resetting target logical column to zero as it is negative (" + column + ")\n");
}
column = 0;
softWrapColumns = 0;
}
if (line < 0) {
if (debugBuffer != null) {
debugBuffer.append("Resetting target logical line to zero as it is negative (" + line + ")");
debugBuffer.append("Resetting target logical line to zero as it is negative (" + line + ")\n");
}
line = 0;
softWrapLinesBefore = 0;
@@ -440,14 +442,14 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
int lineCount = doc.getLineCount();
if (lineCount == 0) {
if (debugBuffer != null) {
debugBuffer.append("Resetting target logical line to zero as the document is empty");
debugBuffer.append("Resetting target logical line to zero as the document is empty\n");
}
line = 0;
}
else if (line > lineCount - 1) {
if (debugBuffer != null) {
debugBuffer.append(String.format(
"Resetting target logical line (%d) to %d as it is greater than total document lines number", line, lineCount - 1
"Resetting target logical line (%d) to %d as it is greater than total document lines number%n", line, lineCount - 1
));
}
line = lineCount - 1;
@@ -470,7 +472,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
if (debugBuffer != null) {
debugBuffer.append(String.format(
"Resetting target logical column (%d) to %d because caret is not allowed to be located after line end (offset: %d, "
+ "logical position: %s). Current soft wrap columns value: %d",
+ "logical position: %s). Current soft wrap columns value: %d%n",
oldColumn, lineEndColumnNumber, lineEndOffset, endLinePosition, softWrapColumns
));
}
@@ -494,14 +496,14 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
setCurrentLogicalCaret(logicalPositionToUse);
final int offset = myEditor.logicalPositionToOffset(myLogicalCaret);
if (debugBuffer != null) {
debugBuffer.append(String.format("Resulting logical position to use: %s. It's mapped to offset %d", myLogicalCaret, offset));
debugBuffer.append(String.format("Resulting logical position to use: %s. It's mapped to offset %d%n", myLogicalCaret, offset));
}
FoldRegion collapsedAt = myEditor.getFoldingModel().getCollapsedRegionAtOffset(offset);
if (collapsedAt != null && offset > collapsedAt.getStartOffset()) {
if (debugBuffer != null) {
debugBuffer.append("Scheduling expansion of fold region ").append(collapsedAt);
debugBuffer.append("Scheduling expansion of fold region ").append(collapsedAt).append("\n");
}
Runnable runnable = new Runnable() {
@Override
@@ -513,7 +515,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
}
};
myEditor.getFoldingModel().runBatchFoldingOperation(runnable);
myEditor.getFoldingModel().runBatchFoldingOperation(runnable, false);
}
myEditor.setLastColumnNumber(myLogicalCaret.column);
@@ -521,7 +523,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
myOffset = myEditor.logicalPositionToOffset(myLogicalCaret);
if (debugBuffer != null) {
debugBuffer.append(String.format("Storing offset %d (mapped from logical position %s)", myOffset, myLogicalCaret));
debugBuffer.append(String.format("Storing offset %d (mapped from logical position %s)%n", myOffset, myLogicalCaret));
}
LOG.assertTrue(myOffset >= 0 && myOffset <= myEditor.getDocument().getTextLength());
@@ -537,7 +539,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
final VisualPosition visualPosition = new VisualPosition(lineToUse, EditorUtil.getLastVisualLineColumnNumber(myEditor, lineToUse));
if (debugBuffer != null) {
debugBuffer.append(String.format(
"Adjusting caret position by moving it before soft wrap. Moving to visual position %s", visualPosition
"Adjusting caret position by moving it before soft wrap. Moving to visual position %s%n", visualPosition
));
}
moveToVisualPosition(visualPosition);
@@ -19,21 +19,21 @@ import com.intellij.ide.IdeEventQueue;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.ui.components.Magnificator;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.impl.ApplicationImpl;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.ui.Queryable;
import com.intellij.openapi.ui.TypingTarget;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.InputMethodEvent;
import java.awt.im.InputContext;
import java.awt.im.InputMethodRequests;
import java.util.Map;
@@ -46,6 +46,19 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP
enableInputMethods(true);
setFocusCycleRoot(true);
setOpaque(true);
putClientProperty(Magnificator.CLIENT_PROPERTY_KEY, new Magnificator() {
@Override
public Point magnify(double scale, Point at) {
VisualPosition magnificationPosition = myEditor.xyToVisualPosition(at);
double currentSize = myEditor.getColorsScheme().getEditorFontSize();
int defaultFontSize = EditorColorsManager.getInstance().getGlobalScheme().getEditorFontSize();
myEditor.setFontSize((int)(double)(int)(Math.max(currentSize * scale, defaultFontSize)));
return myEditor.visualPositionToXY(magnificationPosition);
}
});
}
public EditorImpl getEditor() {
@@ -885,7 +885,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
public void setHighlighter(@NotNull EditorHighlighter highlighter) {
assertIsDispatchThread();
final Document document = getDocument();
if (myHighlighter != null) {
if (myHighlighter != null && !isDisposed()) {
document.removeDocumentListener(myHighlighter);
}
@@ -990,14 +990,14 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
CharSequence text = myDocument.getCharsNoThreadCheck();
LogicalPosition endLogicalPosition = visualToLogicalPosition(new VisualPosition(line+1, 0));
LogicalPosition endLogicalPosition = visualToLogicalPosition(new VisualPosition(line + 1, 0));
int endOffset = logicalPositionToOffset(endLogicalPosition);
if (offset > endOffset) {
LOG.error(String.format(
"Detected invalid (x;y)->VisualPosition processing. Given point: %s, mapped to visual line %d. Visual(%d; %d) is mapped to "
+ "logical position '%s' which is mapped to offset %d (start offset). Visual(%d; %d) is mapped to logical '%s' which is mapped "
+ "to offset %d (end offset). State: %s",
LogMessageEx.error(LOG, "Detected invalid (x; y)->VisualPosition processing", String.format(
"Given point: %s, mapped to visual line %d. Visual(%d; %d) is mapped to "
+ "logical position '%s' which is mapped to offset %d (start offset). Visual(%d; %d) is mapped to logical '%s' which is mapped "
+ "to offset %d (end offset). State: %s",
p, line, line, 0, logicalPosition, offset, line + 1, 0, endLogicalPosition, endOffset, dumpState()
));
return new VisualPosition(line, EditorUtil.columnsNumber(p.x, EditorUtil.getSpaceWidth(Font.PLAIN, this)));
@@ -3292,7 +3292,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
int foldedLinesCountBefore = myFoldingModel.getFoldedLinesCountBefore(offset);
line -= foldedLinesCountBefore;
if (line < 0) {
LOG.error(String.format(
LogMessageEx.error(
LOG, "Invalid LogicalPosition -> VisualPosition processing", String.format(
"Given logical position: %s; matched line: %d; fold lines before: %d, state: %s",
logicalPos, line, foldedLinesCountBefore, dumpState()
));
@@ -3300,7 +3301,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
FoldRegion[] topLevel = myFoldingModel.fetchTopLevel();
LogicalPosition anchorFoldingPosition = logicalPos;
for (int idx = myFoldingModel.getLastTopLevelIndexBefore(offset); idx >= 0; idx--) {
for (int idx = myFoldingModel.getLastTopLevelIndexBefore(offset); idx >= 0 && topLevel != null; idx--) {
FoldRegion region = topLevel[idx];
if (region.isValid()) {
if (region.getDocument().getLineNumber(region.getEndOffset()) == anchorFoldingPosition.line && region.getEndOffset() <= offset) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -110,7 +110,7 @@ public class FoldRegionImpl extends RangeMarkerImpl implements FoldRegion {
}
public String toString() {
return "FoldRegion " + (isExpanded() ? "-" : "+") +
"(" + getStartOffset() + ":" + getEndOffset() + ")" + (isValid() ? "" : "(invalid)");
return "FoldRegion " + (isExpanded() ? "-" : "+") + "(" + getStartOffset() + ":" + getEndOffset() + ")"
+ (isValid() ? "" : "(invalid)") + ", placeholder='" + getPlaceholderText() + "'";
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -188,10 +188,15 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList
@Override
public void runBatchFoldingOperation(@NotNull Runnable operation) {
runBatchFoldingOperation(operation, false);
runBatchFoldingOperation(operation, false, true);
}
private void runBatchFoldingOperation(final Runnable operation, final boolean dontCollapseCaret) {
@Override
public void runBatchFoldingOperation(@NotNull Runnable operation, boolean moveCaret) {
runBatchFoldingOperation(operation, false, moveCaret);
}
private void runBatchFoldingOperation(final Runnable operation, final boolean dontCollapseCaret, final boolean moveCaret) {
assertIsDispatchThread();
boolean oldDontCollapseCaret = myDoNotCollapseCaret;
myDoNotCollapseCaret |= dontCollapseCaret;
@@ -207,7 +212,7 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList
if (!oldBatchFlag) {
if (myFoldRegionsProcessed) {
notifyBatchFoldingProcessingDone();
notifyBatchFoldingProcessingDone(moveCaret);
myFoldRegionsProcessed = false;
}
myIsBatchFoldingProcessing = false;
@@ -217,7 +222,7 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList
@Override
public void runBatchFoldingOperationDoNotCollapseCaret(@NotNull final Runnable operation) {
runBatchFoldingOperation(operation, true);
runBatchFoldingOperation(operation, true, true);
}
public void flushCaretShift() {
@@ -337,11 +342,7 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList
notifyListenersOnFoldRegionStateChange(region);
}
private void notifyBatchFoldingProcessingDone() {
doNotifyBatchFoldingProcessingDone();
}
private void doNotifyBatchFoldingProcessingDone() {
private void notifyBatchFoldingProcessingDone(final boolean moveCaretFromCollapsedRegion) {
myFoldTree.rebuild();
for (FoldingListener listener : myListeners) {
@@ -390,14 +391,16 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList
boolean oldCaretPositionSaved = myCaretPositionSaved;
if (offsetToUse >= 0) {
myEditor.getCaretModel().moveToOffset(offsetToUse);
}
else if (column != -1) {
myEditor.getCaretModel().moveToLogicalPosition(new LogicalPosition(line, column));
}
else {
myEditor.getCaretModel().moveToLogicalPosition(caretPosition);
if (moveCaretFromCollapsedRegion) {
if (offsetToUse >= 0) {
myEditor.getCaretModel().moveToOffset(offsetToUse);
}
else if (column != -1) {
myEditor.getCaretModel().moveToLogicalPosition(new LogicalPosition(line, column));
}
else {
myEditor.getCaretModel().moveToLogicalPosition(caretPosition);
}
}
myCaretPositionSaved = oldCaretPositionSaved;
@@ -619,6 +619,11 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
myDirty = true;
}
}
@NotNull
public CachingSoftWrapDataMapper getDataMapper() {
return myDataMapper;
}
@Override
public void release() {
@@ -42,8 +42,6 @@ import java.util.List;
abstract class AbstractMappingStrategy<T> implements MappingStrategy<T> {
private static final Logger LOG = Logger.getInstance("#" + AbstractMappingStrategy.class.getName());
protected static final CacheEntry SEARCH_KEY = new CacheEntry(0, null, null, null);
protected final Editor myEditor;
protected final EditorTextRepresentationHelper myRepresentationHelper;
@@ -61,7 +61,6 @@ class CacheEntry implements Comparable<CacheEntry>, Cloneable {
public boolean locked;
private final List<CacheEntry> myCache;
private final Editor myEditor;
private final EditorTextRepresentationHelper myRepresentationHelper;
@@ -71,11 +70,10 @@ class CacheEntry implements Comparable<CacheEntry>, Cloneable {
/** Holds information about single line fold regions representation data. */
private TIntObjectHashMap<FoldingData> myFoldingData = DUMMY;
CacheEntry(int visualLine, Editor editor, EditorTextRepresentationHelper representationHelper, List<CacheEntry> cache) {
CacheEntry(int visualLine, @NotNull Editor editor, @NotNull EditorTextRepresentationHelper representationHelper) {
this.visualLine = visualLine;
myEditor = editor;
myRepresentationHelper = representationHelper;
myCache = cache;
}
public void setLineStartPosition(@NotNull EditorPosition context) {
@@ -228,13 +226,17 @@ class CacheEntry implements Comparable<CacheEntry>, Cloneable {
@Override
public String toString() {
return System.identityHashCode(this) + "=visual line: " + visualLine + ", offsets: " + startOffset + "-" + endOffset
+ ", fold regions: " + Arrays.toString(myFoldingData.getValues()) + ", tab data: " + myTabPositions;
return String.format(
"%d - visual line: %d, offsets: %d-%d, logical lines: %d-%d, logical columns: %d-%d, end visual column: %d, "
+ "fold regions: %s, tab data: %s",
System.identityHashCode(this), visualLine, startOffset, endOffset, startLogicalLine, endLogicalLine, startLogicalColumn,
endLogicalColumn, endVisualColumn, Arrays.toString(myFoldingData.getValues()), myTabPositions
);
}
@Override
protected CacheEntry clone() {
final CacheEntry result = new CacheEntry(visualLine, myEditor, myRepresentationHelper, myCache);
final CacheEntry result = new CacheEntry(visualLine, myEditor, myRepresentationHelper);
result.startLogicalLine = startLogicalLine;
result.startLogicalColumn = startLogicalColumn;
@@ -15,16 +15,15 @@
*/
package com.intellij.openapi.editor.impl.softwrap.mapping;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.FoldingModelEx;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper;
import com.intellij.openapi.editor.impl.softwrap.SoftWrapDataMapper;
import com.intellij.openapi.editor.impl.softwrap.SoftWrapImpl;
import com.intellij.openapi.editor.impl.softwrap.SoftWrapsStorage;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Trinity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -56,12 +55,10 @@ import java.util.List;
*/
public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAwareDocumentParsingListener {
private static final Logger LOG = Logger.getInstance("#" + CachingSoftWrapDataMapper.class.getName());
private static final boolean DEBUG_SOFT_WRAP_PROCESSING = false;
/** Caches information for the document visual line starts sorted in ascending order. */
private final List<CacheEntry> myCache = new ArrayList<CacheEntry>();
private final CacheEntry mySearchKey = new CacheEntry(0, null, null, null);
private final List<CacheEntry> myAffectedByUpdateCacheEntries = new ArrayList<CacheEntry>();
private final List<CacheEntry> myNotAffectedByUpdateTailCacheEntries = new ArrayList<CacheEntry>();
private final CacheState myBeforeChangeState = new CacheState();
@@ -72,6 +69,7 @@ public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAw
private final EditorEx myEditor;
private final SoftWrapsStorage myStorage;
private final EditorTextRepresentationHelper myRepresentationHelper;
private final CacheEntry mySearchKey;
public CachingSoftWrapDataMapper(@NotNull EditorEx editor, @NotNull SoftWrapsStorage storage,
@NotNull EditorTextRepresentationHelper representationHelper)
@@ -79,6 +77,7 @@ public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAw
myEditor = editor;
myStorage = storage;
myRepresentationHelper = representationHelper;
mySearchKey = new CacheEntry(0, editor, representationHelper);
myOffsetToLogicalStrategy = new OffsetToLogicalCalculationStrategy(editor, storage, myCache, representationHelper);
myVisualToLogicalStrategy = new VisualToLogicalCalculationStrategy(editor, storage, myCache, representationHelper);
@@ -316,7 +315,7 @@ public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAw
return lastEntry;
}
else if (lastEntry.visualLine < visualLine && createIfNecessary) {
CacheEntry result = new CacheEntry(visualLine, myEditor, myRepresentationHelper, myCache);
CacheEntry result = new CacheEntry(visualLine, myEditor, myRepresentationHelper);
myCache.add(result);
return result;
}
@@ -347,7 +346,7 @@ public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAw
if (cacheEntryIndex < 0) {
cacheEntryIndex = start;
if (createIfNecessary) {
myCache.add(cacheEntryIndex, result = new CacheEntry(visualLine, myEditor, myRepresentationHelper, myCache));
myCache.add(cacheEntryIndex, result = new CacheEntry(visualLine, myEditor, myRepresentationHelper));
}
}
else {
@@ -447,30 +446,6 @@ public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAw
}
applyStateChange(exactOffsetsDiff);
// TODO den remove before v.11 release
if (myCache.size() > 1) {
CacheEntry beforeLast = myCache.get(myCache.size() - 2);
CacheEntry last = myCache.get(myCache.size() - 1);
if (beforeLast.visualLine == last.visualLine
|| (beforeLast.visualLine + 1 == last.visualLine && last.startOffset - beforeLast.endOffset > 1)
|| last.startOffset > myEditor.getDocument().getTextLength())
{
CharSequence editorState = "";
if (myEditor instanceof EditorImpl) {
editorState = ((EditorImpl)myEditor).dumpState();
}
LOG.error(
"Detected invalid soft wraps cache update",
String.format(
"Event: %s, normal: %b.%n%nTail cache entries: %s%n%nAffected by change cache entries: %s%n%nBefore change state: %s%n%n"
+ "After change state: %s%n%nEditor state: %s",
event, normal, myNotAffectedByUpdateTailCacheEntries, myAffectedByUpdateCacheEntries,
myBeforeChangeState, myAfterChangeState, editorState
)
);
}
}
myAffectedByUpdateCacheEntries.clear();
myNotAffectedByUpdateTailCacheEntries.clear();
@@ -620,6 +595,40 @@ public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAw
return myCache.toString();
}
/**
* Allows to register new entry with the given data at the soft wraps cache.
* <p/>
* One entry is expected to contain information about single visual lines (what logical lines are mapped to it, what fold
* regions and tabulations are located there etc).
*
* @param visualLine target entry's visual line
* @param startOffset target entry's start offset
* @param endOffset target entry's end offset
* @param foldRegions target entry's fold regions
* @param tabData target entry's tab data
*/
public void rawAdd(int visualLine,
int startOffset,
int endOffset,
@NotNull List<Trinity<Integer, Integer, FoldRegion>> foldRegions,
@NotNull List<Pair<Integer, Integer>> tabData)
{
final CacheEntry entry = new CacheEntry(visualLine, myEditor, myRepresentationHelper);
entry.startOffset = startOffset;
entry.endOffset = endOffset;
entry.startLogicalLine = myEditor.getDocument().getLineNumber(startOffset);
entry.endLogicalLine = myEditor.getDocument().getLineNumber(endOffset);
for (Trinity<Integer, Integer, FoldRegion> region : foldRegions) {
final FoldingData foldData = new FoldingData(region.third, region.second, myRepresentationHelper, myEditor);
foldData.widthInColumns = region.first;
entry.store(foldData, region.third.getStartOffset());
}
for (Pair<Integer, Integer> pair : tabData) {
entry.storeTabData(new TabData(pair.second, pair.first));
}
myCache.add(entry);
}
@SuppressWarnings({"UnusedDeclaration"})
public static void log(Object o) {
//try {
@@ -30,20 +30,22 @@ import java.util.List;
*/
class VisualToLogicalCalculationStrategy extends AbstractMappingStrategy<LogicalPosition> {
private final CacheEntry mySearchKey;
private VisualPosition myTargetVisual;
VisualToLogicalCalculationStrategy(@NotNull Editor editor, @NotNull SoftWrapsStorage storage, @NotNull List<CacheEntry> cache,
@NotNull EditorTextRepresentationHelper representationHelper)
{
super(editor, storage, cache, representationHelper);
mySearchKey = new CacheEntry(0, editor, representationHelper);
}
public void init(@NotNull final VisualPosition targetVisual, @NotNull final List<CacheEntry> cache) {
reset();
myTargetVisual = targetVisual;
SEARCH_KEY.visualLine = targetVisual.line;
int i = Collections.binarySearch(cache, SEARCH_KEY);
mySearchKey.visualLine = targetVisual.line;
int i = Collections.binarySearch(cache, mySearchKey);
if (i >= 0) {
CacheEntry cacheEntry = cache.get(i);
if (cacheEntry.visualLine == targetVisual.line) {
@@ -1,3 +1,18 @@
/*
* Copyright 2000-2011 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.openapi.editor.textarea;
import com.intellij.openapi.editor.FoldRegion;
@@ -34,7 +49,7 @@ public class TextComponentFoldingModel implements FoldingModel {
public boolean isOffsetCollapsed(int offset) {
return false;
}
@Override
public FoldRegion getCollapsedRegionAtOffset(int offset) {
return null;
@@ -44,6 +59,10 @@ public class TextComponentFoldingModel implements FoldingModel {
public void runBatchFoldingOperation(@NotNull Runnable operation) {
}
@Override
public void runBatchFoldingOperation(@NotNull Runnable operation, boolean moveCaretFromCollapsedRegion) {
}
@Override
public void runBatchFoldingOperationDoNotCollapseCaret(@NotNull Runnable operation) {
}
@@ -527,7 +527,7 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx {
myFileNames = ContainerUtil.map(readOnlyFiles, new Function<VirtualFile, String>() {
@Override
public String fun(VirtualFile file) {
return file.getPath();
return file.getPresentableUrl();
}
}, new String[readOnlyFiles.length]);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2011 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,12 +15,25 @@
*/
package com.intellij.openapi.editor.impl;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.FoldRegion;
import com.intellij.openapi.editor.FoldingModel;
import com.intellij.openapi.editor.ex.FoldingModelEx;
import com.intellij.openapi.editor.impl.softwrap.mapping.CachingSoftWrapDataMapper;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
import com.intellij.testFramework.TestFileType;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
/**
* Base super class for tests that check various IJ editor functionality on managed document modification.
@@ -79,4 +92,117 @@ public abstract class AbstractEditorProcessingOnDocumentModificationTest extends
startOffset, Arrays.toString(foldRegions), myEditor.getDocument().getCharsSequence()
));
}
/**
* Setups document of the {@link #getEditor() current editor} according to the given text that is expected to contain
* information about document lines obtained from the {@link DocumentImpl#dumpState()}.
*
* @param data string representation of the target document's lines
*/
@SuppressWarnings("UnusedDeclaration")
protected static void setupDocument(@NotNull String data) {
Scanner scanner = new Scanner(data);
Pattern pattern = Pattern.compile("(\\d+)\\s*:\\s*(\\d+)\\s*-\\s*(\\d+)");
StringBuilder buffer = new StringBuilder();
while (scanner.findInLine(pattern) != null) {
final MatchResult match = scanner.match();
int startOffset = Integer.parseInt(match.group(2));
int endOffset = Integer.parseInt(match.group(3));
buffer.append(StringUtil.repeatSymbol('a', endOffset - startOffset)).append('\n');
}
if (buffer.length() > 0) {
buffer.setLength(buffer.length() - 1);
}
myEditor.getDocument().setText(buffer.toString());
}
/**
* Setups {@link Editor#getFoldingModel() folding model} of the {@link #getEditor() current editor} according to the given text
* that is expected to contain information obtained from the {@link FoldingModelImpl#toString()}.
*
* @param data string representation of the target fold regions
*/
protected static void setupFolding(@NotNull String data) {
Scanner scanner = new Scanner(data);
Pattern pattern = Pattern.compile("FoldRegion ([+-])\\((\\d+):(\\d+)");
final List<Trinity<Boolean, Integer, Integer>> infos = new ArrayList<Trinity<Boolean, Integer, Integer>>();
while (scanner.findInLine(pattern) != null) {
final MatchResult match = scanner.match();
boolean expanded = "-".equals(match.group(1));
int startOffset = Integer.parseInt(match.group(2));
int endOffset = Integer.parseInt(match.group(3));
infos.add(new Trinity<Boolean, Integer, Integer>(expanded, startOffset, endOffset));
}
final FoldingModel foldingModel = myEditor.getFoldingModel();
foldingModel.runBatchFoldingOperation(new Runnable() {
@Override
public void run() {
for (Trinity<Boolean, Integer, Integer> info : infos) {
final FoldRegion region = foldingModel.addFoldRegion(info.second, info.third, "...");
assert region != null;
region.setExpanded(info.first);
}
}
});
}
/**
* Setups {@link Editor#getSoftWrapModel() soft wraps model} of the {@link #getEditor() current editor} according to the given text
* that is expected to contain information obtained from the {@link CachingSoftWrapDataMapper#toString()}.
*
* @param data string representation of the target soft wraps cache
*/
@SuppressWarnings("UnusedDeclaration")
protected static void setupSoftWraps(@NotNull String data) {
Scanner scanner = new Scanner(data);
Pattern generalPattern =
Pattern.compile("visual line: (\\d+), offsets: (\\d+)-(\\d+), fold regions: \\[([^\\]]*)\\], tab data: \\[([^\\]]*)\\]");
Pattern foldPattern = Pattern.compile("width in columns: (-?\\d+), start X: (-?\\d+), fold region: FoldRegion [-+]\\((\\d+):(\\d+)");
Pattern tabPattern = Pattern.compile("\\[(\\d+), width: (\\d+)");
final SoftWrapModelImpl softWrapModel = (SoftWrapModelImpl)myEditor.getSoftWrapModel();
final CachingSoftWrapDataMapper mapper = softWrapModel.getDataMapper();
mapper.release();
final FoldingModelEx foldingModel = (FoldingModelEx)myEditor.getFoldingModel();
while (scanner.findInLine(generalPattern) != null) {
final MatchResult generalMatch = scanner.match();
int visualLine = Integer.parseInt(generalMatch.group(1));
int startOffset = Integer.parseInt(generalMatch.group(2));
int endOffset = Integer.parseInt(generalMatch.group(3));
List<Trinity<Integer, Integer, FoldRegion>> foldRegions = new ArrayList<Trinity<Integer, Integer, FoldRegion>>();
Scanner foldScanner = new Scanner(generalMatch.group(4));
while (foldScanner.findInLine(foldPattern) != null) {
final MatchResult foldMatch = foldScanner.match();
int widthInColumns = Integer.parseInt(foldMatch.group(1));
int startX = Integer.parseInt(foldMatch.group(2));
int foldStartOffset = Integer.parseInt(foldMatch.group(3));
int foldEndOffset = Integer.parseInt(foldMatch.group(4));
FoldRegion region = null;
for (FoldRegion candidate : foldingModel.getAllFoldRegions()) {
if (candidate.getStartOffset() == foldStartOffset && candidate.getEndOffset() == foldEndOffset) {
region = candidate;
break;
}
}
foldRegions.add(new Trinity<Integer, Integer, FoldRegion>(widthInColumns, startX, region));
}
List<Pair<Integer, Integer>> tabData = new ArrayList<Pair<Integer, Integer>>();
Scanner tabScanner = new Scanner(generalMatch.group(5));
while (tabScanner.findInLine(tabPattern) != null) {
final MatchResult tabMatch = tabScanner.match();
int offset = Integer.parseInt(tabMatch.group(1));
int widthInColumns = Integer.parseInt(tabMatch.group(2));
tabData.add(new Pair<Integer, Integer>(offset, widthInColumns));
}
mapper.rawAdd(visualLine, startOffset, endOffset, foldRegions, tabData);
}
}
public static void main(String[] args) {
setupFolding(
"FoldRegion +(0:600), FoldRegion +(640:1573), FoldRegion +(8130:8233), FoldRegion +(10189:10257), FoldRegion +(13582:13686), FoldRegion +(22805:22829), FoldRegion +(24069:24147), FoldRegion +(25024:25214), FoldRegion +(28313:28362), FoldRegion -(-1:-1)(invalid), FoldRegion -(-1:-1)(invalid), FoldRegion -(-1:-1)(invalid), FoldRegion -(-1:-1)(invalid)"
);
}
}
@@ -499,11 +499,11 @@ error.list.of.plugins.was.not.loaded=List of plugins was not loaded: {0}
action.download.and.install.plugin=Download and Install
action.update.plugin=Update Plugin
error.plugin.download.failed=Plugin download failed
prompt.download.and.install.plugin=Would you like to download and install plugin \"{0}\"?
prompt.update.plugin=Would you like to update plugin \"{0}\"?
prompt.download.and.install.plugin=Would you like to download and install plugin ''{0}''?
prompt.update.plugin=Would you like to update plugin ''{0}''?
prompt.install.several.plugins=Install or update {0} plugins ?
action.uninstall.plugin=Uninstall
prompt.uninstall.plugin=Do you really want to uninstall plugin \"{0}\"?
prompt.uninstall.plugin=Do you really want to uninstall plugin ''{0}''?
prompt.uninstall.several.plugins=Do you really want to uninstall these {0} plugins ?
title.plugin.uninstall=Plugin Uninstall
progress.downloading.list.of.plugins=Downloading List of Plugins
@@ -989,7 +989,6 @@ project.import.default.name=ImportedFrom{0}
project.import.default.name.dotIdea=Imported From {0}
project.import.select.title=Select {0} projects to import
project.import.show.settings.after=&Open Project Structure after import
project.import.open.existing=There is {0} in ''{1}''.\nDo you want to proceed with reimporting ''{2}'' or open the existing project?
project.import.open.existing=There is {0} in ''{1}''.\nDo you want to open the existing project or delete it and import ''{2}''?
project.import.open.existing.openExisting=Open Existing Project
project.import.open.existing.reimport=Delete Existing Project and Import
@@ -145,7 +145,7 @@ public class OutputLineSplitterTest extends UsefulTestCase {
if (i % 10 == 0) {
written.release();
try {
if (!read.tryAcquire(1, TimeUnit.SECONDS)) throw new TimeoutException();
if (!read.tryAcquire(10, TimeUnit.SECONDS)) throw new TimeoutException();
}
catch (Exception e) {
throw new RuntimeException(e);
@@ -179,10 +179,15 @@ public class OutputLineSplitterTest extends UsefulTestCase {
assertTrue(hadOutput);
}
finally {
isFinished.set(true);
try {
isFinished.set(true);
for (Future<?> each : futures) {
each.get(1, TimeUnit.SECONDS);
for (Future<?> each : futures) {
each.get(10, TimeUnit.SECONDS);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -84,6 +84,7 @@ public abstract class ProjectLevelVcsManager {
* @param name the name of the VCS to find.
* @return the VCS instance, or null if none is found.
*/
@Nullable
public abstract AbstractVcs findVcsByName(@NonNls String name);
@Nullable
@@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.VcsDirectoryMapping;
@@ -27,6 +28,7 @@ import com.intellij.openapi.vcs.VcsDirectoryMapping;
import java.util.Arrays;
public class StartUseVcsAction extends AnAction implements DumbAware {
@Override
public void update(final AnActionEvent e) {
final VcsDataWrapper data = new VcsDataWrapper(e);
@@ -40,6 +42,7 @@ public class StartUseVcsAction extends AnAction implements DumbAware {
}
}
@Override
public void actionPerformed(final AnActionEvent e) {
final VcsDataWrapper data = new VcsDataWrapper(e);
final boolean enabled = data.enabled();
@@ -53,7 +56,9 @@ public class StartUseVcsAction extends AnAction implements DumbAware {
final String vcsName = dialog.getVcs();
if (vcsName.length() > 0) {
final ProjectLevelVcsManager manager = data.getManager();
manager.findVcsByName(vcsName).generalPreConfigurationStep();
AbstractVcs vcs = manager.findVcsByName(vcsName);
assert vcs != null : "No vcs found for name " + vcsName;
vcs.generalPreConfigurationStep();
manager.setDirectoryMappings(Arrays.asList(new VcsDirectoryMapping("", vcsName)));
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.ide.actions;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.MultiLineLabelUI;
import com.intellij.openapi.vcs.VcsBundle;
@@ -29,13 +28,14 @@ import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class StartUseVcsDialog extends DialogWrapper {
class StartUseVcsDialog extends DialogWrapper {
private final VcsDataWrapper myData;
private VcsCombo myVcsCombo;
private String mySelected;
public StartUseVcsDialog(final VcsDataWrapper data) {
StartUseVcsDialog(final VcsDataWrapper data) {
super(data.getProject(), true);
myData = data;
setTitle(VcsBundle.message("dialog.enable.version.control.integration.title"));
@@ -93,13 +93,8 @@ public class StartUseVcsDialog extends DialogWrapper {
}
@Override
protected Action[] createActions() {
return new Action[]{getOKAction(), getCancelAction(), getHelpAction()};
}
@Override
protected void doHelpAction() {
HelpManager.getInstance().invokeHelp("reference.version.control.enable.version.control.integration");
protected String getHelpId() {
return "reference.version.control.enable.version.control.integration";
}
@Override
@@ -110,15 +105,19 @@ public class StartUseVcsDialog extends DialogWrapper {
private Object[] prepareComboData() {
final Collection<String> displayNames = myData.getVcses().keySet();
final java.util.List<String> keys = new ArrayList<String>(displayNames.size() + 1);
final List<String> keys = new ArrayList<String>(displayNames.size() + 1);
keys.add("");
keys.addAll(displayNames);
Collections.sort(keys);
return ArrayUtil.toObjectArray(keys);
}
String getVcs() {
return myData.getVcses().get(mySelected);
}
private static class VcsCombo extends JComboBox {
private VcsCombo(final Object items[]) {
private VcsCombo(final Object[] items) {
super(items);
setSelectedIndex(0);
setEditable(false);
@@ -130,7 +129,4 @@ public class StartUseVcsDialog extends DialogWrapper {
}
}
public String getVcs() {
return myData.getVcses().get(mySelected);
}
}
@@ -140,7 +140,7 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
for (GenerationItem item : generationItems) {
final MyGenerationItem genItem = (MyGenerationItem)item;
final File genDir = new File(genItem.myGenRootPath);
CompilerUtil.refreshIOFile(genDir);
CompilerUtil.refreshIODirectories(Arrays.asList(genDir));
final VirtualFile generatedVFile = LocalFileSystem.getInstance().findFileByIoFile(genDir);
if (generatedVFile != null) {
AndroidUtils.collectFiles(generatedVFile, visited, generatedVFiles);
@@ -86,6 +86,11 @@ public class AndroidClassTagDescriptor implements XmlElementDescriptor {
return myParentDescriptor.getContentType();
}
@Override
public String getDefaultValue() {
return null;
}
public PsiElement getDeclaration() {
return myClass;
}
@@ -79,7 +79,7 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb
@NonNls private static final String ANDROID_TARGET_DEVICES_PROPERTY = "AndroidTargetDevices";
private static final IDevice[] EMPTY_DEVICE_ARRAY = new IDevice[0];
public static final int WAITING_TIME = 10;
public static final int WAITING_TIME = 20;
private static final Pattern FAILURE = Pattern.compile("Failure\\s+\\[(.*)\\]");
private static final Pattern TYPED_ERROR = Pattern.compile("Error\\s+[Tt]ype\\s+(\\d+).*");
@@ -281,7 +281,7 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent {
public void render() {
ApplicationManager.getApplication().assertIsDispatchThread();
if (!myToolWindow.isVisible()) {
if (myToolWindow == null || !myToolWindow.isVisible()) {
return;
}
@@ -76,6 +76,10 @@ public class LineReader {
@Nullable
public byte[] readLine() throws IOException {
if (myBytesBuffered == -1) {
if (myLastEol != 0) {
myLastEol = 0;
return getLineArray();
}
return null;
} else if (myPosition >= myBytesBuffered) {
fillBuffer();
-1
View File
@@ -24,7 +24,6 @@
<orderEntry type="module" module-name="java-impl" />
<orderEntry type="library" name="TestNG" level="project" />
<orderEntry type="module" module-name="compiler-impl" />
<orderEntry type="module" module-name="idea" scope="TEST" />
<orderEntry type="module" module-name="properties" />
</component>
</module>
+8 -67
View File
@@ -46,7 +46,7 @@ import com.intellij.openapi.vcs.rollback.RollbackEnvironment;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vcs.update.UpdateEnvironment;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.WindowManager;
@@ -73,7 +73,9 @@ import git4idea.rollback.GitRollbackEnvironment;
import git4idea.status.GitChangeProvider;
import git4idea.ui.branch.GitBranchWidget;
import git4idea.update.GitUpdateEnvironment;
import git4idea.vfs.*;
import git4idea.vfs.GitRootTracker;
import git4idea.vfs.GitRootsListener;
import git4idea.vfs.GitVFSListener;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -119,15 +121,10 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
private GitRootTracker myRootTracker; // The tracker that checks validity of git roots
private final EventDispatcher<GitRootsListener> myRootListeners = EventDispatcher.create(GitRootsListener.class);
private final EventDispatcher<GitConfigListener> myConfigListeners = EventDispatcher.create(GitConfigListener.class);
private final EventDispatcher<GitReferenceListener> myReferenceListeners = EventDispatcher.create(GitReferenceListener.class);
private GitConfigTracker myConfigTracker;
private final BackgroundTaskQueue myTaskQueue; // The queue that is used to schedule background task from actions
private final ReadWriteLock myCommandLock = new ReentrantReadWriteLock(true); // The command read/write lock
private final TreeDiffProvider myTreeDiffProvider;
private final GitCommitAndPushExecutor myCommitAndPushExecutor;
private GitReferenceTracker myReferenceTracker;
private boolean isActivated; // If true, the vcs was activated
private final GitExecutableValidator myExecutableValidator;
private GitBranchWidget myBranchWidget;
@@ -167,20 +164,11 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
myOutgoingChangesProvider = new GitOutgoingChangesProvider(myProject);
myTreeDiffProvider = new GitTreeDiffProvider(myProject);
myCommitAndPushExecutor = new GitCommitAndPushExecutor(myCheckinEnvironment);
myReferenceTracker = new GitReferenceTracker(myProject, this, myReferenceListeners.getMulticaster());
myTaskQueue = new BackgroundTaskQueue(myProject, GitBundle.getString("task.queue.title"));
myExecutableValidator = new GitExecutableValidator(myProject, this);
}
public BackgroundTaskQueue getTaskQueue() {
return myTaskQueue;
}
public GitVFSListener getVFSListener() {
return myVFSListener;
}
public ReadWriteLock getCommandLock() {
return myCommandLock;
}
@@ -196,30 +184,6 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
}
}
public void addGitConfigListener(GitConfigListener listener) {
myConfigListeners.addListener(listener);
}
public void removeGitConfigListener(GitConfigListener listener) {
myConfigListeners.removeListener(listener);
}
public void addGitReferenceListener(GitReferenceListener listener) {
myReferenceListeners.addListener(listener);
}
public void removeGitReferenceListener(GitReferenceListener listener) {
myReferenceListeners.removeListener(listener);
}
public void addGitRootsListener(GitRootsListener listener) {
myRootListeners.addListener(listener);
}
public void removeGitRootsListener(GitRootsListener listener) {
myRootListeners.removeListener(listener);
}
/**
* @return a reverse merge provider for git (with reversed meaning of "theirs" and "yours", needed for the rebase and unstash)
*/
@@ -298,10 +262,9 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
return myRevSelector;
}
@SuppressWarnings({"deprecation"})
@Override
@Nullable
public VcsRevisionNumber parseRevisionNumber(String revision, FilePath path) throws VcsException {
public VcsRevisionNumber parseRevisionNumber(@Nullable String revision, @Nullable FilePath path) throws VcsException {
if (revision == null || revision.length() == 0) return null;
if (revision.length() > 40) { // date & revision-id encoded string
String dateString = revision.substring(0, revision.indexOf("["));
@@ -323,10 +286,9 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
}
@SuppressWarnings({"deprecation"})
@Override
@Nullable
public VcsRevisionNumber parseRevisionNumber(String revision) throws VcsException {
public VcsRevisionNumber parseRevisionNumber(@Nullable String revision) throws VcsException {
return parseRevisionNumber(revision, null);
}
@@ -345,8 +307,6 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
@Override
protected void activate() {
isActivated = true;
if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
if (myExecutableValidator.checkExecutableAndNotifyIfNeeded()) {
checkVersion();
@@ -359,10 +319,6 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
if (myVFSListener == null) {
myVFSListener = new GitVFSListener(myProject, this);
}
if (myConfigTracker == null) {
myConfigTracker = new GitConfigTracker(myProject, this, myConfigListeners.getMulticaster());
}
myReferenceTracker.activate();
NewGitUsersComponent.getInstance(myProject).activate();
GitProjectLogManager.getInstance(myProject).activate();
@@ -378,7 +334,6 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
@Override
protected void deactivate() {
isActivated = false;
if (myRootTracker != null) {
myRootTracker.dispose();
myRootTracker = null;
@@ -387,11 +342,6 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
Disposer.dispose(myVFSListener);
myVFSListener = null;
}
if (myConfigTracker != null) {
myConfigTracker.dispose();
myConfigTracker = null;
}
myReferenceTracker.deactivate();
NewGitUsersComponent.getInstance(myProject).deactivate();
GitProjectLogManager.getInstance(myProject).deactivate();
@@ -422,7 +372,7 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
*/
public void showErrors(@NotNull List<VcsException> list, @NotNull String action) {
if (list.size() > 0) {
StringBuffer buffer = new StringBuffer();
StringBuilder buffer = new StringBuilder();
buffer.append("\n");
buffer.append(GitBundle.message("error.list.title", action));
for (final VcsException exception : list) {
@@ -447,11 +397,6 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
showMessage(message, ConsoleViewContentType.NORMAL_OUTPUT.getAttributes());
}
@NotNull
public GitVcsApplicationSettings getAppSettings() {
return myAppSettings;
}
/**
* Show message in the Version Control Console
* @param message a message to show
@@ -531,7 +476,7 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
final S sParent = in.get(j);
final VirtualFile parent = convertor.convert(sParent);
// the method check both that parent is an ancestor of the child and that they share common git root
if (VfsUtil.isAncestor(parent, child, false) && VfsUtil.isAncestor(childRoot, parent, false)) {
if (VfsUtilCore.isAncestor(parent, child, false) && VfsUtilCore.isAncestor(childRoot, parent, false)) {
in.remove(i);
//noinspection AssignmentToForLoopParameter
--i;
@@ -578,10 +523,6 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
return Collections.<CommitExecutor>singletonList(myCommitAndPushExecutor);
}
public boolean isActivated() {
return isActivated;
}
@NotNull
public GitExecutableValidator getExecutableValidator() {
return myExecutableValidator;
@@ -19,8 +19,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
import git4idea.commands.GitHandlerUtil;
import git4idea.commands.GitLineHandler;
import git4idea.commands.*;
import git4idea.i18n.GitBundle;
import git4idea.rebase.GitInteractiveRebaseEditorHandler;
import git4idea.rebase.GitRebaseEditorService;
@@ -51,51 +50,58 @@ public abstract class GitRebaseActionBase extends GitRepositoryAction {
}
final VirtualFile root = h.workingDirectoryFile();
GitRebaseEditorService service = GitRebaseEditorService.getInstance();
GitInteractiveRebaseEditorHandler editor = new GitInteractiveRebaseEditorHandler(service, project, root, h);
GitRebaseLineListener resultListener = new GitRebaseLineListener();
final GitInteractiveRebaseEditorHandler editor = new GitInteractiveRebaseEditorHandler(service, project, root, h);
final GitRebaseLineListener resultListener = new GitRebaseLineListener();
h.addLineListener(resultListener);
configureEditor(editor);
affectedRoots.add(root);
try {
service.configureHandler(h, editor.getHandlerNo());
GitHandlerUtil.doSynchronously(h, GitBundle.getString("rebasing.title"), h.printableCommandLine(), false);
}
finally {
editor.close();
GitRepositoryManager.getInstance(project).updateRepository(root, GitRepository.TrackedTopic.ALL_CURRENT);
final GitRebaseLineListener.Result result = resultListener.getResult();
String messageId;
boolean isError = true;
switch (result.status) {
case CONFLICT:
messageId = "rebase.result.conflict";
break;
case ERROR:
messageId = "rebase.result.error";
break;
case CANCELLED:
isError = false;
messageId = "rebase.result.cancelled";
// we do not need to show a message if editing was cancelled.
exceptions.clear();
break;
case EDIT:
isError = false;
messageId = "rebase.result.amend";
break;
case FINISHED:
default:
messageId = null;
service.configureHandler(h, editor.getHandlerNo());
GitTask task = new GitTask(project, h, GitBundle.getString("rebasing.title"));
task.executeInBackground(false, new GitTaskResultHandlerAdapter() {
@Override
protected void run(GitTaskResult taskResult) {
editor.close();
GitRepositoryManager.getInstance(project).updateRepository(root, GitRepository.TrackedTopic.ALL_CURRENT);
notifyAboutErrorResult(taskResult, resultListener, exceptions, project);
}
if (messageId != null) {
String message = GitBundle.message(messageId, result.current, result.total);
String title = GitBundle.message(messageId + ".title");
if (isError) {
Messages.showErrorDialog(project, message, title);
}
else {
Messages.showInfoMessage(project, message, title);
}
});
}
private static void notifyAboutErrorResult(GitTaskResult taskResult, GitRebaseLineListener resultListener, List<VcsException> exceptions, Project project) {
if (taskResult == GitTaskResult.CANCELLED) {
return;
}
final GitRebaseLineListener.Result result = resultListener.getResult();
String messageId;
boolean isError = true;
switch (result.status) {
case CONFLICT:
messageId = "rebase.result.conflict";
break;
case ERROR:
messageId = "rebase.result.error";
break;
case CANCELLED:
// we do not need to show a message if editing was cancelled.
exceptions.clear();
return;
case EDIT:
isError = false;
messageId = "rebase.result.amend";
break;
case FINISHED:
default:
messageId = null;
}
if (messageId != null) {
String message = GitBundle.message(messageId, result.current, result.total);
String title = GitBundle.message(messageId + ".title");
if (isError) {
Messages.showErrorDialog(project, message, title);
}
else {
Messages.showInfoMessage(project, message, title);
}
}
}
@@ -13,6 +13,7 @@
package git4idea.history.wholeTree;
import com.intellij.ide.DataManager;
import com.intellij.ide.actions.ContextHelpAction;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
@@ -21,14 +22,12 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.impl.CaptionIcon;
import com.intellij.openapi.diff.impl.patch.formove.FilePathComparator;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.MultiLineLabelUI;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.ui.*;
import com.intellij.openapi.ui.popup.*;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
@@ -892,6 +891,7 @@ public class GitLogUI implements Disposable {
myMyGotoCommitAction = new MyGotoCommitAction();
group.add(myMyGotoCommitAction);
group.add(myRefreshAction);
group.add(new ContextHelpAction("reference.changesToolWindow.log"));
//group.add(new TestIndexAction());
myMoreAction = new MoreAction() {
@@ -1,256 +0,0 @@
/*
* Copyright 2000-2009 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 git4idea.vfs;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vfs.*;
import com.intellij.util.containers.HashSet;
import com.intellij.vcsUtil.VcsFileUtil;
import git4idea.GitUtil;
import git4idea.GitVcs;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Set;
/**
* The tracker for configuration files, it tracks the following events:
* <ul>
* <li>Changes in configuration files: .git/config and ~/.gitconfig</li>
* </ul>
* The tracker assumes that git roots are configured correctly.
*/
public class GitConfigTracker implements GitRootsListener {
/**
* The context project
*/
private final Project myProject;
/**
* The vcs object
*/
private final GitVcs myVcs;
/**
* The vcs manager that tracks content roots
*/
private final ProjectLevelVcsManager myVcsManager;
/**
* The listener collection (managed by GitVcs object since lifetime of this object is less than lifetime of GitVcs)
*/
private final GitConfigListener myMulticaster;
/**
* The appeared roots that has been already reported as changed
*/
private final HashSet<VirtualFile> myReportedRoots = new HashSet<VirtualFile>();
/**
* Local file system service
*/
private final LocalFileSystem myLocalFileSystem;
/**
* The file listener
*/
private final MyFileListener myFileListener;
/**
* The constructor
*
* @param project the context project
* @param vcs the vcs object
* @param multicaster the listener collection to use
*/
public GitConfigTracker(Project project, GitVcs vcs, GitConfigListener multicaster) {
myProject = project;
myVcs = vcs;
myMulticaster = multicaster;
myLocalFileSystem = LocalFileSystem.getInstance();
myVcsManager = ProjectLevelVcsManager.getInstance(project);
myVcs.addGitRootsListener(this);
myFileListener = new MyFileListener();
VirtualFileManager.getInstance().addVirtualFileListener(myFileListener);
gitRootsChanged();
}
/**
* This method is invoked when set of configured roots changed.
*/
public void gitRootsChanged() {
VirtualFile[] contentRoots = myVcsManager.getRootsUnderVcs(myVcs);
if (contentRoots == null || contentRoots.length == 0) {
return;
}
Set<VirtualFile> currentRootSet = GitUtil.gitRootsForPaths(Arrays.asList(contentRoots));
HashSet<VirtualFile> newRoots = new HashSet<VirtualFile>(currentRootSet);
synchronized (myReportedRoots) {
for (Iterator<VirtualFile> i = myReportedRoots.iterator(); i.hasNext();) {
VirtualFile root = i.next();
if (!root.isValid()) {
i.remove();
}
}
newRoots.removeAll(myReportedRoots);
myReportedRoots.clear();
myReportedRoots.addAll(currentRootSet);
}
for (VirtualFile root : newRoots) {
VirtualFile config = root.findFileByRelativePath(".git/config");
myMulticaster.configChanged(root, config);
}
// visit user home directory in order to notice .gitconfig changes later
VirtualFile userHome = getUserHome();
if (userHome != null) {
userHome.getChildren();
}
}
/**
* @return user home directory
*/
@Nullable
private VirtualFile getUserHome() {
return myLocalFileSystem.findFileByPath(System.getProperty("user.home"));
}
/**
* Dispose the tracker removing all registered listeners
*/
public void dispose() {
myVcs.removeGitRootsListener(this);
VirtualFileManager.getInstance().removeVirtualFileListener(myFileListener);
}
/**
* The listener for the file system that checks if the configuration files are changed.
* Note that events are checked in quite a shallow form. More radical events will cause
* remapping of git roots and gitRootsChanged() event will be delivered.
*/
private class MyFileListener extends VirtualFileAdapter {
/**
* Check if the event affects configuration files in registered roots
*
* @param file the file to check
*/
private void checkConfigAffected(VirtualFile file) {
if (file.getName().equals(".gitconfig")) {
VirtualFile userHome = getUserHome();
VirtualFile parent = file.getParent();
if (userHome != null && parent != null && parent.equals(userHome)) {
HashSet<VirtualFile> allRoots;
synchronized (myReportedRoots) {
allRoots = new HashSet<VirtualFile>(myReportedRoots);
}
for (VirtualFile root : allRoots) {
myMulticaster.configChanged(root, file);
}
}
return;
}
VirtualFile base = VcsFileUtil.getPossibleBase(file, ".git", "config");
if (base != null) {
boolean reported;
synchronized (myReportedRoots) {
reported = myReportedRoots.contains(base);
}
if (reported) {
myMulticaster.configChanged(base, file);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void fileCreated(VirtualFileEvent event) {
checkConfigAffected(event.getFile());
}
/**
* {@inheritDoc}
*/
@Override
public void beforeFileDeletion(VirtualFileEvent event) {
checkConfigAffected(event.getFile());
}
/**
* {@inheritDoc}
*/
@Override
public void contentsChanged(VirtualFileEvent event) {
checkConfigAffected(event.getFile());
}
/**
* {@inheritDoc}
*/
@Override
public void fileCopied(VirtualFileCopyEvent event) {
super.fileCopied(event);
}
/**
* {@inheritDoc}
*/
@Override
public void fileMoved(VirtualFileMoveEvent event) {
String fileName = event.getFileName();
VirtualFile newParent = event.getNewParent();
VirtualFile oldParent = event.getOldParent();
if (fileName.equals("config")) {
checkParent(newParent);
checkParent(oldParent);
}
if (fileName.equals(".gitconfig")) {
VirtualFile userHome = getUserHome();
if (userHome != null && (newParent.equals(userHome) || oldParent.equals(userHome))) {
HashSet<VirtualFile> allRoots;
synchronized (myReportedRoots) {
allRoots = new HashSet<VirtualFile>(myReportedRoots);
}
VirtualFile config = userHome.findChild(".gitconfig");
for (VirtualFile root : allRoots) {
myMulticaster.configChanged(root, config);
}
}
}
}
/**
* Check parent and report event if it is one of reported roots
*
* @param parent the parent to check
*/
private void checkParent(VirtualFile parent) {
if (parent.getName().equals(".git")) {
VirtualFile base = parent.getParent();
if (base != null) {
boolean reported;
synchronized (myReportedRoots) {
reported = myReportedRoots.contains(base);
}
if (reported) {
myMulticaster.configChanged(base, parent.findChild("config"));
}
}
}
}
}
}
@@ -1,280 +0,0 @@
/*
* Copyright 2000-2010 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 git4idea.vfs;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.*;
import com.intellij.util.containers.HashSet;
import git4idea.GitUtil;
import git4idea.GitVcs;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
/**
* The tracker for the git references
*/
public class GitReferenceTracker {
/**
* The root references that must be tracked
*/
private static final Set<String> myRootReferences = new HashSet<String>();
static {
myRootReferences.add("HEAD");
myRootReferences.add("refs");
myRootReferences.add("MERGE_HEAD");
// note, they are here intentionally, since their presence changes the way HEAD is interpreted
myRootReferences.add("rebase_merge");
myRootReferences.add("rebase_apply");
}
/**
* The context project
*/
private final Project myProject;
/**
* The vcs instance that requested the tracking
*/
private final GitVcs myVcs;
/**
* The event multicaster
*/
private final GitReferenceListener myListener;
/**
* The listener for vcs roots
*/
private final GitRootsListener myRootsListener;
/**
* The list of git roots
*/
private final AtomicReference<List<VirtualFile>> myGitRoots =
new AtomicReference<List<VirtualFile>>(Collections.<VirtualFile>emptyList());
/**
* The list of git roots
*/
private final AtomicReference<State> myState = new AtomicReference<State>(State.DEACTIVATED);
/**
* File system listener
*/
private final MyVfsListener myVfsListener;
/**
* The reference tracker
*
* @param project the project
* @param vcs the vcs that created tracker
* @param listener the listener to use for notifications (multicaster is expected)
*/
public GitReferenceTracker(Project project, GitVcs vcs, GitReferenceListener listener) {
myProject = project;
myVcs = vcs;
myListener = listener;
myVfsListener = new MyVfsListener();
myRootsListener = new GitRootsListener() {
@Override
public void gitRootsChanged() {
checkRoots();
}
};
}
/**
* Start listening for events
*/
public void activate() {
if (!myState.compareAndSet(State.DEACTIVATED, State.ACTIVATED)) {
return;
}
if (myProject.isDefault()) {
return;
}
checkRoots();
LocalFileSystem.getInstance().addVirtualFileListener(myVfsListener);
myVcs.addGitRootsListener(myRootsListener);
}
/**
* Deactivate service
*/
public void deactivate() {
if (!myState.compareAndSet(State.ACTIVATED, State.DEACTIVATED)) {
return;
}
removeListeners();
}
/**
* Remove listeners from services
*/
private void removeListeners() {
myVcs.removeGitRootsListener(myRootsListener);
LocalFileSystem.getInstance().removeVirtualFileListener(myVfsListener);
}
/**
* Dispose the tracker removing all listeners
*/
public void dispose() {
if (myState.getAndSet(State.DISPOSED) != State.ACTIVATED) {
return;
}
removeListeners();
}
/**
* Visit roots so file listener will be modified if special status changed
*/
private void checkRoots() {
try {
List<VirtualFile> roots = GitUtil.getGitRoots(myProject, myVcs);
myGitRoots.set(roots);
for (VirtualFile root : roots) {
final VirtualFile git = root.findChild(".git");
if (git != null) {
for (String name : myRootReferences) {
final VirtualFile child = git.findChild(name);
if (child != null) {
child.getTimeStamp();
}
}
final VirtualFile infoRefs = root.findFileByRelativePath("info/refs");
if (infoRefs != null) {
infoRefs.getTimeStamp();
}
visitRecursively(git.findChild("refs"));
}
}
notifyChanges(null);
}
catch (VcsException e) {
myGitRoots.set(Collections.<VirtualFile>emptyList());
}
}
private void notifyChanges(VirtualFile root) {
myListener.referencesChanged(root);
}
/**
* Visit recursively
*
* @param child the child directory to visit
*/
private static void visitRecursively(VirtualFile child) {
if (child == null) {
return;
}
child.getTimeStamp();
LinkedList<VirtualFile> toVisit = new LinkedList<VirtualFile>();
toVisit.add(child);
while (!toVisit.isEmpty()) {
VirtualFile file = toVisit.removeLast();
if (file.isValid() && file.isDirectory()) {
toVisit.addAll(Arrays.asList(file.getChildren()));
}
}
}
/**
* The listener for vfs events
*/
class MyVfsListener extends VirtualFileAdapter {
@Override
public void contentsChanged(VirtualFileEvent event) {
checkFile(event.getParent(), event.getFileName());
}
@Override
public void fileCreated(VirtualFileEvent event) {
checkFile(event.getParent(), event.getFileName());
}
@Override
public void fileDeleted(VirtualFileEvent event) {
checkFile(event.getParent(), event.getFileName());
}
@Override
public void fileMoved(VirtualFileMoveEvent event) {
checkFile(event.getNewParent(), event.getFileName());
checkFile(event.getOldParent(), event.getFileName());
}
@Override
public void fileCopied(VirtualFileCopyEvent event) {
checkFile(event.getParent(), event.getFileName());
}
@Override
public void propertyChanged(VirtualFilePropertyEvent event) {
if (event.getPropertyName() == VirtualFile.PROP_NAME) {
checkFile(event.getParent(), (String)event.getOldValue());
checkFile(event.getParent(), (String)event.getNewValue());
}
}
/**
* Check if the file change might affect reference mapping
*
* @param parent the file parent to check
* @param name the name check
*/
private void checkFile(VirtualFile parent, String name) {
VirtualFile git = parent;
while (git != null && !git.getName().equals(".git")) {
git = git.getParent();
}
if (git == null) {
return;
}
if (parent == git && myRootReferences.contains(name)) {
notifyChanges(git.getParent());
}
else if (parent.getParent() == git && name.equals("refs") && parent.getName().equals("info")) {
notifyChanges(git.getParent());
}
else {
while (parent != null && parent.getParent() != git) {
parent = parent.getParent();
}
if (parent != null && parent.isDirectory() && parent.getName().equals("refs")) {
notifyChanges(git.getParent());
}
}
}
}
/**
* The component state
*/
private enum State {
/**
* Initial state
*/
DEACTIVATED,
/**
* Started state
*/
ACTIVATED,
/**
* Disposed
*/
DISPOSED
}
}
+1 -1
View File
@@ -233,7 +233,7 @@
implementationClass="org.jetbrains.plugins.groovy.codeInsight.GroovyLineMarkerProvider"/>
<codeInsight.gotoSuper language="Groovy" implementationClass="org.jetbrains.plugins.groovy.codeInsight.navigation.actions.GroovyGotoSuperHandler"/>
<lookup.charFilter implementation="org.jetbrains.plugins.groovy.lang.completion.GroovyReferenceCharFilter"/>
<completion.contributor language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.completion.GroovyNoVariantsDelegator" id="groovyBasic2ClassName" order="first"/>
<completion.contributor language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.completion.GroovyNoVariantsDelegator" id="groovyBasic2ClassName" order="first, after liveTemplates"/>
<completion.contributor language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionContributor" id="groovyBasic"/>
<completion.contributor language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.completion.GroovySmartCompletionContributor"/>
<completion.contributor language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.completion.GrMethodMergingContributor"
@@ -852,7 +852,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
final GroovyConfigUtils config = GroovyConfigUtils.getInstance();
if ("$/".equals(quote)) {
if (!config.isVersionAtLeast(regex, GroovyConfigUtils.GROOVY1_9)) {
if (!config.isVersionAtLeast(regex, GroovyConfigUtils.GROOVY1_8)) {
myHolder
.createErrorAnnotation(regex, GroovyBundle.message("dollar.slash.strings.are.not.allowed.in.0", config.getSDKVersion(regex)));
}
@@ -85,12 +85,24 @@ public class GrThisReferenceExpressionImpl extends GrThisSuperReferenceExpressio
}
private PsiType createType(PsiClass context) {
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
if (PsiUtil.isInStaticContext(this)) {
return elementFactory.createTypeFromText(CommonClassNames.JAVA_LANG_CLASS + "<" + context.getName() + ">", this);
//in case of anonymous class this code don't matter because anonymous classes can't have static methods
final JavaPsiFacade facade = JavaPsiFacade.getInstance(context.getProject());
PsiElementFactory elementFactory = facade.getElementFactory();
if (!PsiUtil.isInStaticContext(this)) return elementFactory.createType(context);
//create instance of java.lang.Class<CurrentClass>
if (context instanceof PsiAnonymousClass) {
final PsiClassType type = ((PsiAnonymousClass)context).getBaseClassType();
final PsiClass aClass =
facade.findClass(CommonClassNames.JAVA_LANG_CLASS, context.getResolveScope());
if (aClass != null) {
return elementFactory.createType(aClass, type);
}
else {
return elementFactory.createTypeFromText(CommonClassNames.JAVA_LANG_CLASS + "<" + type.getCanonicalText() + ">", this);
}
}
return elementFactory.createType(context);
return elementFactory.createTypeFromText(CommonClassNames.JAVA_LANG_CLASS + "<" + context.getName() + ">", this);
}
@NotNull
@@ -538,4 +538,21 @@ class Bar {{
void testOctalInspection() {
doTest(new GroovyOctalIntegerInspection())
}
void testThisInStaticMethodOfAnonymousClass() {
myFixture.configureByText('a.groovy', '''\
class A {
static abc
def foo() {
new Runnable() {
<error descr="Inner classes cannot have static declarations">static</error> void run() {
print this.@abc
}
}.run()
}
}''')
myFixture.enableInspections(GroovyAssignabilityCheckInspection)
myFixture.checkHighlighting(true, false, false);
}
}
@@ -18,6 +18,7 @@
package org.jetbrains.idea.svn.actions;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
@@ -163,15 +164,9 @@ public class CopyAction extends BasicAction {
}
};
final Task.Backgroundable task =
new Task.Backgroundable(project, "Checking target folder", false, BackgroundFromStartOption.getInstance()) {
public void run(@NotNull ProgressIndicator indicator) {
taskImpl.run();
}
};
if (ApplicationManager.getApplication().isDispatchThread()) {
ProgressManager.getInstance().run(task);
final Application application = ApplicationManager.getApplication();
if (application.isDispatchThread()) {
ProgressManager.getInstance().runProcessWithProgressSynchronously(taskImpl, "Checking target folder", true, project);
} else {
taskImpl.run();
}
@@ -14,7 +14,6 @@
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
<orderEntry type="module" module-name="vcs-impl" />
<orderEntry type="module" module-name="idea" />
</component>
</module>
@@ -181,6 +181,7 @@ label.base.renderer.configurable.hide.null.array.elements=Hide &null array eleme
label.base.renderer.configurable.show.static.fields=&Static fields
label.base.renderer.configurable.show.static.final.fields=Static &final fields
label.base.renderer.configurable.show.declared.type=Declared &type
label.base.renderer.configurable.show.fq.names=Fully &qualified names
label.base.renderer.configurable.show.object.id=Object &id
label.base.renderer.configurable.alternate.view=Enable alternative view for Coll&ections classes
label.base.renderer.configurable.enable.tostring=Enable 't&oString()' object view:
+1 -1
View File
@@ -210,7 +210,7 @@
<completion.confidence language="JAVA" implementationClass="com.intellij.codeInsight.completion.SkipAutopopupInStrings" id="javaSkipAutopopupInStrings"/>
<completion.contributor language="JAVA" implementationClass="com.intellij.codeInsight.completion.JavaNoVariantsDelegator" id="javaBasic2ClassName"
order="first, before javaMemberName"/>
order="first, before javaMemberName, after liveTemplates"/>
<completion.contributor language="XML" implementationClass="com.intellij.codeInsight.completion.XmlBasicToClassNameDelegator" id="basic2ClassName"
order="first, after xml"/>
<completion.contributor language="JAVA" implementationClass="com.intellij.codeInsight.completion.JavaCompletionContributor" id="javaLegacy"
@@ -212,6 +212,11 @@ public abstract class AbstractDomChildrenDescriptor implements XmlElementDescrip
return CONTENT_TYPE_UNKNOWN;
}
@Override
public String getDefaultValue() {
return null;
}
public void init(final PsiElement element) {
throw new UnsupportedOperationException("Method init not implemented in " + getClass());
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlDocument;
@@ -30,6 +31,7 @@ import com.intellij.util.IncorrectOperationException;
import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
@@ -42,15 +44,14 @@ public class GenerateDTDAction extends BaseCodeInsightAction{
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.GenerateDTDAction");
protected CodeInsightActionHandler getHandler(){
return new CodeInsightActionHandler(){
public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file){
if(file instanceof XmlFile && file.getVirtualFile() != null && file.getVirtualFile().isWritable()){
public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
final XmlDocument document = findSuitableXmlDocument(file);
if (document != null) {
final @NonNls StringBuffer buffer = new StringBuffer();
final XmlDocument document = ((XmlFile) file).getDocument();
if (document != null && document.getRootTag() != null){
buffer.append("<!DOCTYPE " + document.getRootTag().getName() + " [\n");
buffer.append(XmlUtil.generateDocumentDTD(document, true));
buffer.append("]>\n");
XmlFile tempFile;
buffer.append("<!DOCTYPE " + document.getRootTag().getName() + " [\n");
buffer.append(XmlUtil.generateDocumentDTD(document, true));
buffer.append("]>\n");
XmlFile tempFile;
try{
final XmlProlog prolog = document.getProlog();
final PsiElement childOfType = PsiTreeUtil.getChildOfType(prolog, XmlProcessingInstruction.class);
@@ -65,9 +66,8 @@ public class GenerateDTDAction extends BaseCodeInsightAction{
tempFile = (XmlFile)PsiFileFactory.getInstance(file.getProject()).createFileFromText("dummy.xml", buffer.toString());
prolog.replace(tempFile.getDocument().getProlog());
}
catch(IncorrectOperationException e){
LOG.error(e);
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
}
@@ -78,6 +78,20 @@ public class GenerateDTDAction extends BaseCodeInsightAction{
};
}
@Nullable
private static XmlDocument findSuitableXmlDocument(@Nullable PsiFile psiFile) {
if (psiFile instanceof XmlFile) {
final VirtualFile virtualFile = psiFile.getVirtualFile();
if (virtualFile != null && virtualFile.isWritable()) {
final XmlDocument document = ((XmlFile)psiFile).getDocument();
if (document != null && document.getRootTag() != null) {
return document;
}
}
}
return null;
}
public void update(AnActionEvent event) {
super.update(event);
@@ -89,7 +103,7 @@ public class GenerateDTDAction extends BaseCodeInsightAction{
final boolean enabled;
if (editor != null && project != null) {
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
enabled = file instanceof XmlFile;
enabled = findSuitableXmlDocument(file) != null;
}
else {
enabled = false;
@@ -21,6 +21,7 @@ import com.intellij.codeInsight.template.*;
import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.codeInsight.template.zencoding.filters.ZenCodingFilter;
import com.intellij.codeInsight.template.zencoding.generators.XmlZenCodingGenerator;
import com.intellij.codeInsight.template.zencoding.generators.ZenCodingGenerator;
import com.intellij.codeInsight.template.zencoding.nodes.*;
import com.intellij.codeInsight.template.zencoding.tokens.*;
@@ -145,9 +146,24 @@ public class ZenCodingTemplate implements CustomLiveTemplate {
if (tokens == null) {
return null;
}
if (generator != null && !validate(tokens, generator)) {
return null;
}
MyParser parser = new MyParser(tokens, callback, generator);
ZenCodingNode node = parser.parse();
return parser.myIndex == tokens.size() ? node : null;
if (parser.myIndex != tokens.size() || node instanceof TextNode) {
return null;
}
return node;
}
private static boolean validate(@NotNull List<ZenCodingToken> tokens, @NotNull ZenCodingGenerator generator) {
for (ZenCodingToken token : tokens) {
if (token instanceof TextToken && !(generator instanceof XmlZenCodingGenerator)) {
return false;
}
}
return true;
}
@Nullable
@@ -41,6 +41,11 @@ public abstract class BaseXmlElementDescriptorImpl implements XmlElementDescript
return null;
}
@Override
public String getDefaultValue() {
return null;
}
// Read-only action
protected abstract XmlElementDescriptor[] doCollectXmlDescriptors(final XmlTag context);
@@ -101,4 +101,9 @@ public class AnyXmlElementDescriptor implements XmlElementDescriptor {
public int getContentType() {
return CONTENT_TYPE_UNKNOWN;
}
@Override
public String getDefaultValue() {
return null;
}
}
@@ -80,6 +80,11 @@ public class NullElementDescriptor implements XmlElementDescriptor {
return 0;
}
@Override
public String getDefaultValue() {
return null;
}
public PsiElement getDeclaration() {
return null;
}
@@ -45,7 +45,7 @@ public class XmlElementDescriptorImpl implements XmlElementDescriptor, PsiWritab
@NonNls
private static final String ELEMENT_FORM_DEFAULT = "elementFormDefault";
public XmlElementDescriptorImpl(XmlTag descriptorTag) {
public XmlElementDescriptorImpl(@Nullable XmlTag descriptorTag) {
myDescriptorTag = descriptorTag;
}
@@ -358,6 +358,11 @@ public class XmlElementDescriptorImpl implements XmlElementDescriptor, PsiWritab
return CONTENT_TYPE_MIXED;
}
@Override
public String getDefaultValue() {
return myDescriptorTag.getAttributeValue("default");
}
@Nullable
public XmlElementDescriptor getElementDescriptor(final String name) {
final String localName = XmlUtil.findLocalNameByQualifiedName(name);
@@ -68,4 +68,7 @@ public interface XmlElementDescriptor extends PsiMetaData {
int CONTENT_TYPE_ANY = 1;
int CONTENT_TYPE_CHILDREN = 2;
int CONTENT_TYPE_MIXED = 3;
@Nullable
String getDefaultValue();
}
@@ -84,6 +84,11 @@ public class RelaxedHtmlFromRngElementDescriptor implements XmlElementDescriptor
return myDelegate.getContentType();
}
@Override
public String getDefaultValue() {
return null;
}
public XmlAttributeDescriptor getAttributeDescriptor(String attributeName, final XmlTag context) {
final XmlAttributeDescriptor descriptor = myDelegate.getAttributeDescriptor(attributeName.toLowerCase(), context);
if (descriptor != null) return descriptor;
@@ -209,6 +209,11 @@ public class RngElementDescriptor implements XmlElementDescriptor {
}
}
@Override
public String getDefaultValue() {
return null;
}
public PsiElement getDeclaration() {
if (myDeclaration != null) {
final PsiElement element = myDeclaration.getElement();