mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-23 19:43:13 -04:00
Custom save/load UI tweaks and blocking saving online MP games locally (#10358)
* Allow typing Y and N in file names in Linux custom save file dialog * Fix default custom save location suggestion on X11 * Minor linting * Allow clean reactivation of custom buttons after cancelling the file chooser * User-Cancel support on Android and non-X11 desktop * Block custom save for online multiplayer games * Fix X11 custom save remembering location * Fix X11 custom save "Save" button enabling, forbid potentially bad names * Add overwrite confirmation to X11 custom save * Redefine how local saving of online multiplayer games is blocked
This commit is contained in:
parent
74cfda9854
commit
eb33b7d513
@ -10,9 +10,6 @@ import com.unciv.utils.Log
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
private class Request(
|
||||
val onFileChosen: (Uri) -> Unit
|
||||
)
|
||||
|
||||
class AndroidSaverLoader(private val activity: Activity) : PlatformSaverLoader {
|
||||
|
||||
@ -20,6 +17,13 @@ class AndroidSaverLoader(private val activity: Activity) : PlatformSaverLoader {
|
||||
private val requests = HashMap<Int, Request>()
|
||||
private var requestCode = 100
|
||||
|
||||
private class Request(
|
||||
val onFileChosen: (Uri) -> Unit,
|
||||
onError: (ex: Exception) -> Unit
|
||||
) {
|
||||
val onCancel: () -> Unit = { onError(PlatformSaverLoader.Cancelled()) }
|
||||
}
|
||||
|
||||
override fun saveGame(
|
||||
data: String,
|
||||
suggestedLocation: String,
|
||||
@ -31,7 +35,7 @@ class AndroidSaverLoader(private val activity: Activity) : PlatformSaverLoader {
|
||||
val suggestedUri = Uri.parse(suggestedLocation)
|
||||
val fileName = getFilename(suggestedUri, suggestedLocation)
|
||||
|
||||
val onFileChosen = {uri: Uri ->
|
||||
val onFileChosen = { uri: Uri ->
|
||||
var stream: OutputStream? = null
|
||||
try {
|
||||
stream = contentResolver.openOutputStream(uri, "rwt")
|
||||
@ -44,14 +48,15 @@ class AndroidSaverLoader(private val activity: Activity) : PlatformSaverLoader {
|
||||
}
|
||||
}
|
||||
|
||||
requests[requestCode] = Request(onFileChosen)
|
||||
requests[requestCode] = Request(onFileChosen, onError)
|
||||
openSaveFileChooser(fileName, suggestedUri, requestCode)
|
||||
requestCode += 1
|
||||
}
|
||||
|
||||
override fun loadGame(
|
||||
onLoaded: (data: String, location: String) -> Unit,
|
||||
onError: (ex: Exception) -> Unit) {
|
||||
onError: (ex: Exception) -> Unit
|
||||
) {
|
||||
|
||||
val onFileChosen = {uri: Uri ->
|
||||
var stream: InputStream? = null
|
||||
@ -66,14 +71,16 @@ class AndroidSaverLoader(private val activity: Activity) : PlatformSaverLoader {
|
||||
}
|
||||
}
|
||||
|
||||
requests[requestCode] = Request(onFileChosen)
|
||||
requests[requestCode] = Request(onFileChosen, onError)
|
||||
openLoadFileChooser(requestCode)
|
||||
requestCode += 1
|
||||
}
|
||||
|
||||
fun onActivityResult(requestCode: Int, data: Intent?) {
|
||||
val uri: Uri = data?.data ?: return
|
||||
val request = requests.remove(requestCode) ?: return
|
||||
// data is null if the user back out of the activity without choosing a file
|
||||
if (data == null) return request.onCancel()
|
||||
val uri: Uri = data.data ?: return
|
||||
request.onFileChosen(uri)
|
||||
}
|
||||
|
||||
|
@ -16,22 +16,22 @@ import com.badlogic.gdx.scenes.scene2d.ui.Skin
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.badlogic.gdx.utils.Array as GdxArray
|
||||
import com.unciv.Constants
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.widgets.AutoScrollPane
|
||||
import com.unciv.ui.components.input.KeyboardBinding
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.extensions.addSeparator
|
||||
import com.unciv.ui.components.extensions.isEnabled
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.components.input.onChange
|
||||
import com.unciv.ui.components.input.onClick
|
||||
import com.unciv.ui.components.input.onDoubleClick
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.components.widgets.AutoScrollPane
|
||||
import com.unciv.ui.popups.ConfirmPopup
|
||||
import com.unciv.ui.popups.Popup
|
||||
import java.io.File
|
||||
import java.io.FileFilter
|
||||
import com.badlogic.gdx.utils.Array as GdxArray
|
||||
|
||||
typealias ResultListener = (success: Boolean, file: FileHandle) -> Unit
|
||||
|
||||
@ -125,7 +125,13 @@ open class FileChooser(
|
||||
innerTable.top().left()
|
||||
|
||||
fileList.selection.setProgrammaticChangeEvents(false)
|
||||
fileNameInput.setTextFieldListener { textField, _ -> result = textField.text }
|
||||
fileNameInput.setTextFieldListener { textField, _ ->
|
||||
result = textField.text
|
||||
enableOKButton()
|
||||
}
|
||||
fileNameInput.setTextFieldFilter { _, char ->
|
||||
char != File.separatorChar
|
||||
}
|
||||
|
||||
if (title != null) {
|
||||
addGoodSizedLabel(title).colspan(2).center().row()
|
||||
@ -138,10 +144,10 @@ open class FileChooser(
|
||||
fileNameCell = add().colspan(2).growX()
|
||||
row()
|
||||
|
||||
addCloseButton("Cancel", KeyboardBinding.Cancel) {
|
||||
addCloseButton("Cancel") {
|
||||
reportResult(false)
|
||||
}
|
||||
okButton = addOKButton(Constants.OK, KeyboardBinding.Confirm) {
|
||||
okButton = addOKButton(Constants.OK) {
|
||||
reportResult(true)
|
||||
}.actor
|
||||
equalizeLastTwoButtonWidths()
|
||||
@ -175,7 +181,18 @@ open class FileChooser(
|
||||
override fun getMaxHeight() = maxHeight
|
||||
|
||||
private fun reportResult(success: Boolean) {
|
||||
resultListener?.invoke(success, getResult())
|
||||
val file = getResult()
|
||||
if (!(success && fileNameEnabled && file.exists())) {
|
||||
resultListener?.invoke(success, file)
|
||||
return
|
||||
}
|
||||
ConfirmPopup(stageToShowOn, "Do you want to overwrite ${file.name()}?", "Overwrite",
|
||||
restoreDefault = {
|
||||
resultListener?.invoke(false, file)
|
||||
}, action = {
|
||||
resultListener?.invoke(true, file)
|
||||
}
|
||||
).open(true)
|
||||
}
|
||||
|
||||
private fun makeAbsolute(file: FileHandle): FileHandle {
|
||||
@ -200,7 +217,11 @@ open class FileChooser(
|
||||
startFile == null ->
|
||||
Gdx.files.absolute(absoluteLocalPath)
|
||||
startFile.isDirectory -> startFile
|
||||
else -> startFile.parent()
|
||||
else -> {
|
||||
fileNameInput.text = startFile.name()
|
||||
result = startFile.name()
|
||||
startFile.parent()
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
@ -253,12 +274,17 @@ open class FileChooser(
|
||||
}
|
||||
|
||||
private fun enableOKButton() {
|
||||
fun getEnable(): Boolean {
|
||||
fun getLoadEnable(): Boolean {
|
||||
val file = fileList.selected?.file ?: return false
|
||||
if (!file.exists()) return false
|
||||
return (allowFolderSelect || !file.isDirectory)
|
||||
}
|
||||
okButton.isEnabled = getEnable()
|
||||
fun getSaveEnable(): Boolean {
|
||||
if (currentDir?.exists() != true) return false
|
||||
if (allowFolderSelect) return true
|
||||
return result?.run { isEmpty() || startsWith(' ') || endsWith(' ') } == false
|
||||
}
|
||||
okButton.isEnabled = if (fileNameEnabled) getSaveEnable() else getLoadEnable()
|
||||
}
|
||||
|
||||
fun setOkButtonText(text: String) {
|
||||
|
@ -4,7 +4,14 @@ import com.badlogic.gdx.Gdx
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.utils.Concurrency
|
||||
import java.awt.GraphicsEnvironment
|
||||
import java.io.File
|
||||
|
||||
|
||||
/**
|
||||
* A dedicated PlatformSaverLoader for X11-based Linux boxes, as using the Java AWT/Swing file chooser dialog will kill the App after closing that dialog
|
||||
*
|
||||
* Tested as required from Mint 20.1 up to Mint 21.2, seems independent of Java runtime (mostly tested with adoptium temurin 11 and 17 versions).
|
||||
*/
|
||||
class LinuxX11SaverLoader : PlatformSaverLoader {
|
||||
override fun saveGame(
|
||||
data: String,
|
||||
@ -13,15 +20,21 @@ class LinuxX11SaverLoader : PlatformSaverLoader {
|
||||
onError: (ex: Exception) -> Unit
|
||||
) {
|
||||
Concurrency.runOnGLThread {
|
||||
FileChooser.createSaveDialog(stage, "Save game", Gdx.files.absolute(suggestedLocation)) {
|
||||
val startLocation =
|
||||
if (suggestedLocation.startsWith(File.separator)) Gdx.files.absolute(suggestedLocation)
|
||||
else if (Gdx.files.external(suggestedLocation).parent().exists()) Gdx.files.external(suggestedLocation)
|
||||
else Gdx.files.local(suggestedLocation)
|
||||
FileChooser.createSaveDialog(stage, "Save game", startLocation) {
|
||||
success, file ->
|
||||
if (!success) return@createSaveDialog
|
||||
try {
|
||||
file.writeString(data, false, Charsets.UTF_8.name())
|
||||
onSaved(file.path())
|
||||
} catch (ex: Exception) {
|
||||
onError(ex)
|
||||
}
|
||||
if (!success)
|
||||
onError(PlatformSaverLoader.Cancelled())
|
||||
else
|
||||
try {
|
||||
file.writeString(data, false, Charsets.UTF_8.name())
|
||||
onSaved(file.path())
|
||||
} catch (ex: Exception) {
|
||||
onError(ex)
|
||||
}
|
||||
}.open(true)
|
||||
}
|
||||
}
|
||||
@ -32,13 +45,15 @@ class LinuxX11SaverLoader : PlatformSaverLoader {
|
||||
) {
|
||||
Concurrency.runOnGLThread {
|
||||
FileChooser.createLoadDialog(stage, "Load game") { success, file ->
|
||||
if (!success) return@createLoadDialog
|
||||
try {
|
||||
val data = file.readString(Charsets.UTF_8.name())
|
||||
onLoaded(data, file.path())
|
||||
} catch (ex: Exception) {
|
||||
onError(ex)
|
||||
}
|
||||
if (!success)
|
||||
onError(PlatformSaverLoader.Cancelled())
|
||||
else
|
||||
try {
|
||||
val data = file.readString(Charsets.UTF_8.name())
|
||||
onLoaded(data, file.path())
|
||||
} catch (ex: Exception) {
|
||||
onError(ex)
|
||||
}
|
||||
}.open(true)
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,9 @@ interface PlatformSaverLoader {
|
||||
onError: (Exception) -> Unit = {} // On-load-error callback
|
||||
)
|
||||
|
||||
/** Invisible Exception can be used with onError callbacks to indicate the User cancelled the operation and needs no message */
|
||||
class Cancelled : Exception()
|
||||
|
||||
companion object {
|
||||
val None = object : PlatformSaverLoader {
|
||||
override fun saveGame(
|
||||
|
@ -22,9 +22,9 @@ import com.unciv.ui.screens.savescreens.Gzip
|
||||
import com.unciv.utils.Concurrency
|
||||
import com.unciv.utils.Log
|
||||
import com.unciv.utils.debug
|
||||
import kotlinx.coroutines.Job
|
||||
import java.io.File
|
||||
import java.io.Writer
|
||||
import kotlinx.coroutines.Job
|
||||
|
||||
private const val SAVE_FILES_FOLDER = "SaveFiles"
|
||||
private const val MULTIPLAYER_FILES_FOLDER = "MultiplayerGames"
|
||||
@ -199,12 +199,13 @@ class UncivFiles(
|
||||
game: GameInfo,
|
||||
gameName: String,
|
||||
onSaved: () -> Unit,
|
||||
onError: (Exception) -> Unit) {
|
||||
onError: (Exception) -> Unit
|
||||
) {
|
||||
val saveLocation = game.customSaveLocation ?: Gdx.files.local(gameName).path()
|
||||
|
||||
try {
|
||||
val data = gameInfoToString(game)
|
||||
debug("Saving GameInfo %s to custom location %s", game.gameId, saveLocation)
|
||||
debug("Initiating UI to save GameInfo %s to custom location %s", game.gameId, saveLocation)
|
||||
saverLoader.saveGame(data, saveLocation,
|
||||
{ location ->
|
||||
game.customSaveLocation = location
|
||||
|
@ -8,27 +8,28 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.badlogic.gdx.utils.SerializationException
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.MissingModsException
|
||||
import com.unciv.logic.files.UncivFiles
|
||||
import com.unciv.logic.UncivShowableException
|
||||
import com.unciv.logic.files.PlatformSaverLoader
|
||||
import com.unciv.logic.files.UncivFiles
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.screens.pickerscreens.Github
|
||||
import com.unciv.ui.popups.Popup
|
||||
import com.unciv.ui.popups.ToastPopup
|
||||
import com.unciv.ui.components.input.KeyCharAndCode
|
||||
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
||||
import com.unciv.ui.components.extensions.disable
|
||||
import com.unciv.ui.components.extensions.enable
|
||||
import com.unciv.ui.components.extensions.isEnabled
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.components.extensions.toTextButton
|
||||
import com.unciv.ui.components.input.KeyCharAndCode
|
||||
import com.unciv.ui.components.input.keyShortcuts
|
||||
import com.unciv.ui.components.input.onActivation
|
||||
import com.unciv.ui.components.input.onClick
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.components.extensions.toTextButton
|
||||
import com.unciv.ui.popups.LoadingPopup
|
||||
import com.unciv.ui.popups.Popup
|
||||
import com.unciv.ui.popups.ToastPopup
|
||||
import com.unciv.ui.screens.pickerscreens.Github
|
||||
import com.unciv.ui.screens.pickerscreens.Github.folderNameToRepoName
|
||||
import com.unciv.utils.Log
|
||||
import com.unciv.utils.Concurrency
|
||||
import com.unciv.utils.Log
|
||||
import com.unciv.utils.launchOnGLThread
|
||||
import java.io.FileNotFoundException
|
||||
|
||||
@ -170,25 +171,26 @@ class LoadGameScreen : LoadOrSaveScreen() {
|
||||
}
|
||||
|
||||
private fun Table.addLoadFromCustomLocationButton() {
|
||||
val loadFromCustomLocation = loadFromCustomLocation.toTextButton()
|
||||
loadFromCustomLocation.onClick {
|
||||
val loadFromCustomLocationButton = loadFromCustomLocation.toTextButton()
|
||||
loadFromCustomLocationButton.onClick {
|
||||
errorLabel.isVisible = false
|
||||
loadFromCustomLocation.setText(Constants.loading.tr())
|
||||
loadFromCustomLocation.disable()
|
||||
loadFromCustomLocationButton.setText(Constants.loading.tr())
|
||||
loadFromCustomLocationButton.disable()
|
||||
Concurrency.run(Companion.loadFromCustomLocation) {
|
||||
game.files.loadGameFromCustomLocation(
|
||||
{
|
||||
Concurrency.run { game.loadGame(it, true) }
|
||||
loadFromCustomLocation.enable()
|
||||
},
|
||||
{
|
||||
handleLoadGameException(it, "Could not load game from custom location!")
|
||||
loadFromCustomLocation.enable()
|
||||
if (it !is PlatformSaverLoader.Cancelled)
|
||||
handleLoadGameException(it, "Could not load game from custom location!")
|
||||
loadFromCustomLocationButton.setText(loadFromCustomLocation.tr())
|
||||
loadFromCustomLocationButton.enable()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
add(loadFromCustomLocation).row()
|
||||
add(loadFromCustomLocationButton).row()
|
||||
}
|
||||
|
||||
private fun getCopyExistingSaveToClipboardButton(): TextButton {
|
||||
|
@ -1,21 +1,24 @@
|
||||
package com.unciv.ui.screens.savescreens
|
||||
|
||||
import com.unciv.ui.screens.mainmenuscreen.MainMenuScreen
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.GameInfo
|
||||
import com.unciv.logic.UncivShowableException
|
||||
import com.unciv.ui.popups.LoadingPopup
|
||||
import com.unciv.ui.popups.ToastPopup
|
||||
import com.unciv.ui.screens.mainmenuscreen.MainMenuScreen
|
||||
import com.unciv.ui.screens.worldscreen.WorldScreen
|
||||
import com.unciv.utils.Concurrency
|
||||
import com.unciv.utils.launchOnGLThread
|
||||
import com.unciv.utils.Log
|
||||
import com.unciv.utils.launchOnGLThread
|
||||
|
||||
|
||||
//todo reduce code duplication
|
||||
|
||||
object QuickSave {
|
||||
fun save(gameInfo: GameInfo, screen: WorldScreen) {
|
||||
// See #10353 - we don't support locally saving an online multiplayer game
|
||||
if (gameInfo.gameParameters.isOnlineMultiplayer) return
|
||||
|
||||
val files = UncivGame.Current.files
|
||||
val toast = ToastPopup("Quicksaving...", screen)
|
||||
Concurrency.runOnNonDaemonThreadPool("QuickSaveGame") {
|
||||
|
@ -6,18 +6,19 @@ import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.UncivGame
|
||||
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.input.KeyCharAndCode
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
||||
import com.unciv.ui.components.extensions.disable
|
||||
import com.unciv.ui.components.extensions.enable
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.components.extensions.toTextButton
|
||||
import com.unciv.ui.components.input.KeyCharAndCode
|
||||
import com.unciv.ui.components.input.keyShortcuts
|
||||
import com.unciv.ui.components.input.onActivation
|
||||
import com.unciv.ui.components.input.onClick
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.components.extensions.toTextButton
|
||||
import com.unciv.ui.popups.ConfirmPopup
|
||||
import com.unciv.ui.popups.ToastPopup
|
||||
import com.unciv.utils.Concurrency
|
||||
@ -25,7 +26,13 @@ import com.unciv.utils.launchOnGLThread
|
||||
|
||||
|
||||
class SaveGameScreen(val gameInfo: GameInfo) : LoadOrSaveScreen("Current saves") {
|
||||
private val gameNameTextField = UncivTextField.create("Saved game name")
|
||||
companion object {
|
||||
const val nameFieldLabelText = "Saved game name"
|
||||
const val savingText = "Saving..."
|
||||
const val saveToCustomText = "Save to custom location"
|
||||
}
|
||||
|
||||
private val gameNameTextField = UncivTextField.create(nameFieldLabelText)
|
||||
|
||||
init {
|
||||
setDefaultCloseAction()
|
||||
@ -63,7 +70,7 @@ class SaveGameScreen(val gameInfo: GameInfo) : LoadOrSaveScreen("Current saves")
|
||||
gameNameTextField.text = defaultSaveName
|
||||
gameNameTextField.setSelection(0, defaultSaveName.length)
|
||||
|
||||
add("Saved game name".toLabel()).row()
|
||||
add(nameFieldLabelText.toLabel()).row()
|
||||
add(gameNameTextField).width(300f).row()
|
||||
}
|
||||
|
||||
@ -82,22 +89,24 @@ class SaveGameScreen(val gameInfo: GameInfo) : LoadOrSaveScreen("Current saves")
|
||||
}
|
||||
|
||||
private fun Table.addSaveToCustomLocation() {
|
||||
val saveToCustomLocation = "Save to custom location".toTextButton()
|
||||
val saveToCustomLocation = saveToCustomText.toTextButton()
|
||||
val errorLabel = "".toLabel(Color.RED)
|
||||
saveToCustomLocation.onClick {
|
||||
errorLabel.setText("")
|
||||
saveToCustomLocation.setText("Saving...".tr())
|
||||
saveToCustomLocation.setText(savingText.tr())
|
||||
saveToCustomLocation.disable()
|
||||
Concurrency.runOnNonDaemonThreadPool("Save to custom location") {
|
||||
Concurrency.runOnNonDaemonThreadPool(saveToCustomText) {
|
||||
|
||||
game.files.saveGameToCustomLocation(gameInfo, gameNameTextField.text,
|
||||
{
|
||||
game.popScreen()
|
||||
saveToCustomLocation.enable()
|
||||
},
|
||||
{
|
||||
errorLabel.setText("Could not save game to custom location!".tr())
|
||||
it.printStackTrace()
|
||||
if (it !is PlatformSaverLoader.Cancelled) {
|
||||
errorLabel.setText("Could not save game to custom location!".tr())
|
||||
it.printStackTrace()
|
||||
}
|
||||
saveToCustomLocation.setText(saveToCustomText.tr())
|
||||
saveToCustomLocation.enable()
|
||||
}
|
||||
)
|
||||
@ -108,7 +117,7 @@ class SaveGameScreen(val gameInfo: GameInfo) : LoadOrSaveScreen("Current saves")
|
||||
}
|
||||
|
||||
private fun saveGame() {
|
||||
rightSideButton.setText("Saving...".tr())
|
||||
rightSideButton.setText(savingText.tr())
|
||||
Concurrency.runOnNonDaemonThreadPool("SaveGame") {
|
||||
game.files.saveGame(gameInfo, gameNameTextField.text) {
|
||||
launchOnGLThread {
|
||||
|
@ -233,6 +233,12 @@ class WorldScreen(
|
||||
game.pushScreen(newGameScreen)
|
||||
}
|
||||
|
||||
fun openSaveGameScreen() {
|
||||
// See #10353 - we don't support locally saving an online multiplayer game
|
||||
if (gameInfo.gameParameters.isOnlineMultiplayer) return
|
||||
game.pushScreen(SaveGameScreen(gameInfo))
|
||||
}
|
||||
|
||||
private fun addKeyboardPresses() {
|
||||
// Space and N are assigned in NextTurnButton constructor
|
||||
// Functions that have a big button are assigned there (WorldScreenTopBar, TechPolicyDiplomacyButtons..)
|
||||
@ -254,7 +260,7 @@ class WorldScreen(
|
||||
globalShortcuts.add(KeyboardBinding.Options) { // Game Options
|
||||
openOptionsPopup { nextTurnButton.update() }
|
||||
}
|
||||
globalShortcuts.add(KeyboardBinding.SaveGame) { game.pushScreen(SaveGameScreen(gameInfo)) } // Save
|
||||
globalShortcuts.add(KeyboardBinding.SaveGame) { openSaveGameScreen() } // Save
|
||||
globalShortcuts.add(KeyboardBinding.LoadGame) { game.pushScreen(LoadGameScreen()) } // Load
|
||||
globalShortcuts.add(KeyboardBinding.QuitGame) { game.popScreen() } // WorldScreen is the last screen, so this quits
|
||||
globalShortcuts.add(KeyboardBinding.NewGame) { openNewGameScreen() }
|
||||
|
@ -4,7 +4,6 @@ import com.unciv.ui.components.input.KeyboardBinding
|
||||
import com.unciv.ui.popups.Popup
|
||||
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen
|
||||
import com.unciv.ui.screens.savescreens.LoadGameScreen
|
||||
import com.unciv.ui.screens.savescreens.SaveGameScreen
|
||||
import com.unciv.ui.screens.victoryscreen.VictoryScreen
|
||||
import com.unciv.ui.screens.worldscreen.WorldScreen
|
||||
|
||||
@ -19,10 +18,11 @@ class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen, sc
|
||||
close()
|
||||
worldScreen.game.pushScreen(CivilopediaScreen(worldScreen.gameInfo.ruleset))
|
||||
}.row()
|
||||
addButton("Save game", KeyboardBinding.SaveGame) {
|
||||
close()
|
||||
worldScreen.game.pushScreen(SaveGameScreen(worldScreen.gameInfo))
|
||||
}.row()
|
||||
if (!worldScreen.gameInfo.gameParameters.isOnlineMultiplayer)
|
||||
addButton("Save game", KeyboardBinding.SaveGame) {
|
||||
close()
|
||||
worldScreen.openSaveGameScreen()
|
||||
}.row()
|
||||
addButton("Load game", KeyboardBinding.LoadGame) {
|
||||
close()
|
||||
worldScreen.game.pushScreen(LoadGameScreen())
|
||||
|
@ -2,7 +2,6 @@ package com.unciv.app.desktop
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.unciv.logic.files.PlatformSaverLoader
|
||||
import com.unciv.utils.Log
|
||||
import java.awt.Component
|
||||
import java.awt.EventQueue
|
||||
import java.awt.event.WindowEvent
|
||||
@ -76,7 +75,7 @@ class DesktopSaverLoader : PlatformSaverLoader {
|
||||
frame.dispose()
|
||||
|
||||
if (result == JFileChooser.CANCEL_OPTION) {
|
||||
return@invokeLater
|
||||
onError(PlatformSaverLoader.Cancelled())
|
||||
} else {
|
||||
val value = createValue(fileChooser.selectedFile)
|
||||
onSuccess(value, fileChooser.selectedFile.absolutePath)
|
||||
|
Loading…
x
Reference in New Issue
Block a user