Change EmpireOverviewScreen closing to use the same button and UX as Civilopedia (#11169)

* Centralize a "round X" close button factory with global scope

* Change EmpireOverviewScreen closing to use the same button and UX as Civilopedia
This commit is contained in:
SomeTroglodyte
2024-02-22 16:33:26 +01:00
committed by GitHub
parent 3047c1abad
commit 382d966696
7 changed files with 75 additions and 42 deletions

View File

@ -31,6 +31,9 @@ import com.unciv.ui.components.extensions.GdxKeyCodeFixes.DEL
import com.unciv.ui.components.extensions.GdxKeyCodeFixes.toString
import com.unciv.ui.components.extensions.GdxKeyCodeFixes.valueOf
import com.unciv.ui.components.fonts.Fonts
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.components.input.onChange
import com.unciv.ui.images.IconCircleGroup
import com.unciv.ui.images.ImageGetter
@ -253,6 +256,24 @@ fun String.toImageButton(iconSize: Float, circleSize: Float, circleColor: Color,
return button.surroundWithCircle( circleSize, false, circleColor)
}
/** Return a "close" button, visually a circle with "x" icon that goes red on mouse-over.
*
* For use e.g. in the top-right corner of screens such as CivilopediaScreen.
* Automatically binds the BACK key to the [action].
*/
fun getCloseButton(
size: Float,
iconSize: Float = size - 20f,
circleColor: Color = BaseScreen.skinStrings.skinConfig.baseColor,
overColor: Color = Color.RED,
action: () -> Unit
): Group {
val closeButton = "OtherIcons/Close".toImageButton(iconSize, size, circleColor, overColor)
closeButton.onActivation(action)
closeButton.keyShortcuts.add(KeyCharAndCode.BACK)
return closeButton
}
/** Translate a [String] and make a [Label] widget from it */
fun String.toLabel() = Label(this.tr(), BaseScreen.skin)
/** Make a [Label] widget containing this [Int] as text */

View File

@ -86,6 +86,7 @@ open class TabbedPager(
private val header = Table(BaseScreen.skin)
val headerScroll = LinkedScrollPane(horizontalOnly = true, header)
protected var headerHeight = 0f
private val headerDecorationRightCell: Cell<Actor?>
private val fixedContentScroll = LinkedScrollPane(horizontalOnly = true)
private val fixedContentScrollCell: Cell<ScrollPane>
@ -309,7 +310,9 @@ open class TabbedPager(
header.defaults().pad(headerPadding, headerPadding * 0.5f)
// Measure header height, most likely its final value
removePage(addPage("Dummy"))
add(headerScroll).growX().minHeight(headerHeight).row()
add(headerScroll).growX().minHeight(headerHeight)
headerDecorationRightCell = add().pad(0f)
row()
if (separatorColor != Color.CLEAR)
addSeparator(separatorColor)
@ -622,6 +625,37 @@ open class TabbedPager(
}).open(true)
}
/** Gets total width of the header buttons including their padding.
* Header will be scrollable if getHeaderPrefWidth > width. */
fun getHeaderPrefWidth() = header.prefWidth
/** Adds any Actor to the header, e.g. informative labels.
* Must be called _after_ all pages are final, otherwise effects not guaranteed.
*
* Notes:
* * Using [fixed] will make the widths of content and header Scrollpanes different. Synchronized scrolling will look off.
* * [fixed] decorations have predefined cells, thus decorateHeader will replace any previous decoration. Non-[fixed] are cumulative and cannot be removed.
* * [leftSide] and [fixed] both true is not implemented.
*
* @param leftSide If `true` then [actor] is inserted on the left, otherwise on the right of the page buttons.
* @param fixed If `true` [actor] is outside the header ScrollPane and thus always shown.
*/
fun decorateHeader(actor: Actor, leftSide: Boolean, fixed: Boolean = false) {
if (fixed) headerDecorationRightCell.pad(headerPadding).setActor(actor)
else insertHeaderCellAt(if (leftSide) 0 else -1).setActor(actor)
invalidate()
if (!leftSide || fixed) return
val addWidth = actor.width
for (page in pages) {
page.buttonX += addWidth
}
}
/** Alternative selection handler to [IPageExtensions.activated] */
fun onSelection(action: ((index: Int, caption: String, pager: TabbedPager) -> Unit)?) {
onSelectionCallback = action
}
//endregion
//region Helper routines
@ -682,26 +716,6 @@ open class TabbedPager(
}
}
/** Gets total width of the header buttons including their padding.
* Header will be scrollable if getHeaderPrefWidth > width. */
fun getHeaderPrefWidth() = header.prefWidth
//endregion
/** Adds any Actor to the header, e.g. informative labels.
* Must be called _after_ all pages are final, otherwise effects not guaranteed.
* @param leftSide If `true` then [actor] is inserted on the left, otherwise on the right of the page buttons.
*/
fun decorateHeader(actor: Actor, leftSide: Boolean) {
val cell = insertHeaderCellAt(if (leftSide) 0 else -1)
cell.setActor(actor)
if (!leftSide) return
val addWidth = actor.width
for (page in pages) {
page.buttonX += addWidth
}
}
/** Alternative selection handler to [IPageExtensions.activated] */
fun onSelection(action: ((index: Int, caption: String, pager: TabbedPager) -> Unit)?) {
onSelectionCallback = action
}
}

View File

@ -15,12 +15,11 @@ import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.stats.INamed
import com.unciv.models.translations.tr
import com.unciv.ui.components.extensions.colorFromRGB
import com.unciv.ui.components.extensions.getCloseButton
import com.unciv.ui.components.extensions.toImageButton
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.fonts.Fonts
import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.components.input.keyShortcuts
import com.unciv.ui.components.input.onActivation
import com.unciv.ui.components.input.onClick
import com.unciv.ui.images.IconTextButton
@ -248,9 +247,7 @@ class CivilopediaScreen(
val searchButton = "OtherIcons/Search".toImageButton(imageSize - 16f, imageSize, skinStrings.skinConfig.baseColor, Color.GOLD)
searchButton.onActivation(binding = KeyboardBinding.PediaSearch) { searchPopup.open(true) }
val closeButton = "OtherIcons/Close".toImageButton(imageSize - 20f, imageSize, skinStrings.skinConfig.baseColor, Color.RED)
closeButton.onActivation { game.popScreen() }
closeButton.keyShortcuts.add(KeyCharAndCode.BACK)
val closeButton = getCloseButton(imageSize) { game.popScreen() }
val topTable = Table()
topTable.add(buttonTableScroll).growX()

View File

@ -17,14 +17,12 @@ import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.tr
import com.unciv.ui.audio.MusicMood
import com.unciv.ui.audio.MusicTrackChooserFlags
import com.unciv.ui.components.extensions.getCloseButton
import com.unciv.ui.components.extensions.pad
import com.unciv.ui.components.extensions.toCheckBox
import com.unciv.ui.components.extensions.toImageButton
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.extensions.toTextButton
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.components.input.onChange
import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.widgets.AutoScrollPane
@ -539,9 +537,7 @@ private class RandomNationPickerPopup(
update()
pack()
val closeButton = "OtherIcons/Close".toImageButton(Color.FIREBRICK)
closeButton.onActivation { close() }
closeButton.keyShortcuts.add(KeyCharAndCode.BACK)
val closeButton = getCloseButton(buttonsCircleSize, buttonsIconSize, buttonsBackColor, Color.FIREBRICK) { close() }
closeButton.setPosition(buttonsOffsetFromEdge, buttonsOffsetFromEdge, Align.bottomLeft)
innerTable.addActor(closeButton)
clickBehindToClose = true

View File

@ -17,8 +17,8 @@ import com.unciv.models.ruleset.nation.Nation
import com.unciv.models.translations.tr
import com.unciv.ui.audio.MusicMood
import com.unciv.ui.audio.MusicTrackChooserFlags
import com.unciv.ui.components.widgets.AutoScrollPane
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
import com.unciv.ui.components.extensions.getCloseButton
import com.unciv.ui.components.extensions.isNarrowerThan4to3
import com.unciv.ui.components.extensions.toImageButton
import com.unciv.ui.components.input.KeyCharAndCode
@ -26,6 +26,7 @@ import com.unciv.ui.components.input.keyShortcuts
import com.unciv.ui.components.input.onActivation
import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.input.onDoubleClick
import com.unciv.ui.components.widgets.AutoScrollPane
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.images.Portrait
import com.unciv.ui.popups.Popup
@ -116,9 +117,7 @@ internal class NationPickerPopup(
private fun addActionIcons() {
// Despite being a Popup we use our own buttons - floating circular ones
val closeButton = "OtherIcons/Close".toImageButton(Color.FIREBRICK)
closeButton.onActivation { close() }
closeButton.keyShortcuts.add(KeyCharAndCode.BACK)
val closeButton = getCloseButton(buttonsCircleSize, buttonsIconSize, buttonsBackColor, Color.FIREBRICK) { close() }
closeButton.setPosition(buttonsOffsetFromEdge, buttonsOffsetFromEdge, Align.bottomLeft)
innerTable.addActor(closeButton)

View File

@ -5,6 +5,7 @@ import com.unciv.Constants
import com.unciv.GUI
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.civilization.Notification
import com.unciv.ui.components.extensions.getCloseButton
import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.widgets.TabbedPager
import com.unciv.ui.images.ImageGetter
@ -52,8 +53,6 @@ class EmpireOverviewScreen(
separatorColor = Color.WHITE,
capacity = EmpireOverviewCategories.values().size)
tabbedPager.addClosePage { game.popScreen() }
for (category in EmpireOverviewCategories.values()) {
val tabState = category.testState(viewingPlayer)
if (tabState == EmpireOverviewTabState.Hidden) continue
@ -75,8 +74,14 @@ class EmpireOverviewScreen(
}
}
val closeButton = getCloseButton(50f) { game.popScreen() }
tabbedPager.decorateHeader(closeButton, leftSide = false, fixed = true)
tabbedPager.setFillParent(true)
stage.addActor(tabbedPager)
// closeButton.setPosition(stage.width - 10f, stage.height - 10f, Align.topRight)
// stage.addActor(closeButton)
}
override fun recreate(): BaseScreen {

View File

@ -14,9 +14,10 @@ import com.unciv.models.translations.tr
import com.unciv.ui.components.extensions.addSeparator
import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.darken
import com.unciv.ui.components.extensions.getCloseButton
import com.unciv.ui.components.extensions.isShiftKeyPressed
import com.unciv.ui.components.extensions.toImageButton
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.input.keyShortcuts
import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.widgets.UnitGroup
import com.unciv.ui.images.ImageGetter
@ -83,12 +84,12 @@ class UnitTable(val worldScreen: WorldScreen) : Table() {
promotionsTable.touchable = Touchable.enabled
val deselectUnitButton = "OtherIcons/Close".toImageButton(20f, 50f, Color.CLEAR, Color.RED)
deselectUnitButton.onClick {
val deselectUnitButton = getCloseButton(50f, 20f, Color.CLEAR, Color.RED) {
selectUnit()
worldScreen.shouldUpdate = true
this@UnitTable.isVisible = false
}
deselectUnitButton.keyShortcuts.clear() // This is the only place we don't want the BACK keyshortcut getCloseButton assigns
add(deselectUnitButton).left()
add(Table().apply {