From 7f67190a6dcdb319c1466665c8e847de6e7812fa Mon Sep 17 00:00:00 2001 From: "M. Rittweger" Date: Sat, 18 Jan 2025 00:24:19 +0100 Subject: [PATCH] Constructions table: avoid vertical movement of lower table --- .../ui/components/widgets/ExpanderTab.kt | 6 +- .../cityscreen/CityConstructionsTable.kt | 56 +++++++++++-------- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/core/src/com/unciv/ui/components/widgets/ExpanderTab.kt b/core/src/com/unciv/ui/components/widgets/ExpanderTab.kt index c29a89d24531c..370b1ba30e764 100644 --- a/core/src/com/unciv/ui/components/widgets/ExpanderTab.kt +++ b/core/src/com/unciv/ui/components/widgets/ExpanderTab.kt @@ -27,6 +27,7 @@ import com.unciv.ui.screens.basescreen.BaseScreen * @param defaultPad Padding between content and wrapper. * @param headerPad Default padding for the header Table. * @param expanderWidth If set initializes header width + * @param expanderHeight If set initializes header height * @param persistenceID If specified, the ExpanderTab will remember its open/closed state for the duration of one app run * @param onChange If specified, this will be called after the visual change for a change in [isOpen] completes (e.g. to react to changed size) * @param initContent Optional lambda with [innerTable] as parameter, to help initialize content. @@ -39,6 +40,7 @@ class ExpanderTab( defaultPad: Float = 10f, headerPad: Float = 10f, expanderWidth: Float = 0f, + expanderHeight: Float = 0f, private val persistenceID: String? = null, toggleKey: KeyboardBinding = KeyboardBinding.None, private val onChange: (() -> Unit)? = null, @@ -56,7 +58,7 @@ class ExpanderTab( val header = Table(skin) // Header with label and icon, touchable to show/hide val headerContent = Table() private val headerLabel = title.toLabel(fontSize = fontSize, hideIcons = true) - private val headerIcon = ImageGetter.getImage(arrowImage) + val headerIcon = ImageGetter.getImage(arrowImage) private val contentWrapper = Table() // Wrapper for innerTable, this is what will be shown/hidden /** The container where the client should add the content to toggle */ @@ -73,6 +75,8 @@ class ExpanderTab( init { header.defaults().pad(headerPad) + if (expanderHeight > 0f) + header.defaults().height(expanderHeight) headerIcon.setSize(arrowSize, arrowSize) headerIcon.setOrigin(Align.center) headerIcon.rotation = 0f diff --git a/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt b/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt index d40167cf966ae..a366e5aafbc45 100644 --- a/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt +++ b/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt @@ -14,7 +14,6 @@ import com.unciv.GUI import com.unciv.logic.city.City import com.unciv.logic.city.CityConstructions import com.unciv.models.UncivSound -import com.unciv.models.metadata.GameSettings import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.IConstruction import com.unciv.models.ruleset.INonPerpetualConstruction @@ -37,6 +36,7 @@ import com.unciv.ui.components.extensions.packIfNeeded import com.unciv.ui.components.extensions.setEnabled import com.unciv.ui.components.extensions.surroundWithCircle import com.unciv.ui.components.extensions.toLabel +import com.unciv.ui.components.extensions.toTextButton import com.unciv.ui.components.fonts.Fonts import com.unciv.ui.components.input.KeyboardBinding import com.unciv.ui.components.input.keyShortcuts @@ -83,6 +83,7 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { private val lowerTableScrollCell: Cell private val pad = 10f + private val miniQueueHeight = 54f private val posFromEdge = CityScreen.posFromEdge private val stageHeight = cityScreen.stage.height @@ -106,8 +107,10 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { queueExpander = ExpanderTab( "Construction queue", onChange = { cityScreen.update() }, - startsOutOpened = cityScreen.game.settings.screenSize >= GameSettings.ScreenSize.Large, - defaultPad = 0f + defaultPad = 0f, + // keep lowerTable at fixed position + startsOutOpened = false, + expanderHeight = miniQueueHeight ) upperTable.defaults().left().top() @@ -120,7 +123,9 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { // by default, and by expancing the construction queue, the user changes precedence to the // construction queue. upperTable.add(constructionsQueueScrollPane).padBottom(pad).maxHeight(stageHeight*3/4).row() - upperTable.add(buttonsTable).padBottom(pad).row() + upperTable.add(buttonsTable) + .height("".toTextButton().height) // constant height in order to not let the lowerTable jump + .padBottom(pad).row() availableConstructionsScrollPane = ScrollPane(availableConstructionsTable.addBorder(2f, Color.WHITE)) availableConstructionsScrollPane.setOverscroll(false, false) @@ -207,26 +212,26 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { else constructionsQueueTable.add("Pick a construction".toLabel()).pad(2f).row() - if (queue.size > 1) { - queueExpander.innerTable.clear() - queueExpander.headerContent.clear() - queueExpander.header.pad(0f) - queueExpander.setText("Construction queue".tr()) - queue.forEachIndexed { i, constructionName -> - // The first entry is already displayed as "Current construction" - if (i != 0) { - queueExpander.innerTable.add(getQueueEntry(i, constructionName)) - .expandX().fillX().row() - if (i != queue.lastIndex) { - queueExpander.innerTable.addSeparator() - } + // always show queue expander, even when empty, in order to keep lowerTable at constant position + queueExpander.innerTable.clear() + queueExpander.headerContent.clear() + queueExpander.headerIcon.isVisible = queue.size >= 2 + queueExpander.header.pad(0f) + queueExpander.setText("Construction queue".tr()) + queue.forEachIndexed { i, constructionName -> + // The first entry is already displayed as "Current construction" + if (i != 0) { + queueExpander.innerTable.add(getQueueEntry(i, constructionName)) + .expandX().fillX().row() + if (i != queue.lastIndex) { + queueExpander.innerTable.addSeparator() } } - if (!queueExpander.isOpen) { - updateQueuePreview(queue) - } - constructionsQueueTable.add(queueExpander).fillX().pad(2f) } + if (!queueExpander.isOpen) { + updateQueuePreview(queue) + } + constructionsQueueTable.add(queueExpander).fillX().pad(2f) constructionsQueueScrollPane.layout() constructionsQueueScrollPane.scrollY = queueScrollY @@ -235,11 +240,16 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { private fun updateQueuePreview(queue: MutableList) { queueExpander.header.pad(-5f, 0f, -5f, 0f) - queueExpander.setText(if (queue.size <= 3) "Queue".tr() else "") + val title = when(queue.size) { + in 0..1 -> "Queue empty".tr() + in 2..4 -> "Queue".tr() + else -> "" + } + queueExpander.setText(title) queue.forEachIndexed { i, constructionName -> if (i in 1..3) { val color = if (selectedQueueEntry == i) highlightColor else BaseScreen.skinStrings.skinConfig.baseColor - val image = ImageGetter.getConstructionPortrait(constructionName, 40f).surroundWithCircle(54f, false, color) + val image = ImageGetter.getConstructionPortrait(constructionName, 40f).surroundWithCircle(miniQueueHeight, false, color) image.addListener(object: ClickListener() { // Calling event.stop() to prevent click propagation to the parent, // the expander header.