diff --git a/core/src/com/unciv/ui/components/BorderedTable.kt b/core/src/com/unciv/ui/components/BorderedTable.kt index c004d8a909..4427ed84cd 100644 --- a/core/src/com/unciv/ui/components/BorderedTable.kt +++ b/core/src/com/unciv/ui/components/BorderedTable.kt @@ -6,10 +6,21 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.utils.Drawable import com.unciv.ui.screens.basescreen.BaseScreen +/** + * Attention: UiElementDocsWriter parses source for usages of this, and is limited to recognize + * string literals for the [path] parameter. No other expressions please, or your skinnable element + * will not be documented. + */ open class BorderedTable( - val path: String = "", + val path: String, defaultBgShape: String = BaseScreen.skinStrings.rectangleWithOutlineShape, - defaultBgBorder: String = BaseScreen.skinStrings.rectangleWithOutlineShape) : Table() { + defaultBgBorder: String = BaseScreen.skinStrings.rectangleWithOutlineShape +) : Table() { + + /** Note: **This class breaks automatic getUiBackground recognition in UiElementDocsWriter**, + * and therefore gets its own parser there. Any significant changes here **must** check whether + * that parser still works! + */ var bgColor: Color = Color.BLACK var bgBorderColor: Color = Color.WHITE diff --git a/desktop/src/com/unciv/app/desktop/UiElementDocsWriter.kt b/desktop/src/com/unciv/app/desktop/UiElementDocsWriter.kt index da4ce73120..fc3c0e7c82 100644 --- a/desktop/src/com/unciv/app/desktop/UiElementDocsWriter.kt +++ b/desktop/src/com/unciv/app/desktop/UiElementDocsWriter.kt @@ -10,6 +10,7 @@ class UiElementDocsWriter { private const val srcPath = "../../core/src/com/unciv/" } + @Suppress("RegExpRepeatedSpace") // IDE doesn't know about commented RegExes fun write() { val docFile = File(docPath) val srcFile = File(srcPath) @@ -20,29 +21,70 @@ class UiElementDocsWriter { val startIndex = originalLines.indexOf(startMarker).takeIf { it != -1 } ?: (endIndex + 1) val elements = mutableListOf() - val backgroundRegex = Regex("""getUiBackground\((\X*?)"(?.*)"[ ,\n\r]*((BaseScreen\.)?skinStrings\.(?.*)Shape)?\X*?\)""") - @Suppress("RegExpRepeatedSpace") // IDE doesn't know about commented RegExes + + val backgroundRegex = Regex(""" + getUiBackground\s*\(\s* # function call, whitespace around opening round bracket optional. + (?:path\s*=\s*)? # allow for named parameter + "(?[^"]*)"\s* # captures "path", anything between double-quotes, not allowing for embedded quotes + (?:,\s* # group for optional default parameter + (?:default\s*=\s*)? # allow for named parameter + (?:(?:BaseScreen\.)?skinStrings\.)? # skip qualifiers, optional + (?.*)Shape # capture default, check required "Shape" suffix but don't capture it + \s*)?[,)] # ends default parameter group and checks closing round bracket of the getUiBackground call - or check a comma and ignore tintColor parameter + """.trimIndent(), RegexOption.COMMENTS) + val colorRegex = Regex(""" getUIColor\s*\(\s* # function call, whitespace around opening round bracket optional. All \s also allow line breaks! + (?:path\s*=\s*)? # allow for named parameter "(?[^"]*)"\s* # captures "path", anything between double-quotes, not allowing for embedded quotes (?:,\s* # group for optional default parameter (?:default\s*=\s*)? # allow for named parameter (?:Color\s*\(|colorFromRGB\s*\(|Color\.) # recognize only Color constructor, colorFromRGB helper, or Color.* constants as argument (?[^)]*) # capture "default" up until a closing round bracket - )?\s*\) # ends default parameter group and checks closing round bracket of the getUIColor call + \s*)?\) # ends default parameter group and checks closing round bracket of the getUIColor call """, RegexOption.COMMENTS) + val borderedTableRegEx = Regex(""" + (?[^"]*)"\s* # capture string literal for path + (?:,\s* # group for optional defaultBgShape parameter + (?!defaultBgBorder\s*=) # skip if second parameter skipped by naming the third + (?:defaultBgShape\s*=\s*)? # allow for named parameter + (?:(?:BaseScreen\.)?skinStrings\.)? # skip qualifiers, optional + (?.*)Shape # capture default, check required "Shape" suffix but don't capture it + \s*)? # ends defaultBgShape parameter group + (?:,\s* # group for optional defaultBgBorder parameter + (?:defaultBgBorder\s*=\s*)? # allow for named parameter + (?:(?:BaseScreen\.)?skinStrings\.)? # skip qualifiers, optional + (?.*)Shape # capture default, check required "Shape" suffix but don't capture it + \s*)? # ends defaultBgBorder parameter group + \) # check closing bracket + """, RegexOption.COMMENTS) + for (file in srcFile.walk()) { if (file.path.endsWith(".kt")) { val sourceText = file.readText() - val matches: Sequence = - backgroundRegex.findAll(sourceText) + colorRegex.findAll(sourceText) - for (result in matches) { - val path = result.groups["path"]?.value + val backgroundAndColorPairs = ( + backgroundRegex.findAll(sourceText) + + colorRegex.findAll(sourceText) + ).map { + it.groups["path"]?.value to it.groups["default"]?.value + } + val borderedTablePairs = borderedTableRegEx.findAll(sourceText) + .flatMap { + val path = it.groups["path"]?.value + sequenceOf( + path to (it.groups["defaultBgShape"]?.value ?: "rectangleWithOutline"), + "${path}Border" to (it.groups["defaultBgBorder"]?.value ?: "rectangleWithOutline") + ) + } + for ((path, default) in (backgroundAndColorPairs + borderedTablePairs)) { val name = path?.takeLastWhile { it != '/' } ?: "" - val default = result.groups["default"]?.value - if (name.isNotBlank()) - elements.add("| ${path!!.dropLast(name.length)} | $name | $default | |") + if (name.isBlank()) continue + val basePath = path!!.dropLast(name.length) + elements.add("| $basePath | $name | $default | |") } } } diff --git a/docs/Modders/Creating-a-UI-skin.md b/docs/Modders/Creating-a-UI-skin.md index 492967df7e..12cf466d5d 100644 --- a/docs/Modders/Creating-a-UI-skin.md +++ b/docs/Modders/Creating-a-UI-skin.md @@ -34,7 +34,6 @@ These shapes are used all over Unciv and can be replaced to make a lot of UI ele | Directory | Name | Default shape | Image | |---|:---:|:---:|---| -| | Border | null | | | CityScreen/ | CityPickerTable | roundedEdgeRectangle | | | CityScreen/CitizenManagementTable/ | AvoidCell | null | | | CityScreen/CitizenManagementTable/ | FocusCell | null | | @@ -56,7 +55,7 @@ These shapes are used all over Unciv and can be replaced to make a lot of UI ele | General/ | Border | null | | | General/ | ExpanderTab | null | | | General/ | HealthBar | null | | -| General/ | KeyCapturingButton | null | | +| General/ | KeyCapturingButton | roundedEdgeRectangleSmall | | | General/ | TabbedPager | null | | | General/ | Tooltip | roundedEdgeRectangle | | | General/Popup/ | Background | null | | @@ -88,6 +87,14 @@ These shapes are used all over Unciv and can be replaced to make a lot of UI ele | OverviewScreen/TradesOverviewTab/ | OffersTable | null | | | OverviewScreen/UnitOverviewTab/ | UnitSupplyTable | null | | | PlayerReadyScreen/ | Background | null | | +| PolicyScreen/ | PolicyBranchAdoptButton | roundedEdgeRectangleSmall | | +| PolicyScreen/ | PolicyBranchAdoptButtonBorder | roundedEdgeRectangleSmall | | +| PolicyScreen/ | PolicyBranchBackground | rectangleWithOutline | | +| PolicyScreen/ | PolicyBranchBackgroundBorder | rectangleWithOutline | | +| PolicyScreen/ | PolicyBranchHeader | rectangleWithOutline | | +| PolicyScreen/ | PolicyBranchHeaderBorder | rectangleWithOutline | | +| PromotionScreen/ | PromotionButton | roundedEdgeRectangleMid | | +| PromotionScreen/ | PromotionButtonBorder | roundedEdgeRectangleMidBorder | | | TechPickerScreen/ | Background | null | | | TechPickerScreen/ | BottomTable | null | | | TechPickerScreen/ | CurrentTechColor | 72, 147, 175 | | @@ -105,6 +112,12 @@ These shapes are used all over Unciv and can be replaced to make a lot of UI ele | WorldScreen/ | TileInfoTable | null | | | WorldScreen/ | TutorialTaskTable | null | | | WorldScreen/ | UnitTable | roundedEdgeRectangleMid | | +| WorldScreen/CityButton/ | AirUnitTable | roundedEdgeRectangleSmall | | +| WorldScreen/CityButton/ | AirUnitTableBorder | roundedEdgeRectangleSmall | | +| WorldScreen/CityButton/ | DefenceTable | roundedTopEdgeRectangleSmall | | +| WorldScreen/CityButton/ | DefenceTableBorder | roundedTopEdgeRectangleSmallBorder | | +| WorldScreen/CityButton/ | IconTable | roundedEdgeRectangleMid | | +| WorldScreen/CityButton/ | IconTableBorder | roundedEdgeRectangleMidBorder | | | WorldScreen/CityButton/ | InfluenceBar | null | | | WorldScreen/Minimap/ | Background | null | | | WorldScreen/Minimap/ | Border | null | |