Refactor: Extract PickerPane from PickerScreen (#6870)

Refactor: Extract PickerPane from PickerScreen
This commit is contained in:
Timo T 2022-05-20 21:23:25 +02:00 committed by GitHub
parent a2bc1a1a29
commit 5d835c762a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 122 additions and 80 deletions

View File

@ -19,7 +19,7 @@ class DiplomaticVotePickerScreen(private val votingCiv: CivilizationInfo) : Pick
val choosableCivs = votingCiv.gameInfo.civilizations.filter { it.isMajorCiv() && it != votingCiv && !it.isDefeated() } val choosableCivs = votingCiv.gameInfo.civilizations.filter { it.isMajorCiv() && it != votingCiv && !it.isDefeated() }
for (civ in choosableCivs) for (civ in choosableCivs)
{ {
val button = getPickerOptionButton(ImageGetter.getNationIndicator(civ.nation, pickerOptionIconSize), civ.civName) val button = PickerPane.getPickerOptionButton(ImageGetter.getNationIndicator(civ.nation, PickerPane.pickerOptionIconSize), civ.civName)
button.pack() button.pack()
button.onClick { button.onClick {
chosenCiv = civ.civName chosenCiv = civ.civName

View File

@ -19,7 +19,7 @@ class GreatPersonPickerScreen(val civInfo:CivilizationInfo) : PickerScreen() {
val useMayaLongCount = civInfo.greatPeople.mayaLimitedFreeGP > 0 val useMayaLongCount = civInfo.greatPeople.mayaLimitedFreeGP > 0
for (unit in greatPersonUnits) { for (unit in greatPersonUnits) {
val button = getPickerOptionButton(ImageGetter.getUnitIcon(unit.name), unit.name) val button = PickerPane.getPickerOptionButton(ImageGetter.getUnitIcon(unit.name), unit.name)
button.pack() button.pack()
button.isEnabled = !useMayaLongCount || unit.name in civInfo.greatPeople.longCountGPPool button.isEnabled = !useMayaLongCount || unit.name in civInfo.greatPeople.longCountGPPool
if (button.isEnabled) button.onClick { if (button.isEnabled) button.onClick {

View File

@ -131,7 +131,7 @@ class ImprovementPickerScreen(
regularImprovements.add(statIcons).align(Align.right) regularImprovements.add(statIcons).align(Align.right)
val improvementButton = getPickerOptionButton(image, labelText) val improvementButton = PickerPane.getPickerOptionButton(image, labelText)
improvementButton.onClick { improvementButton.onClick {
selectedImprovement = improvement selectedImprovement = improvement
pick(improvement.name.tr()) pick(improvement.name.tr())

View File

@ -375,7 +375,7 @@ class ModManagementScreen(
private fun onlineButtonAction(repo: Github.Repo, button: Button) { private fun onlineButtonAction(repo: Github.Repo, button: Button) {
syncOnlineSelected(repo.name, button) syncOnlineSelected(repo.name, button)
showModDescription(repo.name) showModDescription(repo.name)
removeRightSideClickListeners() rightSideButton.clearListeners()
rightSideButton.enable() rightSideButton.enable()
val label = if (installedModInfo[repo.name]?.state?.hasUpdate == true) val label = if (installedModInfo[repo.name]?.state?.hasUpdate == true)
"Update [${repo.name}]" "Update [${repo.name}]"
@ -519,7 +519,7 @@ class ModManagementScreen(
// Don't let the player think he can delete Vanilla and G&K rulesets // Don't let the player think he can delete Vanilla and G&K rulesets
rightSideButton.isEnabled = mod.ruleset.folderLocation!=null rightSideButton.isEnabled = mod.ruleset.folderLocation!=null
showModDescription(mod.name) showModDescription(mod.name)
removeRightSideClickListeners() rightSideButton.clearListeners()
rightSideButton.onClick { rightSideButton.onClick {
rightSideButton.isEnabled = false rightSideButton.isEnabled = false
YesNoPopup( YesNoPopup(

View File

@ -0,0 +1,85 @@
package com.unciv.ui.pickerscreens
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.ui.Button
import com.badlogic.gdx.scenes.scene2d.ui.SplitPane
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup
import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.ui.images.IconTextButton
import com.unciv.ui.utils.*
class PickerPane(
disableScroll: Boolean = false,
) : Table() {
/** The close button on the lower left of [bottomTable], see [setDefaultCloseAction] */
val closeButton = Constants.close.toTextButton()
/** A scrollable wrapped Label you can use to show descriptions in the [bottomTable], starts empty */
val descriptionLabel = "".toLabel()
/** A wrapper containing [rightSideButton]. You can add buttons, they will be arranged vertically */
val rightSideGroup = VerticalGroup()
/** A button on the lower right of [bottomTable] you can use for a "OK"-type action, starts disabled */
val rightSideButton = "".toTextButton()
private val screenSplit = 0.85f
private val maxBottomTableHeight = 150f // about 7 lines of normal text
/**
* The table displaying the choices from which to pick (usually).
* Also the element which most of the screen real estate is devoted to displaying.
*/
val topTable = Table()
/** Holds the [Close button][closeButton], a [description label][descriptionLabel] and an [action button][rightSideButton] */
val bottomTable = Table()
/** A ScrollPane scrolling [topTable], disabled by the disableScroll parameter */
val scrollPane = AutoScrollPane(topTable)
/** A fixed SplitPane holds [scrollPane] and [bottomTable] */
val splitPane = SplitPane(scrollPane, bottomTable, true, BaseScreen.skin)
init {
bottomTable.add(closeButton).pad(10f)
descriptionLabel.wrap = true
val labelScroll = AutoScrollPane(descriptionLabel, BaseScreen.skin)
bottomTable.add(labelScroll).pad(5f).fill().expand()
rightSideButton.disable()
rightSideGroup.addActor(rightSideButton)
bottomTable.add(rightSideGroup).pad(10f).right()
scrollPane.setScrollingDisabled(disableScroll, disableScroll) // lock scrollPane
if (disableScroll) scrollPane.clearListeners() // remove focus capture of AutoScrollPane too
add(splitPane).expand().fill()
}
override fun layout() {
super.layout()
bottomTable.height = bottomTable.height.coerceAtMost(maxBottomTableHeight)
splitPane.splitAmount = (scrollPane.height / (scrollPane.height + bottomTable.height)).coerceAtLeast(screenSplit)
}
/** Enables the [rightSideButton]. See [pick] for a way to set the text. */
fun setRightSideButtonEnabled(enabled: Boolean) {
rightSideButton.isEnabled = enabled
}
/** Sets the text of the [rightSideButton] and enables it if it's the player's turn */
fun pick(rightButtonText: String) {
if (UncivGame.Current.worldScreen.isPlayersTurn) rightSideButton.enable()
rightSideButton.setText(rightButtonText)
}
companion object {
/** Icon size used in [getPickerOptionButton]. */
const val pickerOptionIconSize = 30f
/** Return a button for picker screens that display a list of big buttons with icons and labels. */
fun getPickerOptionButton(icon: Actor, label: String): Button {
return IconTextButton(label, icon).apply {
iconCell!!.size(pickerOptionIconSize).pad(10f)
labelCell.pad(10f)
}
}
}
}

View File

@ -1,64 +1,38 @@
package com.unciv.ui.pickerscreens package com.unciv.ui.pickerscreens
import com.badlogic.gdx.scenes.scene2d.Actor import com.unciv.ui.utils.BaseScreen
import com.badlogic.gdx.scenes.scene2d.ui.* import com.unciv.ui.utils.onClick
import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.ui.images.IconTextButton
import com.unciv.ui.utils.*
import com.unciv.ui.utils.AutoScrollPane as ScrollPane
open class PickerScreen(disableScroll: Boolean = false) : BaseScreen() { open class PickerScreen(disableScroll: Boolean = false) : BaseScreen() {
/** The close button on the lower left of [bottomTable], see [setDefaultCloseAction] */
protected var closeButton: TextButton = Constants.close.toTextButton()
/** A scrollable wrapped Label you can use to show descriptions in the [bottomTable], starts empty */
protected var descriptionLabel: Label
/** A wrapper containing [rightSideButton]. You can add buttons, they will be arranged vertically */
protected var rightSideGroup = VerticalGroup()
/** A button on the lower right of [bottomTable] you can use for a "OK"-type action, starts disabled */
protected var rightSideButton: TextButton
private val screenSplit = 0.85f val pickerPane = PickerPane(disableScroll = disableScroll)
private val maxBottomTableHeight = 150f // about 7 lines of normal text
/** /** @see PickerPane.closeButton */
* The table displaying the choices from which to pick (usually). val closeButton by pickerPane::closeButton
* Also the element which most of the screen real estate is devoted to displaying. /** @see PickerPane.descriptionLabel */
*/ val descriptionLabel by pickerPane::descriptionLabel
protected var topTable: Table /** @see PickerPane.rightSideGroup */
/** Holds the [Close button][closeButton], a [description label][descriptionLabel] and an [action button][rightSideButton] */ val rightSideGroup by pickerPane::rightSideGroup
protected var bottomTable:Table = Table() /** @see PickerPane.rightSideButton */
/** A fixed SplitPane holds [scrollPane] and [bottomTable] */ val rightSideButton by pickerPane::rightSideButton
protected var splitPane: SplitPane
/** A ScrollPane scrolling [topTable], disabled by the disableScroll parameter */ /** @see PickerPane.topTable */
protected var scrollPane: ScrollPane val topTable by pickerPane::topTable
/** @see PickerPane.scrollPane */
val scrollPane by pickerPane::scrollPane
/** @see PickerPane.splitPane */
val splitPane by pickerPane::splitPane
init { init {
bottomTable.add(closeButton).pad(10f) pickerPane.setFillParent(true)
stage.addActor(pickerPane)
ensureLayout()
}
descriptionLabel = "".toLabel() /** Make sure that anyone relying on sizes of the tables within this class during construction gets correct size readings.
descriptionLabel.wrap = true * (see [com.unciv.ui.pickerscreens.PolicyPickerScreen]) */
val labelScroll = ScrollPane(descriptionLabel, skin) private fun ensureLayout() {
bottomTable.add(labelScroll).pad(5f).fill().expand() pickerPane.validate()
rightSideButton = "".toTextButton()
rightSideButton.disable()
rightSideGroup.addActor(rightSideButton)
bottomTable.add(rightSideGroup).pad(10f).right()
bottomTable.height = (stage.height * (1 - screenSplit)).coerceAtMost(maxBottomTableHeight)
topTable = Table()
scrollPane = ScrollPane(topTable)
scrollPane.setScrollingDisabled(disableScroll, disableScroll) // lock scrollPane
if (disableScroll) scrollPane.clearListeners() // remove focus capture of AutoScrollPane too
scrollPane.setSize(stage.width, stage.height - bottomTable.height)
splitPane = SplitPane(scrollPane, bottomTable, true, skin)
splitPane.splitAmount = scrollPane.height / stage.height
splitPane.setFillParent(true)
stage.addActor(splitPane)
} }
/** /**
@ -71,35 +45,17 @@ open class PickerScreen(disableScroll: Boolean = false) : BaseScreen() {
else game.setWorldScreen() else game.setWorldScreen()
dispose() dispose()
} }
closeButton.onClick(closeAction) pickerPane.closeButton.onClick(closeAction)
onBackButtonClicked(closeAction) onBackButtonClicked(closeAction)
} }
/** Enables the [rightSideButton]. See [pick] for a way to set the text. */ /** Enables the [rightSideButton]. See [pick] for a way to set the text. */
fun setRightSideButtonEnabled(enabled: Boolean) { fun setRightSideButtonEnabled(enabled: Boolean) {
rightSideButton.isEnabled = enabled pickerPane.setRightSideButtonEnabled(enabled)
} }
/** Sets the text of the [rightSideButton] and enables it if it's the player's turn */ /** Sets the text of the [rightSideButton] and enables it if it's the player's turn */
protected fun pick(rightButtonText: String) { fun pick(rightButtonText: String) {
if (UncivGame.Current.worldScreen.isPlayersTurn) rightSideButton.enable() pickerPane.pick(rightButtonText)
rightSideButton.setText(rightButtonText)
}
/** Remove listeners from [rightSideButton] to prepare giving it a new onClick */
fun removeRightSideClickListeners() {
rightSideButton.clearListeners()
}
companion object {
/** Icon size used in [getPickerOptionButton]. */
const val pickerOptionIconSize = 30f
/** Return a button for picker screens that display a list of big buttons with icons and labels. */
fun getPickerOptionButton(icon: Actor, label: String): Button {
return IconTextButton(label, icon).apply {
iconCell!!.size(pickerOptionIconSize).pad(10f)
labelCell.pad(10f)
}
}
} }
} }

View File

@ -73,6 +73,7 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
var rowChangeWidth = Float.MAX_VALUE var rowChangeWidth = Float.MAX_VALUE
// estimate how many branch boxes fit using average size (including pad) // estimate how many branch boxes fit using average size (including pad)
// TODO If we'd want to use scene2d correctly, this is supposed to happen inside an overridden layout() method
val numBranchesX = scrollPane.width / 242f val numBranchesX = scrollPane.width / 242f
val numBranchesY = scrollPane.height / 305f val numBranchesY = scrollPane.height / 305f
// plan a nice geometry // plan a nice geometry

View File

@ -77,7 +77,7 @@ class PromotionPickerScreen(val unit: MapUnit) : PickerScreen() {
val isPromotionAvailable = promotion in unitAvailablePromotions val isPromotionAvailable = promotion in unitAvailablePromotions
val unitHasPromotion = unit.promotions.promotions.contains(promotion.name) val unitHasPromotion = unit.promotions.promotions.contains(promotion.name)
val selectPromotionButton = getPickerOptionButton(ImageGetter.getPromotionIcon(promotion.name), promotion.name) val selectPromotionButton = PickerPane.getPickerOptionButton(ImageGetter.getPromotionIcon(promotion.name), promotion.name)
selectPromotionButton.isEnabled = true selectPromotionButton.isEnabled = true
selectPromotionButton.onClick { selectPromotionButton.onClick {
val enable = canBePromoted && isPromotionAvailable && !unitHasPromotion && canChangeState val enable = canBePromoted && isPromotionAvailable && !unitHasPromotion && canChangeState