mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 06:50:54 +07:00
IJPL-158075 MacScrollBarAnimationBehavior - use flow for hideThumb
GitOrigin-RevId: 630f4fd27a19efdd973bcf8c73111a06643425ae
This commit is contained in:
committed by
intellij-monorepo-bot
parent
7a927bdadf
commit
8d8130566f
@@ -8,6 +8,7 @@ import com.intellij.ui.scale.JBUIScale;
|
||||
import com.intellij.util.MathUtil;
|
||||
import com.intellij.util.ui.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
@@ -38,7 +39,7 @@ class DefaultScrollBarUI extends ScrollBarUI {
|
||||
private int myCachedValue;
|
||||
private int myOldValue;
|
||||
|
||||
protected final ScrollBarAnimationBehavior myAnimationBehavior = createWrapAnimationBehaviour();
|
||||
protected @Nullable ScrollBarAnimationBehavior myAnimationBehavior = null;
|
||||
|
||||
DefaultScrollBarUI() {
|
||||
this(ScrollSettings.isThumbSmallIfOpaque() ? 13 : 10, 14, 10);
|
||||
@@ -73,7 +74,9 @@ class DefaultScrollBarUI extends ScrollBarUI {
|
||||
}
|
||||
|
||||
void toggle(boolean isOn) {
|
||||
myAnimationBehavior.onToggle(isOn);
|
||||
if (myAnimationBehavior != null) {
|
||||
myAnimationBehavior.onToggle(isOn);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isOpaque(Component c) {
|
||||
@@ -88,7 +91,7 @@ class DefaultScrollBarUI extends ScrollBarUI {
|
||||
}
|
||||
|
||||
boolean isTrackClickable() {
|
||||
return isOpaque(myScrollBar) || myAnimationBehavior.getTrackFrame() > 0;
|
||||
return isOpaque(myScrollBar) || (myAnimationBehavior != null && myAnimationBehavior.getTrackFrame() > 0);
|
||||
}
|
||||
|
||||
boolean isTrackExpandable() {
|
||||
@@ -148,7 +151,7 @@ class DefaultScrollBarUI extends ScrollBarUI {
|
||||
|
||||
private int getTrackOffset(int offset) {
|
||||
if (!isTrackExpandable()) return offset;
|
||||
float value = myAnimationBehavior.getTrackFrame();
|
||||
float value = myAnimationBehavior == null ? 0 :myAnimationBehavior.getTrackFrame();
|
||||
if (value <= 0) return offset;
|
||||
if (value >= 1) return 0;
|
||||
return (int)(.5f + offset * (1 - value));
|
||||
@@ -174,6 +177,8 @@ class DefaultScrollBarUI extends ScrollBarUI {
|
||||
|
||||
@Override
|
||||
public void installUI(JComponent c) {
|
||||
myAnimationBehavior = createWrapAnimationBehaviour();
|
||||
|
||||
myScrollBar = (JScrollBar)c;
|
||||
ScrollBarPainter.setBackground(c);
|
||||
myScrollBar.setOpaque(false);
|
||||
@@ -188,7 +193,10 @@ class DefaultScrollBarUI extends ScrollBarUI {
|
||||
|
||||
@Override
|
||||
public void uninstallUI(JComponent c) {
|
||||
assert myAnimationBehavior != null;
|
||||
myAnimationBehavior.onUninstall();
|
||||
myAnimationBehavior = null;
|
||||
|
||||
myScrollTimer.stop();
|
||||
myScrollBar.removeFocusListener(myListener);
|
||||
myScrollBar.removePropertyChangeListener(myListener);
|
||||
@@ -344,7 +352,9 @@ class DefaultScrollBarUI extends ScrollBarUI {
|
||||
}
|
||||
}
|
||||
myOldValue = value;
|
||||
if (animate) myAnimationBehavior.onThumbMove();
|
||||
if (animate && myAnimationBehavior != null) {
|
||||
myAnimationBehavior.onThumbMove();
|
||||
}
|
||||
}
|
||||
|
||||
private int getValue() {
|
||||
@@ -373,9 +383,13 @@ class DefaultScrollBarUI extends ScrollBarUI {
|
||||
|
||||
private void updateMouse(int x, int y) {
|
||||
if (isTrackContains(x, y)) {
|
||||
if (!isOverTrack) myAnimationBehavior.onTrackHover(isOverTrack = true);
|
||||
if (!isOverTrack && myAnimationBehavior != null) {
|
||||
myAnimationBehavior.onTrackHover(isOverTrack = true);
|
||||
}
|
||||
boolean hover = isThumbContains(x, y);
|
||||
if (isOverThumb != hover) myAnimationBehavior.onThumbHover(isOverThumb = hover);
|
||||
if (isOverThumb != hover && myAnimationBehavior != null) {
|
||||
myAnimationBehavior.onThumbHover(isOverThumb = hover);
|
||||
}
|
||||
}
|
||||
else {
|
||||
updateMouseExit();
|
||||
@@ -383,8 +397,12 @@ class DefaultScrollBarUI extends ScrollBarUI {
|
||||
}
|
||||
|
||||
private void updateMouseExit() {
|
||||
if (isOverThumb) myAnimationBehavior.onThumbHover(isOverThumb = false);
|
||||
if (isOverTrack) myAnimationBehavior.onTrackHover(isOverTrack = false);
|
||||
if (isOverThumb && myAnimationBehavior != null) {
|
||||
myAnimationBehavior.onThumbHover(isOverThumb = false);
|
||||
}
|
||||
if (isOverTrack && myAnimationBehavior != null) {
|
||||
myAnimationBehavior.onTrackHover(isOverTrack = false);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean redispatchIfTrackNotClickable(MouseEvent event) {
|
||||
@@ -546,7 +564,9 @@ class DefaultScrollBarUI extends ScrollBarUI {
|
||||
repaint();
|
||||
}
|
||||
if ("opaque".equals(name) || "visible".equals(name)) {
|
||||
myAnimationBehavior.onReset();
|
||||
if (myAnimationBehavior != null) {
|
||||
myAnimationBehavior.onReset();
|
||||
}
|
||||
myTrack.bounds.setBounds(0, 0, 0, 0);
|
||||
myThumb.bounds.setBounds(0, 0, 0, 0);
|
||||
}
|
||||
@@ -565,7 +585,9 @@ class DefaultScrollBarUI extends ScrollBarUI {
|
||||
int minY = Math.min(myThumb.bounds.y, thumbPos);
|
||||
int maxY = Math.max(myThumb.bounds.y, thumbPos) + myThumb.bounds.height;
|
||||
myThumb.bounds.y = thumbPos;
|
||||
myAnimationBehavior.onThumbMove();
|
||||
if (myAnimationBehavior != null) {
|
||||
myAnimationBehavior.onThumbMove();
|
||||
}
|
||||
repaint(myThumb.bounds.x, minY, myThumb.bounds.width, maxY - minY);
|
||||
}
|
||||
}
|
||||
@@ -577,7 +599,9 @@ class DefaultScrollBarUI extends ScrollBarUI {
|
||||
int minX = Math.min(myThumb.bounds.x, thumbPos);
|
||||
int maxX = Math.max(myThumb.bounds.x, thumbPos) + myThumb.bounds.width;
|
||||
myThumb.bounds.x = thumbPos;
|
||||
myAnimationBehavior.onThumbMove();
|
||||
if (myAnimationBehavior != null) {
|
||||
myAnimationBehavior.onThumbMove();
|
||||
}
|
||||
repaint(minX, myThumb.bounds.y, maxX - minX, myThumb.bounds.height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@file:OptIn(FlowPreview::class)
|
||||
|
||||
package com.intellij.ui.components
|
||||
|
||||
import com.intellij.util.SingleAlarm
|
||||
import com.intellij.openapi.application.EDT
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import javax.swing.JScrollBar
|
||||
|
||||
internal abstract class ScrollBarAnimationBehavior(@JvmField protected val trackAnimator: TwoWayAnimator,
|
||||
@@ -52,7 +59,23 @@ internal class MacScrollBarAnimationBehavior(
|
||||
thumbAnimator: TwoWayAnimator,
|
||||
) : DefaultScrollBarAnimationBehavior(trackAnimator, thumbAnimator) {
|
||||
private var isTrackHovered: Boolean = false
|
||||
private val hideThumbAlarm = SingleAlarm(task = { thumbAnimator.start(forward = false) }, delay = 700)
|
||||
@Suppress("SSBasedInspection")
|
||||
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + CoroutineName("IdeRootPane"))
|
||||
private val hideThumbRequests = MutableSharedFlow<Boolean>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
|
||||
init {
|
||||
coroutineScope.launch {
|
||||
hideThumbRequests
|
||||
.debounce(700)
|
||||
.collectLatest { start ->
|
||||
if (start) {
|
||||
withContext(Dispatchers.EDT) {
|
||||
thumbAnimator.start(forward = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTrackHover(hovered: Boolean) {
|
||||
isTrackHovered = hovered
|
||||
@@ -74,19 +97,13 @@ internal class MacScrollBarAnimationBehavior(
|
||||
override fun onThumbMove() {
|
||||
val scrollBar = scrollBarComputable()
|
||||
if (scrollBar != null && scrollBar.isShowing() && !DefaultScrollBarUI.isOpaque(scrollBar)) {
|
||||
if (!isTrackHovered && thumbAnimator.value == 0f) trackAnimator.rewind(false)
|
||||
thumbAnimator.rewind(true)
|
||||
hideThumbAlarm.cancelAllRequests()
|
||||
if (!isTrackHovered) {
|
||||
hideThumbAlarm.request()
|
||||
if (!isTrackHovered && thumbAnimator.value == 0f) {
|
||||
trackAnimator.rewind(false)
|
||||
}
|
||||
thumbAnimator.rewind(true)
|
||||
check(hideThumbRequests.tryEmit(!isTrackHovered))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUninstall() {
|
||||
hideThumbAlarm.cancelAllRequests()
|
||||
super.onUninstall()
|
||||
}
|
||||
}
|
||||
|
||||
internal open class ToggleableScrollBarAnimationBehaviorDecorator(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.ui.components
|
||||
|
||||
import com.intellij.ui.MixedColorProducer
|
||||
@@ -8,8 +8,11 @@ import java.awt.Graphics2D
|
||||
import java.awt.Insets
|
||||
import javax.swing.JComponent
|
||||
|
||||
internal class TabMacScrollBarUI(thickness: Int, thicknessMax: Int, thicknessMin: Int) : ThinMacScrollBarUI(thickness, thicknessMax,
|
||||
thicknessMin) {
|
||||
internal class TabMacScrollBarUI(
|
||||
thickness: Int,
|
||||
thicknessMax: Int,
|
||||
thicknessMin: Int,
|
||||
) : ThinMacScrollBarUI(thickness, thicknessMax, thicknessMin) {
|
||||
private var isHovered: Boolean = false
|
||||
private val defaultColorProducer: MixedColorProducer = MixedColorProducer(
|
||||
ScrollBarPainter.getColor({ myScrollBar }, ScrollBarPainter.TABS_TRANSPARENT_THUMB_BACKGROUND),
|
||||
@@ -39,7 +42,7 @@ internal class TabMacScrollBarUI(thickness: Int, thicknessMax: Int, thicknessMin
|
||||
|
||||
|
||||
override fun paintThumb(g: Graphics2D?, c: JComponent?) {
|
||||
if (myAnimationBehavior.thumbFrame > 0) {
|
||||
if (myAnimationBehavior != null && myAnimationBehavior!!.thumbFrame > 0) {
|
||||
paint(myThumb, g, c, !isHovered)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.ui.components
|
||||
|
||||
import com.intellij.ui.MixedColorProducer
|
||||
@@ -39,7 +39,7 @@ internal class TabScrollBarUI(thickness: Int, thicknessMax: Int, thicknessMin: I
|
||||
|
||||
|
||||
override fun paintThumb(g: Graphics2D?, c: JComponent?) {
|
||||
if (myAnimationBehavior.thumbFrame > 0) {
|
||||
if (myAnimationBehavior != null && myAnimationBehavior!!.thumbFrame > 0) {
|
||||
paint(myThumb, g, c, !isHovered)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user