From 8a024bf9fe8ba42e7ba55977abe8278347e91f01 Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Sun, 4 Jun 2023 07:41:58 +0200 Subject: [PATCH] Popups get the ability to scroll only the content without the buttons (#9513) * Popups get the ability to scroll only the content without the buttons * Centralize LoadingPopup * Split non-WorldScreenMenuPopup classes off from that file * Linting --- core/src/com/unciv/logic/files/FileChooser.kt | 13 +- core/src/com/unciv/ui/popups/AuthPopup.kt | 6 +- core/src/com/unciv/ui/popups/LoadingPopup.kt | 19 +++ core/src/com/unciv/ui/popups/Popup.kt | 144 +++++++++++++++--- .../unciv/ui/popups/options/OptionsPopup.kt | 2 +- .../src/com/unciv/ui/screens/LoadingScreen.kt | 12 +- .../screens/cityscreen/DetailedStatsPopup.kt | 2 +- .../screens/mainmenuscreen/MainMenuScreen.kt | 2 +- .../mapeditorscreen/tabs/MapEditorLoadTab.kt | 6 +- .../screens/overviewscreen/UnitUpgradeMenu.kt | 2 +- .../ui/screens/savescreens/LoadGameScreen.kt | 5 +- .../unciv/ui/screens/savescreens/QuickSave.kt | 7 +- .../mainmenu/WorldScreenCommunityPopup.kt | 26 ++++ .../mainmenu/WorldScreenMenuPopup.kt | 42 +---- .../mainmenu/WorldScreenMusicPopup.kt | 17 +++ 15 files changed, 213 insertions(+), 92 deletions(-) create mode 100644 core/src/com/unciv/ui/popups/LoadingPopup.kt create mode 100644 core/src/com/unciv/ui/screens/worldscreen/mainmenu/WorldScreenCommunityPopup.kt create mode 100644 core/src/com/unciv/ui/screens/worldscreen/mainmenu/WorldScreenMusicPopup.kt diff --git a/core/src/com/unciv/logic/files/FileChooser.kt b/core/src/com/unciv/logic/files/FileChooser.kt index 530da090aa..3054836d87 100644 --- a/core/src/com/unciv/logic/files/FileChooser.kt +++ b/core/src/com/unciv/logic/files/FileChooser.kt @@ -47,7 +47,7 @@ open class FileChooser( title: String?, startFile: FileHandle? = null, private val resultListener: ResultListener? = null -) : Popup(stageToShowOn, false) { +) : Popup(stageToShowOn, Scrollability.None) { // config var filter = FileFilter { true } set(value) { field = value; resetList() } @@ -123,21 +123,20 @@ open class FileChooser( init { innerTable.top().left() - innerTable.touchable = Touchable.enabled fileList.selection.setProgrammaticChangeEvents(false) fileNameInput.setTextFieldListener { textField, _ -> result = textField.text } if (title != null) { addGoodSizedLabel(title).colspan(2).center().row() - innerTable.addSeparator(height = 1f) + addSeparator(height = 1f) } add(pathLabelWrapper).colspan(2).fillX().row() - innerTable.addSeparator(Color.GRAY, height = 1f) + addSeparator(Color.GRAY, height = 1f) add(fileScroll).colspan(2).fill().row() - innerTable.addSeparator(height = 1f) - fileNameCell = innerTable.add().colspan(2).growX() - innerTable.row() + addSeparator(height = 1f) + fileNameCell = add().colspan(2).growX() + row() addCloseButton("Cancel", KeyboardBinding.Cancel) { reportResult(false) diff --git a/core/src/com/unciv/ui/popups/AuthPopup.kt b/core/src/com/unciv/ui/popups/AuthPopup.kt index 607d800390..299b19b395 100644 --- a/core/src/com/unciv/ui/popups/AuthPopup.kt +++ b/core/src/com/unciv/ui/popups/AuthPopup.kt @@ -24,10 +24,10 @@ class AuthPopup(stage: Stage, authSuccessful: ((Boolean) -> Unit)? = null) authSuccessful?.invoke(true) close() } catch (_: Exception) { - innerTable.clear() + clear() addGoodSizedLabel("Authentication failed").colspan(2).row() add(passwordField).colspan(2).growX().pad(16f, 0f, 16f, 0f).row() - addCloseButton(style=negativeButtonStyle) { authSuccessful?.invoke(false) }.growX().padRight(8f) + addCloseButton(style = negativeButtonStyle) { authSuccessful?.invoke(false) }.growX().padRight(8f) add(button).growX().padLeft(8f) return@onClick } @@ -35,7 +35,7 @@ class AuthPopup(stage: Stage, authSuccessful: ((Boolean) -> Unit)? = null) addGoodSizedLabel("Please enter your server password").colspan(2).row() add(passwordField).colspan(2).growX().pad(16f, 0f, 16f, 0f).row() - addCloseButton(style=negativeButtonStyle) { authSuccessful?.invoke(false) }.growX().padRight(8f) + addCloseButton(style = negativeButtonStyle) { authSuccessful?.invoke(false) }.growX().padRight(8f) add(button).growX().padLeft(8f) } } diff --git a/core/src/com/unciv/ui/popups/LoadingPopup.kt b/core/src/com/unciv/ui/popups/LoadingPopup.kt new file mode 100644 index 0000000000..c3a6fc7cd1 --- /dev/null +++ b/core/src/com/unciv/ui/popups/LoadingPopup.kt @@ -0,0 +1,19 @@ +package com.unciv.ui.popups + +import com.unciv.Constants +import com.unciv.ui.screens.LoadingScreen +import com.unciv.ui.screens.basescreen.BaseScreen + + +/** + * Mini popup just displays "Loading..." and opens itself. + * + * Not to be confused with [LoadingScreen], which tries to preserve background as screenshot. + * That screen will use this once the screenshot is on-screen, though. + */ +class LoadingPopup(screen: BaseScreen) : Popup(screen, Scrollability.None) { + init { + addGoodSizedLabel(Constants.loading) + open(true) + } +} diff --git a/core/src/com/unciv/ui/popups/Popup.kt b/core/src/com/unciv/ui/popups/Popup.kt index 16195ea2be..a5ddfbe933 100644 --- a/core/src/com/unciv/ui/popups/Popup.kt +++ b/core/src/com/unciv/ui/popups/Popup.kt @@ -9,10 +9,12 @@ import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.ui.Button import com.badlogic.gdx.scenes.scene2d.ui.Cell import com.badlogic.gdx.scenes.scene2d.ui.Label +import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle import com.badlogic.gdx.scenes.scene2d.ui.TextField +import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup import com.badlogic.gdx.scenes.scene2d.utils.ClickListener import com.badlogic.gdx.utils.Align import com.unciv.Constants @@ -33,27 +35,80 @@ import com.unciv.ui.screens.basescreen.UncivStage /** * Base class for all Popups, i.e. Tables that get rendered in the middle of a screen and on top of everything else + * + * @property stageToShowOn The stage that will be used for [open], measurements or finding other instances + * @param scrollable Controls how content can scroll if too large - see [Scrollability] + * @param maxSizePercentage Causes [topTable] to limit its height - useful if `scrollable` is on. Will be multiplied by stageToShowOn.height. */ @Suppress("MemberVisibilityCanBePrivate") open class Popup( val stageToShowOn: Stage, - scrollable: Boolean = true + scrollable: Scrollability = Scrollability.WithoutButtons, + maxSizePercentage: Float = 0.9f ): Table(BaseScreen.skin) { - constructor(screen: BaseScreen) : this(screen.stage) + constructor( + screen: BaseScreen, + scrollable: Scrollability = Scrollability.WithoutButtons, + maxSizePercentage: Float = 0.9f + ) : this(screen.stage, scrollable, maxSizePercentage) - // This exists to differentiate the actual popup (the inner table) - // from the 'screen blocking' part of the popup (which covers the entire screen) + /** Controls how content may scroll. + * + * With scrolling enabled, the ScrollPane can be accessed via [getScrollPane]. + * @property None No scrolling + * @property All Entire content wrapped in an [AutoScrollPane] so it can scroll if larger than maximum dimensions + * @property WithoutButtons content separated into scrollable upper part and static lower part containing the buttons + */ + enum class Scrollability { None, All, WithoutButtons } + + private val maxPopupWidth = stageToShowOn.width * maxSizePercentage + private val maxPopupHeight = stageToShowOn.height * maxSizePercentage + + /** This exists to differentiate the actual popup (this table) + * from the 'screen blocking' part of the popup (which covers the entire screen). + * + * Note you seldom need to interact directly with it, Popup has many Table method proxies + * that pass through, like [add], [row], [defaults], [addSeparator] or [clear]. + */ + /* Hierarchy: + Scrollability.None: + * Stage + * this@Popup (fills parent, catches click-behind) + * innerTable (entire Popup content, smaller, limited by maxSizePercentage) + * topTable and bottomTable _reference_ innerTable + Scrollability.All: + * Stage + * this@Popup (fills parent, catches click-behind) + * ScrollPane (anonymous) + * innerTable (entire Popup content, smaller, limited by maxSizePercentage) + * topTable and bottomTable _reference_ innerTable + Scrollability.WithoutButtons: + * Stage + * this@Popup (fills parent, catches click-behind) + * innerTable (entire Popup content, smaller, limited by maxSizePercentage) + * ScrollPane (anonymous) + * topTable + * bottomTable + */ protected val innerTable = Table(BaseScreen.skin) + /** This contains most of the Popup content (except the closing buttons which go in [bottomTable]) */ + private val topTable: Table + private val topTableCell: Cell + + /** This contains the bottom row buttons and does not participate in scrolling */ + protected val bottomTable: Table + /** Callbacks that will be called whenever this Popup is shown */ 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>() + /** [EventBus] is used to receive [UncivStage.VisibleAreaChanged] */ protected val events = EventBus.EventReceiver() - /** Enables/disables closing by clicking/trapping outside [innerTable]. + /** Enables/disables closing by clicking/tapping outside [innerTable]. * * Automatically set when [addCloseButton] is called but may be changed back or enabled without such a button. */ @@ -69,15 +124,43 @@ open class Popup( background = BaseScreen.skinStrings.getUiBackground( "General/Popup/Background", tintColor = Color.GRAY.cpy().apply { a = 0.5f }) + + //todo topTable and bottomTable _could_ be separately skinnable - but would need care so rounded edges work innerTable.background = BaseScreen.skinStrings.getUiBackground( "General/Popup/InnerTable", tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f) ) + innerTable.touchable = Touchable.enabled - innerTable.pad(20f) - innerTable.defaults().pad(5f) + fun wrapInScrollPane(table: Table) = AutoScrollPane(table, BaseScreen.skin) + .apply { setOverscroll(false, false) } + when (scrollable) { + Scrollability.None -> { + topTable = innerTable + bottomTable = innerTable + topTableCell = super.add(innerTable) + } + Scrollability.All -> { + topTable = innerTable + bottomTable = innerTable + topTableCell = super.add(wrapInScrollPane(innerTable)) + } + Scrollability.WithoutButtons -> { + topTable = Table(BaseScreen.skin) + topTable.pad(20f).padBottom(0f) + topTable.defaults().fillX().pad(5f) + bottomTable = Table(BaseScreen.skin) + topTableCell = innerTable.add(wrapInScrollPane(topTable)) + innerTable.defaults().fillX() + innerTable.row() + innerTable.add(bottomTable) + super.add(innerTable) + } + } - super.add(if (scrollable) AutoScrollPane(innerTable, BaseScreen.skin) else innerTable) + bottomTable.pad(20f) + bottomTable.defaults().pad(5f) + topTableCell.maxSize(maxPopupWidth, maxPopupHeight) isVisible = false touchable = Touchable.enabled @@ -86,12 +169,20 @@ open class Popup( super.setFillParent(true) } + private fun recalculateInnerTableMaxHeight() { + if (topTable === bottomTable) return + topTableCell.maxHeight(maxPopupHeight - bottomTable.prefHeight) + innerTable.invalidate() + } + + /** * Displays the Popup on the screen. If another popup is already open, this one will display after the other has * closed. Use [force] = true if you want to open this popup above the other one anyway. */ fun open(force: Boolean = false) { stageToShowOn.addActor(this) + recalculateInnerTableMaxHeight() innerTable.pack() pack() center(stageToShowOn) @@ -140,13 +231,26 @@ open class Popup( } } - /* 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 add(actor: T): Cell = innerTable.add(actor) - override fun row(): Cell = innerTable.row() - override fun defaults(): Cell = innerTable.defaults() - fun addSeparator() = innerTable.addSeparator() + /* All additions to the popup are to the inner table - we shouldn't care that there's an inner table at all. + Note the Kdoc mentions innerTable when under Scrollability.WithoutButtons it's actually topTable, + but metioning that distinction seems overkill. innerTable has the clearer Kdoc for "where the Actors go". + */ + /** Popup proxy redirects [add][com.badlogic.gdx.scenes.scene2d.ui.Table.add] to [innerTable] */ + final override fun add(actor: T): Cell = topTable.add(actor) + /** Popup proxy redirects [add][com.badlogic.gdx.scenes.scene2d.ui.Table.add] to [innerTable] */ + final override fun add(): Cell = topTable.add() + /** Popup proxy redirects [row][com.badlogic.gdx.scenes.scene2d.ui.Table.row] to [innerTable] */ + override fun row(): Cell = topTable.row() + /** Popup proxy redirects [defaults][com.badlogic.gdx.scenes.scene2d.ui.Table.defaults] to [innerTable] */ + override fun defaults(): Cell = topTable.defaults() + /** Popup proxy redirects [addSeparator][com.unciv.ui.components.extensions.addSeparator] to [innerTable] */ + fun addSeparator(color: Color = Color.WHITE, colSpan: Int = 0, height: Float = 2f) = + topTable.addSeparator(color, colSpan, height) + /** Proxy redirects [add][com.badlogic.gdx.scenes.scene2d.ui.Table.clear] to clear content: + * [innerTable] or if [Scrollability.WithoutButtons] was used [topTable] and [bottomTable] */ override fun clear() { - innerTable.clear() + topTable.clear() + bottomTable.clear() clickBehindToClose = false onCloseCallback = null } @@ -181,7 +285,7 @@ open class Popup( val button = text.toTextButton(style) button.onActivation { action() } button.keyShortcuts.add(key) - return add(button) + return bottomTable.add(button) } fun addButton(text: String, key: Char, style: TextButtonStyle? = null, action: () -> Unit) = addButton(text, KeyCharAndCode(key), style, action).apply { row() } @@ -250,10 +354,10 @@ open class Popup( * Make their width equal by setting minWidth of one cell to actor width of the other. */ fun equalizeLastTwoButtonWidths() { - val n = innerTable.cells.size + val n = bottomTable.cells.size if (n < 2) throw UnsupportedOperationException() - val cell1 = innerTable.cells[n-2] - val cell2 = innerTable.cells[n-1] + val cell1 = bottomTable.cells[n-2] + val cell2 = bottomTable.cells[n-1] if (cell1.actor !is Button || cell2.actor !is Button) throw UnsupportedOperationException() cell1.minWidth(cell2.actor.width).uniformX() cell2.minWidth(cell1.actor.width).uniformX() @@ -268,7 +372,6 @@ open class Popup( clear() addGoodSizedLabel(newText) if (withCloseButton) { - row() addCloseButton() } } @@ -285,6 +388,9 @@ open class Popup( if (stageToShowOn.setKeyboardFocus(value)) (value as? TextField)?.selectAll() } + + /** Gets the ScrollPane the content is wrapped in (only if Popup was instantiated with scrollable=true) */ + fun getScrollPane() = topTable.parent as? ScrollPane } diff --git a/core/src/com/unciv/ui/popups/options/OptionsPopup.kt b/core/src/com/unciv/ui/popups/options/OptionsPopup.kt index 12040e9100..cf80f7cbd2 100644 --- a/core/src/com/unciv/ui/popups/options/OptionsPopup.kt +++ b/core/src/com/unciv/ui/popups/options/OptionsPopup.kt @@ -29,7 +29,7 @@ class OptionsPopup( screen: BaseScreen, private val selectPage: Int = defaultPage, private val onClose: () -> Unit = {} -) : Popup(screen.stage, /** [TabbedPager] handles scrolling */ scrollable = false ) { +) : Popup(screen.stage, /** [TabbedPager] handles scrolling */ scrollable = Scrollability.None) { val game = screen.game val settings = screen.game.settings diff --git a/core/src/com/unciv/ui/screens/LoadingScreen.kt b/core/src/com/unciv/ui/screens/LoadingScreen.kt index 2e7d9817c6..1604d81310 100644 --- a/core/src/com/unciv/ui/screens/LoadingScreen.kt +++ b/core/src/com/unciv/ui/screens/LoadingScreen.kt @@ -5,18 +5,16 @@ import com.badlogic.gdx.graphics.Pixmap import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.g2d.TextureRegion import com.badlogic.gdx.scenes.scene2d.actions.Actions -import com.unciv.Constants import com.unciv.ui.images.ImageWithCustomSize -import com.unciv.ui.popups.Popup import com.unciv.ui.popups.popups import com.unciv.ui.screens.basescreen.BaseScreen -import com.unciv.ui.components.extensions.toLabel +import com.unciv.ui.popups.LoadingPopup /** A loading screen that creates a screenshot of the current screen and adds a "Loading..." popup on top of that */ class LoadingScreen( previousScreen: BaseScreen? = null ) : BaseScreen() { - val screenshot: Texture + private val screenshot: Texture init { screenshot = takeScreenshot(previousScreen) val image = ImageWithCustomSize( @@ -34,9 +32,7 @@ class LoadingScreen( stage.addAction(Actions.sequence( Actions.delay(1000f), Actions.run { - val popup = Popup(stage) - popup.add(Constants.loading.toLabel()) - popup.open() + LoadingPopup(this) } )) } @@ -44,7 +40,7 @@ class LoadingScreen( private fun takeScreenshot(previousScreen: BaseScreen?): Texture { if (previousScreen != null) { for (popup in previousScreen.popups) popup.isVisible = false - previousScreen.render(Gdx.graphics.getDeltaTime()) + previousScreen.render(Gdx.graphics.deltaTime) } val pixmap = Pixmap.createFromFrameBuffer(0, 0, Gdx.graphics.backBufferWidth, Gdx.graphics.backBufferHeight) val screenshot = Texture(pixmap) diff --git a/core/src/com/unciv/ui/screens/cityscreen/DetailedStatsPopup.kt b/core/src/com/unciv/ui/screens/cityscreen/DetailedStatsPopup.kt index 8d39eb4f95..72632105d1 100644 --- a/core/src/com/unciv/ui/screens/cityscreen/DetailedStatsPopup.kt +++ b/core/src/com/unciv/ui/screens/cityscreen/DetailedStatsPopup.kt @@ -29,7 +29,7 @@ import kotlin.math.max class DetailedStatsPopup( private val cityScreen: CityScreen -) : Popup(stageToShowOn = cityScreen.stage, scrollable = false) { +) : Popup(cityScreen, Scrollability.None) { private val headerTable = Table() private val totalTable = Table() diff --git a/core/src/com/unciv/ui/screens/mainmenuscreen/MainMenuScreen.kt b/core/src/com/unciv/ui/screens/mainmenuscreen/MainMenuScreen.kt index 2c11f4e9f9..afe7cf7d81 100644 --- a/core/src/com/unciv/ui/screens/mainmenuscreen/MainMenuScreen.kt +++ b/core/src/com/unciv/ui/screens/mainmenuscreen/MainMenuScreen.kt @@ -279,7 +279,7 @@ class MainMenuScreen: BaseScreen(), RecreateOnResize { QuickSave.autoLoadGame(this) } else { GUI.resetToWorldScreen() - GUI.getWorldScreen().popups.filterIsInstance(WorldScreenMenuPopup::class.java).forEach(Popup::close) + GUI.getWorldScreen().popups.filterIsInstance().forEach(Popup::close) ImageGetter.ruleset = game.gameInfo!!.ruleset } } else { diff --git a/core/src/com/unciv/ui/screens/mapeditorscreen/tabs/MapEditorLoadTab.kt b/core/src/com/unciv/ui/screens/mapeditorscreen/tabs/MapEditorLoadTab.kt index f641b64e6c..970061b6ec 100644 --- a/core/src/com/unciv/ui/screens/mapeditorscreen/tabs/MapEditorLoadTab.kt +++ b/core/src/com/unciv/ui/screens/mapeditorscreen/tabs/MapEditorLoadTab.kt @@ -22,6 +22,7 @@ import com.unciv.ui.components.extensions.isEnabled import com.unciv.ui.components.extensions.keyShortcuts import com.unciv.ui.components.extensions.onActivation import com.unciv.ui.components.extensions.toTextButton +import com.unciv.ui.popups.LoadingPopup import com.unciv.utils.Concurrency import com.unciv.utils.Log import kotlinx.coroutines.CoroutineScope @@ -105,10 +106,7 @@ class MapEditorLoadTab( var needPopup = true // loadMap can fail faster than postRunnable runs Concurrency.runOnGLThread { if (!needPopup) return@runOnGLThread - popup = Popup(editorScreen).apply { - addGoodSizedLabel(Constants.loading) - open() - } + popup = LoadingPopup(editorScreen) } try { val map = MapSaver.loadMap(chosenMap!!) diff --git a/core/src/com/unciv/ui/screens/overviewscreen/UnitUpgradeMenu.kt b/core/src/com/unciv/ui/screens/overviewscreen/UnitUpgradeMenu.kt index 4b6a1ff658..c06488d778 100644 --- a/core/src/com/unciv/ui/screens/overviewscreen/UnitUpgradeMenu.kt +++ b/core/src/com/unciv/ui/screens/overviewscreen/UnitUpgradeMenu.kt @@ -51,7 +51,7 @@ class UnitUpgradeMenu( private val unit: MapUnit, private val unitAction: UpgradeUnitAction, private val onButtonClicked: () -> Unit -) : Popup(stage, scrollable = false) { +) : Popup(stage, Scrollability.None) { private val container: Container private val allUpgradableUnits: Sequence private val animationDuration = 0.33f diff --git a/core/src/com/unciv/ui/screens/savescreens/LoadGameScreen.kt b/core/src/com/unciv/ui/screens/savescreens/LoadGameScreen.kt index 1a24624fd1..4cae151058 100644 --- a/core/src/com/unciv/ui/screens/savescreens/LoadGameScreen.kt +++ b/core/src/com/unciv/ui/screens/savescreens/LoadGameScreen.kt @@ -25,6 +25,7 @@ import com.unciv.ui.components.extensions.onActivation import com.unciv.ui.components.extensions.onClick import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.components.extensions.toTextButton +import com.unciv.ui.popups.LoadingPopup import com.unciv.utils.Log import com.unciv.utils.Concurrency import com.unciv.utils.launchOnGLThread @@ -116,9 +117,7 @@ class LoadGameScreen : LoadOrSaveScreen() { private fun onLoadGame() { if (selectedSave == null) return - val loadingPopup = Popup( this) - loadingPopup.addGoodSizedLabel(Constants.loading) - loadingPopup.open() + val loadingPopup = LoadingPopup(this) Concurrency.run(loadGame) { try { // This is what can lead to ANRs - reading the file and setting the transients, that's why this is in another thread diff --git a/core/src/com/unciv/ui/screens/savescreens/QuickSave.kt b/core/src/com/unciv/ui/screens/savescreens/QuickSave.kt index f7848e4f84..debe850974 100644 --- a/core/src/com/unciv/ui/screens/savescreens/QuickSave.kt +++ b/core/src/com/unciv/ui/screens/savescreens/QuickSave.kt @@ -1,11 +1,10 @@ package com.unciv.ui.screens.savescreens -import com.unciv.Constants 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.Popup +import com.unciv.ui.popups.LoadingPopup import com.unciv.ui.popups.ToastPopup import com.unciv.ui.screens.worldscreen.WorldScreen import com.unciv.utils.Concurrency @@ -55,9 +54,7 @@ object QuickSave { } fun autoLoadGame(screen: MainMenuScreen) { - val loadingPopup = Popup(screen) - loadingPopup.addGoodSizedLabel(Constants.loading) - loadingPopup.open() + val loadingPopup = LoadingPopup(screen) Concurrency.run("autoLoadGame") { // Load game from file to class on separate thread to avoid ANR... fun outOfMemory() { diff --git a/core/src/com/unciv/ui/screens/worldscreen/mainmenu/WorldScreenCommunityPopup.kt b/core/src/com/unciv/ui/screens/worldscreen/mainmenu/WorldScreenCommunityPopup.kt new file mode 100644 index 0000000000..164d6cc5de --- /dev/null +++ b/core/src/com/unciv/ui/screens/worldscreen/mainmenu/WorldScreenCommunityPopup.kt @@ -0,0 +1,26 @@ +package com.unciv.ui.screens.worldscreen.mainmenu + +import com.badlogic.gdx.Gdx +import com.unciv.ui.popups.Popup +import com.unciv.ui.screens.worldscreen.WorldScreen + +class WorldScreenCommunityPopup(val worldScreen: WorldScreen) : Popup(worldScreen, scrollable = Scrollability.All) { + init { + addButton("Discord") { + Gdx.net.openURI("https://discord.gg/bjrB4Xw") + close() + }.row() + + addButton("Github") { + Gdx.net.openURI("https://github.com/yairm210/Unciv") + close() + }.row() + + addButton("Reddit") { + Gdx.net.openURI("https://www.reddit.com/r/Unciv/") + close() + }.row() + + addCloseButton() + } +} diff --git a/core/src/com/unciv/ui/screens/worldscreen/mainmenu/WorldScreenMenuPopup.kt b/core/src/com/unciv/ui/screens/worldscreen/mainmenu/WorldScreenMenuPopup.kt index bd6e38da45..7b6b6ffda0 100644 --- a/core/src/com/unciv/ui/screens/worldscreen/mainmenu/WorldScreenMenuPopup.kt +++ b/core/src/com/unciv/ui/screens/worldscreen/mainmenu/WorldScreenMenuPopup.kt @@ -1,18 +1,15 @@ package com.unciv.ui.screens.worldscreen.mainmenu -import com.badlogic.gdx.Gdx -import com.unciv.UncivGame import com.unciv.models.metadata.GameSetupInfo +import com.unciv.ui.popups.Popup import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen import com.unciv.ui.screens.newgamescreen.NewGameScreen -import com.unciv.ui.popups.options.addMusicControls -import com.unciv.ui.popups.Popup 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 -class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) { +class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen, scrollable = Scrollability.All) { init { defaults().fillX() @@ -54,42 +51,9 @@ class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) { }.row() addButton("Music") { close() - WorldScreenMusicButton(worldScreen).open(force = true) + WorldScreenMusicPopup(worldScreen).open(force = true) }.row() addCloseButton() pack() } } - -class WorldScreenCommunityPopup(val worldScreen: WorldScreen) : Popup(worldScreen) { - init { - defaults().fillX() - addButton("Discord") { - Gdx.net.openURI("https://discord.gg/bjrB4Xw") - close() - }.row() - - addButton("Github") { - Gdx.net.openURI("https://github.com/yairm210/Unciv") - close() - }.row() - - addButton("Reddit") { - Gdx.net.openURI("https://www.reddit.com/r/Unciv/") - close() - }.row() - - addCloseButton() - } -} - -class WorldScreenMusicButton(val worldScreen: WorldScreen) : Popup(worldScreen) { - init { - val musicController = UncivGame.Current.musicController - val settings = UncivGame.Current.settings - - defaults().fillX() - addMusicControls(this, settings, musicController) - addCloseButton().colspan(2) - } -} diff --git a/core/src/com/unciv/ui/screens/worldscreen/mainmenu/WorldScreenMusicPopup.kt b/core/src/com/unciv/ui/screens/worldscreen/mainmenu/WorldScreenMusicPopup.kt new file mode 100644 index 0000000000..bd2fd09e83 --- /dev/null +++ b/core/src/com/unciv/ui/screens/worldscreen/mainmenu/WorldScreenMusicPopup.kt @@ -0,0 +1,17 @@ +package com.unciv.ui.screens.worldscreen.mainmenu + +import com.unciv.UncivGame +import com.unciv.ui.popups.Popup +import com.unciv.ui.popups.options.addMusicControls +import com.unciv.ui.screens.worldscreen.WorldScreen + +class WorldScreenMusicPopup(val worldScreen: WorldScreen) : Popup(worldScreen) { + init { + val musicController = UncivGame.Current.musicController + val settings = UncivGame.Current.settings + + defaults().fillX() + addMusicControls(this, settings, musicController) + addCloseButton().colspan(2) + } +}