From 382d966696787b5805ad0119046eb868e20a9328 Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Thu, 22 Feb 2024 16:33:26 +0100 Subject: [PATCH] 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 --- .../extensions/Scene2dExtensions.kt | 21 +++++++ .../ui/components/widgets/TabbedPager.kt | 58 ++++++++++++------- .../civilopediascreen/CivilopediaScreen.kt | 7 +-- .../screens/newgamescreen/GameOptionsTable.kt | 8 +-- .../newgamescreen/NationPickerPopup.kt | 7 +-- .../overviewscreen/EmpireOverviewScreen.kt | 9 ++- .../ui/screens/worldscreen/unit/UnitTable.kt | 7 ++- 7 files changed, 75 insertions(+), 42 deletions(-) diff --git a/core/src/com/unciv/ui/components/extensions/Scene2dExtensions.kt b/core/src/com/unciv/ui/components/extensions/Scene2dExtensions.kt index f42e583a14..f4019b86e5 100644 --- a/core/src/com/unciv/ui/components/extensions/Scene2dExtensions.kt +++ b/core/src/com/unciv/ui/components/extensions/Scene2dExtensions.kt @@ -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 */ diff --git a/core/src/com/unciv/ui/components/widgets/TabbedPager.kt b/core/src/com/unciv/ui/components/widgets/TabbedPager.kt index 6c2bf5bffd..0519f1fb76 100644 --- a/core/src/com/unciv/ui/components/widgets/TabbedPager.kt +++ b/core/src/com/unciv/ui/components/widgets/TabbedPager.kt @@ -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 private val fixedContentScroll = LinkedScrollPane(horizontalOnly = true) private val fixedContentScrollCell: Cell @@ -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 - } } diff --git a/core/src/com/unciv/ui/screens/civilopediascreen/CivilopediaScreen.kt b/core/src/com/unciv/ui/screens/civilopediascreen/CivilopediaScreen.kt index b282a33682..bba95e6f44 100644 --- a/core/src/com/unciv/ui/screens/civilopediascreen/CivilopediaScreen.kt +++ b/core/src/com/unciv/ui/screens/civilopediascreen/CivilopediaScreen.kt @@ -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() diff --git a/core/src/com/unciv/ui/screens/newgamescreen/GameOptionsTable.kt b/core/src/com/unciv/ui/screens/newgamescreen/GameOptionsTable.kt index 3f87c8502f..fbd5095061 100644 --- a/core/src/com/unciv/ui/screens/newgamescreen/GameOptionsTable.kt +++ b/core/src/com/unciv/ui/screens/newgamescreen/GameOptionsTable.kt @@ -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 diff --git a/core/src/com/unciv/ui/screens/newgamescreen/NationPickerPopup.kt b/core/src/com/unciv/ui/screens/newgamescreen/NationPickerPopup.kt index 153741e842..2b05ea5f32 100644 --- a/core/src/com/unciv/ui/screens/newgamescreen/NationPickerPopup.kt +++ b/core/src/com/unciv/ui/screens/newgamescreen/NationPickerPopup.kt @@ -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) diff --git a/core/src/com/unciv/ui/screens/overviewscreen/EmpireOverviewScreen.kt b/core/src/com/unciv/ui/screens/overviewscreen/EmpireOverviewScreen.kt index effa1644e6..bc24cbb39b 100644 --- a/core/src/com/unciv/ui/screens/overviewscreen/EmpireOverviewScreen.kt +++ b/core/src/com/unciv/ui/screens/overviewscreen/EmpireOverviewScreen.kt @@ -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 { diff --git a/core/src/com/unciv/ui/screens/worldscreen/unit/UnitTable.kt b/core/src/com/unciv/ui/screens/worldscreen/unit/UnitTable.kt index 311e7b6331..19491d5021 100644 --- a/core/src/com/unciv/ui/screens/worldscreen/unit/UnitTable.kt +++ b/core/src/com/unciv/ui/screens/worldscreen/unit/UnitTable.kt @@ -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 {