mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-25 15:19:51 +07:00
Redesign EmpireOverviewScreen as TabbedPager (#6364)
This commit is contained in:
@ -18,7 +18,18 @@ import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip
|
|||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class CityOverviewTable(private val viewingPlayer: CivilizationInfo, private val overviewScreen: EmpireOverviewScreen): Table() {
|
class CityOverviewTab(
|
||||||
|
viewingPlayer: CivilizationInfo,
|
||||||
|
overviewScreen: EmpireOverviewScreen,
|
||||||
|
persistedData: EmpireOverviewTabPersistableData? = null
|
||||||
|
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
|
||||||
|
class CityTabPersistableData(
|
||||||
|
var sortedBy: String = "City"
|
||||||
|
) : EmpireOverviewTabPersistableData() {
|
||||||
|
override fun isEmpty() = sortedBy == "City"
|
||||||
|
}
|
||||||
|
|
||||||
|
override val persistableData = (persistedData as? CityTabPersistableData) ?: CityTabPersistableData()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val iconSize = 50f //if you set this too low, there is a chance that the tables will be misaligned
|
const val iconSize = 50f //if you set this too low, there is a chance that the tables will be misaligned
|
||||||
@ -31,20 +42,19 @@ class CityOverviewTable(private val viewingPlayer: CivilizationInfo, private val
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
val numHeaderCells = columnsNames.size + 2 // +1 City +1 Filler
|
val numHeaderCells = columnsNames.size + 2 // +1 City +1 Filler
|
||||||
var sortedBy = "City"
|
|
||||||
|
|
||||||
val cityInfoTableIcons = Table(skin)
|
val cityInfoTableIcons = Table(skin)
|
||||||
val cityInfoTableDetails = Table(skin)
|
val cityInfoTableDetails = Table(skin)
|
||||||
val cityInfoTableTotal = Table(skin)
|
val cityInfoTableTotal = Table(skin)
|
||||||
|
|
||||||
fun sortOnClick(iconName: String) {
|
fun sortOnClick(iconName: String) {
|
||||||
val descending = sortedBy == iconName
|
val descending = persistableData.sortedBy == iconName
|
||||||
sortedBy = iconName
|
persistableData.sortedBy = iconName
|
||||||
// sort the table: clear and fill with sorted data
|
// sort the table: clear and fill with sorted data
|
||||||
cityInfoTableDetails.clear()
|
cityInfoTableDetails.clear()
|
||||||
fillCitiesTable(cityInfoTableDetails, iconName, descending)
|
fillCitiesTable(cityInfoTableDetails, iconName, descending)
|
||||||
// reset to return back for ascending next time
|
// reset to return back for ascending next time
|
||||||
if (descending) sortedBy = ""
|
if (descending) persistableData.sortedBy = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addSortIcon(iconName: String, iconParam: Actor? = null) {
|
fun addSortIcon(iconName: String, iconParam: Actor? = null) {
|
||||||
@ -77,7 +87,7 @@ class CityOverviewTable(private val viewingPlayer: CivilizationInfo, private val
|
|||||||
.minWidth(iconSize) //we need the min width so we can align the different tables
|
.minWidth(iconSize) //we need the min width so we can align the different tables
|
||||||
.align(Align.left)
|
.align(Align.left)
|
||||||
|
|
||||||
fillCitiesTable(cityInfoTableDetails, sortedBy, false)
|
fillCitiesTable(cityInfoTableDetails, persistableData.sortedBy, false)
|
||||||
|
|
||||||
val cityInfoScrollPane = AutoScrollPane(cityInfoTableDetails)
|
val cityInfoScrollPane = AutoScrollPane(cityInfoTableDetails)
|
||||||
cityInfoScrollPane.pack()
|
cityInfoScrollPane.pack()
|
||||||
|
@ -12,12 +12,17 @@ import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
|
|||||||
import com.unciv.ui.trade.DiplomacyScreen
|
import com.unciv.ui.trade.DiplomacyScreen
|
||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.*
|
||||||
|
|
||||||
class DiplomacyOverviewTable (
|
class DiplomacyOverviewTab (
|
||||||
private val viewingPlayer: CivilizationInfo,
|
viewingPlayer: CivilizationInfo,
|
||||||
private val overviewScreen: EmpireOverviewScreen
|
overviewScreen: EmpireOverviewScreen,
|
||||||
): Table() {
|
persistedData: EmpireOverviewTabPersistableData? = null
|
||||||
|
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
|
||||||
private var includeCityStates = false
|
class DiplomacyTabPersistableData(
|
||||||
|
var includeCityStates: Boolean = false
|
||||||
|
) : EmpireOverviewTabPersistableData() {
|
||||||
|
override fun isEmpty() = !includeCityStates
|
||||||
|
}
|
||||||
|
override val persistableData = (persistedData as? DiplomacyTabPersistableData) ?: DiplomacyTabPersistableData()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
update()
|
update()
|
||||||
@ -25,9 +30,9 @@ class DiplomacyOverviewTable (
|
|||||||
|
|
||||||
fun update() {
|
fun update() {
|
||||||
clear()
|
clear()
|
||||||
val relevantCivs = viewingPlayer.gameInfo.civilizations
|
val relevantCivs = gameInfo.civilizations
|
||||||
.filter { !it.isBarbarian() && !it.isSpectator() && (includeCityStates || !it.isCityState()) }
|
.filter { !it.isBarbarian() && !it.isSpectator() && (persistableData.includeCityStates || !it.isCityState()) }
|
||||||
val diplomacyGroup = DiplomacyGroup(viewingPlayer, overviewScreen.centerAreaHeight, includeCityStates)
|
val diplomacyGroup = DiplomacyGroup(viewingPlayer, overviewScreen.centerAreaHeight, persistableData.includeCityStates)
|
||||||
val playerKnowsAndUndefeatedCivs = relevantCivs.filter { diplomacyGroup.playerKnows(it) && !it.isDefeated() }
|
val playerKnowsAndUndefeatedCivs = relevantCivs.filter { diplomacyGroup.playerKnows(it) && !it.isDefeated() }
|
||||||
val playerKnowsAndDefeatedCivs = relevantCivs.filter { diplomacyGroup.playerKnows(it) && it.isDefeated() }
|
val playerKnowsAndDefeatedCivs = relevantCivs.filter { diplomacyGroup.playerKnows(it) && it.isDefeated() }
|
||||||
if (playerKnowsAndUndefeatedCivs.size > 1)
|
if (playerKnowsAndUndefeatedCivs.size > 1)
|
||||||
@ -39,12 +44,14 @@ class DiplomacyOverviewTable (
|
|||||||
titleTable.add(viewingPlayer.civName.toLabel()).left().padRight(10f)
|
titleTable.add(viewingPlayer.civName.toLabel()).left().padRight(10f)
|
||||||
titleTable.add(viewingPlayer.calculateScoreBreakdown().values.sum().toInt().toLabel()).row()
|
titleTable.add(viewingPlayer.calculateScoreBreakdown().values.sum().toInt().toLabel()).row()
|
||||||
|
|
||||||
|
|
||||||
val civTableScrollPane = getCivTableScroll(relevantCivs, titleTable, playerKnowsAndUndefeatedCivs, playerKnowsAndDefeatedCivs)
|
val civTableScrollPane = getCivTableScroll(relevantCivs, titleTable, playerKnowsAndUndefeatedCivs, playerKnowsAndDefeatedCivs)
|
||||||
|
|
||||||
val toggleCityStatesButton = "City-States".toTextButton()
|
val toggleCityStatesButton = "City-States".toTextButton()
|
||||||
toggleCityStatesButton.color = if(includeCityStates) Color.RED else Color.GREEN
|
toggleCityStatesButton.color = if (persistableData.includeCityStates) Color.RED else Color.GREEN
|
||||||
toggleCityStatesButton.onClick { includeCityStates = !includeCityStates; update() }
|
toggleCityStatesButton.onClick {
|
||||||
|
persistableData.includeCityStates = !persistableData.includeCityStates
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
|
||||||
val floatingTable = Table()
|
val floatingTable = Table()
|
||||||
floatingTable.add(toggleCityStatesButton).row()
|
floatingTable.add(toggleCityStatesButton).row()
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
package com.unciv.ui.overviewscreen
|
||||||
|
|
||||||
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
|
import com.unciv.ui.utils.KeyCharAndCode
|
||||||
|
import com.unciv.ui.overviewscreen.EmpireOverviewTab.EmpireOverviewTabPersistableData
|
||||||
|
|
||||||
|
private typealias FactoryType = (CivilizationInfo, EmpireOverviewScreen, EmpireOverviewTabPersistableData?) -> EmpireOverviewTab
|
||||||
|
|
||||||
|
enum class EmpireOverviewTabState { Normal, Disabled, Hidden }
|
||||||
|
private typealias StateTesterType = (CivilizationInfo) -> EmpireOverviewTabState
|
||||||
|
private fun Boolean.toState(): EmpireOverviewTabState = if (this) EmpireOverviewTabState.Disabled else EmpireOverviewTabState.Normal
|
||||||
|
|
||||||
|
/** This controls which Tabs for the [EmpireOverviewScreen] exist and their order.
|
||||||
|
*
|
||||||
|
* To add a Tab, build a new [EmpireOverviewTab] subclass and fill out a new entry here, that's all.
|
||||||
|
* Note the enum value's name is used as Tab caption, so if you ever need a non-alphanumeric caption please redesign to include a property for the caption.
|
||||||
|
*/
|
||||||
|
enum class EmpireOverviewCategories(
|
||||||
|
val iconName: String,
|
||||||
|
val shortcutKey: KeyCharAndCode,
|
||||||
|
val factory: FactoryType,
|
||||||
|
val stateTester: StateTesterType
|
||||||
|
) {
|
||||||
|
Cities("OtherIcons/Cities", 'C',
|
||||||
|
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?)
|
||||||
|
= CityOverviewTab(viewingPlayer, overviewScreen, persistedData),
|
||||||
|
fun (viewingPlayer: CivilizationInfo) = viewingPlayer.cities.isEmpty().toState()),
|
||||||
|
Stats("StatIcons/Gold", 'S',
|
||||||
|
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, _: EmpireOverviewTabPersistableData?)
|
||||||
|
= StatsOverviewTab(viewingPlayer, overviewScreen),
|
||||||
|
fun (_: CivilizationInfo) = EmpireOverviewTabState.Normal),
|
||||||
|
Trades("StatIcons/Acquire", 'T',
|
||||||
|
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, _: EmpireOverviewTabPersistableData?)
|
||||||
|
= TradesOverviewTab(viewingPlayer, overviewScreen),
|
||||||
|
fun (viewingPlayer: CivilizationInfo) = viewingPlayer.diplomacy.values.all { it.trades.isEmpty() }.toState()),
|
||||||
|
Units("OtherIcons/Shield", 'U',
|
||||||
|
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, _: EmpireOverviewTabPersistableData?)
|
||||||
|
= UnitOverviewTab(viewingPlayer, overviewScreen),
|
||||||
|
fun (viewingPlayer: CivilizationInfo) = viewingPlayer.getCivUnits().none().toState()),
|
||||||
|
Diplomacy("OtherIcons/DiplomacyW", 'D',
|
||||||
|
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?)
|
||||||
|
= DiplomacyOverviewTab(viewingPlayer, overviewScreen, persistedData),
|
||||||
|
fun (viewingPlayer: CivilizationInfo) = viewingPlayer.diplomacy.isEmpty().toState()),
|
||||||
|
Resources("StatIcons/Happiness", 'R',
|
||||||
|
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, _: EmpireOverviewTabPersistableData?)
|
||||||
|
= ResourcesOverviewTab(viewingPlayer, overviewScreen),
|
||||||
|
fun (viewingPlayer: CivilizationInfo) = viewingPlayer.detailedCivResources.isEmpty().toState()),
|
||||||
|
Religion("StatIcons/Faith", 'F',
|
||||||
|
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?)
|
||||||
|
= ReligionOverviewTab(viewingPlayer, overviewScreen, persistedData),
|
||||||
|
fun (viewingPlayer: CivilizationInfo) = when {
|
||||||
|
!viewingPlayer.gameInfo.isReligionEnabled() -> EmpireOverviewTabState.Hidden
|
||||||
|
viewingPlayer.gameInfo.religions.isEmpty() -> EmpireOverviewTabState.Disabled
|
||||||
|
else -> EmpireOverviewTabState.Normal
|
||||||
|
}),
|
||||||
|
Wonders("OtherIcons/Wonders", 'W',
|
||||||
|
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, _: EmpireOverviewTabPersistableData?)
|
||||||
|
= WonderOverviewTab(viewingPlayer, overviewScreen),
|
||||||
|
fun (viewingPlayer: CivilizationInfo) = (viewingPlayer.naturalWonders.isEmpty() && viewingPlayer.cities.isEmpty()).toState()),
|
||||||
|
;
|
||||||
|
|
||||||
|
constructor(iconName: String, shortcutChar: Char, factory: FactoryType, stateTester: StateTesterType = { _ -> EmpireOverviewTabState.Normal })
|
||||||
|
: this(iconName, KeyCharAndCode(shortcutChar), factory, stateTester)
|
||||||
|
}
|
||||||
|
|
@ -1,73 +1,37 @@
|
|||||||
package com.unciv.ui.overviewscreen
|
package com.unciv.ui.overviewscreen
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
|
||||||
import com.badlogic.gdx.utils.Align
|
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.ui.overviewscreen.EmpireOverviewTab.EmpireOverviewTabPersistableData
|
||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.BaseScreen
|
||||||
import com.unciv.ui.utils.KeyPressDispatcher.Companion.keyboardAvailable
|
import com.unciv.ui.utils.ImageGetter
|
||||||
import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip
|
import com.unciv.ui.utils.TabbedPager
|
||||||
import com.unciv.ui.utils.AutoScrollPane as ScrollPane
|
|
||||||
|
|
||||||
class EmpireOverviewScreen(
|
class EmpireOverviewScreen(
|
||||||
private var viewingPlayer: CivilizationInfo,
|
private var viewingPlayer: CivilizationInfo,
|
||||||
defaultPage: String = ""
|
defaultPage: String = ""
|
||||||
) : BaseScreen() {
|
) : BaseScreen() {
|
||||||
private val topTable = Table().apply { defaults().pad(10f) }
|
|
||||||
private val centerTable = Table().apply { defaults().pad(5f) }
|
|
||||||
|
|
||||||
internal val setCategoryActions = HashMap<String, () -> Unit>()
|
|
||||||
private val categoryButtons = HashMap<String, Button>()
|
|
||||||
|
|
||||||
// 50 normal button height + 2*10 topTable padding + 2 Separator + 2*5 centerTable padding
|
// 50 normal button height + 2*10 topTable padding + 2 Separator + 2*5 centerTable padding
|
||||||
// Since a resize recreates this screen this should be fine as a val
|
// Since a resize recreates this screen this should be fine as a val
|
||||||
internal val centerAreaHeight = stage.height - 82f
|
internal val centerAreaHeight = stage.height - 82f
|
||||||
|
|
||||||
private object ButtonDecorations {
|
private val tabbedPager: TabbedPager
|
||||||
data class IconAndKey (val icon: String, val key: Char = Char.MIN_VALUE)
|
private val pageObjects = HashMap<EmpireOverviewCategories, EmpireOverviewTab>()
|
||||||
val keyIconMap: HashMap<String,IconAndKey> = hashMapOf(
|
|
||||||
Pair("Cities", IconAndKey("OtherIcons/Cities", 'C')),
|
companion object {
|
||||||
Pair("Stats", IconAndKey("StatIcons/Gold", 'S')),
|
// This is what keeps per-tab states between overview invocations
|
||||||
Pair("Trades", IconAndKey("StatIcons/Acquire", 'T')),
|
var persistState: Map<EmpireOverviewCategories, EmpireOverviewTabPersistableData>? = null
|
||||||
Pair("Units", IconAndKey("OtherIcons/Shield", 'U')),
|
|
||||||
Pair("Diplomacy", IconAndKey("OtherIcons/DiplomacyW", 'D')),
|
private fun updatePersistState(pageObjects: HashMap<EmpireOverviewCategories, EmpireOverviewTab>) {
|
||||||
Pair("Resources", IconAndKey("StatIcons/Happiness", 'R')),
|
persistState = pageObjects.mapValues { it.value.persistableData }.filterNot { it.value.isEmpty() }
|
||||||
Pair("Religion", IconAndKey("StatIcons/Faith", 'F')),
|
}
|
||||||
Pair("Wonders", IconAndKey("OtherIcons/Wonders", 'W'))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addCategory(name: String, table: Table, disabled: Boolean = false) {
|
override fun dispose() {
|
||||||
// Buttons now hold their old label plus optionally an indicator for the shortcut key.
|
tabbedPager.selectPage(-1)
|
||||||
// Implement this templated on UnitActionsTable.getUnitActionButton()
|
updatePersistState(pageObjects)
|
||||||
val iconAndKey = ButtonDecorations.keyIconMap[name] ?: return // category without decoration entry disappears
|
super.dispose()
|
||||||
val setCategoryAction = {
|
|
||||||
centerTable.clear()
|
|
||||||
centerTable.add(ScrollPane(table).apply { setOverscroll(false, false) })
|
|
||||||
.height(centerAreaHeight)
|
|
||||||
.width(stage.width)
|
|
||||||
centerTable.pack()
|
|
||||||
for ((key, categoryButton) in categoryButtons.filterNot { it.value.touchable == Touchable.disabled })
|
|
||||||
categoryButton.color = if (key == name) Color.BLUE else Color.WHITE
|
|
||||||
if (name == "Stats")
|
|
||||||
game.settings.addCompletedTutorialTask("See your stats breakdown")
|
|
||||||
game.settings.lastOverviewPage = name
|
|
||||||
}
|
|
||||||
val icon = if (iconAndKey.icon != "") ImageGetter.getImage(iconAndKey.icon) else null
|
|
||||||
val button = IconTextButton(name, icon)
|
|
||||||
if (!disabled && keyboardAvailable && iconAndKey.key != Char.MIN_VALUE) {
|
|
||||||
button.addTooltip(iconAndKey.key)
|
|
||||||
keyPressDispatcher[iconAndKey.key] = setCategoryAction
|
|
||||||
}
|
|
||||||
setCategoryActions[name] = setCategoryAction
|
|
||||||
categoryButtons[name] = button
|
|
||||||
button.onClick(setCategoryAction)
|
|
||||||
if (disabled) button.disable()
|
|
||||||
topTable.add(button)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -77,76 +41,59 @@ class EmpireOverviewScreen(
|
|||||||
defaultPage
|
defaultPage
|
||||||
}
|
}
|
||||||
else game.settings.lastOverviewPage
|
else game.settings.lastOverviewPage
|
||||||
|
val iconSize = Constants.defaultFontSize.toFloat()
|
||||||
|
|
||||||
onBackButtonClicked { game.setWorldScreen() }
|
onBackButtonClicked { game.setWorldScreen() }
|
||||||
|
|
||||||
addCategory("Cities", CityOverviewTable(viewingPlayer, this), viewingPlayer.cities.isEmpty())
|
tabbedPager = TabbedPager(
|
||||||
addCategory("Stats", StatsOverviewTable(viewingPlayer, this))
|
stage.width, stage.width,
|
||||||
addCategory("Trades", TradesOverviewTable(viewingPlayer, this), viewingPlayer.diplomacy.values.all { it.trades.isEmpty() })
|
centerAreaHeight, centerAreaHeight,
|
||||||
addCategory("Units", UnitOverviewTable(viewingPlayer, this), viewingPlayer.getCivUnits().none())
|
separatorColor = Color.WHITE,
|
||||||
addCategory("Diplomacy", DiplomacyOverviewTable(viewingPlayer, this), viewingPlayer.diplomacy.isEmpty())
|
keyPressDispatcher = keyPressDispatcher,
|
||||||
addCategory("Resources", ResourcesOverviewTable(viewingPlayer, this), viewingPlayer.detailedCivResources.isEmpty())
|
capacity = EmpireOverviewCategories.values().size)
|
||||||
if (viewingPlayer.gameInfo.isReligionEnabled())
|
|
||||||
addCategory("Religion", ReligionOverviewTable(viewingPlayer, this), viewingPlayer.gameInfo.religions.isEmpty())
|
|
||||||
addCategory("Wonders", WonderOverviewTable(viewingPlayer, this), viewingPlayer.naturalWonders.isEmpty() && viewingPlayer.cities.isEmpty())
|
|
||||||
|
|
||||||
val closeButton = Constants.close.toTextButton().apply {
|
tabbedPager.addPage(Constants.close) {
|
||||||
setColor(0.75f, 0.1f, 0.1f, 1f)
|
_, _ -> game.setWorldScreen()
|
||||||
}
|
}
|
||||||
closeButton.onClick { game.setWorldScreen() }
|
tabbedPager.getPageButton(0).setColor(0.75f, 0.1f, 0.1f, 1f)
|
||||||
closeButton.y = stage.height - closeButton.height - 5
|
|
||||||
topTable.add(closeButton)
|
|
||||||
|
|
||||||
topTable.pack()
|
for (category in EmpireOverviewCategories.values()) {
|
||||||
val topScroll = ScrollPane(topTable).apply { setScrollingDisabled(false, true) }
|
val tabState = category.stateTester(viewingPlayer)
|
||||||
|
if (tabState == EmpireOverviewTabState.Hidden) continue
|
||||||
|
val icon = if (category.iconName.isEmpty()) null else ImageGetter.getImage(category.iconName)
|
||||||
|
val pageObject = category.factory(viewingPlayer, this, persistState?.get(category))
|
||||||
|
pageObject.pad(10f, 0f, 10f, 0f)
|
||||||
|
pageObjects[category] = pageObject
|
||||||
|
val index = tabbedPager.addPage(
|
||||||
|
caption = category.name,
|
||||||
|
content = pageObject,
|
||||||
|
icon, iconSize,
|
||||||
|
disabled = tabState != EmpireOverviewTabState.Normal,
|
||||||
|
shortcutKey = category.shortcutKey,
|
||||||
|
fixedContent = pageObject.getFixedContent(),
|
||||||
|
onDeactivation = { _, _, scrollY -> pageObject.deactivated(scrollY) }
|
||||||
|
) {
|
||||||
|
index, name ->
|
||||||
|
val scrollY = pageObject.activated()
|
||||||
|
if (scrollY != null) tabbedPager.setPageScrollY(index, scrollY)
|
||||||
|
if (name == "Stats")
|
||||||
|
game.settings.addCompletedTutorialTask("See your stats breakdown")
|
||||||
|
game.settings.lastOverviewPage = name
|
||||||
|
}
|
||||||
|
if (category.name == page)
|
||||||
|
tabbedPager.selectPage(index)
|
||||||
|
}
|
||||||
|
|
||||||
setCategoryActions[page]?.invoke()
|
tabbedPager.setFillParent(true)
|
||||||
|
stage.addActor(tabbedPager)
|
||||||
val table = Table()
|
}
|
||||||
table.add(topScroll).row()
|
|
||||||
table.addSeparator()
|
|
||||||
table.add(centerTable).height(stage.height - topTable.height).expand().row()
|
|
||||||
table.setFillParent(true)
|
|
||||||
stage.addActor(table)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun resize(width: Int, height: Int) {
|
override fun resize(width: Int, height: Int) {
|
||||||
if (stage.viewport.screenWidth != width || stage.viewport.screenHeight != height) {
|
if (stage.viewport.screenWidth != width || stage.viewport.screenHeight != height) {
|
||||||
|
updatePersistState(pageObjects)
|
||||||
game.setScreen(EmpireOverviewScreen(viewingPlayer, game.settings.lastOverviewPage))
|
game.setScreen(EmpireOverviewScreen(viewingPlayer, game.settings.lastOverviewPage))
|
||||||
|
dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo this belongs in VictoryScreen as it's only ever used there
|
|
||||||
companion object {
|
|
||||||
fun getCivGroup(civ: CivilizationInfo, afterCivNameText:String, currentPlayer:CivilizationInfo): Table {
|
|
||||||
val civGroup = Table()
|
|
||||||
|
|
||||||
var labelText = civ.civName.tr()+afterCivNameText
|
|
||||||
var labelColor = Color.WHITE
|
|
||||||
val backgroundColor: Color
|
|
||||||
|
|
||||||
if (civ.isDefeated()) {
|
|
||||||
civGroup.add(ImageGetter.getImage("OtherIcons/DisbandUnit")).size(30f)
|
|
||||||
backgroundColor = Color.LIGHT_GRAY
|
|
||||||
labelColor = Color.BLACK
|
|
||||||
} else if (currentPlayer == civ // || game.viewEntireMapForDebug
|
|
||||||
|| currentPlayer.knows(civ) || currentPlayer.isDefeated() || currentPlayer.victoryManager.hasWon()) {
|
|
||||||
civGroup.add(ImageGetter.getNationIndicator(civ.nation, 30f))
|
|
||||||
backgroundColor = civ.nation.getOuterColor()
|
|
||||||
labelColor = civ.nation.getInnerColor()
|
|
||||||
} else {
|
|
||||||
civGroup.add(ImageGetter.getRandomNationIndicator(30f))
|
|
||||||
backgroundColor = Color.DARK_GRAY
|
|
||||||
labelText = Constants.unknownNationName
|
|
||||||
}
|
|
||||||
|
|
||||||
civGroup.background = ImageGetter.getRoundedEdgeRectangle(backgroundColor)
|
|
||||||
val label = labelText.toLabel(labelColor)
|
|
||||||
label.setAlignment(Align.center)
|
|
||||||
|
|
||||||
civGroup.add(label).padLeft(10f)
|
|
||||||
civGroup.pack()
|
|
||||||
return civGroup
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
40
core/src/com/unciv/ui/overviewscreen/EmpireOverviewTab.kt
Normal file
40
core/src/com/unciv/ui/overviewscreen/EmpireOverviewTab.kt
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package com.unciv.ui.overviewscreen
|
||||||
|
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup
|
||||||
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
|
import com.unciv.ui.utils.BaseScreen
|
||||||
|
|
||||||
|
abstract class EmpireOverviewTab (
|
||||||
|
val viewingPlayer: CivilizationInfo,
|
||||||
|
val overviewScreen: EmpireOverviewScreen,
|
||||||
|
persistedData: EmpireOverviewTabPersistableData? = null
|
||||||
|
) : Table(BaseScreen.skin) {
|
||||||
|
open class EmpireOverviewTabPersistableData {
|
||||||
|
open fun isEmpty() = true
|
||||||
|
}
|
||||||
|
open val persistableData = persistedData ?: EmpireOverviewTabPersistableData()
|
||||||
|
/** Override if your Tab needs to do stuff on activation. @return non-null to scroll the Tab vertically within the TabbedPager. */
|
||||||
|
open fun activated(): Float? = null
|
||||||
|
/** Override if your Tab needs to do housekeeping when it loses focus. [scrollY] is the Tab's current vertical scroll position. */
|
||||||
|
open fun deactivated(scrollY: Float) {}
|
||||||
|
/** Override to supply content not participating in scrolling */
|
||||||
|
open fun getFixedContent(): WidgetGroup? = null
|
||||||
|
|
||||||
|
val gameInfo = viewingPlayer.gameInfo
|
||||||
|
|
||||||
|
protected fun equalizeColumns(vararg tables: Table) {
|
||||||
|
val columns = tables.first().columns
|
||||||
|
val widths = (0 until columns)
|
||||||
|
.mapTo(ArrayList(columns)) { column ->
|
||||||
|
tables.maxOf { it.getColumnWidth(column) }
|
||||||
|
}
|
||||||
|
for (table in tables) {
|
||||||
|
for (column in 0 until columns)
|
||||||
|
table.cells[column].run {
|
||||||
|
minWidth(widths[column] - padLeft - padRight)
|
||||||
|
}
|
||||||
|
table.invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,20 +17,23 @@ import com.unciv.ui.civilopedia.MarkupRenderer
|
|||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.*
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
class ReligionOverviewTable(
|
class ReligionOverviewTab(
|
||||||
private val viewingPlayer: CivilizationInfo,
|
viewingPlayer: CivilizationInfo,
|
||||||
private val overviewScreen: EmpireOverviewScreen
|
overviewScreen: EmpireOverviewScreen,
|
||||||
): Table() {
|
persistedData: EmpireOverviewTabPersistableData? = null
|
||||||
|
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
|
||||||
|
class ReligionTabPersistableData(
|
||||||
|
var selectedReligion: String? = null
|
||||||
|
) : EmpireOverviewTabPersistableData() {
|
||||||
|
override fun isEmpty() = selectedReligion == null
|
||||||
|
}
|
||||||
|
override val persistableData = (persistedData as? ReligionTabPersistableData) ?: ReligionTabPersistableData()
|
||||||
|
|
||||||
val gameInfo = viewingPlayer.gameInfo
|
private val civStatsTable = Table()
|
||||||
|
private val religionButtons = Table()
|
||||||
private val civStatsTable = Table(BaseScreen.skin)
|
|
||||||
private val religionButtons = Table(BaseScreen.skin)
|
|
||||||
private val religionButtonLabel = "Click an icon to see the stats of this religion".toLabel()
|
private val religionButtonLabel = "Click an icon to see the stats of this religion".toLabel()
|
||||||
private val statsTable = Table(BaseScreen.skin)
|
private val statsTable = Table()
|
||||||
private val beliefsTable = Table(BaseScreen.skin)
|
private val beliefsTable = Table()
|
||||||
|
|
||||||
private var selectedReligion: String? = null
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
defaults().pad(5f)
|
defaults().pad(5f)
|
||||||
@ -38,14 +41,15 @@ class ReligionOverviewTable(
|
|||||||
loadReligionButtons()
|
loadReligionButtons()
|
||||||
|
|
||||||
civStatsTable.defaults().left().pad(5f)
|
civStatsTable.defaults().left().pad(5f)
|
||||||
|
statsTable.defaults().left().pad(5f)
|
||||||
|
beliefsTable.defaults().padBottom(20f)
|
||||||
civStatsTable.addCivSpecificStats()
|
civStatsTable.addCivSpecificStats()
|
||||||
add(civStatsTable).row()
|
add(civStatsTable).row()
|
||||||
add(religionButtons).row()
|
add(religionButtons).row()
|
||||||
add(religionButtonLabel)
|
add(religionButtonLabel)
|
||||||
addSeparator()
|
addSeparator()
|
||||||
statsTable.defaults().left().pad(5f)
|
loadReligion(persistableData.selectedReligion)
|
||||||
add(statsTable).row()
|
add(statsTable).row()
|
||||||
beliefsTable.defaults().padBottom(20f)
|
|
||||||
add(beliefsTable).pad(20f)
|
add(beliefsTable).pad(20f)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,18 +89,23 @@ class ReligionOverviewTable(
|
|||||||
val button = Button(image, BaseScreen.skin)
|
val button = Button(image, BaseScreen.skin)
|
||||||
|
|
||||||
button.onClick {
|
button.onClick {
|
||||||
selectedReligion = religion.name
|
persistableData.selectedReligion = religion.name
|
||||||
loadReligionButtons()
|
loadReligionButtons()
|
||||||
loadReligion(religion)
|
loadReligion(religion)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedReligion == religion.name)
|
if (persistableData.selectedReligion == religion.name)
|
||||||
button.disable()
|
button.disable()
|
||||||
|
|
||||||
religionButtons.add(button).pad(5f)
|
religionButtons.add(button).pad(5f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadReligion(religionName: String?) {
|
||||||
|
if (religionName == null) return
|
||||||
|
val religion = gameInfo.religions[religionName] ?: return
|
||||||
|
loadReligion(religion)
|
||||||
|
}
|
||||||
private fun loadReligion(religion: Religion) {
|
private fun loadReligion(religion: Religion) {
|
||||||
statsTable.clear()
|
statsTable.clear()
|
||||||
beliefsTable.clear()
|
beliefsTable.clear()
|
||||||
|
@ -11,11 +11,10 @@ import com.unciv.ui.utils.addSeparator
|
|||||||
import com.unciv.ui.utils.onClick
|
import com.unciv.ui.utils.onClick
|
||||||
import com.unciv.ui.utils.toLabel
|
import com.unciv.ui.utils.toLabel
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER") // Keep all OverviewScreen Pages compatible
|
class ResourcesOverviewTab(
|
||||||
class ResourcesOverviewTable (
|
|
||||||
viewingPlayer: CivilizationInfo,
|
viewingPlayer: CivilizationInfo,
|
||||||
overviewScreen: EmpireOverviewScreen
|
overviewScreen: EmpireOverviewScreen
|
||||||
) : Table() {
|
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
defaults().pad(10f)
|
defaults().pad(10f)
|
||||||
|
@ -6,145 +6,150 @@ import com.unciv.Constants
|
|||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
import com.unciv.models.ruleset.ModOptionsConstants
|
import com.unciv.models.ruleset.ModOptionsConstants
|
||||||
|
import com.unciv.models.stats.Stat
|
||||||
|
import com.unciv.models.stats.StatMap
|
||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.*
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class StatsOverviewTable (
|
class StatsOverviewTab(
|
||||||
private val viewingPlayer: CivilizationInfo,
|
viewingPlayer: CivilizationInfo,
|
||||||
private val overviewScreen: EmpireOverviewScreen
|
overviewScreen: EmpireOverviewScreen
|
||||||
) : Table() {
|
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
|
||||||
|
private val happinessTable = Table()
|
||||||
|
private val goldAndSliderTable = Table()
|
||||||
|
private val goldTable = Table()
|
||||||
|
private val scienceTable = Table()
|
||||||
|
private val greatPeopleTable = Table()
|
||||||
|
private val scoreTable = Table()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
defaults().pad(40f)
|
val tablePadding = 30f // Padding around each of the stat tables
|
||||||
add(getHappinessTable()).top()
|
defaults().pad(tablePadding).top()
|
||||||
add(getGoldTable()).top()
|
|
||||||
add(getScienceTable()).top()
|
|
||||||
add(getGreatPeopleTable()).top()
|
|
||||||
add(getScoreTable()).top()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getHappinessTable(): Table {
|
|
||||||
val happinessTable = Table(BaseScreen.skin)
|
|
||||||
happinessTable.defaults().pad(5f)
|
happinessTable.defaults().pad(5f)
|
||||||
happinessTable.add("Happiness".toLabel(fontSize = Constants.headingFontSize)).colspan(2).row()
|
|
||||||
happinessTable.addSeparator()
|
|
||||||
|
|
||||||
val happinessBreakdown = viewingPlayer.stats().getHappinessBreakdown()
|
|
||||||
|
|
||||||
for (entry in happinessBreakdown.filterNot { it.value.roundToInt()==0 }) {
|
|
||||||
happinessTable.add(entry.key.toLabel())
|
|
||||||
happinessTable.add(entry.value.roundToInt().toString()).right().row()
|
|
||||||
}
|
|
||||||
happinessTable.add("Total".toLabel())
|
|
||||||
happinessTable.add(happinessBreakdown.values.sum().roundToInt().toString()).right()
|
|
||||||
happinessTable.pack()
|
|
||||||
return happinessTable
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getGoldTable(): Table {
|
|
||||||
val goldTable = Table(BaseScreen.skin)
|
|
||||||
goldTable.defaults().pad(5f)
|
goldTable.defaults().pad(5f)
|
||||||
goldTable.add("Gold".toLabel(fontSize = Constants.headingFontSize)).colspan(2).row()
|
|
||||||
goldTable.addSeparator()
|
|
||||||
var total = 0f
|
|
||||||
for (entry in viewingPlayer.stats().getStatMapForNextTurn()) {
|
|
||||||
if (entry.value.gold == 0f) continue
|
|
||||||
goldTable.add(entry.key.toLabel())
|
|
||||||
goldTable.add(entry.value.gold.roundToInt().toString()).right().row()
|
|
||||||
total += entry.value.gold
|
|
||||||
}
|
|
||||||
goldTable.add("Total".toLabel())
|
|
||||||
goldTable.add(total.roundToInt().toString()).right()
|
|
||||||
|
|
||||||
if (viewingPlayer.gameInfo.ruleSet.modOptions.uniques.contains(ModOptionsConstants.convertGoldToScience)) {
|
|
||||||
goldTable.addSeparator()
|
|
||||||
val sliderTable = Table()
|
|
||||||
sliderTable.add("Convert gold to science".toLabel()).row()
|
|
||||||
|
|
||||||
val slider = UncivSlider(0f, 1f, 0.1f,
|
|
||||||
initial = viewingPlayer.tech.goldPercentConvertedToScience,
|
|
||||||
getTipText = UncivSlider::formatPercent
|
|
||||||
) {
|
|
||||||
viewingPlayer.tech.goldPercentConvertedToScience = it
|
|
||||||
for (city in viewingPlayer.cities) { city.cityStats.update() }
|
|
||||||
overviewScreen.setCategoryActions["Stats"]!!() // ? will probably steal focus and so prevent dragging the slider
|
|
||||||
}
|
|
||||||
slider.isDisabled = !UncivGame.Current.worldScreen.canChangeState
|
|
||||||
|
|
||||||
sliderTable.add(slider).padTop(15f)
|
|
||||||
goldTable.add(sliderTable).colspan(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
goldTable.pack()
|
|
||||||
return goldTable
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getScienceTable(): Table {
|
|
||||||
val scienceTable = Table(BaseScreen.skin)
|
|
||||||
scienceTable.defaults().pad(5f)
|
scienceTable.defaults().pad(5f)
|
||||||
scienceTable.add("Science".toLabel(fontSize = Constants.headingFontSize)).colspan(2).row()
|
greatPeopleTable.defaults().pad(5f)
|
||||||
scienceTable.addSeparator()
|
scoreTable.defaults().pad(5f)
|
||||||
val scienceStats = viewingPlayer.stats().getStatMapForNextTurn()
|
|
||||||
.filter { it.value.science != 0f }
|
goldAndSliderTable.add(goldTable).row()
|
||||||
for (entry in scienceStats) {
|
if (gameInfo.ruleSet.modOptions.uniques.contains(ModOptionsConstants.convertGoldToScience))
|
||||||
scienceTable.add(entry.key.toLabel())
|
goldAndSliderTable.addGoldSlider()
|
||||||
scienceTable.add(entry.value.science.roundToInt().toString()).right().row()
|
|
||||||
}
|
update()
|
||||||
scienceTable.add("Total".toLabel())
|
|
||||||
scienceTable.add(scienceStats.map { it.value.science }.sum().roundToInt().toString()).right()
|
add(happinessTable)
|
||||||
scienceTable.pack()
|
add(goldAndSliderTable)
|
||||||
return scienceTable
|
add(scienceTable)
|
||||||
|
add(greatPeopleTable)
|
||||||
|
add(scoreTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getGreatPeopleTable(): Table {
|
fun update() {
|
||||||
val greatPeopleTable = Table(BaseScreen.skin)
|
val statMap = viewingPlayer.stats().getStatMapForNextTurn()
|
||||||
|
updateHappinessTable()
|
||||||
|
goldTable.updateStatTable(Stat.Gold, statMap)
|
||||||
|
scienceTable.updateStatTable(Stat.Science, statMap)
|
||||||
|
updateGreatPeopleTable()
|
||||||
|
updateScoreTable()
|
||||||
|
}
|
||||||
|
|
||||||
greatPeopleTable.defaults().pad(5f)
|
private fun Table.addHeading(label: String) {
|
||||||
val greatPeopleHeader = Table(BaseScreen.skin)
|
clear()
|
||||||
|
add(label.toLabel(fontSize = Constants.headingFontSize)).colspan(2).row()
|
||||||
|
addSeparator()
|
||||||
|
}
|
||||||
|
private fun Table.addLabeledValue(label: String, value: Float) {
|
||||||
|
val roundedValue = value.roundToInt()
|
||||||
|
if (roundedValue == 0) return
|
||||||
|
add(label.toLabel()).left()
|
||||||
|
add(roundedValue.toLabel()).right().row()
|
||||||
|
}
|
||||||
|
private fun Table.addTotal(value: Float) {
|
||||||
|
add("Total".toLabel()).left()
|
||||||
|
add(value.roundToInt().toLabel()).right()
|
||||||
|
pack()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateHappinessTable() = happinessTable.apply {
|
||||||
|
addHeading("Happiness")
|
||||||
|
val happinessBreakdown = viewingPlayer.stats().getHappinessBreakdown()
|
||||||
|
for ((key, value) in happinessBreakdown)
|
||||||
|
addLabeledValue(key, value)
|
||||||
|
addTotal(happinessBreakdown.values.sum())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Table.updateStatTable(stat: Stat, statMap: StatMap) {
|
||||||
|
addHeading(stat.name)
|
||||||
|
var total = 0f
|
||||||
|
for ((source, stats) in statMap) {
|
||||||
|
addLabeledValue(source, stats[stat])
|
||||||
|
total += stats[stat]
|
||||||
|
}
|
||||||
|
addTotal(total)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Table.addGoldSlider() {
|
||||||
|
addSeparator()
|
||||||
|
val sliderTable = Table()
|
||||||
|
sliderTable.add("Convert gold to science".toLabel()).row()
|
||||||
|
|
||||||
|
val slider = UncivSlider(0f, 1f, 0.1f,
|
||||||
|
initial = viewingPlayer.tech.goldPercentConvertedToScience,
|
||||||
|
getTipText = UncivSlider::formatPercent
|
||||||
|
) {
|
||||||
|
viewingPlayer.tech.goldPercentConvertedToScience = it
|
||||||
|
for (city in viewingPlayer.cities) { city.cityStats.update() }
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
slider.isDisabled = !UncivGame.Current.worldScreen.canChangeState
|
||||||
|
|
||||||
|
sliderTable.add(slider).padTop(15f)
|
||||||
|
add(sliderTable).colspan(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateGreatPeopleTable() = greatPeopleTable.apply {
|
||||||
|
clear()
|
||||||
|
val greatPeopleHeader = Table()
|
||||||
val greatPeopleIcon = ImageGetter.getStatIcon("Specialist")
|
val greatPeopleIcon = ImageGetter.getStatIcon("Specialist")
|
||||||
greatPeopleIcon.color = Color.ROYAL
|
greatPeopleIcon.color = Color.ROYAL
|
||||||
greatPeopleHeader.add(greatPeopleIcon).padRight(12f).size(30f)
|
greatPeopleHeader.add(greatPeopleIcon).padRight(1f).size(Constants.headingFontSize.toFloat())
|
||||||
greatPeopleHeader.add("Great person points".toLabel(fontSize = Constants.headingFontSize)).padTop(5f)
|
greatPeopleHeader.add("Great person points".toLabel(fontSize = Constants.headingFontSize))
|
||||||
greatPeopleTable.add(greatPeopleHeader).colspan(3).row()
|
add(greatPeopleHeader).colspan(3).row()
|
||||||
greatPeopleTable.addSeparator()
|
addSeparator()
|
||||||
greatPeopleTable.add()
|
add()
|
||||||
greatPeopleTable.add("Current points".toLabel())
|
add("Current points".toLabel())
|
||||||
greatPeopleTable.add("Points per turn".toLabel()).row()
|
add("Points per turn".toLabel()).row()
|
||||||
|
|
||||||
val greatPersonPoints = viewingPlayer.greatPeople.greatPersonPointsCounter
|
val greatPersonPoints = viewingPlayer.greatPeople.greatPersonPointsCounter
|
||||||
val greatPersonPointsPerTurn = viewingPlayer.getGreatPersonPointsForNextTurn()
|
val greatPersonPointsPerTurn = viewingPlayer.getGreatPersonPointsForNextTurn()
|
||||||
val pointsToGreatPerson = viewingPlayer.greatPeople.pointsForNextGreatPerson
|
val pointsToGreatPerson = viewingPlayer.greatPeople.pointsForNextGreatPerson
|
||||||
|
for ((greatPerson, points) in greatPersonPoints) {
|
||||||
for((greatPerson, points) in greatPersonPoints) {
|
add(greatPerson.toLabel()).left()
|
||||||
greatPeopleTable.add(greatPerson.toLabel())
|
add("$points/$pointsToGreatPerson".toLabel())
|
||||||
greatPeopleTable.add("$points/$pointsToGreatPerson")
|
add(greatPersonPointsPerTurn[greatPerson]!!.toLabel()).right().row()
|
||||||
greatPeopleTable.add(greatPersonPointsPerTurn[greatPerson].toString()).row()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val pointsForGreatGeneral = viewingPlayer.greatPeople.greatGeneralPoints
|
val pointsForGreatGeneral = viewingPlayer.greatPeople.greatGeneralPoints
|
||||||
val pointsForNextGreatGeneral = viewingPlayer.greatPeople.pointsForNextGreatGeneral
|
val pointsForNextGreatGeneral = viewingPlayer.greatPeople.pointsForNextGreatGeneral
|
||||||
greatPeopleTable.add("Great General".toLabel())
|
add("Great General".toLabel()).left()
|
||||||
greatPeopleTable.add("$pointsForGreatGeneral/$pointsForNextGreatGeneral").row()
|
add("$pointsForGreatGeneral/$pointsForNextGreatGeneral".toLabel())
|
||||||
greatPeopleTable.pack()
|
pack()
|
||||||
return greatPeopleTable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getScoreTable(): Table {
|
private fun updateScoreTable() = scoreTable.apply {
|
||||||
val scoreTableHeader = Table(BaseScreen.skin)
|
clear()
|
||||||
scoreTableHeader.add("Score".toLabel(fontSize = Constants.headingFontSize)).padBottom(6f)
|
val scoreHeader = Table()
|
||||||
|
val scoreIcon = ImageGetter.getImage("OtherIcons/Cultured")
|
||||||
val scoreTable = Table(BaseScreen.skin)
|
scoreIcon.color = Color.FIREBRICK
|
||||||
scoreTable.defaults().pad(5f)
|
scoreHeader.add(scoreIcon).padRight(1f).size(Constants.headingFontSize.toFloat())
|
||||||
scoreTable.add(scoreTableHeader).colspan(2).row()
|
scoreHeader.add("Score".toLabel(fontSize = Constants.headingFontSize))
|
||||||
scoreTable.addSeparator()
|
add(scoreHeader).colspan(2).row()
|
||||||
|
addSeparator()
|
||||||
val scoreBreakdown = viewingPlayer.calculateScoreBreakdown().filter { it.value != 0.0 }
|
|
||||||
for ((label, value) in scoreBreakdown) {
|
val scoreBreakdown = viewingPlayer.calculateScoreBreakdown()
|
||||||
scoreTable.add(label.toLabel())
|
for ((label, value) in scoreBreakdown)
|
||||||
scoreTable.add(value.toInt().toLabel()).row()
|
addLabeledValue(label, value.toFloat())
|
||||||
}
|
addTotal(scoreBreakdown.values.sum().toFloat())
|
||||||
|
|
||||||
scoreTable.add("Total".toLabel())
|
|
||||||
scoreTable.add(scoreBreakdown.values.sum().toInt().toLabel())
|
|
||||||
return scoreTable
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,14 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
|||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
import com.unciv.logic.trade.Trade
|
import com.unciv.logic.trade.Trade
|
||||||
import com.unciv.logic.trade.TradeOffersList
|
import com.unciv.logic.trade.TradeOffersList
|
||||||
import com.unciv.ui.utils.BaseScreen
|
|
||||||
import com.unciv.ui.utils.ImageGetter
|
import com.unciv.ui.utils.ImageGetter
|
||||||
import com.unciv.ui.utils.addSeparator
|
import com.unciv.ui.utils.addSeparator
|
||||||
import com.unciv.ui.utils.toLabel
|
import com.unciv.ui.utils.toLabel
|
||||||
|
|
||||||
class TradesOverviewTable (
|
class TradesOverviewTab(
|
||||||
private val viewingPlayer: CivilizationInfo,
|
viewingPlayer: CivilizationInfo,
|
||||||
private val overviewScreen: EmpireOverviewScreen
|
overviewScreen: EmpireOverviewScreen
|
||||||
) : Table() {
|
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
defaults().pad(10f)
|
defaults().pad(10f)
|
||||||
@ -28,14 +27,14 @@ class TradesOverviewTable (
|
|||||||
else -> -1
|
else -> -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(diplomacy in diplomacies) {
|
for (diplomacy in diplomacies) {
|
||||||
for (trade in diplomacy.trades)
|
for (trade in diplomacy.trades)
|
||||||
add(createTradeTable(trade, diplomacy.otherCiv())).row()
|
add(createTradeTable(trade, diplomacy.otherCiv())).row()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTradeTable(trade: Trade, otherCiv: CivilizationInfo): Table {
|
private fun createTradeTable(trade: Trade, otherCiv: CivilizationInfo): Table {
|
||||||
val generalTable = Table(BaseScreen.skin)
|
val generalTable = Table()
|
||||||
generalTable.add(createOffersTable(viewingPlayer, trade.ourOffers, trade.theirOffers.size)).minWidth(overviewScreen.stage.width/4).fillY()
|
generalTable.add(createOffersTable(viewingPlayer, trade.ourOffers, trade.theirOffers.size)).minWidth(overviewScreen.stage.width/4).fillY()
|
||||||
generalTable.add(createOffersTable(otherCiv, trade.theirOffers, trade.ourOffers.size)).minWidth(overviewScreen.stage.width/4).fillY()
|
generalTable.add(createOffersTable(otherCiv, trade.theirOffers, trade.ourOffers.size)).minWidth(overviewScreen.stage.width/4).fillY()
|
||||||
return generalTable
|
return generalTable
|
||||||
@ -47,12 +46,12 @@ class TradesOverviewTable (
|
|||||||
table.background = ImageGetter.getBackground(civ.nation.getOuterColor())
|
table.background = ImageGetter.getBackground(civ.nation.getOuterColor())
|
||||||
table.add(civ.civName.toLabel(civ.nation.getInnerColor())).row()
|
table.add(civ.civName.toLabel(civ.nation.getInnerColor())).row()
|
||||||
table.addSeparator()
|
table.addSeparator()
|
||||||
for(offer in offersList){
|
for (offer in offersList) {
|
||||||
var offerText = offer.getOfferText()
|
var offerText = offer.getOfferText()
|
||||||
if(!offerText.contains("\n")) offerText+="\n"
|
if (!offerText.contains("\n")) offerText += "\n"
|
||||||
table.add(offerText.toLabel(civ.nation.getInnerColor())).row()
|
table.add(offerText.toLabel(civ.nation.getInnerColor())).row()
|
||||||
}
|
}
|
||||||
for(i in 1..numberOfOtherSidesOffers - offersList.size)
|
for (i in 1..numberOfOtherSidesOffers - offersList.size)
|
||||||
table.add("\n".toLabel()).row() // we want both sides of the general table to have the same number of rows
|
table.add("\n".toLabel()).row() // we want both sides of the general table to have the same number of rows
|
||||||
return table
|
return table
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,10 @@ import kotlin.math.abs
|
|||||||
/**
|
/**
|
||||||
* Supplies the Unit sub-table for the Empire Overview
|
* Supplies the Unit sub-table for the Empire Overview
|
||||||
*/
|
*/
|
||||||
class UnitOverviewTable(
|
class UnitOverviewTab(
|
||||||
private val viewingPlayer: CivilizationInfo,
|
viewingPlayer: CivilizationInfo,
|
||||||
private val overviewScreen: EmpireOverviewScreen
|
overviewScreen: EmpireOverviewScreen
|
||||||
) : Table(BaseScreen.skin) {
|
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
add(getUnitSupplyTable()).top().padRight(25f)
|
add(getUnitSupplyTable()).top().padRight(25f)
|
||||||
|
@ -20,11 +20,10 @@ import com.unciv.ui.utils.ImageGetter
|
|||||||
import com.unciv.ui.utils.onClick
|
import com.unciv.ui.utils.onClick
|
||||||
import com.unciv.ui.utils.toLabel
|
import com.unciv.ui.utils.toLabel
|
||||||
|
|
||||||
class WonderOverviewTable(
|
class WonderOverviewTab(
|
||||||
private val viewingPlayer: CivilizationInfo,
|
viewingPlayer: CivilizationInfo,
|
||||||
@Suppress("unused") private val overviewScreen: EmpireOverviewScreen
|
overviewScreen: EmpireOverviewScreen
|
||||||
): Table() {
|
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
|
||||||
val gameInfo = viewingPlayer.gameInfo
|
|
||||||
val ruleSet = gameInfo.ruleSet
|
val ruleSet = gameInfo.ruleSet
|
||||||
|
|
||||||
private val hideReligionItems = !gameInfo.isReligionEnabled()
|
private val hideReligionItems = !gameInfo.isReligionEnabled()
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
package com.unciv.ui.utils
|
package com.unciv.ui.utils
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.graphics.g3d.model.Animation
|
||||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
import com.badlogic.gdx.scenes.scene2d.Group
|
import com.badlogic.gdx.scenes.scene2d.Group
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.*
|
import com.badlogic.gdx.scenes.scene2d.ui.*
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
|
import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Unimplemented ideas:
|
Unimplemented ideas:
|
||||||
Allow "fixed header" content that does not participate in scrolling
|
Use fixedContent for OptionsPopup mod check tab
|
||||||
(OptionsPopup mod check tab)
|
|
||||||
`scrollAlign: Align` property controls initial content scroll position (currently it's Align.top)
|
`scrollAlign: Align` property controls initial content scroll position (currently it's Align.top)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -30,6 +31,8 @@ import kotlin.math.min
|
|||||||
* area of added pages and set the reported pref-W/H to their maximum within these bounds. But, if a
|
* area of added pages and set the reported pref-W/H to their maximum within these bounds. But, if a
|
||||||
* maximum is not specified, that coordinate will grow with content unlimited, and layout max-W/H will
|
* maximum is not specified, that coordinate will grow with content unlimited, and layout max-W/H will
|
||||||
* always report the same as pref-W/H.
|
* always report the same as pref-W/H.
|
||||||
|
*
|
||||||
|
* [keyPressDispatcher] is optional and works with the `shortcutKey` parameter of [addPage] to support key bindings with tooltips.
|
||||||
*/
|
*/
|
||||||
//region Fields and initialization
|
//region Fields and initialization
|
||||||
@Suppress("MemberVisibilityCanBePrivate", "unused") // All member are part of our API
|
@Suppress("MemberVisibilityCanBePrivate", "unused") // All member are part of our API
|
||||||
@ -43,19 +46,23 @@ class TabbedPager(
|
|||||||
private val highlightColor: Color = Color.BLUE,
|
private val highlightColor: Color = Color.BLUE,
|
||||||
backgroundColor: Color = ImageGetter.getBlue().darken(0.5f),
|
backgroundColor: Color = ImageGetter.getBlue().darken(0.5f),
|
||||||
private val headerPadding: Float = 10f,
|
private val headerPadding: Float = 10f,
|
||||||
|
separatorColor: Color = Color.CLEAR,
|
||||||
|
private val keyPressDispatcher: KeyPressDispatcher? = null,
|
||||||
capacity: Int = 4
|
capacity: Int = 4
|
||||||
) : Table() {
|
) : Table() {
|
||||||
|
|
||||||
private class PageState(
|
private class PageState(
|
||||||
caption: String,
|
caption: String,
|
||||||
var content: Actor,
|
var content: Actor,
|
||||||
|
var fixedContent: WidgetGroup? = null,
|
||||||
var disabled: Boolean = false,
|
var disabled: Boolean = false,
|
||||||
val onActivation: ((Int, String)->Unit)? = null,
|
val onActivation: ((Int, String) -> Unit)? = null,
|
||||||
|
val onDeactivation: ((Int, String, Float) -> Unit)? = null,
|
||||||
icon: Actor? = null,
|
icon: Actor? = null,
|
||||||
iconSize: Float = 0f,
|
iconSize: Float = 0f,
|
||||||
|
val shortcutKey: KeyCharAndCode = KeyCharAndCode.UNKNOWN,
|
||||||
pager: TabbedPager
|
pager: TabbedPager
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var scrollX = 0f
|
var scrollX = 0f
|
||||||
var scrollY = 0f
|
var scrollY = 0f
|
||||||
|
|
||||||
@ -90,6 +97,7 @@ class TabbedPager(
|
|||||||
private var headerHeight = 0f
|
private var headerHeight = 0f
|
||||||
|
|
||||||
private val contentScroll = AutoScrollPane(null)
|
private val contentScroll = AutoScrollPane(null)
|
||||||
|
private val fixedContentWrapper = Container<WidgetGroup>()
|
||||||
|
|
||||||
private val deferredSecretPages = ArrayDeque<PageState>(0)
|
private val deferredSecretPages = ArrayDeque<PageState>(0)
|
||||||
private var askPasswordLock = false
|
private var askPasswordLock = false
|
||||||
@ -102,6 +110,9 @@ class TabbedPager(
|
|||||||
// Measure header height, most likely its final value
|
// Measure header height, most likely its final value
|
||||||
removePage(addPage("Dummy"))
|
removePage(addPage("Dummy"))
|
||||||
add(headerScroll).growX().minHeight(headerHeight).row()
|
add(headerScroll).growX().minHeight(headerHeight).row()
|
||||||
|
if (separatorColor != Color.CLEAR)
|
||||||
|
addSeparator(separatorColor)
|
||||||
|
add(fixedContentWrapper).growX().row()
|
||||||
add(contentScroll).grow().row()
|
add(contentScroll).grow().row()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +156,9 @@ class TabbedPager(
|
|||||||
if (index >= 0 && pages[index].disabled) return false
|
if (index >= 0 && pages[index].disabled) return false
|
||||||
if (activePage != -1) {
|
if (activePage != -1) {
|
||||||
pages[activePage].apply {
|
pages[activePage].apply {
|
||||||
|
onDeactivation?.invoke(activePage, button.name, contentScroll.scrollY)
|
||||||
button.color = Color.WHITE
|
button.color = Color.WHITE
|
||||||
|
fixedContentWrapper.actor = null
|
||||||
scrollX = contentScroll.scrollX
|
scrollX = contentScroll.scrollX
|
||||||
scrollY = contentScroll.scrollY
|
scrollY = contentScroll.scrollY
|
||||||
contentScroll.removeActor(content)
|
contentScroll.removeActor(content)
|
||||||
@ -155,6 +168,7 @@ class TabbedPager(
|
|||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
pages[index].apply {
|
pages[index].apply {
|
||||||
button.color = highlightColor
|
button.color = highlightColor
|
||||||
|
fixedContentWrapper.actor = fixedContent
|
||||||
contentScroll.actor = content
|
contentScroll.actor = content
|
||||||
contentScroll.layout()
|
contentScroll.layout()
|
||||||
if (scrollX < 0f) // was marked to center on first show
|
if (scrollX < 0f) // was marked to center on first show
|
||||||
@ -196,6 +210,19 @@ class TabbedPager(
|
|||||||
*/
|
*/
|
||||||
fun setPageDisabled(caption: String, disabled: Boolean) = setPageDisabled(getPageIndex(caption), disabled)
|
fun setPageDisabled(caption: String, disabled: Boolean) = setPageDisabled(getPageIndex(caption), disabled)
|
||||||
|
|
||||||
|
/** Access a page's header button e.g. for unusual formatting */
|
||||||
|
fun getPageButton(index: Int) = pages[index].button
|
||||||
|
|
||||||
|
/** Change the vertical scroll position af a page's contents */
|
||||||
|
fun setPageScrollY(index: Int, scrollY: Float, animation: Boolean = false) {
|
||||||
|
if (index !in 0 until pages.size) return
|
||||||
|
val page = pages[index]
|
||||||
|
page.scrollY = scrollY
|
||||||
|
if (index != activePage) return
|
||||||
|
contentScroll.scrollY = scrollY
|
||||||
|
if (!animation) contentScroll.updateVisualScroll()
|
||||||
|
}
|
||||||
|
|
||||||
/** Remove a page by its index.
|
/** Remove a page by its index.
|
||||||
* @return `true` if page successfully removed */
|
* @return `true` if page successfully removed */
|
||||||
fun removePage(index: Int): Boolean {
|
fun removePage(index: Int): Boolean {
|
||||||
@ -211,7 +238,7 @@ class TabbedPager(
|
|||||||
* @return `true` if page successfully removed */
|
* @return `true` if page successfully removed */
|
||||||
fun removePage(caption: String) = removePage(getPageIndex(caption))
|
fun removePage(caption: String) = removePage(getPageIndex(caption))
|
||||||
|
|
||||||
/** Replace a page's content by its index. */
|
/** Replace a page's [content] by its [index]. */
|
||||||
fun replacePage(index: Int, content: Actor) {
|
fun replacePage(index: Int, content: Actor) {
|
||||||
if (index !in 0 until pages.size) return
|
if (index !in 0 until pages.size) return
|
||||||
val isActive = index == activePage
|
val isActive = index == activePage
|
||||||
@ -219,9 +246,20 @@ class TabbedPager(
|
|||||||
pages[index].content = content
|
pages[index].content = content
|
||||||
if (isActive) selectPage(index)
|
if (isActive) selectPage(index)
|
||||||
}
|
}
|
||||||
|
/** Replace a page's [content] and [fixedContent] by its [index]. */
|
||||||
|
fun replacePage(index: Int, content: Actor, fixedContent: WidgetGroup?) {
|
||||||
|
if (index !in 0 until pages.size) return
|
||||||
|
val isActive = index == activePage
|
||||||
|
if (isActive) selectPage(-1)
|
||||||
|
pages[index].content = content
|
||||||
|
pages[index].fixedContent = fixedContent
|
||||||
|
if (isActive) selectPage(index)
|
||||||
|
}
|
||||||
|
|
||||||
/** Replace a page's content by its caption. */
|
/** Replace a page's [content] by its [caption]. */
|
||||||
fun replacePage(caption: String, content: Actor) = replacePage(getPageIndex(caption), content)
|
fun replacePage(caption: String, content: Actor) = replacePage(getPageIndex(caption), content)
|
||||||
|
/** Replace a page's [content] and [fixedContent] by its [caption]. */
|
||||||
|
fun replacePage(caption: String, content: Actor, fixedContent: WidgetGroup?) = replacePage(getPageIndex(caption), content, fixedContent)
|
||||||
|
|
||||||
/** Add a page!
|
/** Add a page!
|
||||||
* @param caption Text to be shown on the header button (automatically translated), can later be used to reference the page in other calls.
|
* @param caption Text to be shown on the header button (automatically translated), can later be used to reference the page in other calls.
|
||||||
@ -231,6 +269,9 @@ class TabbedPager(
|
|||||||
* @param insertBefore -1 to add at the end or index of existing page to insert this before
|
* @param insertBefore -1 to add at the end or index of existing page to insert this before
|
||||||
* @param secret Marks page as 'secret'. A password is asked once per [TabbedPager] and if it does not match the has passed in the constructor the page and all subsequent secret pages are dropped.
|
* @param secret Marks page as 'secret'. A password is asked once per [TabbedPager] and if it does not match the has passed in the constructor the page and all subsequent secret pages are dropped.
|
||||||
* @param disabled Initial disabled state. Disabled pages cannot be selected even with [selectPage], their button is dimmed.
|
* @param disabled Initial disabled state. Disabled pages cannot be selected even with [selectPage], their button is dimmed.
|
||||||
|
* @param shortcutKey Optional keyboard key to associate - goes to the [KeyPressDispatcher] passed in the constructor.
|
||||||
|
* @param fixedContent Optional second content [WidgetGroup], will be placed outside the tab's [ScrollPane] between header and [content].
|
||||||
|
* @param onDeactivation _Optional_ callback called when this page is hidden. Lambda arguments are page index and caption, and scrollY of the tab's [ScrollPane].
|
||||||
* @param onActivation _Optional_ callback called when this page is shown (per actual change to this page, not per header click). Lambda arguments are page index and caption.
|
* @param onActivation _Optional_ callback called when this page is shown (per actual change to this page, not per header click). Lambda arguments are page index and caption.
|
||||||
* @return The new page's index or -1 if it could not be immediately added (secret).
|
* @return The new page's index or -1 if it could not be immediately added (secret).
|
||||||
*/
|
*/
|
||||||
@ -242,16 +283,22 @@ class TabbedPager(
|
|||||||
insertBefore: Int = -1,
|
insertBefore: Int = -1,
|
||||||
secret: Boolean = false,
|
secret: Boolean = false,
|
||||||
disabled: Boolean = false,
|
disabled: Boolean = false,
|
||||||
onActivation: ((Int, String)->Unit)? = null
|
shortcutKey: KeyCharAndCode = KeyCharAndCode.UNKNOWN,
|
||||||
|
fixedContent: WidgetGroup? = null,
|
||||||
|
onDeactivation: ((Int, String, Float) -> Unit)? = null,
|
||||||
|
onActivation: ((Int, String) -> Unit)? = null
|
||||||
): Int {
|
): Int {
|
||||||
// Build page descriptor and header button
|
// Build page descriptor and header button
|
||||||
val page = PageState(
|
val page = PageState(
|
||||||
caption = caption,
|
caption = caption,
|
||||||
content = content ?: Group(),
|
content = content ?: Group(),
|
||||||
|
fixedContent = fixedContent,
|
||||||
disabled = disabled,
|
disabled = disabled,
|
||||||
onActivation = onActivation,
|
onActivation = onActivation,
|
||||||
|
onDeactivation = onDeactivation,
|
||||||
icon = icon,
|
icon = icon,
|
||||||
iconSize = iconSize,
|
iconSize = iconSize,
|
||||||
|
shortcutKey = shortcutKey,
|
||||||
pager = this
|
pager = this
|
||||||
)
|
)
|
||||||
page.button.apply {
|
page.button.apply {
|
||||||
@ -260,6 +307,7 @@ class TabbedPager(
|
|||||||
onClick {
|
onClick {
|
||||||
selectPage(page)
|
selectPage(page)
|
||||||
}
|
}
|
||||||
|
addTooltip(shortcutKey, if (iconSize > 0f) iconSize else 18f)
|
||||||
pack()
|
pack()
|
||||||
if (height + 2 * headerPadding > headerHeight) {
|
if (height + 2 * headerPadding > headerHeight) {
|
||||||
headerHeight = height + 2 * headerPadding
|
headerHeight = height + 2 * headerPadding
|
||||||
@ -310,6 +358,22 @@ class TabbedPager(
|
|||||||
|
|
||||||
private fun getPageIndex(page: PageState) = pages.indexOf(page)
|
private fun getPageIndex(page: PageState) = pages.indexOf(page)
|
||||||
|
|
||||||
|
private fun measureContent(group: WidgetGroup) {
|
||||||
|
group.packIfNeeded()
|
||||||
|
var needLayout = false
|
||||||
|
val contentWidth = min(group.width, limitWidth)
|
||||||
|
if (contentWidth > preferredWidth) {
|
||||||
|
preferredWidth = contentWidth
|
||||||
|
needLayout = true
|
||||||
|
}
|
||||||
|
val contentHeight = min(group.height, limitHeight)
|
||||||
|
if (contentHeight > preferredHeight) {
|
||||||
|
preferredHeight = contentHeight
|
||||||
|
needLayout = true
|
||||||
|
}
|
||||||
|
if (needLayout && activePage >= 0) invalidateHierarchy()
|
||||||
|
}
|
||||||
|
|
||||||
private fun addAndShowPage(page: PageState, insertBefore: Int): Int {
|
private fun addAndShowPage(page: PageState, insertBefore: Int): Int {
|
||||||
// Update pages array and header table
|
// Update pages array and header table
|
||||||
val newIndex: Int
|
val newIndex: Int
|
||||||
@ -330,23 +394,16 @@ class TabbedPager(
|
|||||||
pages[i].buttonX += page.buttonW
|
pages[i].buttonX += page.buttonW
|
||||||
|
|
||||||
// Content Sizing
|
// Content Sizing
|
||||||
if (page.content is WidgetGroup) {
|
if (page.fixedContent != null) measureContent(page.fixedContent!!)
|
||||||
(page.content as WidgetGroup).packIfNeeded()
|
(page.content as? WidgetGroup)?.let {
|
||||||
val contentWidth = min(page.content.width, limitWidth)
|
measureContent(it)
|
||||||
if (contentWidth > preferredWidth) {
|
|
||||||
preferredWidth = contentWidth
|
|
||||||
if (activePage >= 0) invalidateHierarchy()
|
|
||||||
}
|
|
||||||
val contentHeight = min(page.content.height, limitHeight)
|
|
||||||
if (contentHeight > preferredHeight) {
|
|
||||||
preferredHeight = contentHeight
|
|
||||||
if (activePage >= 0) invalidateHierarchy()
|
|
||||||
}
|
|
||||||
page.scrollX = -1f // mark to center later when all pages are measured
|
page.scrollX = -1f // mark to center later when all pages are measured
|
||||||
}
|
}
|
||||||
if (growMaxWidth) maximumWidth = minimumWidth
|
if (growMaxWidth) maximumWidth = minimumWidth
|
||||||
if (growMaxHeight) maximumHeight = minimumHeight
|
if (growMaxHeight) maximumHeight = minimumHeight
|
||||||
|
|
||||||
|
keyPressDispatcher?.set(page.shortcutKey) { selectPage(newIndex) }
|
||||||
|
|
||||||
return newIndex
|
return newIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,13 +13,12 @@ import com.unciv.models.translations.tr
|
|||||||
import com.unciv.models.metadata.GameSetupInfo
|
import com.unciv.models.metadata.GameSetupInfo
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.ui.newgamescreen.NewGameScreen
|
import com.unciv.ui.newgamescreen.NewGameScreen
|
||||||
import com.unciv.ui.overviewscreen.EmpireOverviewScreen
|
|
||||||
import com.unciv.ui.pickerscreens.PickerScreen
|
import com.unciv.ui.pickerscreens.PickerScreen
|
||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.*
|
||||||
import com.unciv.ui.worldscreen.WorldScreen
|
import com.unciv.ui.worldscreen.WorldScreen
|
||||||
|
|
||||||
class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() {
|
class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() {
|
||||||
|
|
||||||
val gameInfo = worldScreen.gameInfo
|
val gameInfo = worldScreen.gameInfo
|
||||||
private val playerCivInfo = worldScreen.viewingCiv
|
private val playerCivInfo = worldScreen.viewingCiv
|
||||||
val victoryTypes = gameInfo.gameParameters.victoryTypes
|
val victoryTypes = gameInfo.gameParameters.victoryTypes
|
||||||
@ -27,7 +26,6 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() {
|
|||||||
private val culturalVictoryEnabled = victoryTypes.contains(VictoryType.Cultural)
|
private val culturalVictoryEnabled = victoryTypes.contains(VictoryType.Cultural)
|
||||||
private val dominationVictoryEnabled = victoryTypes.contains(VictoryType.Domination)
|
private val dominationVictoryEnabled = victoryTypes.contains(VictoryType.Domination)
|
||||||
|
|
||||||
|
|
||||||
private val contentsTable = Table()
|
private val contentsTable = Table()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -193,10 +191,10 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() {
|
|||||||
dominationVictoryColumn.addSeparator()
|
dominationVictoryColumn.addSeparator()
|
||||||
|
|
||||||
for (civ in majorCivs.filter { !it.isDefeated() })
|
for (civ in majorCivs.filter { !it.isDefeated() })
|
||||||
dominationVictoryColumn.add(EmpireOverviewScreen.getCivGroup(civ, "", playerCivInfo)).fillX().row()
|
dominationVictoryColumn.add(getCivGroup(civ, "", playerCivInfo)).fillX().row()
|
||||||
|
|
||||||
for (civ in majorCivs.filter { it.isDefeated() })
|
for (civ in majorCivs.filter { it.isDefeated() })
|
||||||
dominationVictoryColumn.add(EmpireOverviewScreen.getCivGroup(civ, "", playerCivInfo)).fillX().row()
|
dominationVictoryColumn.add(getCivGroup(civ, "", playerCivInfo)).fillX().row()
|
||||||
|
|
||||||
return dominationVictoryColumn
|
return dominationVictoryColumn
|
||||||
}
|
}
|
||||||
@ -213,7 +211,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() {
|
|||||||
}.sortedByDescending { it.branchesCompleted }
|
}.sortedByDescending { it.branchesCompleted }
|
||||||
|
|
||||||
for (entry in civsToBranchesCompleted) {
|
for (entry in civsToBranchesCompleted) {
|
||||||
val civToBranchesHaveCompleted = EmpireOverviewScreen.getCivGroup(entry.civ, " - " + entry.branchesCompleted, playerCivInfo)
|
val civToBranchesHaveCompleted = getCivGroup(entry.civ, " - " + entry.branchesCompleted, playerCivInfo)
|
||||||
policyVictoryColumn.add(civToBranchesHaveCompleted).fillX().row()
|
policyVictoryColumn.add(civToBranchesHaveCompleted).fillX().row()
|
||||||
}
|
}
|
||||||
return policyVictoryColumn
|
return policyVictoryColumn
|
||||||
@ -232,7 +230,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (entry in civsToPartsRemaining) {
|
for (entry in civsToPartsRemaining) {
|
||||||
val civToPartsBeRemaining = (EmpireOverviewScreen.getCivGroup(entry.civ, " - " + entry.partsRemaining, playerCivInfo))
|
val civToPartsBeRemaining = (getCivGroup(entry.civ, " - " + entry.partsRemaining, playerCivInfo))
|
||||||
scientificVictoryColumn.add(civToPartsBeRemaining).fillX().row()
|
scientificVictoryColumn.add(civToPartsBeRemaining).fillX().row()
|
||||||
}
|
}
|
||||||
return scientificVictoryColumn
|
return scientificVictoryColumn
|
||||||
@ -248,7 +246,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() {
|
|||||||
column.addSeparator()
|
column.addSeparator()
|
||||||
|
|
||||||
for (civ in majorCivs.sortedByDescending { it.getStatForRanking(category) }) {
|
for (civ in majorCivs.sortedByDescending { it.getStatForRanking(category) }) {
|
||||||
column.add(EmpireOverviewScreen.getCivGroup(civ, ": " + civ.getStatForRanking(category).toString(), playerCivInfo)).fillX().row()
|
column.add(getCivGroup(civ, ": " + civ.getStatForRanking(category).toString(), playerCivInfo)).fillX().row()
|
||||||
}
|
}
|
||||||
|
|
||||||
civRankingsTable.add(column)
|
civRankingsTable.add(column)
|
||||||
@ -258,4 +256,36 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() {
|
|||||||
contentsTable.add(civRankingsTable)
|
contentsTable.add(civRankingsTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getCivGroup(civ: CivilizationInfo, afterCivNameText:String, currentPlayer:CivilizationInfo): Table {
|
||||||
|
val civGroup = Table()
|
||||||
|
|
||||||
|
var labelText = civ.civName.tr()+afterCivNameText
|
||||||
|
var labelColor = Color.WHITE
|
||||||
|
val backgroundColor: Color
|
||||||
|
|
||||||
|
if (civ.isDefeated()) {
|
||||||
|
civGroup.add(ImageGetter.getImage("OtherIcons/DisbandUnit")).size(30f)
|
||||||
|
backgroundColor = Color.LIGHT_GRAY
|
||||||
|
labelColor = Color.BLACK
|
||||||
|
} else if (currentPlayer == civ // || game.viewEntireMapForDebug
|
||||||
|
|| currentPlayer.knows(civ) || currentPlayer.isDefeated() || currentPlayer.victoryManager.hasWon()) {
|
||||||
|
civGroup.add(ImageGetter.getNationIndicator(civ.nation, 30f))
|
||||||
|
backgroundColor = civ.nation.getOuterColor()
|
||||||
|
labelColor = civ.nation.getInnerColor()
|
||||||
|
} else {
|
||||||
|
civGroup.add(ImageGetter.getRandomNationIndicator(30f))
|
||||||
|
backgroundColor = Color.DARK_GRAY
|
||||||
|
labelText = Constants.unknownNationName
|
||||||
|
}
|
||||||
|
|
||||||
|
civGroup.background = ImageGetter.getRoundedEdgeRectangle(backgroundColor)
|
||||||
|
val label = labelText.toLabel(labelColor)
|
||||||
|
label.setAlignment(Align.center)
|
||||||
|
|
||||||
|
civGroup.add(label).padLeft(10f)
|
||||||
|
civGroup.pack()
|
||||||
|
return civGroup
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user