mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 05:21:29 +07:00
IDEA-309322, EA-772915 Move image loading out of EDT for ImageEditorImpl
Create a service and use coroutines to freely jump between IO threads and EDT. To avoid converting too much stuff to Kotlin at once, use dependency inversion and provide an object for image file loading to ImageEditorImpl through the new service. Cancelling the image loader's job through dispose() looks a bit ugly, but until we move the entire thing to coroutines, it seems to be the only reasonable way. GitOrigin-RevId: ce42805acfcb67bbdbb3de869fb7a3606adcf383
This commit is contained in:
committed by
intellij-monorepo-bot
parent
0d9751ac2b
commit
2fd2b39fbf
@@ -26,8 +26,8 @@ import org.intellij.images.editor.ImageEditor;
|
||||
import org.intellij.images.editor.ImageZoomModel;
|
||||
import org.intellij.images.fileTypes.ImageFileTypeManager;
|
||||
import org.intellij.images.thumbnail.actionSystem.ThumbnailViewActions;
|
||||
import org.intellij.images.vfs.IfsUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -41,6 +41,7 @@ public final class ImageEditorImpl implements ImageEditor {
|
||||
private final Project project;
|
||||
private final VirtualFile file;
|
||||
private final ImageEditorUI editorUI;
|
||||
private final @NotNull ImageFileLoader imageFileLoader;
|
||||
private boolean disposed;
|
||||
|
||||
public ImageEditorImpl(@NotNull Project project, @NotNull VirtualFile file) {
|
||||
@@ -70,17 +71,18 @@ public final class ImageEditorImpl implements ImageEditor {
|
||||
}
|
||||
}, this);
|
||||
|
||||
imageFileLoader = project.getService(ImageFileService.class).createImageFileLoader(this);
|
||||
Disposer.register(this, imageFileLoader);
|
||||
|
||||
setValue(file);
|
||||
}
|
||||
|
||||
void setValue(VirtualFile file) {
|
||||
try {
|
||||
editorUI.setImageProvider(IfsUtil.getImageProvider(file), IfsUtil.getFormat(file));
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Error loading image file
|
||||
editorUI.setImageProvider(null, null);
|
||||
}
|
||||
imageFileLoader.loadFile(file);
|
||||
}
|
||||
|
||||
void setImageProvider(@Nullable ImageDocument.ScaledImageProvider imageProvider, @Nullable String format) {
|
||||
editorUI.setImageProvider(imageProvider, format);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.intellij.images.editor.impl
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
|
||||
internal interface ImageFileLoader : Disposable {
|
||||
|
||||
fun loadFile(file: VirtualFile?)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.intellij.images.editor.impl
|
||||
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import org.intellij.images.vfs.IfsUtil
|
||||
|
||||
@Service(Service.Level.APP)
|
||||
internal class ImageFileService(
|
||||
private val coroutineScope: CoroutineScope,
|
||||
) {
|
||||
|
||||
fun createImageFileLoader(target: ImageEditorImpl): ImageFileLoader =
|
||||
ImageFileLoaderImpl(
|
||||
target,
|
||||
coroutineScope
|
||||
)
|
||||
|
||||
class ImageFileLoaderImpl(private val target: ImageEditorImpl, childScope: CoroutineScope) : ImageFileLoader {
|
||||
|
||||
private val flow = MutableSharedFlow<VirtualFile>(
|
||||
replay = 1,
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST,
|
||||
)
|
||||
|
||||
private val job = childScope.launch(CoroutineName("ImageFileLoader for $target")) {
|
||||
flow.collectLatest { file ->
|
||||
val imageProvider = withContext(Dispatchers.IO) { IfsUtil.getImageProvider(file) }
|
||||
val format = withContext(Dispatchers.IO) { IfsUtil.getFormat(file) }
|
||||
withContext(Dispatchers.EDT) {
|
||||
target.setImageProvider(imageProvider, format)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadFile(file: VirtualFile?) {
|
||||
if (file == null) {
|
||||
target.setImageProvider(null, null)
|
||||
return
|
||||
}
|
||||
flow.tryEmit(file)
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
job.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user