From 0f75947d18c423c9dae86f5efb46fc647f11b1f3 Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Sun, 1 Oct 2023 08:43:53 +0200 Subject: [PATCH] City overview restore fixed header (#10197) * More SortableGrid comments * Fix City Overview header row * CityOverviewTab minor lint * Documentation for the 'Gdx Scene2D debug' option * Lint - TabbedPager sort imports and some spaces --- .../com/unciv/ui/components/SortableGrid.kt | 12 ++++++-- .../com/unciv/ui/components/TabbedPager.kt | 14 ++++----- .../screens/overviewscreen/CityOverviewTab.kt | 12 ++++++-- docs/Developers/UI-development.md | 29 +++++++++++++++++++ 4 files changed, 53 insertions(+), 14 deletions(-) diff --git a/core/src/com/unciv/ui/components/SortableGrid.kt b/core/src/com/unciv/ui/components/SortableGrid.kt index 4f0c99db40..ed26ffcdcb 100644 --- a/core/src/com/unciv/ui/components/SortableGrid.kt +++ b/core/src/com/unciv/ui/components/SortableGrid.kt @@ -75,7 +75,7 @@ class SortableGrid> ( */ fun getHeader(): Table { if (!separateHeader) - throw IllegalStateException("You can't call SortableGrid.getHeader unless you override separateHeader to true") + throw IllegalStateException("You can't call SortableGrid.getHeader unless you set separateHeader to true") return headerRow } @@ -116,8 +116,13 @@ class SortableGrid> ( } private fun initHeader() { - sortSymbols[false] = "↑".toLabel() - sortSymbols[true] = "↓".toLabel() + // These are possibly the highest codepoints in use in Unciv - + // Take into account when limiting Fonts.nextUnusedCharacterNumber + // Alternatives: "↑" U+2191, "↓" U+2193 - much wider and weird spacing in some fonts (e.g. Verdana) + // Note: These will scale with GameSettings.fontSizeMultiplier - could be *partly* countered + // with `toLabel(fontSize = (Constants.defaultFontSize / GUI.getSettings().fontSizeMultiplier).toInt())` + sortSymbols[false] = "↑".toLabel() // U+FFEA + sortSymbols[true] = "↓".toLabel() // U+FFEC for (column in columns) { val group = HeaderGroup(column) @@ -208,6 +213,7 @@ class SortableGrid> ( // Using Group to overlay an optional sort symbol on top of the icon - we could also // do HorizontalGroup to have them side by side. Also, note this is not a WidgetGroup // so all layout details are left to the container - in this case, a Table.Cell + // This will knowingly place the arrow partly outside the Group bounds. /** Wrap icon and sort symbol for a header cell */ inner class HeaderGroup(column: CT) : Group() { private val icon = column.getHeaderIcon(iconSize) diff --git a/core/src/com/unciv/ui/components/TabbedPager.kt b/core/src/com/unciv/ui/components/TabbedPager.kt index 1c882d2c27..bbef19d270 100644 --- a/core/src/com/unciv/ui/components/TabbedPager.kt +++ b/core/src/com/unciv/ui/components/TabbedPager.kt @@ -9,7 +9,6 @@ import com.badlogic.gdx.scenes.scene2d.InputListener import com.badlogic.gdx.scenes.scene2d.ui.Button import com.badlogic.gdx.scenes.scene2d.ui.Cell import com.badlogic.gdx.scenes.scene2d.ui.Image -import com.badlogic.gdx.scenes.scene2d.ui.Label import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup @@ -21,12 +20,11 @@ import com.unciv.ui.components.UncivTooltip.Companion.addTooltip import com.unciv.ui.components.extensions.addSeparator import com.unciv.ui.components.extensions.darken import com.unciv.ui.components.extensions.isEnabled -import com.unciv.ui.components.input.keyShortcuts -import com.unciv.ui.components.input.onActivation import com.unciv.ui.components.extensions.packIfNeeded import com.unciv.ui.components.extensions.pad -import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.components.input.KeyCharAndCode +import com.unciv.ui.components.input.keyShortcuts +import com.unciv.ui.components.input.onActivation import com.unciv.ui.images.IconTextButton import com.unciv.ui.popups.Popup import com.unciv.ui.screens.basescreen.BaseScreen @@ -225,8 +223,8 @@ open class TabbedPager( } } - class SyncedScrollListener(val linkedScrollPane: LinkedScrollPane):InputListener(){ - val oldScrollListener = linkedScrollPane.listeners.removeIndex(linkedScrollPane.listeners.size-1) as InputListener + class SyncedScrollListener(val linkedScrollPane: LinkedScrollPane) : InputListener() { + val oldScrollListener = linkedScrollPane.listeners.removeIndex(linkedScrollPane.listeners.size - 1) as InputListener override fun scrolled(event: InputEvent?, x: Float, y: Float, amountX: Float, amountY: Float): Boolean { val toReturn = oldScrollListener.scrolled(event, x, y, amountX, amountY) linkedScrollPane.sync(false) @@ -239,7 +237,7 @@ open class TabbedPager( addListener(SyncedScrollListener(this)) } - class LinkedCaptureListener(val linkedScrollPane: LinkedScrollPane):InputListener(){ + class LinkedCaptureListener(val linkedScrollPane: LinkedScrollPane) : InputListener() { val oldListener = linkedScrollPane.captureListeners.removeIndex(0) as InputListener override fun touchDown(event: InputEvent?, x: Float, y: Float, pointer: Int, button: Int): Boolean { val toReturn = oldListener.touchDown(event, x, y, pointer, button) @@ -265,7 +263,7 @@ open class TabbedPager( addCaptureListener(LinkedCaptureListener(this)) } - class LinkedFlickScrollListener(val stdFlickListener: ActorGestureListener, val linkedScrollPane: LinkedScrollPane):ActorGestureListener(){ + class LinkedFlickScrollListener(val stdFlickListener: ActorGestureListener, val linkedScrollPane: LinkedScrollPane) : ActorGestureListener() { override fun pan(event: InputEvent?, x: Float, y: Float, deltaX: Float, deltaY: Float) { stdFlickListener.pan(event, x, y, deltaX, deltaY) linkedScrollPane.sync() diff --git a/core/src/com/unciv/ui/screens/overviewscreen/CityOverviewTab.kt b/core/src/com/unciv/ui/screens/overviewscreen/CityOverviewTab.kt index 06286f7dcc..95a9484524 100644 --- a/core/src/com/unciv/ui/screens/overviewscreen/CityOverviewTab.kt +++ b/core/src/com/unciv/ui/screens/overviewscreen/CityOverviewTab.kt @@ -5,6 +5,11 @@ import com.unciv.ui.components.SortableGrid import com.unciv.ui.components.extensions.equalizeColumns +/** + * Provides the Cities tab for Empire Overview. + * + * Uses [SortableGrid], so all actual content implementation is in the [CityOverviewTabColumn] enum. + */ class CityOverviewTab( viewingPlayer: Civilization, overviewScreen: EmpireOverviewScreen, @@ -28,14 +33,15 @@ class CityOverviewTab( iconSize = 50f, //if you set this too low, there is a chance that the tables will be misaligned paddingVert = 5f, paddingHorz = 8f, - separateHeader = false + separateHeader = true ) { header, details, totals -> - this.name equalizeColumns(details, header, totals) - this.layout() + this.validate() } + override fun getFixedContent() = grid.getHeader() + init { add(grid) } diff --git a/docs/Developers/UI-development.md b/docs/Developers/UI-development.md index 4e831e6e87..c96f66c0fc 100644 --- a/docs/Developers/UI-development.md +++ b/docs/Developers/UI-development.md @@ -27,3 +27,32 @@ class DevElement( ``` You can then simply run the `main` method of `FasterUIDevelopment` to show your UI element. + + +## The 'Gdx Scene2D debug' option + +This option (on the secret 'Debug' page) turns on several UI debug features: +* Gdx Actor debug lines +* Mouse coordinates and FPS +* Descriptor of the Actor under the mouse +* Coordinate scales + +### Gdx Actor debug lines +See [Gdx wiki](https://libgdx.com/wiki/graphics/2d/scene2d/table#logical-table) +The Scene2D debug option turns on mouse-over Gdx debug lines at the stage level using `setDebugUnderMouse`, `setDebugTableUnderMouse` and `setDebugParentUnderMouse`. +* Blue lines are Table bounds - Each Table has dimensions as a Widget and as a logical table determined by the cells. They will coincide if there is both expandX and expandY set somewhere. +* Red lines are Cell bounds - the part within cell padding. +* Green lines are Actor bounds of the Cell contents. If the Cell has both Fill directions set, they disappear below the red cell bounds (that is, unless the content Actor has a maxSize limiting the fill). + +### Mouse coordinates and FPS +On the bottom right is a semi-transparent panel with 3 numbers on top: X and Y of the mouse in Gdx stage coordinates, and FPS. + +### Descriptor of the Actor under the mouse +The lower part of said panel shows a string helping to identify which Actor the mouse is over. This will look for the actor's parent and potentially children, and the optional Actor.name field. Java class names or Label text are used when appropriate - it tries to build something short, but just descriptive enough. It uses the following separators / symbols: +* `:` a colon separates class name from Actor.name - or Actor.name is used undecorated if it contains the class name. +* `"` double-quotes show actual Label or TextButton text, max 20 characters, prefixed directly with the class name. +* `.` a dot separates parent from hit Actor: If the above alone does not yield a descriptive label, the parent (if any) is added as descriptive label per the rules above or as simple class name. +* `(`..`)` after the above designates a sample from the children (the first nicely descriptive one), only if the parent won't add good recognition value. + +### Coordinate scales +The bottom and right edges of the screen get tiny tick marks, each 20 units in the Gdx stage coordinates, to help estimate paddings or sizes.