(UX, QOL) World screen top stats row scales down to squeeze into available width (#10473)

* Let WorldScreenTopBarStats scale itself down when content exceeds available width

* Refactor scale mapper functionality into reusable ScalingTableWrapper

* Use ScalingTableWrapper on WorldScreenTopBarResources too

* Oops, they're now equal, but technically it should be prefWidth now, and the comment is moot
This commit is contained in:
SomeTroglodyte 2023-11-13 21:17:58 +01:00 committed by GitHub
parent ec148309f7
commit 27a783104c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 12 deletions

View File

@ -0,0 +1,72 @@
package com.unciv.ui.components.widgets
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.ui.Cell
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup
import com.badlogic.gdx.scenes.scene2d.utils.Drawable
/** Allows inserting a scaled Table into another, such that the outer Table "sees" correct inner Table dimensions.
*
* Note: Delegates only the basic Table API: [background], [columns], [rows], [add], [row] and [defaults].
* Add to these as needed.
*/
open class ScalingTableWrapper(
private val minScale: Float = 0.5f
) : WidgetGroup() {
private val innerTable = Table()
init {
isTransform = false
super.addActor(innerTable)
}
//region WidgetGroup overrides
// I'd like to report "we could, if needed, shrink to innerTable.minWidth * minScale"
// - but then we get overall a glitch during resizes where the outer Table sets our height
// to minHeight despite there being room (as far as WorldScreenTopBar is concened) and scale > minScale...
override fun getMinWidth() = innerTable.minWidth * innerTable.scaleX
override fun getPrefWidth() = innerTable.prefWidth * innerTable.scaleX
override fun getMaxWidth() = innerTable.prefWidth
override fun getMinHeight() = innerTable.minHeight * innerTable.scaleY
override fun getPrefHeight() = innerTable.prefHeight * innerTable.scaleY
override fun getMaxHeight() = innerTable.prefHeight
override fun layout() {
innerTable.setBounds(0f, 0f, width / innerTable.scaleX, height / innerTable.scaleY)
}
//endregion
//region Table API delegates
var background: Drawable?
get() = innerTable.background
set(value) { innerTable.background = value }
val columns: Int get() = innerTable.columns
val rows: Int get() = innerTable.rows
fun defaults(): Cell<Actor> = innerTable.defaults()
fun add(actor: Actor): Cell<Actor> = innerTable.add(actor)
fun add(): Cell<Actor?> = innerTable.add()
fun row(): Cell<Actor> = innerTable.row()
//endregion
fun resetScale() {
innerTable.setScale(1f)
innerTable.isTransform = false
}
fun scaleTo(maxWidth: Float) {
innerTable.pack()
val scale = (maxWidth / innerTable.prefWidth).coerceIn(minScale, 1f)
if (scale >= 1f) return
innerTable.isTransform = true
innerTable.setScale(scale)
if (!innerTable.needsLayout()) {
innerTable.invalidate()
invalidate()
}
}
}

View File

@ -104,8 +104,8 @@ class WorldScreenTopBar(internal val worldScreen: WorldScreen) : Table() {
/** Performs the layout tricks mentioned in the class Kdoc */
private fun updateLayout() {
val targetWidth = stage.width
val statsWidth = statsTable.minWidth
val resourceWidth = resourceTable.minWidth
val statsWidth = statsTable.prefWidth
val resourceWidth = resourceTable.prefWidth
val overviewWidth = overviewButton.minWidth
val overviewHeight = overviewButton.minHeight
val selectedCivWidth = selectedCivTable.minWidth

View File

@ -14,15 +14,17 @@ import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.extensions.toStringSigned
import com.unciv.ui.components.fonts.Fonts
import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.widgets.ScalingTableWrapper
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.overviewscreen.EmpireOverviewCategories
import com.unciv.ui.screens.victoryscreen.VictoryScreen
internal class WorldScreenTopBarResources(topbar: WorldScreenTopBar) : Table() {
internal class WorldScreenTopBarResources(topbar: WorldScreenTopBar) : ScalingTableWrapper() {
private val turnsLabel = "Turns: 0/400".toLabel()
private data class ResourceActors(val resource: TileResource, val label: Label, val icon: Group)
private val resourceActors = ArrayList<ResourceActors>(12)
private val resourcesWrapper = Table()
val worldScreen = topbar.worldScreen
// Note: For a proper functioning of the "shift floating buttons down when cramped" feature, it is
// important that this entire Widget has only the bare minimum padding to its left and right.
@ -46,7 +48,6 @@ internal class WorldScreenTopBarResources(topbar: WorldScreenTopBar) : Table() {
resourcesWrapper.defaults().space(defaultPad)
resourcesWrapper.touchable = Touchable.enabled
val worldScreen = topbar.worldScreen
turnsLabel.onClick {
if (worldScreen.selectedCiv.isLongCountDisplay()) {
val gameInfo = worldScreen.selectedCiv.gameInfo
@ -77,6 +78,8 @@ internal class WorldScreenTopBarResources(topbar: WorldScreenTopBar) : Table() {
}
fun update(civInfo: Civilization) {
resetScale()
val yearText = YearTextUtil.toYearText(
civInfo.gameInfo.getYear(), civInfo.isLongCountDisplay()
)
@ -108,6 +111,6 @@ internal class WorldScreenTopBarResources(topbar: WorldScreenTopBar) : Table() {
resourcesWrapper.add(label).padTop(resourceAmountDescentTweak) // digits don't have descenders, so push them down a little
}
pack()
scaleTo(worldScreen.stage.width)
}
}

View File

@ -2,7 +2,6 @@ package com.unciv.ui.screens.worldscreen.topbar
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.logic.civilization.Civilization
import com.unciv.models.stats.Stats
import com.unciv.models.translations.tr
@ -11,6 +10,7 @@ import com.unciv.ui.components.extensions.setFontColor
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.extensions.toStringSigned
import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.widgets.ScalingTableWrapper
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.overviewscreen.EmpireOverviewCategories
@ -20,7 +20,7 @@ import com.unciv.ui.screens.pickerscreens.TechPickerScreen
import kotlin.math.ceil
import kotlin.math.roundToInt
internal class WorldScreenTopBarStats(topbar: WorldScreenTopBar) : Table() {
internal class WorldScreenTopBarStats(topbar: WorldScreenTopBar) : ScalingTableWrapper() {
private val goldLabel = "0".toLabel(colorFromRGB(225, 217, 71))
private val scienceLabel = "0".toLabel(colorFromRGB(78, 140, 151))
private val happinessLabel = "0".toLabel()
@ -48,6 +48,8 @@ internal class WorldScreenTopBarStats(topbar: WorldScreenTopBar) : Table() {
}
init {
isTransform = false
fun addStat(label: Label, icon: String, isLast: Boolean = false, screenFactory: ()-> BaseScreen) {
val image = ImageGetter.getStatIcon(icon)
@ -83,14 +85,13 @@ internal class WorldScreenTopBarStats(topbar: WorldScreenTopBar) : Table() {
} else {
add("Religion: Off".toLabel())
}
//saveDimensions()
}
private fun rateLabel(value: Float) = value.roundToInt().toStringSigned()
fun update(civInfo: Civilization) {
//resetChildrenSizes()
resetScale()
val nextTurnStats = civInfo.stats.statsForNextTurn
val goldPerTurn = " (" + rateLabel(nextTurnStats.gold) + ")"
@ -113,8 +114,8 @@ internal class WorldScreenTopBarStats(topbar: WorldScreenTopBar) : Table() {
cultureLabel.setText(getCultureText(civInfo, nextTurnStats))
faithLabel.setText(civInfo.religionManager.storedFaith.toString() +
" (" + rateLabel(nextTurnStats.faith) + ")")
//scaleToMaxWidth(worldScreen.stage.width)
pack()
scaleTo(worldScreen.stage.width)
}
private fun getCultureText(civInfo: Civilization, nextTurnStats: Stats): String {