Analog scroll bar, slim scroll bar, canvas scroll panel
This commit is contained in:
parent
93b3a01ee4
commit
bb689a39eb
@ -256,6 +256,11 @@ minecraft.runs.all {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
// If you have mod jar dependencies in ./libs, you can declare them as a repository like so:
|
||||||
|
flatDir {
|
||||||
|
dir("libs")
|
||||||
|
}
|
||||||
|
|
||||||
maven {
|
maven {
|
||||||
url = uri("https://maven.dbotthepony.ru")
|
url = uri("https://maven.dbotthepony.ru")
|
||||||
}
|
}
|
||||||
@ -285,11 +290,6 @@ repositories {
|
|||||||
name = "Kotlin for Forge"
|
name = "Kotlin for Forge"
|
||||||
url = uri("https://thedarkcolour.github.io/KotlinForForge/")
|
url = uri("https://thedarkcolour.github.io/KotlinForForge/")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If you have mod jar dependencies in ./libs, you can declare them as a repository like so:
|
|
||||||
flatDir {
|
|
||||||
dir("libs")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun org.gradle.jvm.tasks.Jar.attachManifest() {
|
fun org.gradle.jvm.tasks.Jar.attachManifest() {
|
||||||
|
@ -171,15 +171,24 @@ class ExoSuitInventoryScreen(menu: ExoSuitInventoryMenu) : MatteryScreen<ExoSuit
|
|||||||
var x = -4f
|
var x = -4f
|
||||||
|
|
||||||
if (menu.curiosSlots.isNotEmpty()) {
|
if (menu.curiosSlots.isNotEmpty()) {
|
||||||
val curiosRect = BackgroundPanel.padded(this, frame, x,
|
val curiosWidth = if (menu.curiosSlots.stream().anyMatch { it.second != null }) AbstractSlotPanel.SIZE * 2f else AbstractSlotPanel.SIZE
|
||||||
width = if (menu.curiosSlots.stream().anyMatch { it.second != null }) AbstractSlotPanel.SIZE * 2f else AbstractSlotPanel.SIZE,
|
val curiosHeight = menu.curiosSlots.size.coerceAtMost(4) * AbstractSlotPanel.SIZE
|
||||||
height = menu.curiosSlots.size * AbstractSlotPanel.SIZE)
|
|
||||||
|
val curiosRect =
|
||||||
|
if (menu.curiosSlots.size > 4)
|
||||||
|
ScrollbarBackgroundPanel.padded(this, frame, x,
|
||||||
|
width = curiosWidth,
|
||||||
|
height = curiosHeight, alwaysShowScrollbar = true)
|
||||||
|
else
|
||||||
|
BackgroundPanel.padded(this, frame, x,
|
||||||
|
width = curiosWidth,
|
||||||
|
height = curiosHeight)
|
||||||
|
|
||||||
x -= curiosRect.width
|
x -= curiosRect.width
|
||||||
curiosRect.x = x
|
curiosRect.x = x
|
||||||
|
|
||||||
for ((slot, cosmetic) in menu.curiosSlots) {
|
for ((slot, cosmetic) in menu.curiosSlots) {
|
||||||
val row = EditablePanel(this, curiosRect, height = AbstractSlotPanel.SIZE)
|
val row = EditablePanel(this, if (curiosRect is ScrollbarBackgroundPanel) curiosRect.canvas else curiosRect, height = AbstractSlotPanel.SIZE)
|
||||||
row.dock = Dock.TOP
|
row.dock = Dock.TOP
|
||||||
|
|
||||||
SlotPanel(this, row, slot).dock = Dock.RIGHT
|
SlotPanel(this, row, slot).dock = Dock.RIGHT
|
||||||
|
@ -0,0 +1,179 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.client.screen.panels
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.InputConstants
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack
|
||||||
|
import net.minecraft.client.gui.screens.Screen
|
||||||
|
import ru.dbotthepony.mc.otm.core.linearInterpolation
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
open class AnalogScrollBarPanel<out S : Screen>(
|
||||||
|
screen: S,
|
||||||
|
parent: EditablePanel<*>?,
|
||||||
|
val maxScroll: (panel: AnalogScrollBarPanel<*>) -> Float,
|
||||||
|
val scrollCallback: (panel: AnalogScrollBarPanel<*>, oldScroll: Float, newScroll: Float) -> Unit = { _, _, _ -> },
|
||||||
|
val smoothScrollCallback: (panel: AnalogScrollBarPanel<*>, oldScroll: Float, newScroll: Float) -> Unit = { _, _, _ -> },
|
||||||
|
x: Float = 0f,
|
||||||
|
y: Float = 0f,
|
||||||
|
height: Float = 20f,
|
||||||
|
open val allowSmoothScroll: Boolean = true,
|
||||||
|
open var scrollStep: Float = AbstractSlotPanel.SIZE,
|
||||||
|
isSlim: Boolean = false
|
||||||
|
) : EditablePanel<S>(screen, parent, x, y, width = if (isSlim) ScrollBarConstants.SLIM_WIDTH else ScrollBarConstants.WIDTH, height = height) {
|
||||||
|
inner class Button : EditablePanel<S>(screen, this@AnalogScrollBarPanel, 1f, 1f, this@AnalogScrollBarPanel.width - 2f, 15f) {
|
||||||
|
var isScrolling = false
|
||||||
|
private set
|
||||||
|
|
||||||
|
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||||
|
if (this@AnalogScrollBarPanel.width == ScrollBarConstants.SLIM_WIDTH) {
|
||||||
|
if (isScrolling) {
|
||||||
|
ScrollBarConstants.scrollSlimBarButtonPress.render(stack, width = width, height = height)
|
||||||
|
} else if (maxScroll.invoke(this@AnalogScrollBarPanel) <= 0) {
|
||||||
|
ScrollBarConstants.scrollSlimBarButtonDisabled.render(stack, width = width, height = height)
|
||||||
|
} else if (isHovered) {
|
||||||
|
ScrollBarConstants.scrollSlimBarButtonHover.render(stack, width = width, height = height)
|
||||||
|
} else {
|
||||||
|
ScrollBarConstants.scrollSlimBarButton.render(stack, width = width, height = height)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isScrolling) {
|
||||||
|
ScrollBarConstants.scrollBarButtonPress.render(stack, width = width, height = height)
|
||||||
|
} else if (maxScroll.invoke(this@AnalogScrollBarPanel) <= 0) {
|
||||||
|
ScrollBarConstants.scrollBarButtonDisabled.render(stack, width = width, height = height)
|
||||||
|
} else if (isHovered) {
|
||||||
|
ScrollBarConstants.scrollBarButtonHover.render(stack, width = width, height = height)
|
||||||
|
} else {
|
||||||
|
ScrollBarConstants.scrollBarButton.render(stack, width = width, height = height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var rememberScroll = 0f
|
||||||
|
private var rememberY = 0.0
|
||||||
|
|
||||||
|
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
|
||||||
|
if (maxScroll.invoke(this@AnalogScrollBarPanel) <= 0f) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (button == InputConstants.MOUSE_BUTTON_LEFT && tryToGrabMouseInput()) {
|
||||||
|
isScrolling = true
|
||||||
|
rememberScroll = scroll
|
||||||
|
rememberY = y
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseReleasedInner(x: Double, y: Double, button: Int): Boolean {
|
||||||
|
if (isScrolling && button == InputConstants.MOUSE_BUTTON_LEFT) {
|
||||||
|
isScrolling = false
|
||||||
|
grabMouseInput = false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
|
||||||
|
return this@AnalogScrollBarPanel.mouseScrolledInner(x, y, scroll)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseDraggedInner(x: Double, y: Double, button: Int, xDelta: Double, yDelta: Double): Boolean {
|
||||||
|
if (isScrolling) {
|
||||||
|
val pixelsPerRow = (this@AnalogScrollBarPanel.height - height) / maxScroll.invoke(this@AnalogScrollBarPanel)
|
||||||
|
val diff = y - rememberY
|
||||||
|
|
||||||
|
this@AnalogScrollBarPanel.scroll = rememberScroll + (diff / pixelsPerRow).roundToInt()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val scrollButton = Button()
|
||||||
|
|
||||||
|
private var lastRender = System.nanoTime()
|
||||||
|
|
||||||
|
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||||
|
if (width == ScrollBarConstants.SLIM_WIDTH) {
|
||||||
|
ScrollBarConstants.scrollSlimBarBody.render(stack, y = 2f, height = height - 4f)
|
||||||
|
ScrollBarConstants.scrollSlimBarTop.render(stack)
|
||||||
|
ScrollBarConstants.scrollSlimBarBottom.render(stack, y = height - 2f)
|
||||||
|
} else {
|
||||||
|
ScrollBarConstants.scrollBarBody.render(stack, y = 2f, height = height - 4f)
|
||||||
|
ScrollBarConstants.scrollBarTop.render(stack)
|
||||||
|
ScrollBarConstants.scrollBarBottom.render(stack, y = height - 2f)
|
||||||
|
}
|
||||||
|
|
||||||
|
val time = System.nanoTime()
|
||||||
|
val diff = time - lastRender
|
||||||
|
lastRender = time
|
||||||
|
|
||||||
|
if (scroll != smoothScroll) {
|
||||||
|
smoothScroll = linearInterpolation(diff / 50_000_000.0, smoothScroll.toDouble(), scroll.toDouble()).toFloat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
|
||||||
|
this.scroll -= scroll.toFloat() * scrollStep
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var scroll = 0f
|
||||||
|
set(value) {
|
||||||
|
val newValue = value.coerceAtLeast(0f).coerceAtMost(maxScroll.invoke(this))
|
||||||
|
|
||||||
|
if (newValue != field) {
|
||||||
|
val old = field
|
||||||
|
field = newValue
|
||||||
|
scrollChanged(old, newValue)
|
||||||
|
|
||||||
|
if (!allowSmoothScroll) {
|
||||||
|
smoothScroll = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var smoothScroll = 0f
|
||||||
|
set(value) {
|
||||||
|
val newValue = value.coerceAtLeast(0f).coerceAtMost(maxScroll.invoke(this))
|
||||||
|
|
||||||
|
if (newValue != field) {
|
||||||
|
val old = field
|
||||||
|
field = newValue
|
||||||
|
smoothScrollChanged(old, newValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hardSetScroll(scroll: Float) {
|
||||||
|
this.scroll = scroll
|
||||||
|
this.smoothScroll = scroll
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun updateScrollButtonPosition() {
|
||||||
|
val maxScroll = this.maxScroll.invoke(this)
|
||||||
|
|
||||||
|
if (maxScroll <= 0f) {
|
||||||
|
scrollButton.y = 1f
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val availableHeight = height - scrollButton.height - 2f
|
||||||
|
scrollButton.y = 1f + availableHeight * (scroll / maxScroll)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun scrollChanged(oldScroll: Float, newScroll: Float) {
|
||||||
|
scrollCallback.invoke(this, oldScroll, newScroll)
|
||||||
|
updateScrollButtonPosition()
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun smoothScrollChanged(oldScroll: Float, newScroll: Float) {
|
||||||
|
smoothScrollCallback.invoke(this, oldScroll, newScroll)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun performLayout() {
|
||||||
|
super.performLayout()
|
||||||
|
updateScrollButtonPosition()
|
||||||
|
}
|
||||||
|
}
|
@ -5,20 +5,32 @@ import com.mojang.blaze3d.vertex.PoseStack
|
|||||||
import net.minecraft.client.gui.screens.Screen
|
import net.minecraft.client.gui.screens.Screen
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
open class DiscreteScrollBarPanel<S : Screen> @JvmOverloads constructor(
|
open class DiscreteScrollBarPanel<out S : Screen>(
|
||||||
screen: S,
|
screen: S,
|
||||||
parent: EditablePanel<*>?,
|
parent: EditablePanel<*>?,
|
||||||
val maxScroll: (panel: DiscreteScrollBarPanel<S>) -> Int,
|
val maxScroll: (panel: DiscreteScrollBarPanel<*>) -> Int,
|
||||||
val scrollCallback: (panel: DiscreteScrollBarPanel<S>, oldScroll: Int, newScroll: Int) -> Unit,
|
val scrollCallback: (panel: DiscreteScrollBarPanel<*>, oldScroll: Int, newScroll: Int) -> Unit,
|
||||||
x: Float = 0f,
|
x: Float = 0f,
|
||||||
y: Float = 0f,
|
y: Float = 0f,
|
||||||
height: Float = 20f
|
height: Float = 20f,
|
||||||
) : EditablePanel<S>(screen, parent, x, y, width = ScrollBarConstants.WIDTH, height = height) {
|
isSlim: Boolean = false
|
||||||
open inner class Button : EditablePanel<S>(screen, this@DiscreteScrollBarPanel, 1f, 1f, 12f, 15f) {
|
) : EditablePanel<S>(screen, parent, x, y, width = if (isSlim) ScrollBarConstants.SLIM_WIDTH else ScrollBarConstants.WIDTH, height = height) {
|
||||||
|
inner class Button : EditablePanel<S>(screen, this@DiscreteScrollBarPanel, 1f, 1f, this@DiscreteScrollBarPanel.width - 12f, 15f) {
|
||||||
var isScrolling = false
|
var isScrolling = false
|
||||||
protected set
|
private set
|
||||||
|
|
||||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||||
|
if (this@DiscreteScrollBarPanel.width == ScrollBarConstants.SLIM_WIDTH) {
|
||||||
|
if (isScrolling) {
|
||||||
|
ScrollBarConstants.scrollSlimBarButtonPress.render(stack, width = width, height = height)
|
||||||
|
} else if (maxScroll.invoke(this@DiscreteScrollBarPanel) <= 0) {
|
||||||
|
ScrollBarConstants.scrollSlimBarButtonDisabled.render(stack, width = width, height = height)
|
||||||
|
} else if (isHovered) {
|
||||||
|
ScrollBarConstants.scrollSlimBarButtonHover.render(stack, width = width, height = height)
|
||||||
|
} else {
|
||||||
|
ScrollBarConstants.scrollSlimBarButton.render(stack, width = width, height = height)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (isScrolling) {
|
if (isScrolling) {
|
||||||
ScrollBarConstants.scrollBarButtonPress.render(stack, width = width, height = height)
|
ScrollBarConstants.scrollBarButtonPress.render(stack, width = width, height = height)
|
||||||
} else if (maxScroll.invoke(this@DiscreteScrollBarPanel) <= 0) {
|
} else if (maxScroll.invoke(this@DiscreteScrollBarPanel) <= 0) {
|
||||||
@ -29,8 +41,9 @@ open class DiscreteScrollBarPanel<S : Screen> @JvmOverloads constructor(
|
|||||||
ScrollBarConstants.scrollBarButton.render(stack, width = width, height = height)
|
ScrollBarConstants.scrollBarButton.render(stack, width = width, height = height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected var rememberScroll = 0
|
private var rememberScroll = 0
|
||||||
private var rememberY = 0.0
|
private var rememberY = 0.0
|
||||||
|
|
||||||
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
|
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
|
||||||
@ -77,9 +90,15 @@ open class DiscreteScrollBarPanel<S : Screen> @JvmOverloads constructor(
|
|||||||
val scrollButton = Button()
|
val scrollButton = Button()
|
||||||
|
|
||||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||||
ScrollBarConstants.scrollBarBody.render(stack, y = 2f, height = height - 4)
|
if (width == ScrollBarConstants.SLIM_WIDTH) {
|
||||||
|
ScrollBarConstants.scrollSlimBarBody.render(stack, y = 2f, height = height - 4f)
|
||||||
|
ScrollBarConstants.scrollSlimBarTop.render(stack)
|
||||||
|
ScrollBarConstants.scrollSlimBarBottom.render(stack, y = height - 2f)
|
||||||
|
} else {
|
||||||
|
ScrollBarConstants.scrollBarBody.render(stack, y = 2f, height = height - 4f)
|
||||||
ScrollBarConstants.scrollBarTop.render(stack)
|
ScrollBarConstants.scrollBarTop.render(stack)
|
||||||
ScrollBarConstants.scrollBarBottom.render(stack, y = height - 2)
|
ScrollBarConstants.scrollBarBottom.render(stack, y = height - 2f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
|
public override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
|
||||||
|
@ -5,7 +5,8 @@ import ru.dbotthepony.mc.otm.client.render.element
|
|||||||
|
|
||||||
object ScrollBarConstants {
|
object ScrollBarConstants {
|
||||||
const val WIDTH = 14f
|
const val WIDTH = 14f
|
||||||
const val TEXTURE_WIDTH = 14f
|
const val SLIM_WIDTH = 8f
|
||||||
|
const val TEXTURE_WIDTH = 22f
|
||||||
const val TEXTURE_HEIGHT = 68f
|
const val TEXTURE_HEIGHT = 68f
|
||||||
|
|
||||||
val scrollBarTop = WidgetLocation.SCROLL.element(0f, 45f, 14f, 2f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
val scrollBarTop = WidgetLocation.SCROLL.element(0f, 45f, 14f, 2f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
@ -16,4 +17,13 @@ object ScrollBarConstants {
|
|||||||
val scrollBarButtonHover = WidgetLocation.SCROLL.element(0f, 15f, 12f, 15f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
val scrollBarButtonHover = WidgetLocation.SCROLL.element(0f, 15f, 12f, 15f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
val scrollBarButtonPress = WidgetLocation.SCROLL.element(0f, 30f, 12f, 15f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
val scrollBarButtonPress = WidgetLocation.SCROLL.element(0f, 30f, 12f, 15f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
val scrollBarButtonDisabled = WidgetLocation.SCROLL.element(0f, 53f, 12f, 15f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
val scrollBarButtonDisabled = WidgetLocation.SCROLL.element(0f, 53f, 12f, 15f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
|
|
||||||
|
val scrollSlimBarTop = WidgetLocation.SCROLL.element(14f, 45f, 8f, 2f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
|
val scrollSlimBarBody = WidgetLocation.SCROLL.element(14f, 46f, 8f, 6f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
|
val scrollSlimBarBottom = WidgetLocation.SCROLL.element(14f, 51f, 8f, 2f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
|
|
||||||
|
val scrollSlimBarButton = WidgetLocation.SCROLL.element(14f, 0f, 6f, 15f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
|
val scrollSlimBarButtonHover = WidgetLocation.SCROLL.element(14f, 15f, 6f, 15f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
|
val scrollSlimBarButtonPress = WidgetLocation.SCROLL.element(14f, 30f, 6f, 15f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
|
val scrollSlimBarButtonDisabled = WidgetLocation.SCROLL.element(14f, 53f, 6f, 15f, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,166 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.client.screen.panels
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.screens.Screen
|
||||||
|
|
||||||
|
open class ScrollbarBackgroundPanel<out S : Screen>(
|
||||||
|
screen: S,
|
||||||
|
parent: EditablePanel<*>?,
|
||||||
|
x: Float = 0f,
|
||||||
|
y: Float = 0f,
|
||||||
|
width: Float = 30f,
|
||||||
|
height: Float = 30f,
|
||||||
|
alwaysShowScrollbar: Boolean = false,
|
||||||
|
autoResizeForScrollbar: Boolean = true,
|
||||||
|
autoMoveForScrollbar: Boolean = true,
|
||||||
|
scrollStep: Float = AbstractSlotPanel.SIZE,
|
||||||
|
) : BackgroundPanel<S>(screen, parent, x, y, width, height) {
|
||||||
|
/**
|
||||||
|
* Whenever is to hide scrollbar when there is nothing to scroll
|
||||||
|
*/
|
||||||
|
var alwaysShowScrollbar = alwaysShowScrollbar
|
||||||
|
set(value) {
|
||||||
|
if (field != value) {
|
||||||
|
field = value
|
||||||
|
determineScrollbarVisible()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var lastResizedForScrollbar: Boolean = false
|
||||||
|
private var lastMovedForScrollbar: Boolean = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whenever is to auto resize width when scrollbar has to be shown
|
||||||
|
*
|
||||||
|
* Has no effect if [alwaysShowScrollbar] is true
|
||||||
|
*/
|
||||||
|
var autoResizeForScrollbar = autoResizeForScrollbar
|
||||||
|
set(value) {
|
||||||
|
if (field != value) {
|
||||||
|
field = value
|
||||||
|
determineScrollbarVisible()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whenever is to auto move panel along X axis when scrollbar has to be shown (given no [dock] is [Dock.NONE])
|
||||||
|
*
|
||||||
|
* Has no effect if [alwaysShowScrollbar] is true
|
||||||
|
*/
|
||||||
|
var autoMoveForScrollbar = autoMoveForScrollbar
|
||||||
|
set(value) {
|
||||||
|
if (field != value) {
|
||||||
|
field = value
|
||||||
|
determineScrollbarVisible()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMaxScroll(it: AnalogScrollBarPanel<*>): Float {
|
||||||
|
return (canvas.childrenRectHeight - canvas.height).coerceAtLeast(0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onScrollUpdate(it: AnalogScrollBarPanel<*>, old: Float, new: Float) {
|
||||||
|
this.canvas.yOffset = -new
|
||||||
|
}
|
||||||
|
|
||||||
|
val scrollbar = AnalogScrollBarPanel(screen, this, this::getMaxScroll, smoothScrollCallback = this::onScrollUpdate, isSlim = true, scrollStep = scrollStep)
|
||||||
|
|
||||||
|
fun determineScrollbarVisible() {
|
||||||
|
if (alwaysShowScrollbar) {
|
||||||
|
scrollbar.visible = true
|
||||||
|
|
||||||
|
if (lastResizedForScrollbar) {
|
||||||
|
width -= scrollbar.width
|
||||||
|
lastResizedForScrollbar = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastMovedForScrollbar) {
|
||||||
|
x += scrollbar.width
|
||||||
|
lastMovedForScrollbar = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (canvas.childrenRectHeight > (height - dockPadding.top - dockPadding.bottom)) {
|
||||||
|
if (!scrollbar.visible) {
|
||||||
|
scrollbar.visible = true
|
||||||
|
|
||||||
|
if (autoResizeForScrollbar) {
|
||||||
|
width += scrollbar.width
|
||||||
|
lastResizedForScrollbar = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autoMoveForScrollbar && dock == Dock.NONE) {
|
||||||
|
x -= scrollbar.width
|
||||||
|
lastMovedForScrollbar = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (scrollbar.visible) {
|
||||||
|
scrollbar.visible = false
|
||||||
|
|
||||||
|
if (lastResizedForScrollbar) {
|
||||||
|
width -= scrollbar.width
|
||||||
|
lastResizedForScrollbar = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastMovedForScrollbar) {
|
||||||
|
x += scrollbar.width
|
||||||
|
lastMovedForScrollbar = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val canvas = object : EditablePanel<S>(screen, this@ScrollbarBackgroundPanel) {
|
||||||
|
init {
|
||||||
|
scissor = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun performLayout() {
|
||||||
|
super.performLayout()
|
||||||
|
determineScrollbarVisible()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
|
||||||
|
scrollbar.mouseScrolledInner(x, y, scroll)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addPanel(panel: EditablePanel<*>) {
|
||||||
|
panel.parent = canvas
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
scrollbar.dock = Dock.RIGHT
|
||||||
|
canvas.dock = Dock.FILL
|
||||||
|
scrollbar.visible = alwaysShowScrollbar
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun <S : Screen> padded(
|
||||||
|
screen: S,
|
||||||
|
parent: EditablePanel<*>?,
|
||||||
|
x: Float = 0f,
|
||||||
|
y: Float = 0f,
|
||||||
|
width: Float = 30f,
|
||||||
|
height: Float = 30f,
|
||||||
|
alwaysShowScrollbar: Boolean = false,
|
||||||
|
autoResizeForScrollbar: Boolean = true,
|
||||||
|
autoMoveForScrollbar: Boolean = true,
|
||||||
|
scrollStep: Float = AbstractSlotPanel.SIZE,
|
||||||
|
) = ScrollbarBackgroundPanel(screen, parent, x, y, width + 6f + (if (alwaysShowScrollbar) ScrollBarConstants.SLIM_WIDTH else 0f), height + 6f, alwaysShowScrollbar, autoResizeForScrollbar, autoMoveForScrollbar, scrollStep)
|
||||||
|
|
||||||
|
fun <S : Screen> paddedCenter(
|
||||||
|
screen: S,
|
||||||
|
parent: EditablePanel<*>?,
|
||||||
|
x: Float = 0f,
|
||||||
|
y: Float = 0f,
|
||||||
|
width: Float = 30f,
|
||||||
|
height: Float = 30f,
|
||||||
|
alwaysShowScrollbar: Boolean = false,
|
||||||
|
autoResizeForScrollbar: Boolean = true,
|
||||||
|
autoMoveForScrollbar: Boolean = true,
|
||||||
|
scrollStep: Float = AbstractSlotPanel.SIZE,
|
||||||
|
) = ScrollbarBackgroundPanel(screen, parent, x - 3f, y - 3f - (if (alwaysShowScrollbar) ScrollBarConstants.SLIM_WIDTH / 2f else 0f), width + 6f + (if (alwaysShowScrollbar) ScrollBarConstants.SLIM_WIDTH else 0f), height + 6f, alwaysShowScrollbar, autoResizeForScrollbar, autoMoveForScrollbar, scrollStep)
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 714 B After Width: | Height: | Size: 779 B |
Binary file not shown.
Loading…
Reference in New Issue
Block a user