|
|
@ -3,6 +3,7 @@ package com.unciv.ui.popups
|
|
|
|
import com.badlogic.gdx.graphics.Color
|
|
|
|
import com.badlogic.gdx.graphics.Color
|
|
|
|
import com.badlogic.gdx.math.Rectangle
|
|
|
|
import com.badlogic.gdx.math.Rectangle
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
|
|
|
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.InputEvent
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.Stage
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.Stage
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.Touchable
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.Touchable
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
|
|
@ -12,6 +13,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.ui.TextField
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.ui.TextField
|
|
|
|
|
|
|
|
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener
|
|
|
|
import com.badlogic.gdx.utils.Align
|
|
|
|
import com.badlogic.gdx.utils.Align
|
|
|
|
import com.unciv.Constants
|
|
|
|
import com.unciv.Constants
|
|
|
|
import com.unciv.logic.event.EventBus
|
|
|
|
import com.unciv.logic.event.EventBus
|
|
|
@ -42,12 +44,23 @@ open class Popup(
|
|
|
|
|
|
|
|
|
|
|
|
// This exists to differentiate the actual popup (the inner table)
|
|
|
|
// This exists to differentiate the actual popup (the inner table)
|
|
|
|
// from the 'screen blocking' part of the popup (which covers the entire screen)
|
|
|
|
// from the 'screen blocking' part of the popup (which covers the entire screen)
|
|
|
|
val innerTable = Table(BaseScreen.skin)
|
|
|
|
protected val innerTable = Table(BaseScreen.skin)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Callbacks that will be called whenever this Popup is shown */
|
|
|
|
val showListeners = mutableListOf<() -> Unit>()
|
|
|
|
val showListeners = mutableListOf<() -> Unit>()
|
|
|
|
|
|
|
|
/** Callbacks that will be called whenever this Popup is closed, no matter how (e.g. no distinction OK/Cancel) */
|
|
|
|
val closeListeners = mutableListOf<() -> Unit>()
|
|
|
|
val closeListeners = mutableListOf<() -> Unit>()
|
|
|
|
|
|
|
|
|
|
|
|
val events = EventBus.EventReceiver()
|
|
|
|
protected val events = EventBus.EventReceiver()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Enables/disables closing by clicking/trapping outside [innerTable].
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* Automatically set when [addCloseButton] is called but may be changed back or enabled without such a button.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
protected var clickBehindToClose = false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Unlike [closeListeners] this is only fired on "click-behind" closing */
|
|
|
|
|
|
|
|
protected var onCloseCallback: (() -> Unit)? = null
|
|
|
|
|
|
|
|
|
|
|
|
init {
|
|
|
|
init {
|
|
|
|
// Set actor name for debugging
|
|
|
|
// Set actor name for debugging
|
|
|
@ -55,7 +68,7 @@ open class Popup(
|
|
|
|
|
|
|
|
|
|
|
|
background = BaseScreen.skinStrings.getUiBackground(
|
|
|
|
background = BaseScreen.skinStrings.getUiBackground(
|
|
|
|
"General/Popup/Background",
|
|
|
|
"General/Popup/Background",
|
|
|
|
tintColor = Color.GRAY.cpy().apply { a=.5f })
|
|
|
|
tintColor = Color.GRAY.cpy().apply { a = 0.5f })
|
|
|
|
innerTable.background = BaseScreen.skinStrings.getUiBackground(
|
|
|
|
innerTable.background = BaseScreen.skinStrings.getUiBackground(
|
|
|
|
"General/Popup/InnerTable",
|
|
|
|
"General/Popup/InnerTable",
|
|
|
|
tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f)
|
|
|
|
tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f)
|
|
|
@ -66,9 +79,11 @@ open class Popup(
|
|
|
|
|
|
|
|
|
|
|
|
super.add(if (scrollable) AutoScrollPane(innerTable, BaseScreen.skin) else innerTable)
|
|
|
|
super.add(if (scrollable) AutoScrollPane(innerTable, BaseScreen.skin) else innerTable)
|
|
|
|
|
|
|
|
|
|
|
|
this.isVisible = false
|
|
|
|
isVisible = false
|
|
|
|
touchable = Touchable.enabled // don't allow clicking behind
|
|
|
|
touchable = Touchable.enabled
|
|
|
|
this.setFillParent(true)
|
|
|
|
// clicking behind gets special treatment
|
|
|
|
|
|
|
|
super.addListener(getBehindClickListener())
|
|
|
|
|
|
|
|
super.setFillParent(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -114,11 +129,28 @@ open class Popup(
|
|
|
|
if (nextPopup != null) (nextPopup as Popup).show()
|
|
|
|
if (nextPopup != null) (nextPopup as Popup).show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Allow closing a popup by clicking 'outside', Android-style, but only if a Close button exists */
|
|
|
|
|
|
|
|
private fun getBehindClickListener() = object : ClickListener() {
|
|
|
|
|
|
|
|
override fun clicked(event: InputEvent?, x: Float, y: Float) {
|
|
|
|
|
|
|
|
if (!clickBehindToClose) return
|
|
|
|
|
|
|
|
// Since Gdx doesn't limit events to the actually `hit` actors...
|
|
|
|
|
|
|
|
if (event?.target != this@Popup) return
|
|
|
|
|
|
|
|
close()
|
|
|
|
|
|
|
|
onCloseCallback?.invoke()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* All additions to the popup are to the inner table - we shouldn't care that there's an inner table at all */
|
|
|
|
/* All additions to the popup are to the inner table - we shouldn't care that there's an inner table at all */
|
|
|
|
final override fun <T : Actor?> add(actor: T): Cell<T> = innerTable.add(actor)
|
|
|
|
final override fun <T : Actor?> add(actor: T): Cell<T> = innerTable.add(actor)
|
|
|
|
override fun row(): Cell<Actor> = innerTable.row()
|
|
|
|
override fun row(): Cell<Actor> = innerTable.row()
|
|
|
|
override fun defaults(): Cell<Actor> = innerTable.defaults()
|
|
|
|
override fun defaults(): Cell<Actor> = innerTable.defaults()
|
|
|
|
fun addSeparator() = innerTable.addSeparator()
|
|
|
|
fun addSeparator() = innerTable.addSeparator()
|
|
|
|
|
|
|
|
override fun clear() {
|
|
|
|
|
|
|
|
innerTable.clear()
|
|
|
|
|
|
|
|
clickBehindToClose = false
|
|
|
|
|
|
|
|
onCloseCallback = null
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Adds a [caption][text] label: A label with word wrap enabled over half the stage width.
|
|
|
|
* Adds a [caption][text] label: A label with word wrap enabled over half the stage width.
|
|
|
@ -126,7 +158,7 @@ open class Popup(
|
|
|
|
* @param text The caption text.
|
|
|
|
* @param text The caption text.
|
|
|
|
* @param size The font size for the label.
|
|
|
|
* @param size The font size for the label.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
fun addGoodSizedLabel(text: String, size:Int=Constants.defaultFontSize): Cell<Label> {
|
|
|
|
fun addGoodSizedLabel(text: String, size: Int = Constants.defaultFontSize): Cell<Label> {
|
|
|
|
val label = text.toLabel(fontSize = size)
|
|
|
|
val label = text.toLabel(fontSize = size)
|
|
|
|
label.wrap = true
|
|
|
|
label.wrap = true
|
|
|
|
label.setAlignment(Align.center)
|
|
|
|
label.setAlignment(Align.center)
|
|
|
@ -140,7 +172,12 @@ open class Popup(
|
|
|
|
* @param action A lambda to be executed when the button is clicked.
|
|
|
|
* @param action A lambda to be executed when the button is clicked.
|
|
|
|
* @return The new [Cell]
|
|
|
|
* @return The new [Cell]
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
fun addButton(text: String, key: KeyCharAndCode? = null, style: TextButtonStyle? = null, action: () -> Unit): Cell<TextButton> {
|
|
|
|
fun addButton(
|
|
|
|
|
|
|
|
text: String,
|
|
|
|
|
|
|
|
key: KeyCharAndCode? = null,
|
|
|
|
|
|
|
|
style: TextButtonStyle? = null,
|
|
|
|
|
|
|
|
action: () -> Unit
|
|
|
|
|
|
|
|
): Cell<TextButton> {
|
|
|
|
val button = text.toTextButton(style)
|
|
|
|
val button = text.toTextButton(style)
|
|
|
|
button.onActivation { action() }
|
|
|
|
button.onActivation { action() }
|
|
|
|
button.keyShortcuts.add(key)
|
|
|
|
button.keyShortcuts.add(key)
|
|
|
@ -148,6 +185,7 @@ open class Popup(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fun addButton(text: String, key: Char, style: TextButtonStyle? = null, action: () -> Unit)
|
|
|
|
fun addButton(text: String, key: Char, style: TextButtonStyle? = null, action: () -> Unit)
|
|
|
|
= addButton(text, KeyCharAndCode(key), style, action).apply { row() }
|
|
|
|
= addButton(text, KeyCharAndCode(key), style, action).apply { row() }
|
|
|
|
|
|
|
|
@Suppress("unused") // Keep the offer to pass an Input.keys value
|
|
|
|
fun addButton(text: String, key: Int, style: TextButtonStyle? = null, action: () -> Unit)
|
|
|
|
fun addButton(text: String, key: Int, style: TextButtonStyle? = null, action: () -> Unit)
|
|
|
|
= addButton(text, KeyCharAndCode(key), style, action).apply { row() }
|
|
|
|
= addButton(text, KeyCharAndCode(key), style, action).apply { row() }
|
|
|
|
|
|
|
|
|
|
|
@ -164,7 +202,12 @@ open class Popup(
|
|
|
|
style: TextButtonStyle? = null,
|
|
|
|
style: TextButtonStyle? = null,
|
|
|
|
action: (()->Unit)? = null
|
|
|
|
action: (()->Unit)? = null
|
|
|
|
): Cell<TextButton> {
|
|
|
|
): Cell<TextButton> {
|
|
|
|
val cell = addButton(text, additionalKey, style) { close(); if(action!=null) action() }
|
|
|
|
clickBehindToClose = true
|
|
|
|
|
|
|
|
onCloseCallback = action
|
|
|
|
|
|
|
|
val cell = addButton(text, additionalKey, style) {
|
|
|
|
|
|
|
|
close()
|
|
|
|
|
|
|
|
action?.invoke()
|
|
|
|
|
|
|
|
}
|
|
|
|
cell.actor.keyShortcuts.add(KeyCharAndCode.BACK)
|
|
|
|
cell.actor.keyShortcuts.add(KeyCharAndCode.BACK)
|
|
|
|
return cell
|
|
|
|
return cell
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -224,7 +267,7 @@ open class Popup(
|
|
|
|
* and a close button if requested
|
|
|
|
* and a close button if requested
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
fun reuseWith(newText: String, withCloseButton: Boolean = false) {
|
|
|
|
fun reuseWith(newText: String, withCloseButton: Boolean = false) {
|
|
|
|
innerTable.clear()
|
|
|
|
clear()
|
|
|
|
addGoodSizedLabel(newText)
|
|
|
|
addGoodSizedLabel(newText)
|
|
|
|
if (withCloseButton) {
|
|
|
|
if (withCloseButton) {
|
|
|
|
row()
|
|
|
|
row()
|
|
|
@ -264,12 +307,5 @@ val BaseScreen.activePopup: Popup?
|
|
|
|
fun BaseScreen.hasOpenPopups(): Boolean = stage.hasOpenPopups()
|
|
|
|
fun BaseScreen.hasOpenPopups(): Boolean = stage.hasOpenPopups()
|
|
|
|
private fun Stage.hasOpenPopups(): Boolean = actors.any { it is Popup && it.isVisible }
|
|
|
|
private fun Stage.hasOpenPopups(): Boolean = actors.any { it is Popup && it.isVisible }
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Counts number of visible[Popup]s.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* Used for key dispatcher precedence.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private fun Stage.countOpenPopups() = actors.count { it is Popup && it.isVisible }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Closes all [Popup]s. */
|
|
|
|
/** Closes all [Popup]s. */
|
|
|
|
fun BaseScreen.closeAllPopups() = popups.forEach { it.close() }
|
|
|
|
fun BaseScreen.closeAllPopups() = popups.forEach { it.close() }
|
|
|
|