mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-23 03:23:17 -04:00
Refactor: UncivTextField (#11705)
* Refactor UncivTextField to be a normal Widget * Remove UncivTextField `create` factory
This commit is contained in:
parent
149e90bfed
commit
05020a7d7e
@ -19,7 +19,7 @@ import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.Constants
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.addSeparator
|
||||
import com.unciv.ui.components.extensions.isEnabled
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
@ -65,7 +65,7 @@ open class FileChooser(
|
||||
}
|
||||
|
||||
// components
|
||||
private val fileNameInput = UncivTextField.create("Please enter a file name")
|
||||
private val fileNameInput = UncivTextField("Please enter a file name")
|
||||
private val fileNameLabel = "File name:".toLabel()
|
||||
private val fileNameWrapper = Table().apply {
|
||||
defaults().space(10f)
|
||||
|
@ -1,240 +0,0 @@
|
||||
package com.unciv.ui.components
|
||||
|
||||
import com.badlogic.gdx.Application
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.g2d.Batch
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent
|
||||
import com.badlogic.gdx.scenes.scene2d.InputListener
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextField
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.FocusListener
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.event.EventBus
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.extensions.getAscendant
|
||||
import com.unciv.ui.components.extensions.getOverlap
|
||||
import com.unciv.ui.components.extensions.right
|
||||
import com.unciv.ui.components.extensions.stageBoundingBox
|
||||
import com.unciv.ui.components.extensions.top
|
||||
import com.unciv.ui.components.input.KeyCharAndCode
|
||||
import com.unciv.ui.components.input.keyShortcuts
|
||||
import com.unciv.ui.popups.Popup
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.screens.basescreen.UncivStage
|
||||
import com.unciv.utils.Concurrency
|
||||
import com.unciv.utils.withGLContext
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
object UncivTextField {
|
||||
/**
|
||||
* Creates a text field that has nicer platform-specific input added compared to the default Gdx [TextField].
|
||||
*
|
||||
* - On Android, manages on-screen keyboard visibility and reacts to how the on-screen keyboard reduces screen space.
|
||||
* - Tries to scroll the field into view when receiving focus using an ascendant ScrollPane.
|
||||
* - If view of the field is still obscured, show am "emergency" Popup instead (can help when on Android the on-screen keyboard is large and the screen small).
|
||||
* - If this TextField handles the Tab key (see [keyShortcuts]), its [focus navigation feature][TextField.next] is disabled (otherwise it would search for another TextField in the same parent to give focus to, and remove the on-screen keyboard if it finds none).
|
||||
* - All parameters are supported on all platforms.
|
||||
*
|
||||
* @param hint The text that should be displayed in the text field when no text is entered and it does not have focus, will automatically be translated. Also shown as Label in the "emergency" Popup.
|
||||
* @param preEnteredText the text initially entered within this text field.
|
||||
* @param onFocusChange a callback that will be notified when this TextField loses or gains the [keyboardFocus][com.badlogic.gdx.scenes.scene2d.Stage.keyboardFocus].
|
||||
* Receiver is the field, so you can simply use its elements. Parameter `it` is a Boolean indicating focus was received.
|
||||
*/
|
||||
fun create(hint: String, preEnteredText: String = "", onFocusChange: (TextField.(Boolean) -> Unit)? = null): TextField {
|
||||
@Suppress("UNCIV_RAW_TEXTFIELD")
|
||||
val textField = object : TextField(preEnteredText, BaseScreen.skin) {
|
||||
override fun next(up: Boolean) {
|
||||
if (KeyCharAndCode.TAB in keyShortcuts) return
|
||||
super.next(up)
|
||||
}
|
||||
|
||||
// Note - this way to force TextField to display `[]` characters normally is an incomplete hack.
|
||||
// The complete way would either require overriding `updateDisplayText` which is private, or all methods calling it,
|
||||
// which are many including the keyboard listener, or keep a separate font without markup enabled around and put that
|
||||
// into the default style, including its own NativeBitmapFontData instance and texture - involves quite some redesign.
|
||||
// That said, observing the deficiency is hard - the internal `glyphPositions` could theoretically get out of sync, affecting selection and caret display.
|
||||
override fun layout() {
|
||||
val oldEnable = style.font.data.markupEnabled
|
||||
style.font.data.markupEnabled = false
|
||||
super.layout()
|
||||
style.font.data.markupEnabled = oldEnable
|
||||
}
|
||||
override fun drawText(batch: Batch, font: BitmapFont, x: Float, y: Float) {
|
||||
val oldEnable = font.data.markupEnabled
|
||||
font.data.markupEnabled = false
|
||||
super.drawText(batch, font, x, y)
|
||||
font.data.markupEnabled = oldEnable
|
||||
}
|
||||
}
|
||||
val translatedHint = hint.tr()
|
||||
textField.messageText = translatedHint
|
||||
textField.addListener(object : FocusListener() {
|
||||
override fun keyboardFocusChanged(event: FocusEvent, actor: Actor, focused: Boolean) {
|
||||
if (focused) {
|
||||
textField.scrollAscendantToTextField()
|
||||
}
|
||||
onFocusChange?.invoke(textField, focused)
|
||||
}
|
||||
})
|
||||
|
||||
if (Gdx.app.type == Application.ApplicationType.Android)
|
||||
TextfieldImprovements.add(textField)
|
||||
return textField
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to scroll a [ScrollPane] ascendant of the text field so that this text field is in the middle of the visible area.
|
||||
*
|
||||
* @return true if the text field is visible after this operation
|
||||
*/
|
||||
fun TextField.scrollAscendantToTextField(): Boolean {
|
||||
val stage = this.stage
|
||||
if (stage !is UncivStage) return false
|
||||
|
||||
val scrollPane = this.getAscendant { it is ScrollPane } as ScrollPane?
|
||||
val visibleArea = stage.lastKnownVisibleArea
|
||||
val textFieldStageBoundingBox = this.stageBoundingBox
|
||||
if (scrollPane == null) return visibleArea.contains(textFieldStageBoundingBox)
|
||||
|
||||
val scrollPaneBounds = scrollPane.stageBoundingBox
|
||||
val visibleScrollPaneArea = scrollPaneBounds.getOverlap(visibleArea)
|
||||
if (visibleScrollPaneArea == null) {
|
||||
return false
|
||||
} else if (visibleScrollPaneArea.contains(textFieldStageBoundingBox)) {
|
||||
return true
|
||||
}
|
||||
|
||||
val scrollContent = scrollPane.actor
|
||||
val textFieldScrollContentCoords = localToAscendantCoordinates(scrollContent, Vector2(0f, 0f))
|
||||
|
||||
// It's possible that our textField can't be (fully) scrolled to be within the visible scrollPane area
|
||||
val pixelsNotVisibleOnLeftSide = (visibleScrollPaneArea.x - scrollPaneBounds.x).coerceAtLeast(0f)
|
||||
val textFieldDistanceFromLeftSide = textFieldScrollContentCoords.x
|
||||
val pixelsNotVisibleOnRightSide = (scrollPaneBounds.right - visibleScrollPaneArea.right).coerceAtLeast(0f)
|
||||
val textFieldDistanceFromRightSide = scrollContent.width - (textFieldScrollContentCoords.x + this.width)
|
||||
val pixelsNotVisibleOnTop = (scrollPaneBounds.top - visibleScrollPaneArea.top).coerceAtLeast(0f)
|
||||
val textFieldDistanceFromTop = scrollContent.height - (textFieldScrollContentCoords.y + this.height)
|
||||
val pixelsNotVisibleOnBottom = (visibleScrollPaneArea.y - scrollPaneBounds.y).coerceAtLeast(0f)
|
||||
val textFieldDistanceFromBottom = textFieldScrollContentCoords.y
|
||||
// If the visible scroll pane area is smaller than our text field, it will always be partly obscured
|
||||
if (visibleScrollPaneArea.width < this.width || visibleScrollPaneArea.height < this.height
|
||||
// If the amount of pixels obscured near a scrollContent edge is larger than the distance of the text field to that edge, it will always be (partly) obscured
|
||||
|| pixelsNotVisibleOnLeftSide > textFieldDistanceFromLeftSide
|
||||
|| pixelsNotVisibleOnRightSide > textFieldDistanceFromRightSide
|
||||
|| pixelsNotVisibleOnTop > textFieldDistanceFromTop
|
||||
|| pixelsNotVisibleOnBottom > textFieldDistanceFromBottom) {
|
||||
return false
|
||||
}
|
||||
|
||||
// We want to put the text field in the middle of the visible area
|
||||
val scrollXMiddle = textFieldScrollContentCoords.x - this.width / 2 + visibleScrollPaneArea.width / 2
|
||||
// If the visible area is to the right of the left edge of the scroll pane, we need to scroll that much farther to get to the real visible middle
|
||||
scrollPane.scrollX = pixelsNotVisibleOnLeftSide + scrollXMiddle
|
||||
|
||||
// ScrollPane.scrollY has the origin at the top instead of at the bottom, so + for height / 2 instead of -
|
||||
// We want to put the text field in the middle of the visible area
|
||||
val scrollYMiddleGdxOrigin = textFieldScrollContentCoords.y + this.height / 2 + visibleScrollPaneArea.height / 2
|
||||
// If the visible area is below the top edge of the scroll pane, we need to scroll that much farther to get to the real visible middle
|
||||
// Also, convert to scroll pane origin (0 is on top instead of bottom)
|
||||
scrollPane.scrollY = pixelsNotVisibleOnTop + scrollContent.height - scrollYMiddleGdxOrigin
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
object TextfieldImprovements {
|
||||
private val hideKeyboard = { Gdx.input.setOnscreenKeyboardVisible(false) }
|
||||
fun add(textField: TextField): TextField {
|
||||
textField.addListener(object : InputListener() {
|
||||
private val events = EventBus.EventReceiver()
|
||||
init {
|
||||
events.receive(UncivStage.VisibleAreaChanged::class) {
|
||||
if (textField.stage == null || !textField.hasKeyboardFocus()) return@receive
|
||||
Concurrency.run {
|
||||
// If anything resizes, it also does so with this event. So we need to wait for that to finish to update the scroll position.
|
||||
delay(100)
|
||||
withGLContext {
|
||||
if (textField.stage == null) return@withGLContext
|
||||
|
||||
if (textField.scrollAscendantToTextField()) {
|
||||
val scrollPane = textField.getAscendant { it is ScrollPane } as ScrollPane?
|
||||
// when screen dimensions change, we don't want an animation for scrolling, just show, just show the textfield immediately
|
||||
scrollPane?.updateVisualScroll()
|
||||
} else {
|
||||
// We can't scroll the text field into view, so we need to show a popup
|
||||
TextfieldPopup(textField).open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun touchDown(event: InputEvent, x: Float, y: Float, pointer: Int, button: Int): Boolean {
|
||||
addPopupCloseListener(textField)
|
||||
return false
|
||||
}
|
||||
})
|
||||
textField.addListener(object : FocusListener() {
|
||||
override fun keyboardFocusChanged(event: FocusEvent?, actor: Actor?, focused: Boolean) {
|
||||
if (focused) {
|
||||
addPopupCloseListener(textField)
|
||||
Gdx.input.setOnscreenKeyboardVisible(true)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return textField
|
||||
}
|
||||
|
||||
private fun addPopupCloseListener(textField: TextField) {
|
||||
val popup = textField.getAscendant { it is Popup } as Popup?
|
||||
if (popup != null && !popup.closeListeners.contains(hideKeyboard)) {
|
||||
popup.closeListeners.add(hideKeyboard)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TextfieldPopup(
|
||||
textField: TextField
|
||||
) : Popup(textField.stage) {
|
||||
val popupTextfield = clone(textField)
|
||||
init {
|
||||
addGoodSizedLabel(popupTextfield.messageText)
|
||||
.colspan(2)
|
||||
.row()
|
||||
|
||||
add(popupTextfield)
|
||||
.width(stageToShowOn.width / 2)
|
||||
.colspan(2)
|
||||
.row()
|
||||
|
||||
addCloseButton(Constants.cancel)
|
||||
.left()
|
||||
addOKButton { textField.text = popupTextfield.text }
|
||||
.right()
|
||||
.row()
|
||||
|
||||
showListeners.add {
|
||||
stageToShowOn.keyboardFocus = popupTextfield
|
||||
}
|
||||
closeListeners.add {
|
||||
stageToShowOn.keyboardFocus = null
|
||||
Gdx.input.setOnscreenKeyboardVisible(false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun clone(textField: TextField): TextField {
|
||||
@Suppress("UNCIV_RAW_TEXTFIELD") // we are copying the existing text field
|
||||
val copy = TextField(textField.text, textField.style)
|
||||
copy.textFieldFilter = textField.textFieldFilter
|
||||
copy.messageText = textField.messageText
|
||||
copy.setSelection(textField.selectionStart, textField.selection.length)
|
||||
copy.cursorPosition = textField.cursorPosition
|
||||
copy.alignment = textField.alignment
|
||||
copy.isPasswordMode = textField.isPasswordMode
|
||||
copy.onscreenKeyboard = textField.onscreenKeyboard
|
||||
return copy
|
||||
}
|
||||
}
|
@ -17,7 +17,6 @@ import com.badlogic.gdx.scenes.scene2d.utils.Layout
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
||||
import com.unciv.ui.components.extensions.addSeparator
|
||||
import com.unciv.ui.components.extensions.darken
|
||||
@ -593,7 +592,7 @@ open class TabbedPager(
|
||||
*/
|
||||
fun askForPassword(secretHashCode: Int = 0) {
|
||||
class PassPopup(screen: BaseScreen, unlockAction: ()->Unit, lockAction: ()->Unit) : Popup(screen) {
|
||||
val passEntry = UncivTextField.create("Password")
|
||||
val passEntry = UncivTextField("Password")
|
||||
init {
|
||||
passEntry.isPasswordMode = true
|
||||
add(passEntry).row()
|
||||
|
@ -0,0 +1,59 @@
|
||||
package com.unciv.ui.components.widgets
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.Batch
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextField
|
||||
import com.unciv.ui.components.input.KeyCharAndCode
|
||||
import com.unciv.ui.components.input.keyShortcuts
|
||||
|
||||
/**
|
||||
* Creates a text field with two deviations from the default Gdx [TextField]:
|
||||
* - Turns off Gdx color markup support while drawing, so [] in the text display properly
|
||||
* - If this TextField handles the Tab key (see [keyShortcuts]), its [focus navigation feature][TextField.next] is disabled (otherwise it would search for another TextField in the same parent to give focus to, and remove the on-screen keyboard if it finds none).
|
||||
* - constructors same as standard TextField, plus a cloning constructor.
|
||||
*/
|
||||
open class TextFieldWithFixes private constructor(text: String, style: TextFieldStyle) : TextField(text, style) {
|
||||
internal constructor(text: String, skin: Skin) : this(text, skin.get(TextFieldStyle::class.java))
|
||||
internal constructor(textField: TextFieldWithFixes) : this(textField.text, textField.style) {
|
||||
textFieldFilter = textField.textFieldFilter
|
||||
messageText = textField.messageText
|
||||
hasSelection = textField.hasSelection
|
||||
cursor = textField.cursor
|
||||
selectionStart = textField.selectionStart
|
||||
alignment = textField.alignment
|
||||
isPasswordMode = textField.isPasswordMode
|
||||
onscreenKeyboard = textField.onscreenKeyboard
|
||||
}
|
||||
|
||||
// Without this, the DeveloperConsole can't catch the Tab key for Autocomplete reliably
|
||||
override fun next(up: Boolean) {
|
||||
if (KeyCharAndCode.TAB in keyShortcuts) return
|
||||
super.next(up)
|
||||
}
|
||||
|
||||
// Note - this way to force TextField to display `[]` characters normally is an incomplete hack.
|
||||
// The complete way would either require overriding `updateDisplayText` which is private, or all methods calling it,
|
||||
// which are many including the keyboard listener, or keep a separate font without markup enabled around and put that
|
||||
// into the default style, including its own NativeBitmapFontData instance and texture - involves quite some redesign.
|
||||
// That said, observing the deficiency is hard - the internal `glyphPositions` could theoretically get out of sync, affecting selection and caret display.
|
||||
override fun layout() {
|
||||
val oldEnable = style.font.data.markupEnabled
|
||||
style.font.data.markupEnabled = false
|
||||
super.layout()
|
||||
style.font.data.markupEnabled = oldEnable
|
||||
}
|
||||
override fun drawText(batch: Batch, font: BitmapFont, x: Float, y: Float) {
|
||||
val oldEnable = font.data.markupEnabled
|
||||
font.data.markupEnabled = false
|
||||
super.drawText(batch, font, x, y)
|
||||
font.data.markupEnabled = oldEnable
|
||||
}
|
||||
|
||||
fun copyTextAndSelection(textField: TextFieldWithFixes) {
|
||||
text = textField.text
|
||||
hasSelection = textField.hasSelection
|
||||
cursor = textField.cursor
|
||||
selectionStart = textField.selectionStart
|
||||
}
|
||||
}
|
192
core/src/com/unciv/ui/components/widgets/UncivTextField.kt
Normal file
192
core/src/com/unciv/ui/components/widgets/UncivTextField.kt
Normal file
@ -0,0 +1,192 @@
|
||||
package com.unciv.ui.components.widgets
|
||||
|
||||
import com.badlogic.gdx.Application
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent
|
||||
import com.badlogic.gdx.scenes.scene2d.InputListener
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextField
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.FocusListener
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.event.EventBus
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.extensions.getAscendant
|
||||
import com.unciv.ui.components.extensions.getOverlap
|
||||
import com.unciv.ui.components.extensions.right
|
||||
import com.unciv.ui.components.extensions.stageBoundingBox
|
||||
import com.unciv.ui.components.extensions.top
|
||||
import com.unciv.ui.components.input.keyShortcuts
|
||||
import com.unciv.ui.popups.Popup
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.screens.basescreen.UncivStage
|
||||
import com.unciv.utils.Concurrency
|
||||
import com.unciv.utils.withGLContext
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
/**
|
||||
* Creates a text field that has nicer platform-specific input added compared to the default Gdx [TextField].
|
||||
*
|
||||
* - On Android, manages on-screen keyboard visibility and reacts to how the on-screen keyboard reduces screen space.
|
||||
* - Tries to scroll the field into view when receiving focus using an ascendant ScrollPane.
|
||||
* - If view of the field is still obscured, show am "emergency" Popup instead (can help when on Android the on-screen keyboard is large and the screen small).
|
||||
* - If this TextField handles the Tab key (see [keyShortcuts]), its [focus navigation feature][TextField.next] is disabled (otherwise it would search for another TextField in the same parent to give focus to, and remove the on-screen keyboard if it finds none).
|
||||
* - All parameters are supported on all platforms.
|
||||
*
|
||||
* @param hint The text that should be displayed in the text field when no text is entered and it does not have focus, will automatically be translated. Also shown as Label in the "emergency" Popup.
|
||||
* @param preEnteredText the text initially entered within this text field.
|
||||
* @param onFocusChange a callback that will be notified when this TextField loses or gains the [keyboardFocus][com.badlogic.gdx.scenes.scene2d.Stage.keyboardFocus].
|
||||
* Receiver is the field, so you can simply use its elements. Parameter `it` is a Boolean indicating focus was received.
|
||||
*/
|
||||
class UncivTextField(
|
||||
hint: String,
|
||||
preEnteredText: String = "",
|
||||
private val onFocusChange: (TextField.(Boolean) -> Unit)? = null
|
||||
) : TextFieldWithFixes(preEnteredText, BaseScreen.skin) {
|
||||
private val isAndroid = Gdx.app.type == Application.ApplicationType.Android
|
||||
private val hideKeyboard = { Gdx.input.setOnscreenKeyboardVisible(false) }
|
||||
|
||||
init {
|
||||
messageText = hint.tr()
|
||||
|
||||
addListener(UncivTextFieldFocusListener())
|
||||
|
||||
if (isAndroid) addListener(VisibleAreaChangedListener())
|
||||
}
|
||||
|
||||
private inner class UncivTextFieldFocusListener : FocusListener() {
|
||||
override fun keyboardFocusChanged(event: FocusEvent, actor: Actor, focused: Boolean) {
|
||||
if (focused) {
|
||||
scrollAscendantToTextField()
|
||||
if (isAndroid) {
|
||||
addPopupCloseListener()
|
||||
Gdx.input.setOnscreenKeyboardVisible(true)
|
||||
}
|
||||
}
|
||||
onFocusChange?.invoke(this@UncivTextField, focused)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class VisibleAreaChangedListener : InputListener() {
|
||||
private val events = EventBus.EventReceiver()
|
||||
init {
|
||||
events.receive(UncivStage.VisibleAreaChanged::class) {
|
||||
if (stage == null || !hasKeyboardFocus()) return@receive
|
||||
Concurrency.run {
|
||||
// If anything resizes, it also does so with this event. So we need to wait for that to finish to update the scroll position.
|
||||
delay(100)
|
||||
withGLContext {
|
||||
if (stage == null) return@withGLContext
|
||||
|
||||
if (scrollAscendantToTextField()) {
|
||||
val scrollPane = getAscendant<ScrollPane>()
|
||||
// when screen dimensions change, we don't want an animation for scrolling, just show the textfield immediately
|
||||
scrollPane?.updateVisualScroll()
|
||||
} else {
|
||||
// We can't scroll the text field into view, so we need to show a popup
|
||||
TextfieldPopup().open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun touchDown(event: InputEvent, x: Float, y: Float, pointer: Int, button: Int): Boolean {
|
||||
addPopupCloseListener()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private fun addPopupCloseListener() {
|
||||
val popup = getAscendant<Popup>()
|
||||
if (popup != null && !popup.closeListeners.contains(hideKeyboard)) {
|
||||
popup.closeListeners.add(hideKeyboard)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to scroll a [ScrollPane] ascendant of the text field so that this text field is in the middle of the visible area.
|
||||
*
|
||||
* @return true if the text field is visible after this operation
|
||||
*/
|
||||
private fun scrollAscendantToTextField(): Boolean {
|
||||
val stage = this.stage as? UncivStage ?: return false
|
||||
|
||||
val scrollPane = this.getAscendant<ScrollPane>()
|
||||
val visibleArea = stage.lastKnownVisibleArea
|
||||
val textFieldStageBoundingBox = this.stageBoundingBox
|
||||
if (scrollPane == null) return visibleArea.contains(textFieldStageBoundingBox)
|
||||
|
||||
val scrollPaneBounds = scrollPane.stageBoundingBox
|
||||
val visibleScrollPaneArea = scrollPaneBounds.getOverlap(visibleArea)
|
||||
if (visibleScrollPaneArea == null) {
|
||||
return false
|
||||
} else if (visibleScrollPaneArea.contains(textFieldStageBoundingBox)) {
|
||||
return true
|
||||
}
|
||||
|
||||
val scrollContent = scrollPane.actor
|
||||
val textFieldScrollContentCoords = localToAscendantCoordinates(scrollContent, Vector2(0f, 0f))
|
||||
|
||||
// It's possible that our textField can't be (fully) scrolled to be within the visible scrollPane area
|
||||
val pixelsNotVisibleOnLeftSide = (visibleScrollPaneArea.x - scrollPaneBounds.x).coerceAtLeast(0f)
|
||||
val textFieldDistanceFromLeftSide = textFieldScrollContentCoords.x
|
||||
val pixelsNotVisibleOnRightSide = (scrollPaneBounds.right - visibleScrollPaneArea.right).coerceAtLeast(0f)
|
||||
val textFieldDistanceFromRightSide = scrollContent.width - (textFieldScrollContentCoords.x + this.width)
|
||||
val pixelsNotVisibleOnTop = (scrollPaneBounds.top - visibleScrollPaneArea.top).coerceAtLeast(0f)
|
||||
val textFieldDistanceFromTop = scrollContent.height - (textFieldScrollContentCoords.y + this.height)
|
||||
val pixelsNotVisibleOnBottom = (visibleScrollPaneArea.y - scrollPaneBounds.y).coerceAtLeast(0f)
|
||||
val textFieldDistanceFromBottom = textFieldScrollContentCoords.y
|
||||
// If the visible scroll pane area is smaller than our text field, it will always be partly obscured
|
||||
if (visibleScrollPaneArea.width < this.width || visibleScrollPaneArea.height < this.height
|
||||
// If the amount of pixels obscured near a scrollContent edge is larger than the distance of the text field to that edge, it will always be (partly) obscured
|
||||
|| pixelsNotVisibleOnLeftSide > textFieldDistanceFromLeftSide
|
||||
|| pixelsNotVisibleOnRightSide > textFieldDistanceFromRightSide
|
||||
|| pixelsNotVisibleOnTop > textFieldDistanceFromTop
|
||||
|| pixelsNotVisibleOnBottom > textFieldDistanceFromBottom) {
|
||||
return false
|
||||
}
|
||||
|
||||
// We want to put the text field in the middle of the visible area
|
||||
val scrollXMiddle = textFieldScrollContentCoords.x - this.width / 2 + visibleScrollPaneArea.width / 2
|
||||
// If the visible area is to the right of the left edge of the scroll pane, we need to scroll that much farther to get to the real visible middle
|
||||
scrollPane.scrollX = pixelsNotVisibleOnLeftSide + scrollXMiddle
|
||||
|
||||
// ScrollPane.scrollY has the origin at the top instead of at the bottom, so + for height / 2 instead of -
|
||||
// We want to put the text field in the middle of the visible area
|
||||
val scrollYMiddleGdxOrigin = textFieldScrollContentCoords.y + this.height / 2 + visibleScrollPaneArea.height / 2
|
||||
// If the visible area is below the top edge of the scroll pane, we need to scroll that much farther to get to the real visible middle
|
||||
// Also, convert to scroll pane origin (0 is on top instead of bottom)
|
||||
scrollPane.scrollY = pixelsNotVisibleOnTop + scrollContent.height - scrollYMiddleGdxOrigin
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private inner class TextfieldPopup : Popup(stage) {
|
||||
val popupTextfield = TextFieldWithFixes(this@UncivTextField)
|
||||
init {
|
||||
addGoodSizedLabel(popupTextfield.messageText)
|
||||
.colspan(2)
|
||||
.row()
|
||||
|
||||
add(popupTextfield)
|
||||
.width(stageToShowOn.width / 2)
|
||||
.colspan(2)
|
||||
.row()
|
||||
|
||||
addCloseButton(Constants.cancel)
|
||||
.left()
|
||||
addOKButton { this@UncivTextField.copyTextAndSelection(popupTextfield) }
|
||||
.right()
|
||||
.row()
|
||||
|
||||
showListeners.add {
|
||||
stageToShowOn.keyboardFocus = popupTextfield
|
||||
}
|
||||
closeListeners.add {
|
||||
stageToShowOn.keyboardFocus = null
|
||||
Gdx.input.setOnscreenKeyboardVisible(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextField
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.input.onChange
|
||||
import com.unciv.ui.components.input.onClick
|
||||
import com.unciv.ui.components.extensions.surroundWithCircle
|
||||
@ -62,7 +62,7 @@ class AskNumberPopup(
|
||||
wrapper.add(label.toLabel())
|
||||
add(wrapper).colspan(2).row()
|
||||
|
||||
val nameField = UncivTextField.create(label, defaultValue)
|
||||
val nameField = UncivTextField(label, defaultValue)
|
||||
nameField.textFieldFilter = TextField.TextFieldFilter { _, char -> char.isDigit() || char == '-' }
|
||||
|
||||
fun isValidInt(input: String): Boolean {
|
||||
|
@ -6,7 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextField
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.surroundWithCircle
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
|
||||
@ -40,7 +40,7 @@ class AskTextPopup(
|
||||
wrapper.add(label.toLabel())
|
||||
add(wrapper).colspan(2).row()
|
||||
|
||||
val nameField = UncivTextField.create(label, defaultText)
|
||||
val nameField = UncivTextField(label, defaultText)
|
||||
nameField.textFieldFilter = TextField.TextFieldFilter { _, char -> char !in illegalChars}
|
||||
nameField.maxLength = maxLength
|
||||
|
||||
|
@ -3,7 +3,7 @@ package com.unciv.ui.popups
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.input.onClick
|
||||
import com.unciv.ui.components.extensions.toTextButton
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
@ -14,7 +14,7 @@ class AuthPopup(stage: Stage, authSuccessful: ((Boolean) -> Unit)? = null)
|
||||
constructor(screen: BaseScreen, authSuccessful: ((Boolean) -> Unit)? = null) : this(screen.stage, authSuccessful)
|
||||
|
||||
init {
|
||||
val passwordField = UncivTextField.create("Password")
|
||||
val passwordField = UncivTextField("Password")
|
||||
val button = "Authenticate".toTextButton()
|
||||
val negativeButtonStyle = BaseScreen.skin.get("negative", TextButton.TextButtonStyle::class.java)
|
||||
|
||||
|
@ -10,7 +10,7 @@ import com.unciv.logic.files.MapSaver
|
||||
import com.unciv.logic.files.UncivFiles
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.ruleset.tile.ResourceType
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.addSeparator
|
||||
import com.unciv.ui.components.extensions.toCheckBox
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
@ -31,7 +31,7 @@ fun debugTab(
|
||||
|
||||
if (GUI.isWorldLoaded()) {
|
||||
val simulateButton = "Simulate until turn:".toTextButton()
|
||||
val simulateTextField = UncivTextField.create("Turn", DebugUtils.SIMULATE_UNTIL_TURN.toString())
|
||||
val simulateTextField = UncivTextField("Turn", DebugUtils.SIMULATE_UNTIL_TURN.toString())
|
||||
val invalidInputLabel = "This is not a valid integer!".toLabel().also { it.isVisible = false }
|
||||
simulateButton.onClick {
|
||||
val simulateUntilTurns = simulateTextField.text.toIntOrNull()
|
||||
|
@ -9,11 +9,9 @@ import com.unciv.logic.files.IMediaFinder
|
||||
import com.unciv.logic.multiplayer.OnlineMultiplayer
|
||||
import com.unciv.logic.multiplayer.storage.FileStorageRateLimitReached
|
||||
import com.unciv.logic.multiplayer.storage.MultiplayerAuthException
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.models.metadata.GameSettings
|
||||
import com.unciv.models.metadata.GameSettings.GameSetting
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.addSeparator
|
||||
import com.unciv.ui.components.extensions.brighten
|
||||
import com.unciv.ui.components.extensions.format
|
||||
@ -113,7 +111,7 @@ private fun addMultiplayerServerOptions(
|
||||
} else {
|
||||
"https://"
|
||||
}
|
||||
val multiplayerServerTextField = UncivTextField.create("Server address", textToShowForMultiplayerAddress)
|
||||
val multiplayerServerTextField = UncivTextField("Server address", textToShowForMultiplayerAddress)
|
||||
multiplayerServerTextField.setTextFieldFilter { _, c -> c !in " \r\n\t\\" }
|
||||
multiplayerServerTextField.programmaticChangeEvents = true
|
||||
val serverIpTable = Table()
|
||||
@ -160,7 +158,7 @@ private fun addMultiplayerServerOptions(
|
||||
}).row()
|
||||
|
||||
if (UncivGame.Current.onlineMultiplayer.multiplayerServer.featureSet.authVersion > 0) {
|
||||
val passwordTextField = UncivTextField.create(
|
||||
val passwordTextField = UncivTextField(
|
||||
settings.multiplayer.passwords[settings.multiplayer.server] ?: "Password"
|
||||
)
|
||||
val setPasswordButton = "Set password".toTextButton()
|
||||
|
@ -10,7 +10,7 @@ import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.stats.INamed
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.disable
|
||||
import com.unciv.ui.components.extensions.enable
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
@ -34,7 +34,7 @@ class CivilopediaSearchPopup(
|
||||
private val linkAction: (String) -> Unit
|
||||
) : Popup(pediaScreen) {
|
||||
private var ruleset = pediaScreen.ruleset
|
||||
private val searchText = UncivTextField.create("") // Always focused, "hint" never seen
|
||||
private val searchText = UncivTextField("") // Always focused, "hint" never seen
|
||||
private val modSelect = ModSelectBox()
|
||||
private lateinit var resultExpander: ExpanderTab
|
||||
private val resultCell: Cell<Actor?>
|
||||
|
@ -11,7 +11,7 @@ import com.unciv.Constants
|
||||
import com.unciv.GUI
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.logic.map.mapunit.MapUnit
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.surroundWithCircle
|
||||
import com.unciv.ui.components.extensions.toCheckBox
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
@ -34,7 +34,7 @@ class DevConsolePopup(val screen: WorldScreen) : Popup(screen) {
|
||||
|
||||
private var currentHistoryEntry = history.size
|
||||
|
||||
private val textField = UncivTextField.create("", "") // always has focus, so a hint won't show
|
||||
private val textField = UncivTextField("") // always has focus, so a hint won't show
|
||||
private val responseLabel = "".toLabel(Color.RED).apply { wrap = true }
|
||||
private val inputWrapper = Table()
|
||||
|
||||
|
@ -21,7 +21,7 @@ import com.unciv.models.metadata.GameParameters
|
||||
import com.unciv.models.metadata.GameSetupInfo
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.input.KeyCharAndCode
|
||||
import com.unciv.ui.components.input.KeyShortcutDispatcherVeto
|
||||
import com.unciv.ui.components.input.KeyboardPanningListener
|
||||
@ -85,7 +85,7 @@ class MapEditorScreen(map: TileMap? = null) : BaseScreen(), RecreateOnResize {
|
||||
val tabs: MapEditorMainTabs
|
||||
var tileClickHandler: ((tile: Tile)->Unit)? = null
|
||||
private var zoomController: ZoomButtonPair? = null
|
||||
val descriptionTextField = UncivTextField.create("Enter a description for the users of this map")
|
||||
val descriptionTextField = UncivTextField("Enter a description for the users of this map")
|
||||
|
||||
private val highlightedTileGroups = mutableListOf<TileGroup>()
|
||||
|
||||
|
@ -9,7 +9,7 @@ import com.unciv.logic.files.MapSaver
|
||||
import com.unciv.logic.map.MapGeneratedMainType
|
||||
import com.unciv.logic.map.TileMap
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.isEnabled
|
||||
import com.unciv.ui.components.extensions.toTextButton
|
||||
import com.unciv.ui.components.input.KeyCharAndCode
|
||||
@ -45,7 +45,7 @@ class MapEditorSaveTab(
|
||||
private val deleteButton = "Delete map".toTextButton()
|
||||
private val quitButton = "Exit map editor".toTextButton()
|
||||
|
||||
private val mapNameTextField = UncivTextField.create("Map Name")
|
||||
private val mapNameTextField = UncivTextField("Map Name")
|
||||
|
||||
private var chosenMap: FileHandle? = null
|
||||
|
||||
|
@ -7,7 +7,7 @@ import com.unciv.Constants
|
||||
import com.unciv.models.metadata.ModCategories
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.widgets.ExpanderTab
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
||||
import com.unciv.ui.components.extensions.surroundWithCircle
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
@ -78,7 +78,7 @@ internal class ModManagementOptions(private val modManagementScreen: ModManageme
|
||||
return Filter(textField.text, category.topic)
|
||||
}
|
||||
|
||||
private val textField = UncivTextField.create("Enter search text")
|
||||
private val textField = UncivTextField("Enter search text")
|
||||
|
||||
var category = ModCategories.default()
|
||||
|
||||
|
@ -12,8 +12,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.badlogic.gdx.utils.SerializationException
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.json.fromJsonFile
|
||||
import com.unciv.json.json
|
||||
import com.unciv.logic.UncivShowableException
|
||||
import com.unciv.logic.github.Github
|
||||
import com.unciv.logic.github.Github.repoNameToFolderName
|
||||
@ -22,7 +20,7 @@ import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.tilesets.TileSetCache
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.addSeparator
|
||||
import com.unciv.ui.components.extensions.disable
|
||||
import com.unciv.ui.components.extensions.enable
|
||||
@ -409,7 +407,7 @@ class ModManagementScreen private constructor(
|
||||
downloadButton.onClick {
|
||||
val popup = Popup(this)
|
||||
popup.addGoodSizedLabel("Please enter the mod repository -or- archive zip -or- branch -or- release url:").row()
|
||||
val textField = UncivTextField.create("").apply { maxLength = 666 }
|
||||
val textField = UncivTextField("").apply { maxLength = 666 }
|
||||
popup.add(textField).width(stage.width / 2).row()
|
||||
val pasteLinkButton = "Paste from clipboard".toTextButton()
|
||||
pasteLinkButton.onClick {
|
||||
|
@ -8,7 +8,7 @@ import com.unciv.logic.multiplayer.FriendList
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.screens.pickerscreens.PickerScreen
|
||||
import com.unciv.ui.popups.ToastPopup
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.enable
|
||||
import com.unciv.ui.components.input.onClick
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
@ -17,9 +17,9 @@ import java.util.UUID
|
||||
|
||||
class AddFriendScreen : PickerScreen() {
|
||||
init {
|
||||
val friendNameTextField = UncivTextField.create("Please input a name for your friend!")
|
||||
val friendNameTextField = UncivTextField("Please input a name for your friend!")
|
||||
val pastePlayerIDButton = "Paste player ID from clipboard".toTextButton()
|
||||
val playerIDTextField = UncivTextField.create("Please input a player ID for your friend!")
|
||||
val playerIDTextField = UncivTextField("Please input a player ID for your friend!")
|
||||
val friendlist = FriendList()
|
||||
|
||||
topTable.add("Friend name".toLabel()).row()
|
||||
|
@ -5,7 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.IdChecker
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.enable
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.components.extensions.toTextButton
|
||||
@ -23,8 +23,8 @@ import java.util.UUID
|
||||
|
||||
class AddMultiplayerGameScreen(multiplayerScreen: MultiplayerScreen) : PickerScreen() {
|
||||
init {
|
||||
val gameNameTextField = UncivTextField.create("Game name")
|
||||
val gameIDTextField = UncivTextField.create("GameID")
|
||||
val gameNameTextField = UncivTextField("Game name")
|
||||
val gameIDTextField = UncivTextField("GameID")
|
||||
val pasteGameIDButton = "Paste gameID from clipboard".toTextButton()
|
||||
pasteGameIDButton.onClick {
|
||||
gameIDTextField.text = Gdx.app.clipboard.contents
|
||||
|
@ -10,7 +10,7 @@ import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.screens.pickerscreens.PickerScreen
|
||||
import com.unciv.ui.popups.ConfirmPopup
|
||||
import com.unciv.ui.popups.ToastPopup
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.enable
|
||||
import com.unciv.ui.components.input.onClick
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
@ -19,9 +19,9 @@ import java.util.UUID
|
||||
|
||||
class EditFriendScreen(selectedFriend: FriendList.Friend) : PickerScreen() {
|
||||
init {
|
||||
val friendNameTextField = UncivTextField.create("Please input a name for your friend!", selectedFriend.name)
|
||||
val friendNameTextField = UncivTextField("Please input a name for your friend!", selectedFriend.name)
|
||||
val pastePlayerIDButton = "Player ID from clipboard".toTextButton()
|
||||
val playerIDTextField = UncivTextField.create("Please input a player ID for your friend!", selectedFriend.playerID)
|
||||
val playerIDTextField = UncivTextField("Please input a player ID for your friend!", selectedFriend.playerID)
|
||||
val deleteFriendButton = "Delete".toTextButton()
|
||||
val friendlist = FriendList()
|
||||
|
||||
|
@ -7,7 +7,7 @@ import com.unciv.Constants
|
||||
import com.unciv.logic.multiplayer.OnlineMultiplayerGame
|
||||
import com.unciv.logic.multiplayer.storage.MultiplayerAuthException
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.disable
|
||||
import com.unciv.ui.components.extensions.enable
|
||||
import com.unciv.ui.components.extensions.toTextButton
|
||||
@ -190,7 +190,7 @@ class MultiplayerScreen : PickerScreen() {
|
||||
val btn = "Rename".toTextButton().apply { disable() }
|
||||
btn.onClick {
|
||||
Popup(this).apply {
|
||||
val textField = UncivTextField.create("Game name", selectedGame!!.name)
|
||||
val textField = UncivTextField("Game name", selectedGame!!.name)
|
||||
add(textField).width(stageToShowOn.width / 2).row()
|
||||
val saveButton = "Save".toTextButton()
|
||||
|
||||
|
@ -13,7 +13,7 @@ import com.unciv.logic.map.mapgenerator.MapResourceSetting
|
||||
import com.unciv.logic.map.MapShape
|
||||
import com.unciv.logic.map.MapSize
|
||||
import com.unciv.logic.map.MapType
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.extensions.pad
|
||||
import com.unciv.ui.components.extensions.toCheckBox
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
@ -205,7 +205,7 @@ class MapParametersTable(
|
||||
|
||||
private fun addHexagonalSizeTable() {
|
||||
val defaultRadius = mapParameters.mapSize.radius.toString()
|
||||
customMapSizeRadius = UncivTextField.create("Radius", defaultRadius).apply {
|
||||
customMapSizeRadius = UncivTextField("Radius", defaultRadius).apply {
|
||||
textFieldFilter = DigitsOnlyFilter()
|
||||
}
|
||||
customMapSizeRadius.onChange {
|
||||
@ -219,12 +219,12 @@ class MapParametersTable(
|
||||
|
||||
private fun addRectangularSizeTable() {
|
||||
val defaultWidth = mapParameters.mapSize.width.toString()
|
||||
customMapWidth = UncivTextField.create("Width", defaultWidth).apply {
|
||||
customMapWidth = UncivTextField("Width", defaultWidth).apply {
|
||||
textFieldFilter = DigitsOnlyFilter()
|
||||
}
|
||||
|
||||
val defaultHeight = mapParameters.mapSize.height.toString()
|
||||
customMapHeight = UncivTextField.create("Height", defaultHeight).apply {
|
||||
customMapHeight = UncivTextField("Height", defaultHeight).apply {
|
||||
textFieldFilter = DigitsOnlyFilter()
|
||||
}
|
||||
|
||||
@ -360,7 +360,7 @@ class MapParametersTable(
|
||||
private fun addAdvancedControls(table: Table) {
|
||||
table.defaults().pad(5f)
|
||||
|
||||
seedTextField = UncivTextField.create("RNG Seed", mapParameters.seed.toString())
|
||||
seedTextField = UncivTextField("RNG Seed", mapParameters.seed.toString())
|
||||
seedTextField.textFieldFilter = DigitsOnlyFilter()
|
||||
|
||||
// If the field is empty, fallback seed value to 0
|
||||
|
@ -17,7 +17,7 @@ import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.nation.Nation
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.input.KeyCharAndCode
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.widgets.WrappableLabel
|
||||
import com.unciv.ui.components.extensions.darken
|
||||
import com.unciv.ui.components.extensions.isEnabled
|
||||
@ -229,7 +229,7 @@ class PlayerPickerTable(
|
||||
private fun Table.addPlayerTableMultiplayerControls(player: Player) {
|
||||
row()
|
||||
|
||||
val playerIdTextField = UncivTextField.create("Please input Player ID!", player.playerId)
|
||||
val playerIdTextField = UncivTextField("Please input Player ID!", player.playerId)
|
||||
add(playerIdTextField).colspan(2).fillX().pad(5f)
|
||||
val errorLabel = "✘".toLabel(Color.RED)
|
||||
add(errorLabel).pad(5f).row()
|
||||
|
@ -9,7 +9,7 @@ import com.unciv.logic.GameInfo
|
||||
import com.unciv.logic.files.PlatformSaverLoader
|
||||
import com.unciv.logic.files.UncivFiles
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
||||
import com.unciv.ui.components.extensions.disable
|
||||
import com.unciv.ui.components.extensions.enable
|
||||
@ -32,7 +32,7 @@ class SaveGameScreen(val gameInfo: GameInfo) : LoadOrSaveScreen("Current saves")
|
||||
const val saveToCustomText = "Save to custom location"
|
||||
}
|
||||
|
||||
private val gameNameTextField = UncivTextField.create(nameFieldLabelText)
|
||||
private val gameNameTextField = UncivTextField(nameFieldLabelText)
|
||||
|
||||
init {
|
||||
setDefaultCloseAction()
|
||||
|
Loading…
x
Reference in New Issue
Block a user