diff --git a/core/src/com/unciv/Constants.kt b/core/src/com/unciv/Constants.kt index 19392990bb..ad041a32e5 100644 --- a/core/src/com/unciv/Constants.kt +++ b/core/src/com/unciv/Constants.kt @@ -67,9 +67,12 @@ object Constants { const val cancelImprovementOrder = "Cancel improvement order" const val tutorialPopupNamePrefix = "Tutorial: " + const val OK = "OK" const val close = "Close" - const val disabled = "disabled" + const val yes = "Yes" + const val no = "No" const val enabled = "enabled" + const val disabled = "disabled" const val barbarians = "Barbarians" const val spectator = "Spectator" diff --git a/core/src/com/unciv/MainMenuScreen.kt b/core/src/com/unciv/MainMenuScreen.kt index 31887deebb..3364c3bad2 100644 --- a/core/src/com/unciv/MainMenuScreen.kt +++ b/core/src/com/unciv/MainMenuScreen.kt @@ -185,7 +185,7 @@ class MainMenuScreen: CameraStageBaseScreen() { add(loadMapButton).row() keyPressDispatcher['l'] = loadMapAction - add(screen.getMenuButton("Close", "OtherIcons/Close") { close() } + add(screen.getMenuButton(Constants.close, "OtherIcons/Close") { close() } .apply { background=tableBackground }) keyPressDispatcher[KeyCharAndCode.BACK] = { close() } diff --git a/core/src/com/unciv/ui/mapeditor/GameParametersScreen.kt b/core/src/com/unciv/ui/mapeditor/GameParametersScreen.kt index 2e76c6d164..6c4684955a 100644 --- a/core/src/com/unciv/ui/mapeditor/GameParametersScreen.kt +++ b/core/src/com/unciv/ui/mapeditor/GameParametersScreen.kt @@ -1,5 +1,6 @@ package com.unciv.ui.mapeditor +import com.unciv.Constants import com.unciv.UncivGame import com.unciv.models.ruleset.RulesetCache import com.unciv.models.translations.tr @@ -30,7 +31,7 @@ class GameParametersScreen(var mapEditorScreen: MapEditorScreen): IPreviousScree .maxHeight(topTable.parent.height).width(stage.width / 2).padTop(20f).top() topTable.addSeparatorVertical() topTable.add(playerPickerTable).maxHeight(topTable.parent.height).width(stage.width / 2).padTop(20f).top() - rightSideButton.setText("OK".tr()) + rightSideButton.setText(Constants.OK.tr()) rightSideButton.onClick { mapEditorScreen.gameSetupInfo = gameSetupInfo mapEditorScreen.ruleset.clear() diff --git a/core/src/com/unciv/ui/mapeditor/MapEditorMenuPopup.kt b/core/src/com/unciv/ui/mapeditor/MapEditorMenuPopup.kt index eea6bfb7f9..9c8f480478 100644 --- a/core/src/com/unciv/ui/mapeditor/MapEditorMenuPopup.kt +++ b/core/src/com/unciv/ui/mapeditor/MapEditorMenuPopup.kt @@ -3,6 +3,7 @@ package com.unciv.ui.mapeditor import com.badlogic.gdx.Gdx import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.unciv.Constants import com.unciv.MainMenuScreen import com.unciv.UncivGame import com.unciv.models.ruleset.RulesetCache @@ -64,13 +65,14 @@ class MapEditorMenuPopup(var mapEditorScreen: MapEditorScreen): Popup(mapEditorS add(ScrollPane(incompatibilityTable)).colspan(2) .maxHeight(screen.stage.height * 0.8f).row() add("Change map to fit selected ruleset?".toLabel()).colspan(2).row() - addButtonInRow("Yes", 'y') { + addButtonInRow(Constants.yes, 'y') { for (tile in mapEditorScreen.tileMap.values) tile.normalizeToRuleset(ruleset) mapEditorScreen.tileMap.mapParameters.mods = mods mapEditorScreen.game.setScreen(MapEditorScreen(mapEditorScreen.tileMap)) } - addButtonInRow("No", 'n') { close() } + addButtonInRow(Constants.no, 'n') { close() } + equalizeLastTwoButtonWidths() }.open(true) } diff --git a/core/src/com/unciv/ui/pickerscreens/RenameUnitPopup.kt b/core/src/com/unciv/ui/pickerscreens/RenameUnitPopup.kt index 76ccc34abb..f3c4794cc4 100644 --- a/core/src/com/unciv/ui/pickerscreens/RenameUnitPopup.kt +++ b/core/src/com/unciv/ui/pickerscreens/RenameUnitPopup.kt @@ -1,33 +1,32 @@ package com.unciv.ui.pickerscreens +import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.TextField import com.unciv.logic.map.MapUnit -import com.unciv.ui.utils.CameraStageBaseScreen -import com.unciv.ui.utils.Popup -import com.unciv.ui.utils.onClick -import com.unciv.ui.utils.toTextButton +import com.unciv.ui.utils.* class RenameUnitPopup(unit: MapUnit, screen: CameraStageBaseScreen): Popup(screen) { init { - addGoodSizedLabel("Choose name for [${unit.baseUnit.name}]").row() + val wrapper = Table() + wrapper.add(ImageGetter.getUnitIcon(unit.name).surroundWithCircle(80f)).padRight(10f) + wrapper.add("Choose name for [${unit.baseUnit.name}]".toLabel()) + add(wrapper).colspan(2).row() val nameField = TextField("", skin) - // Disallowed special characters determined with US keyboard and a certain binary - // copyrighted by Firaxis Games - val illegal_chars = "%*[]\"\\|<>/?" - nameField.textFieldFilter = TextField.TextFieldFilter { _, char -> !(char in illegal_chars)} - // Max name length decided arbitrarily - nameField.maxLength = 10 - add(nameField) - row() - add("OK".toTextButton().onClick { - if (nameField.text != "") { + // Disallowed special characters - used by tr() or simply precaution + val illegalChars = "[]{}\"\\<>" + nameField.textFieldFilter = TextField.TextFieldFilter { _, char -> char !in illegalChars} + nameField.maxLength = unit.civInfo.gameInfo.ruleSet.units.values.maxOf { it.name.length } + add(nameField).growX().colspan(2).row() + addOKButton { + if (nameField.text != "" && nameField.text != unit.name) { unit.instanceName = nameField.text } screen.game.setScreen(PromotionPickerScreen(unit)) - }) - add("Close".toTextButton().onClick { close() }) - + } + addCloseButton() + equalizeLastTwoButtonWidths() + keyboardFocus = nameField } } \ No newline at end of file diff --git a/core/src/com/unciv/ui/utils/KeyPressDispatcher.kt b/core/src/com/unciv/ui/utils/KeyPressDispatcher.kt index 8a10be87d5..2334a2032a 100644 --- a/core/src/com/unciv/ui/utils/KeyPressDispatcher.kt +++ b/core/src/com/unciv/ui/utils/KeyPressDispatcher.kt @@ -51,9 +51,13 @@ data class KeyCharAndCode(val char: Char, val code: Int) { companion object { // Convenience shortcuts for frequently used constants + /** Android back, assigns ESC automatically as well */ val BACK = KeyCharAndCode(Input.Keys.BACK) + /** Automatically assigned for [BACK] */ val ESC = KeyCharAndCode(Input.Keys.ESCAPE) + /** Assigns [NUMPAD_ENTER] automatically as well */ val RETURN = KeyCharAndCode(Input.Keys.ENTER) + /** Automatically assigned for [RETURN] */ val NUMPAD_ENTER = KeyCharAndCode(Input.Keys.NUMPAD_ENTER) val SPACE = KeyCharAndCode(Input.Keys.SPACE) val BACKSPACE= KeyCharAndCode(Input.Keys.BACKSPACE) diff --git a/core/src/com/unciv/ui/utils/Popup.kt b/core/src/com/unciv/ui/utils/Popup.kt index 2bbf2a63ea..c9427d5da8 100644 --- a/core/src/com/unciv/ui/utils/Popup.kt +++ b/core/src/com/unciv/ui/utils/Popup.kt @@ -78,7 +78,7 @@ open class Popup(val screen: CameraStageBaseScreen): Table(CameraStageBaseScreen /** * Adds a [caption][text] label: A label with word wrap enabled over half the stage width. - * Will be larger than normal text if the [size] parameter is set to >18f. + * Will be larger than normal text if the [size] parameter is set to >18. * @param text The caption text. * @param size The font size for the label. */ @@ -97,7 +97,7 @@ open class Popup(val screen: CameraStageBaseScreen): Table(CameraStageBaseScreen * @return The new [Cell] */ fun addButtonInRow(text: String, key: KeyCharAndCode? = null, action: () -> Unit): Cell { - val button = text.toTextButton().apply { color = ImageGetter.getBlue() } + val button = text.toTextButton() button.onClick(action) if (key != null) { keyPressDispatcher[key] = action @@ -125,11 +125,11 @@ open class Popup(val screen: CameraStageBaseScreen): Table(CameraStageBaseScreen = addButtonInRow(text, key, action).apply { row() } /** - * Adds a [TextButton] that closes the popup. + * Adds a [TextButton] that closes the popup, with [BACK][KeyCharAndCode.BACK] already mapped. * @param text The button's caption, defaults to "Close". - * @param additionalKey An additional key that should close the popup, Back and ESC are assigned by default. + * @param additionalKey An additional key that should act like a click. * @param action A lambda to be executed after closing the popup when the button is clicked. - * @return The new [Cell] + * @return The new [Cell], marked as end of row. */ fun addCloseButton( text: String = Constants.close, @@ -141,6 +141,37 @@ open class Popup(val screen: CameraStageBaseScreen): Table(CameraStageBaseScreen return addButton(text, additionalKey, closeAction) } + /** + * Adds a [TextButton] that closes the popup, with [RETURN][KeyCharAndCode.RETURN] already mapped. + * @param text The button's caption, defaults to "OK". + * @param additionalKey An additional key that should act like a click. + * @param action A lambda to be executed after closing the popup when the button is clicked. + * @return The new [Cell], NOT marked as end of row. + */ + fun addOKButton( + text: String = Constants.OK, + additionalKey: KeyCharAndCode? = null, + action: (()->Unit) + ): Cell { + val okAction = { close(); action() } + keyPressDispatcher[KeyCharAndCode.RETURN] = okAction + return addButtonInRow(text, additionalKey, okAction) + } + + /** + * The last two additions ***must*** be buttons. + * Make their width equal by setting minWidth of one cell to actor width of the other. + */ + fun equalizeLastTwoButtonWidths() { + val n = innerTable.cells.size + if (n < 2) throw UnsupportedOperationException() + val cell1 = innerTable.cells[n-2] + val cell2 = innerTable.cells[n-1] + if (cell1.actor !is Button || cell2.actor !is Button) throw UnsupportedOperationException() + cell1.minWidth(cell2.actor.width) + cell2.minWidth(cell1.actor.width) + } + /** * Sets or retrieves the [Actor] that currently has keyboard focus. * diff --git a/core/src/com/unciv/ui/utils/YesNoPopup.kt b/core/src/com/unciv/ui/utils/YesNoPopup.kt index 1639c1c270..312de87a51 100644 --- a/core/src/com/unciv/ui/utils/YesNoPopup.kt +++ b/core/src/com/unciv/ui/utils/YesNoPopup.kt @@ -1,6 +1,7 @@ package com.unciv.ui.utils import com.badlogic.gdx.Gdx +import com.unciv.Constants import com.unciv.UncivGame /** Variant of [Popup] pre-populated with one label, plus yes and no buttons @@ -15,15 +16,12 @@ open class YesNoPopup ( screen: CameraStageBaseScreen = UncivGame.Current.worldScreen, restoreDefault:()->Unit = {} ) : Popup(screen) { - private val yes = { close(); action() } - private val no = { close(); restoreDefault() } init { add(question.toLabel()).colspan(2).row() - addButtonInRow("Yes", 'y', yes) - addButtonInRow("No", 'n', no) - keyPressDispatcher[KeyCharAndCode.RETURN] = yes - keyPressDispatcher[KeyCharAndCode.BACK] = no + addOKButton(Constants.yes, KeyCharAndCode('y'), action) + addCloseButton(Constants.no, KeyCharAndCode('n'), restoreDefault) + equalizeLastTwoButtonWidths() } } diff --git a/core/src/com/unciv/ui/worldscreen/mainmenu/OptionsPopup.kt b/core/src/com/unciv/ui/worldscreen/mainmenu/OptionsPopup.kt index e5a45622e1..e5ecd934ce 100644 --- a/core/src/com/unciv/ui/worldscreen/mainmenu/OptionsPopup.kt +++ b/core/src/com/unciv/ui/worldscreen/mainmenu/OptionsPopup.kt @@ -5,6 +5,7 @@ import com.badlogic.gdx.Gdx import com.badlogic.gdx.Input import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.scenes.scene2d.ui.* +import com.unciv.Constants import com.unciv.MainMenuScreen import com.unciv.logic.civilization.PlayerType import com.unciv.models.UncivSound @@ -455,7 +456,7 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr Usage: YesNoButton(someSetting: Boolean, skin) { someSetting = it; sideEffects() } */ -private fun Boolean.toYesNo(): String = (if (this) "Yes" else "No").tr() +private fun Boolean.toYesNo(): String = (if (this) Constants.yes else Constants.no).tr() private class YesNoButton(initialValue: Boolean, skin: Skin, action: (Boolean) -> Unit) : TextButton (initialValue.toYesNo(), skin ) {