mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote branch 'origin/master'
This commit is contained in:
@@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
+9
-3
@@ -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);
|
||||
|
||||
|
||||
+15
-1
@@ -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
|
||||
|
||||
+8
-4
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -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();
|
||||
}
|
||||
|
||||
+1
-1
@@ -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();
|
||||
}
|
||||
|
||||
+4
-1
@@ -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());
|
||||
}
|
||||
}
|
||||
+6
-2
@@ -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;
|
||||
}
|
||||
|
||||
+28
-1
@@ -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() {
|
||||
|
||||
+2
-2
@@ -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() {
|
||||
|
||||
+2
-1
@@ -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())) {
|
||||
|
||||
+4
-1
@@ -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);
|
||||
}
|
||||
+11
-30
@@ -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 :
|
||||
|
||||
+8
-4
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+44
-8
@@ -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) {
|
||||
|
||||
+1
-36
@@ -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);
|
||||
|
||||
+16
-3
@@ -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() {
|
||||
|
||||
-2
@@ -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;
|
||||
|
||||
+8
-6
@@ -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;
|
||||
|
||||
+39
-30
@@ -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 {
|
||||
|
||||
+4
-2
@@ -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) {
|
||||
|
||||
+20
-1
@@ -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]);
|
||||
}
|
||||
|
||||
+127
-1
@@ -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
|
||||
|
||||
+9
-4
@@ -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+).*");
|
||||
|
||||
+1
-1
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
+17
-5
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
+5
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user