From be7434a2905cc8f0a119b7de28279b9fe05ebf49 Mon Sep 17 00:00:00 2001 From: "kirill.safonov" Date: Mon, 31 Oct 2011 20:50:43 +0400 Subject: [PATCH] decouple image file editor from VirtualFile --- .../intellij/images/editor/ImageEditor.java | 8 +- .../editor/impl/ImageContentProvider.java | 51 ++++++ .../images/editor/impl/ImageEditorImpl.java | 147 ++++++++---------- .../editor/impl/ImageEditorManagerImpl.java | 4 +- .../images/editor/impl/ImageEditorUI.java | 6 +- .../editor/impl/ImageFileEditorImpl.java | 10 +- .../editor/impl/ImageFileEditorProvider.java | 5 +- .../impl/VirtualFileImageContentProvider.java | 112 +++++++++++++ 8 files changed, 245 insertions(+), 98 deletions(-) create mode 100644 images/src/org/intellij/images/editor/impl/ImageContentProvider.java create mode 100644 images/src/org/intellij/images/editor/impl/VirtualFileImageContentProvider.java diff --git a/images/src/org/intellij/images/editor/ImageEditor.java b/images/src/org/intellij/images/editor/ImageEditor.java index a888961b8af0..7d235be5d24c 100644 --- a/images/src/org/intellij/images/editor/ImageEditor.java +++ b/images/src/org/intellij/images/editor/ImageEditor.java @@ -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,9 +28,13 @@ import javax.swing.*; * * @author Alexey Efimov */ -public interface ImageEditor extends Disposable, VirtualFileListener, ImageComponentDecorator { +public interface ImageEditor extends Disposable, ImageComponentDecorator { + + @Nullable VirtualFile getFile(); + long getFileLength(); + Project getProject(); ImageDocument getDocument(); diff --git a/images/src/org/intellij/images/editor/impl/ImageContentProvider.java b/images/src/org/intellij/images/editor/impl/ImageContentProvider.java new file mode 100644 index 000000000000..15ad1f54094c --- /dev/null +++ b/images/src/org/intellij/images/editor/impl/ImageContentProvider.java @@ -0,0 +1,51 @@ +/* + * 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.Disposable; +import com.intellij.openapi.vfs.VirtualFile; +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); + + @Nullable + VirtualFile getVirtualFile(); + + long getFileLength(); + +} diff --git a/images/src/org/intellij/images/editor/impl/ImageEditorImpl.java b/images/src/org/intellij/images/editor/impl/ImageEditorImpl.java index 11319e33440a..374fdac87f6c 100644 --- a/images/src/org/intellij/images/editor/impl/ImageEditorImpl.java +++ b/images/src/org/intellij/images/editor/impl/ImageEditorImpl.java @@ -17,16 +17,15 @@ package org.intellij.images.editor.impl; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.*; +import com.intellij.openapi.vfs.VirtualFile; 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.*; @@ -39,58 +38,69 @@ import java.beans.PropertyChangeListener; * * @author Alexey Efimov */ -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; +final 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; - ImageEditorImpl(@NotNull Project project, @NotNull VirtualFile file) { - this.project = project; - this.file = file; + ImageEditorImpl(@NotNull Project project, @NotNull final ImageContentProvider contentProvider) { + this.project = project; + this.contentProvider = contentProvider; - // Options + // 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 = OptionsManager.getInstance().getOptions(); - editorUI = new ImageEditorUI(this, options.getEditorOptions()); - options.addPropertyChangeListener(optionsChangeListener); + ZoomOptions zoomOptions = options.getEditorOptions().getZoomOptions(); + // Open as actual size + zoomModel.setZoomFactor(1.0d); - 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 + if (zoomOptions.isSmartZooming()) { + Dimension prefferedSize = zoomOptions.getPrefferedSize(); + if (prefferedSize.width > image.getWidth() && prefferedSize.height > image.getHeight()) { + // Resize to preferred size + // Calculate zoom factor double factor = (prefferedSize.getWidth() / (double) image.getWidth() + prefferedSize.getHeight() / (double) image.getHeight()) / 2.0d; - zoomModel.setZoomFactor(Math.ceil(factor)); - } - } - } - } catch (Exception e) { - // Error loading image file - document.setValue(null); + zoomModel.setZoomFactor(Math.ceil(factor)); + } } + } } + 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(); @@ -105,10 +115,14 @@ final class ImageEditorImpl extends VirtualFileAdapter implements ImageEditor { return editorUI.getImageComponent(); } - @NotNull - public VirtualFile getFile() { - return file; - } + @Nullable + public VirtualFile getFile() { + return contentProvider.getVirtualFile(); + } + + public long getFileLength() { + return contentProvider.getFileLength(); + } @NotNull public Project getProject() { @@ -154,40 +168,9 @@ final class ImageEditorImpl extends VirtualFileAdapter 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) { diff --git a/images/src/org/intellij/images/editor/impl/ImageEditorManagerImpl.java b/images/src/org/intellij/images/editor/impl/ImageEditorManagerImpl.java index 815c09308e22..c23bcf88b709 100644 --- a/images/src/org/intellij/images/editor/impl/ImageEditorManagerImpl.java +++ b/images/src/org/intellij/images/editor/impl/ImageEditorManagerImpl.java @@ -37,8 +37,8 @@ final class ImageEditorManagerImpl { * @return Image editor for file */ @NotNull - public static ImageEditor createImageEditor(@NotNull Project project, @NotNull VirtualFile file) { - return new ImageEditorImpl(project, file); + public static ImageEditor createImageEditor(@NotNull Project project, @NotNull ImageContentProvider contentProvider) { + return new ImageEditorImpl(project, contentProvider); } /** diff --git a/images/src/org/intellij/images/editor/impl/ImageEditorUI.java b/images/src/org/intellij/images/editor/impl/ImageEditorUI.java index c4f80c1742cf..a69670533b75 100644 --- a/images/src/org/intellij/images/editor/impl/ImageEditorUI.java +++ b/images/src/org/intellij/images/editor/impl/ImageEditorUI.java @@ -152,11 +152,10 @@ 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(), file != null ? StringUtil.formatFileSize(file.getLength()) : "")); + colorModel.getPixelSize(), StringUtil.formatFileSize(editor.getFileLength()))); } else { infoLabel.setText(null); } @@ -348,7 +347,8 @@ 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)) { - return new VirtualFile[]{editor.getFile()}; + final VirtualFile file = editor.getFile(); + return file != null ? new VirtualFile[]{file} : null; } else if (LangDataKeys.PSI_FILE.is(dataId)) { return getData(LangDataKeys.PSI_ELEMENT.getName()); } else if (LangDataKeys.PSI_ELEMENT.is(dataId)) { diff --git a/images/src/org/intellij/images/editor/impl/ImageFileEditorImpl.java b/images/src/org/intellij/images/editor/impl/ImageFileEditorImpl.java index be3c13575781..97af3feb9371 100644 --- a/images/src/org/intellij/images/editor/impl/ImageFileEditorImpl.java +++ b/images/src/org/intellij/images/editor/impl/ImageFileEditorImpl.java @@ -22,8 +22,6 @@ 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; @@ -45,11 +43,8 @@ final class ImageFileEditorImpl extends UserDataHolderBase implements ImageFileE private static final String NAME = "ImageFileEditor"; private final ImageEditor imageEditor; - ImageFileEditorImpl(@NotNull Project project, @NotNull VirtualFile file) { - imageEditor = ImageEditorManagerImpl.createImageEditor(project, file); - - // Append file listener - VirtualFileManager.getInstance().addVirtualFileListener(imageEditor); + ImageFileEditorImpl(@NotNull Project project, @NotNull ImageContentProvider contentProvider) { + imageEditor = ImageEditorManagerImpl.createImageEditor(project, contentProvider); // Set background and grid default options Options options = OptionsManager.getInstance().getOptions(); @@ -126,7 +121,6 @@ final class ImageFileEditorImpl extends UserDataHolderBase implements ImageFileE } public void dispose() { - VirtualFileManager.getInstance().removeVirtualFileListener(imageEditor); ImageEditorManagerImpl.releaseImageEditor(imageEditor); } diff --git a/images/src/org/intellij/images/editor/impl/ImageFileEditorProvider.java b/images/src/org/intellij/images/editor/impl/ImageFileEditorProvider.java index da0f8f1c9a56..9c344f6f8a8a 100644 --- a/images/src/org/intellij/images/editor/impl/ImageFileEditorProvider.java +++ b/images/src/org/intellij/images/editor/impl/ImageFileEditorProvider.java @@ -45,7 +45,10 @@ final class ImageFileEditorProvider implements FileEditorProvider, DumbAware { @NotNull public FileEditor createEditor(@NotNull Project project, @NotNull VirtualFile file) { - return new ImageFileEditorImpl(project, file); + ImageContentProvider contentProvider = new VirtualFileImageContentProvider(file); + ImageFileEditorImpl editor = new ImageFileEditorImpl(project, contentProvider); + Disposer.register(editor, contentProvider); + return editor; } public void disposeEditor(@NotNull FileEditor editor) { diff --git a/images/src/org/intellij/images/editor/impl/VirtualFileImageContentProvider.java b/images/src/org/intellij/images/editor/impl/VirtualFileImageContentProvider.java new file mode 100644 index 000000000000..cb7f8894aa49 --- /dev/null +++ b/images/src/org/intellij/images/editor/impl/VirtualFileImageContentProvider.java @@ -0,0 +1,112 @@ +/* + * 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 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(); + } + }); + } + } +}