mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-07 22:09:38 +07:00
IDEA-369073 JPA in Structure view: slow operations on navigating to DB
(cherry picked from commit 3d8474ac84d0fc9818ea617b16f4dab92adf0c9c) IJ-CR-159980 GitOrigin-RevId: 553f165cf3fc1a14b5f4cecda51e4a97d4badc2d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
13b5dd97c8
commit
4f984e6aea
@@ -53,6 +53,12 @@
|
||||
- a:isFileOpen(com.intellij.openapi.vfs.VirtualFile):Z
|
||||
- a:isImplicitSaveAllowed(com.intellij.openapi.editor.Document):Z
|
||||
- a:saveAs(com.intellij.ide.lightEdit.LightEditorInfo,com.intellij.openapi.vfs.VirtualFile):com.intellij.ide.lightEdit.LightEditorInfo
|
||||
*f:com.intellij.ide.structureView.StructureViewClickEvent
|
||||
- <init>(com.intellij.ide.structureView.StructureViewTreeElement,I):V
|
||||
- f:getElement():com.intellij.ide.structureView.StructureViewTreeElement
|
||||
- f:getFragmentIndex():I
|
||||
*:com.intellij.ide.structureView.StructureViewModel$ClickHandler
|
||||
- a:handleClick(com.intellij.ide.structureView.StructureViewClickEvent):java.util.concurrent.CompletableFuture
|
||||
com.intellij.ide.structureView.StructureViewModel$ExpandInfoProvider
|
||||
- *:getMinimumAutoExpandDepth():I
|
||||
*:com.intellij.ide.ui.ToolbarSettings
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.ide.structureView
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Experimental
|
||||
class StructureViewClickEvent(
|
||||
val element: StructureViewTreeElement,
|
||||
val fragmentIndex: Int
|
||||
)
|
||||
@@ -9,6 +9,8 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Defines the model for the data displayed in the standard structure view or file structure
|
||||
* popup component. The model of the standard structure view is represented as a tree of elements.
|
||||
@@ -105,9 +107,26 @@ public interface StructureViewModel extends TreeModel, Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use ClickHandler
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2025.2")
|
||||
interface ActionHandler {
|
||||
|
||||
boolean handleClick(StructureViewTreeElement element, int fragmentIndex);
|
||||
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
@FunctionalInterface
|
||||
interface ClickHandler {
|
||||
|
||||
/**
|
||||
* @return - true if the event was handled
|
||||
*/
|
||||
@NotNull
|
||||
CompletableFuture<Boolean> handleClick(@NotNull StructureViewClickEvent event);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -1003,14 +1004,16 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre
|
||||
@Override
|
||||
public void processMouseEvent(MouseEvent event) {
|
||||
if (event.getID() == MouseEvent.MOUSE_PRESSED) requestFocus();
|
||||
if (myTreeModel instanceof StructureViewModel.ActionHandler actionHandler) {
|
||||
boolean handled = processCustomEventHandler(actionHandler, event);
|
||||
if (handled) {
|
||||
event.consume();
|
||||
return;
|
||||
}
|
||||
if (myTreeModel instanceof StructureViewModel.ActionHandler || myTreeModel instanceof StructureViewModel.ClickHandler) {
|
||||
processCustomEventHandler(myTreeModel, event)
|
||||
.whenComplete((Boolean handled, Throwable t) -> {
|
||||
if (handled != null && handled)
|
||||
event.consume();
|
||||
else
|
||||
super.processMouseEvent(event);
|
||||
});
|
||||
}
|
||||
super.processMouseEvent(event);
|
||||
else super.processMouseEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1048,24 +1051,32 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre
|
||||
return super.getFileColorForPath(path);
|
||||
}
|
||||
|
||||
private boolean processCustomEventHandler(StructureViewModel.ActionHandler actionHandler, MouseEvent event) {
|
||||
if (event.getClickCount() != 1 || event.getID() != MouseEvent.MOUSE_PRESSED) return false;
|
||||
private CompletableFuture<Boolean> processCustomEventHandler(
|
||||
StructureViewModel handler, MouseEvent event
|
||||
) {
|
||||
if (event.getClickCount() != 1 || event.getID() != MouseEvent.MOUSE_PRESSED) return CompletableFuture.completedFuture(false);
|
||||
TreePath path = getPathForLocation(event.getX(), event.getY());
|
||||
if (path == null) return false;
|
||||
if (path == null) return CompletableFuture.completedFuture(false);
|
||||
Object lastPathComponent = path.getLastPathComponent();
|
||||
StructureViewTreeElement treeElement = getStructureTreeElement(lastPathComponent);
|
||||
if (treeElement == null) return false;
|
||||
if (treeElement == null) return CompletableFuture.completedFuture(false);
|
||||
|
||||
Rectangle pathBounds = getPathBounds(path);
|
||||
if (pathBounds == null) return false;
|
||||
if (pathBounds == null) return CompletableFuture.completedFuture(false);
|
||||
int dx = event.getX() - (int) pathBounds.getX();
|
||||
if (dx < 0 || dx > pathBounds.width) return false;
|
||||
if (dx < 0 || dx > pathBounds.width) return CompletableFuture.completedFuture(false);
|
||||
|
||||
Component component = this.cellRenderer.getTreeCellRendererComponent(this, lastPathComponent, false, false, true, getRowForPath(path), false);
|
||||
if (!(component instanceof SimpleColoredComponent simpleColoredComponent)) return false;
|
||||
if (!(component instanceof SimpleColoredComponent simpleColoredComponent)) return CompletableFuture.completedFuture(false);
|
||||
int fragmentIndex = simpleColoredComponent.findFragmentAt(dx);
|
||||
if (fragmentIndex >= 0) return actionHandler.handleClick(treeElement, fragmentIndex);
|
||||
return false;
|
||||
if (fragmentIndex < 0)
|
||||
return CompletableFuture.completedFuture(false);
|
||||
else if (handler instanceof StructureViewModel.ActionHandler actionHandler)
|
||||
return CompletableFuture.completedFuture(actionHandler.handleClick(treeElement, fragmentIndex));
|
||||
else if (handler instanceof StructureViewModel.ClickHandler actionHandler)
|
||||
return actionHandler.handleClick(new StructureViewClickEvent(treeElement, fragmentIndex));
|
||||
else
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
- *sf:Companion:com.intellij.ide.structureView.logical.model.LogicalModelPresentationProvider$Companion
|
||||
- <init>():V
|
||||
- getColoredText(java.lang.Object):java.util.List
|
||||
- handleClick(java.lang.Object,I):Z
|
||||
- handleClick(java.lang.Object,I):java.util.concurrent.CompletableFuture
|
||||
- isAutoExpand(java.lang.Object):Z
|
||||
*f:com.intellij.ide.structureView.logical.model.LogicalModelPresentationProvider$Companion
|
||||
- f:getForObject(java.lang.Object):com.intellij.ide.structureView.logical.model.LogicalModelPresentationProvider
|
||||
|
||||
@@ -8,6 +8,9 @@ import com.intellij.ide.structureView.logical.impl.LogicalStructureViewTreeEleme
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
||||
import com.intellij.internal.statistic.eventLog.events.EventFields
|
||||
import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.application.ReadAction
|
||||
import com.intellij.util.concurrency.AppExecutorUtil
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
@@ -42,12 +45,24 @@ object StructureViewEventsCollector: CounterUsagesCollector() {
|
||||
|
||||
fun logBuildStructure(viewDescriptor: StructureViewDescriptor) {
|
||||
val tab = viewDescriptor.title?.let { StructureViewTab.ofTitle(it) } ?: return
|
||||
BUILD_STRUCTURE.log(tab, getModelClass(viewDescriptor))
|
||||
ReadAction
|
||||
.nonBlocking<Class<*>?> {
|
||||
getModelClass(viewDescriptor)
|
||||
}
|
||||
.finishOnUiThread(ModalityState.any()) {
|
||||
BUILD_STRUCTURE.log(tab, it)
|
||||
}.submit(AppExecutorUtil.getAppScheduledExecutorService())
|
||||
}
|
||||
|
||||
fun logTabSelected(viewDescriptor: StructureViewDescriptor) {
|
||||
val tab = viewDescriptor.title?.let { StructureViewTab.ofTitle(it) } ?: return
|
||||
TAB_SELECTED.log(tab, getModelClass(viewDescriptor))
|
||||
ReadAction
|
||||
.nonBlocking<Class<*>?> {
|
||||
getModelClass(viewDescriptor)
|
||||
}
|
||||
.finishOnUiThread(ModalityState.any()) {
|
||||
TAB_SELECTED.log(tab, it)
|
||||
}.submit(AppExecutorUtil.getAppScheduledExecutorService())
|
||||
}
|
||||
|
||||
fun logNavigate(modelClass: Class<*>) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.intellij.ide.structureView.logical.impl
|
||||
|
||||
import com.intellij.ide.TypePresentationService
|
||||
import com.intellij.ide.projectView.PresentationData
|
||||
import com.intellij.ide.structureView.StructureViewClickEvent
|
||||
import com.intellij.ide.structureView.StructureViewEventsCollector
|
||||
import com.intellij.ide.structureView.StructureViewModel
|
||||
import com.intellij.ide.structureView.StructureViewModelBase
|
||||
@@ -12,9 +13,9 @@ import com.intellij.ide.structureView.logical.ContainerElementsProvider
|
||||
import com.intellij.ide.structureView.logical.ExternalElementsProvider
|
||||
import com.intellij.ide.structureView.logical.LogicalStructureTreeElementProvider
|
||||
import com.intellij.ide.structureView.logical.PropertyElementProvider
|
||||
import com.intellij.ide.structureView.logical.model.ExtendedLogicalObject
|
||||
import com.intellij.ide.structureView.logical.model.LogicalContainerPresentationProvider
|
||||
import com.intellij.ide.structureView.logical.model.LogicalModelPresentationProvider
|
||||
import com.intellij.ide.structureView.logical.model.ExtendedLogicalObject
|
||||
import com.intellij.ide.structureView.logical.model.LogicalContainer
|
||||
import com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel
|
||||
import com.intellij.ide.structureView.logical.model.ProvidedLogicalContainer
|
||||
@@ -26,13 +27,14 @@ import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiTarget
|
||||
import com.intellij.ui.SimpleTextAttributes
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import javax.swing.Icon
|
||||
|
||||
@ApiStatus.Internal
|
||||
class LogicalStructureViewModel private constructor(psiFile: PsiFile, editor: Editor?, assembledModel: LogicalStructureAssembledModel<*>, elementBuilder: ElementsBuilder)
|
||||
: StructureViewModelBase(psiFile, editor, elementBuilder.createViewTreeElement(assembledModel)),
|
||||
StructureViewModel.ElementInfoProvider, StructureViewModel.ExpandInfoProvider, StructureViewModel.ActionHandler {
|
||||
StructureViewModel.ElementInfoProvider, StructureViewModel.ExpandInfoProvider, StructureViewModel.ClickHandler {
|
||||
|
||||
constructor(psiFile: PsiFile, editor: Editor?, assembledModel: LogicalStructureAssembledModel<*>):
|
||||
this(psiFile, editor, assembledModel, ElementsBuilder())
|
||||
@@ -53,13 +55,18 @@ class LogicalStructureViewModel private constructor(psiFile: PsiFile, editor: Ed
|
||||
|
||||
override fun isSmartExpand(): Boolean = false
|
||||
|
||||
override fun handleClick(element: StructureViewTreeElement, fragmentIndex: Int): Boolean {
|
||||
val model = getModel(element) ?: return false
|
||||
val handled = LogicalModelPresentationProvider.getForObject(model)?.handleClick(model, fragmentIndex) ?: false
|
||||
if (handled) {
|
||||
StructureViewEventsCollector.logCustomClickHandled(model::class.java)
|
||||
override fun handleClick(event: StructureViewClickEvent): CompletableFuture<Boolean> {
|
||||
val model = getModel(event.element)
|
||||
val presentation = model?.let { LogicalModelPresentationProvider.getForObject(it) }
|
||||
if (model == null || presentation == null) {
|
||||
return CompletableFuture.completedFuture(false)
|
||||
}
|
||||
return presentation.handleClick(model, event.fragmentIndex).thenApply { handled ->
|
||||
if (handled) {
|
||||
StructureViewEventsCollector.logCustomClickHandled(model::class.java)
|
||||
}
|
||||
handled
|
||||
}
|
||||
return handled
|
||||
}
|
||||
|
||||
private fun getModel(element: StructureViewTreeElement): Any? {
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.intellij.ide.util.treeView.PresentableNodeDescriptor
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.util.ClassExtension
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
* Adds additional features for common PresentationProvider
|
||||
@@ -30,6 +31,8 @@ abstract class LogicalModelPresentationProvider<T>: PresentationProvider<T>() {
|
||||
|
||||
open fun getColoredText(t: T): List<PresentableNodeDescriptor.ColoredFragment> = emptyList()
|
||||
|
||||
open fun handleClick(t: T, fragmentIndex: Int): Boolean = false
|
||||
open fun handleClick(t: T, fragmentIndex: Int): CompletableFuture<Boolean> {
|
||||
return CompletableFuture.completedFuture(false)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user