feat: Add license viewer /firm licenses
This commit is contained in:
@@ -17,7 +17,7 @@ import org.apache.tools.ant.taskdefs.condition.Os
|
|||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
import java.util.Base64
|
import java.util.*
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
java
|
java
|
||||||
@@ -227,8 +227,10 @@ val testAgent by configurations.creating {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val configuredSourceSet = createIsolatedSourceSet("configured",
|
val configuredSourceSet = createIsolatedSourceSet(
|
||||||
isEnabled = false) // Wait for update (also low prio, because configured sucks)
|
"configured",
|
||||||
|
isEnabled = false
|
||||||
|
) // Wait for update (also low prio, because configured sucks)
|
||||||
val sodiumSourceSet = createIsolatedSourceSet("sodium", isEnabled = false)
|
val sodiumSourceSet = createIsolatedSourceSet("sodium", isEnabled = false)
|
||||||
val citResewnSourceSet = createIsolatedSourceSet("citresewn", isEnabled = false) // TODO: Wait for update
|
val citResewnSourceSet = createIsolatedSourceSet("citresewn", isEnabled = false) // TODO: Wait for update
|
||||||
val yaclSourceSet = createIsolatedSourceSet("yacl")
|
val yaclSourceSet = createIsolatedSourceSet("yacl")
|
||||||
@@ -262,14 +264,14 @@ dependencies {
|
|||||||
include(libs.hypixelmodapi.fabric)
|
include(libs.hypixelmodapi.fabric)
|
||||||
compileOnly(projects.javaplugin)
|
compileOnly(projects.javaplugin)
|
||||||
annotationProcessor(projects.javaplugin)
|
annotationProcessor(projects.javaplugin)
|
||||||
implementation("com.google.auto.service:auto-service-annotations:1.1.1")
|
nonModImplentation("com.google.auto.service:auto-service-annotations:1.1.1")
|
||||||
ksp("dev.zacsweers.autoservice:auto-service-ksp:1.2.0")
|
ksp("dev.zacsweers.autoservice:auto-service-ksp:1.2.0")
|
||||||
include(libs.manninghamMills)
|
include(libs.manninghamMills)
|
||||||
include(libs.moulconfig)
|
include(libs.moulconfig)
|
||||||
|
|
||||||
|
|
||||||
annotationProcessor(libs.mixinextras)
|
annotationProcessor(libs.mixinextras)
|
||||||
implementation(libs.mixinextras)
|
nonModImplentation(libs.mixinextras)
|
||||||
include(libs.mixinextras)
|
include(libs.mixinextras)
|
||||||
|
|
||||||
nonModImplentation(libs.nealisp)
|
nonModImplentation(libs.nealisp)
|
||||||
@@ -332,10 +334,11 @@ loom {
|
|||||||
configureEach {
|
configureEach {
|
||||||
property("fabric.log.level", "info")
|
property("fabric.log.level", "info")
|
||||||
property("firmament.debug", "true")
|
property("firmament.debug", "true")
|
||||||
property("firmament.classroots",
|
property(
|
||||||
compatSourceSets.joinToString(File.pathSeparator) {
|
"firmament.classroots",
|
||||||
File(it.output.classesDirs.asPath).absolutePath
|
compatSourceSets.joinToString(File.pathSeparator) {
|
||||||
})
|
File(it.output.classesDirs.asPath).absolutePath
|
||||||
|
})
|
||||||
property("mixin.debug.export", "true")
|
property("mixin.debug.export", "true")
|
||||||
property("mixin.debug", "true")
|
property("mixin.debug", "true")
|
||||||
|
|
||||||
@@ -370,12 +373,16 @@ val updateTestRepo by tasks.registering {
|
|||||||
doLast {
|
doLast {
|
||||||
val propertiesFile = rootProject.file("gradle.properties")
|
val propertiesFile = rootProject.file("gradle.properties")
|
||||||
val json =
|
val json =
|
||||||
Gson().fromJson(uri("https://api.github.com/repos/NotEnoughUpdates/NotEnoughUpdates-REPO/branches/master")
|
Gson().fromJson(
|
||||||
.toURL().readText(), JsonObject::class.java)
|
uri("https://api.github.com/repos/NotEnoughUpdates/NotEnoughUpdates-REPO/branches/master")
|
||||||
|
.toURL().readText(), JsonObject::class.java
|
||||||
|
)
|
||||||
val latestSha = json["commit"].asJsonObject["sha"].asString
|
val latestSha = json["commit"].asJsonObject["sha"].asString
|
||||||
var text = propertiesFile.readText()
|
var text = propertiesFile.readText()
|
||||||
text = text.replace("firmament\\.compiletimerepohash=[^\n]*".toRegex(),
|
text = text.replace(
|
||||||
"firmament.compiletimerepohash=$latestSha")
|
"firmament\\.compiletimerepohash=[^\n]*".toRegex(),
|
||||||
|
"firmament.compiletimerepohash=$latestSha"
|
||||||
|
)
|
||||||
propertiesFile.writeText(text)
|
propertiesFile.writeText(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -389,8 +396,10 @@ tasks.test {
|
|||||||
doFirst {
|
doFirst {
|
||||||
wd.mkdirs()
|
wd.mkdirs()
|
||||||
wd.resolve("config").deleteRecursively()
|
wd.resolve("config").deleteRecursively()
|
||||||
systemProperty("firmament.testrepo",
|
systemProperty(
|
||||||
downloadTestRepo.flatMap { it.outputDirectory.asFile }.map { it.absolutePath }.get())
|
"firmament.testrepo",
|
||||||
|
downloadTestRepo.flatMap { it.outputDirectory.asFile }.map { it.absolutePath }.get()
|
||||||
|
)
|
||||||
jvmArgs("-javaagent:${testAgent.singleFile.absolutePath}")
|
jvmArgs("-javaagent:${testAgent.singleFile.absolutePath}")
|
||||||
}
|
}
|
||||||
systemProperty("jdk.attach.allowAttachSelf", "true")
|
systemProperty("jdk.attach.allowAttachSelf", "true")
|
||||||
@@ -408,13 +417,15 @@ tasks.withType<JavaCompile> {
|
|||||||
this.targetCompatibility = "21"
|
this.targetCompatibility = "21"
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
val module = "ALL-UNNAMED"
|
val module = "ALL-UNNAMED"
|
||||||
options.forkOptions.jvmArgs!!.addAll(listOf(
|
options.forkOptions.jvmArgs!!.addAll(
|
||||||
"--add-exports=jdk.compiler/com.sun.tools.javac.util=$module",
|
listOf(
|
||||||
"--add-exports=jdk.compiler/com.sun.tools.javac.comp=$module",
|
"--add-exports=jdk.compiler/com.sun.tools.javac.util=$module",
|
||||||
"--add-exports=jdk.compiler/com.sun.tools.javac.tree=$module",
|
"--add-exports=jdk.compiler/com.sun.tools.javac.comp=$module",
|
||||||
"--add-exports=jdk.compiler/com.sun.tools.javac.api=$module",
|
"--add-exports=jdk.compiler/com.sun.tools.javac.tree=$module",
|
||||||
"--add-exports=jdk.compiler/com.sun.tools.javac.code=$module",
|
"--add-exports=jdk.compiler/com.sun.tools.javac.api=$module",
|
||||||
))
|
"--add-exports=jdk.compiler/com.sun.tools.javac.code=$module",
|
||||||
|
)
|
||||||
|
)
|
||||||
options.isFork = true
|
options.isFork = true
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
options.compilerArgs.add("-Xplugin:IntermediaryNameReplacement mappingFile=${LoomGradleExtension.get(project).mappingsFile.absolutePath} sourceNs=named")
|
options.compilerArgs.add("-Xplugin:IntermediaryNameReplacement mappingFile=${LoomGradleExtension.get(project).mappingsFile.absolutePath} sourceNs=named")
|
||||||
@@ -463,12 +474,18 @@ tasks.processResources {
|
|||||||
tasks.scanLicenses {
|
tasks.scanLicenses {
|
||||||
scanConfiguration(nonModImplentation)
|
scanConfiguration(nonModImplentation)
|
||||||
scanConfiguration(configurations.modCompileClasspath.get())
|
scanConfiguration(configurations.modCompileClasspath.get())
|
||||||
|
compatSourceSets.forEach {
|
||||||
|
scanConfiguration(it.modImplementationConfigurationName.get())
|
||||||
|
}
|
||||||
outputFile.set(layout.buildDirectory.file("LICENSES-FIRMAMENT.json"))
|
outputFile.set(layout.buildDirectory.file("LICENSES-FIRMAMENT.json"))
|
||||||
licenseFormatter.set(moe.nea.licenseextractificator.JsonLicenseFormatter())
|
licenseFormatter.set(moe.nea.licenseextractificator.JsonLicenseFormatter())
|
||||||
}
|
}
|
||||||
tasks.create("printAllLicenses", LicenseDiscoveryTask::class.java, licensing).apply {
|
tasks.register("printAllLicenses", LicenseDiscoveryTask::class.java, licensing).configure {
|
||||||
outputFile.set(layout.buildDirectory.file("LICENSES-FIRMAMENT.txt"))
|
outputFile.set(layout.buildDirectory.file("LICENSES-FIRMAMENT.txt"))
|
||||||
licenseFormatter.set(moe.nea.licenseextractificator.TextLicenseFormatter())
|
licenseFormatter.set(moe.nea.licenseextractificator.TextLicenseFormatter())
|
||||||
|
compatSourceSets.forEach {
|
||||||
|
scanConfiguration(it.modImplementationConfigurationName.get())
|
||||||
|
}
|
||||||
scanConfiguration(nonModImplentation)
|
scanConfiguration(nonModImplentation)
|
||||||
scanConfiguration(configurations.modCompileClasspath.get())
|
scanConfiguration(configurations.modCompileClasspath.get())
|
||||||
doLast {
|
doLast {
|
||||||
@@ -505,16 +522,20 @@ fun patchRenderDoc(
|
|||||||
if (!fileF.exists()) {
|
if (!fileF.exists()) {
|
||||||
fileF.parentFile.mkdirs()
|
fileF.parentFile.mkdirs()
|
||||||
if (isWindows) {
|
if (isWindows) {
|
||||||
fileF.writeText("""
|
fileF.writeText(
|
||||||
|
"""
|
||||||
setlocal enableextensions
|
setlocal enableextensions
|
||||||
start "" renderdoccmd.exe capture --opt-hook-children --wait-for-exit --working-dir . "$wrappedJavaExecutable" %*
|
start "" renderdoccmd.exe capture --opt-hook-children --wait-for-exit --working-dir . "$wrappedJavaExecutable" %*
|
||||||
endlocal
|
endlocal
|
||||||
""".trimIndent())
|
""".trimIndent()
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
fileF.writeText("""
|
fileF.writeText(
|
||||||
|
"""
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
exec renderdoccmd capture --opt-hook-children --wait-for-exit --working-dir . "$wrappedJavaExecutable" "$@"
|
exec renderdoccmd capture --opt-hook-children --wait-for-exit --working-dir . "$wrappedJavaExecutable" "$@"
|
||||||
""".trimIndent())
|
""".trimIndent()
|
||||||
|
)
|
||||||
fileF.setExecutable(true)
|
fileF.setExecutable(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
128
src/main/kotlin/features/misc/LicenseViewer.kt
Normal file
128
src/main/kotlin/features/misc/LicenseViewer.kt
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
package moe.nea.firmament.features.misc
|
||||||
|
|
||||||
|
import io.github.notenoughupdates.moulconfig.observer.ObservableList
|
||||||
|
import io.github.notenoughupdates.moulconfig.xml.Bind
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.Transient
|
||||||
|
import kotlinx.serialization.json.decodeFromStream
|
||||||
|
import moe.nea.firmament.Firmament
|
||||||
|
import moe.nea.firmament.annotations.Subscribe
|
||||||
|
import moe.nea.firmament.commands.thenExecute
|
||||||
|
import moe.nea.firmament.events.CommandEvent
|
||||||
|
import moe.nea.firmament.util.ErrorUtil
|
||||||
|
import moe.nea.firmament.util.MC
|
||||||
|
import moe.nea.firmament.util.MoulConfigUtils
|
||||||
|
import moe.nea.firmament.util.ScreenUtil
|
||||||
|
import moe.nea.firmament.util.tr
|
||||||
|
|
||||||
|
object LicenseViewer {
|
||||||
|
@Serializable
|
||||||
|
data class Software(
|
||||||
|
val licenses: List<License> = listOf(),
|
||||||
|
val webPresence: String? = null,
|
||||||
|
val projectName: String,
|
||||||
|
val projectDescription: String? = null,
|
||||||
|
val developers: List<Developer> = listOf(),
|
||||||
|
) {
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun hasWebPresence() = webPresence != null
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun webPresence() = webPresence ?: "<no web presence>"
|
||||||
|
@Bind
|
||||||
|
fun open() {
|
||||||
|
MC.openUrl(webPresence ?: return)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun projectName() = projectName
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun projectDescription() = projectDescription ?: "<no project description>"
|
||||||
|
|
||||||
|
@get:Bind("developers")
|
||||||
|
@Transient
|
||||||
|
val developersO = ObservableList(developers)
|
||||||
|
|
||||||
|
@get:Bind("licenses")
|
||||||
|
@Transient
|
||||||
|
val licenses0 = ObservableList(licenses)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Developer(
|
||||||
|
@get:Bind("name") val name: String,
|
||||||
|
val webPresence: String? = null
|
||||||
|
) {
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun open() {
|
||||||
|
MC.openUrl(webPresence ?: return)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun hasWebPresence() = webPresence != null
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun webPresence() = webPresence ?: "<no web presence>"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class License(
|
||||||
|
@get:Bind("name") val licenseName: String,
|
||||||
|
val licenseUrl: String? = null
|
||||||
|
) {
|
||||||
|
@Bind
|
||||||
|
fun open() {
|
||||||
|
MC.openUrl(licenseUrl ?: return)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun hasUrl() = licenseUrl != null
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun url() = licenseUrl ?: "<no link to license text>"
|
||||||
|
}
|
||||||
|
|
||||||
|
data class LicenseList(
|
||||||
|
val softwares: List<Software>
|
||||||
|
) {
|
||||||
|
@get:Bind("softwares")
|
||||||
|
val obs = ObservableList(softwares)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
val licenses: LicenseList? = ErrorUtil.catch("Could not load licenses") {
|
||||||
|
Firmament.json.decodeFromStream<List<Software>?>(
|
||||||
|
javaClass.getResourceAsStream("/LICENSES-FIRMAMENT.json") ?: error("Could not find LICENSES-FIRMAMENT.json")
|
||||||
|
)?.let { LicenseList(it) }
|
||||||
|
}.orNull()
|
||||||
|
|
||||||
|
fun showLicenses() {
|
||||||
|
ErrorUtil.catch("Could not display licenses") {
|
||||||
|
ScreenUtil.setScreenLater(
|
||||||
|
MoulConfigUtils.loadScreen(
|
||||||
|
"license_viewer/index", licenses!!, null
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}.or {
|
||||||
|
MC.sendChat(
|
||||||
|
tr(
|
||||||
|
"firmament.licenses.notfound",
|
||||||
|
"Could not load licenses. Please check the Firmament source code for information directly."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
fun onSubcommand(event: CommandEvent.SubCommand) {
|
||||||
|
event.subcommand("licenses") {
|
||||||
|
thenExecute {
|
||||||
|
showLicenses()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,6 +38,8 @@ object ErrorUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Catch<T> private constructor(val value: T?, val exc: Throwable?) {
|
class Catch<T> private constructor(val value: T?, val exc: Throwable?) {
|
||||||
|
fun orNull(): T? = value
|
||||||
|
|
||||||
inline fun or(block: (exc: Throwable) -> T): T {
|
inline fun or(block: (exc: Throwable) -> T): T {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ import net.minecraft.registry.Registry
|
|||||||
import net.minecraft.registry.RegistryKey
|
import net.minecraft.registry.RegistryKey
|
||||||
import net.minecraft.registry.RegistryKeys
|
import net.minecraft.registry.RegistryKeys
|
||||||
import net.minecraft.registry.RegistryWrapper
|
import net.minecraft.registry.RegistryWrapper
|
||||||
import net.minecraft.registry.entry.RegistryEntry
|
|
||||||
import net.minecraft.resource.ReloadableResourceManagerImpl
|
import net.minecraft.resource.ReloadableResourceManagerImpl
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
|
import net.minecraft.util.Util
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
import moe.nea.firmament.events.TickEvent
|
import moe.nea.firmament.events.TickEvent
|
||||||
@@ -127,6 +127,10 @@ object MC {
|
|||||||
private set
|
private set
|
||||||
|
|
||||||
|
|
||||||
|
fun openUrl(uri: String) {
|
||||||
|
Util.getOperatingSystem().open(uri)
|
||||||
|
}
|
||||||
|
|
||||||
fun <T> unsafeGetRegistryEntry(registry: RegistryKey<out Registry<T>>, identifier: Identifier) =
|
fun <T> unsafeGetRegistryEntry(registry: RegistryKey<out Registry<T>>, identifier: Identifier) =
|
||||||
unsafeGetRegistryEntry(RegistryKey.of(registry, identifier))
|
unsafeGetRegistryEntry(RegistryKey.of(registry, identifier))
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,19 @@ import moe.nea.firmament.gui.TickComponent
|
|||||||
import moe.nea.firmament.util.render.isUntranslatedGuiDrawContext
|
import moe.nea.firmament.util.render.isUntranslatedGuiDrawContext
|
||||||
|
|
||||||
object MoulConfigUtils {
|
object MoulConfigUtils {
|
||||||
|
@JvmStatic
|
||||||
|
fun main(args: Array<out String>) {
|
||||||
|
generateXSD(File("MoulConfig.xsd"), XMLUniverse.MOULCONFIG_XML_NS)
|
||||||
|
generateXSD(File("MoulConfig.Firmament.xsd"), firmUrl)
|
||||||
|
File("wrapper.xsd").writeText("""
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<xs:import namespace="http://notenoughupdates.org/moulconfig" schemaLocation="MoulConfig.xsd"/>
|
||||||
|
<xs:import namespace="http://firmament.nea.moe/moulconfig" schemaLocation="MoulConfig.Firmament.xsd"/>
|
||||||
|
</xs:schema>
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
|
|
||||||
val firmUrl = "http://firmament.nea.moe/moulconfig"
|
val firmUrl = "http://firmament.nea.moe/moulconfig"
|
||||||
val universe = XMLUniverse.getDefaultUniverse().also { uni ->
|
val universe = XMLUniverse.getDefaultUniverse().also { uni ->
|
||||||
uni.registerMapper(java.awt.Color::class.java) {
|
uni.registerMapper(java.awt.Color::class.java) {
|
||||||
@@ -181,10 +194,8 @@ object MoulConfigUtils {
|
|||||||
uni.registerLoader(object : XMLGuiLoader.Basic<FixedComponent> {
|
uni.registerLoader(object : XMLGuiLoader.Basic<FixedComponent> {
|
||||||
override fun createInstance(context: XMLContext<*>, element: Element): FixedComponent {
|
override fun createInstance(context: XMLContext<*>, element: Element): FixedComponent {
|
||||||
return FixedComponent(
|
return FixedComponent(
|
||||||
context.getPropertyFromAttribute(element, QName("width"), Int::class.java)
|
context.getPropertyFromAttribute(element, QName("width"), Int::class.java),
|
||||||
?: error("Requires width specified"),
|
context.getPropertyFromAttribute(element, QName("height"), Int::class.java),
|
||||||
context.getPropertyFromAttribute(element, QName("height"), Int::class.java)
|
|
||||||
?: error("Requires height specified"),
|
|
||||||
context.getChildFragment(element)
|
context.getChildFragment(element)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -198,7 +209,7 @@ object MoulConfigUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getAttributeNames(): Map<String, Boolean> {
|
override fun getAttributeNames(): Map<String, Boolean> {
|
||||||
return mapOf("width" to true, "height" to true)
|
return mapOf("width" to false, "height" to false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -212,19 +223,6 @@ object MoulConfigUtils {
|
|||||||
generator.dumpToFile(file)
|
generator.dumpToFile(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun main(args: Array<out String>) {
|
|
||||||
generateXSD(File("MoulConfig.xsd"), XMLUniverse.MOULCONFIG_XML_NS)
|
|
||||||
generateXSD(File("MoulConfig.Firmament.xsd"), firmUrl)
|
|
||||||
File("wrapper.xsd").writeText("""
|
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
||||||
<xs:import namespace="http://notenoughupdates.org/moulconfig" schemaLocation="MoulConfig.xsd"/>
|
|
||||||
<xs:import namespace="http://firmament.nea.moe/moulconfig" schemaLocation="MoulConfig.Firmament.xsd"/>
|
|
||||||
</xs:schema>
|
|
||||||
""".trimIndent())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadScreen(name: String, bindTo: Any, parent: Screen?): Screen {
|
fun loadScreen(name: String, bindTo: Any, parent: Screen?): Screen {
|
||||||
return object : GuiComponentWrapper(loadGui(name, bindTo)) {
|
return object : GuiComponentWrapper(loadGui(name, bindTo)) {
|
||||||
override fun close() {
|
override fun close() {
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<Root xmlns="http://notenoughupdates.org/moulconfig"
|
||||||
|
xmlns:firm="http://firmament.nea.moe/moulconfig"
|
||||||
|
>
|
||||||
|
<Center>
|
||||||
|
<Panel background="VANILLA">
|
||||||
|
<Column>
|
||||||
|
<Center>
|
||||||
|
<Scale scale="2">
|
||||||
|
<Text text="Firmament Licenses"/>
|
||||||
|
</Scale>
|
||||||
|
</Center>
|
||||||
|
<!-- <firm:Line/>-->
|
||||||
|
<ScrollPanel width="306" height="250">
|
||||||
|
<Panel insets="3" background="TRANSPARENT">
|
||||||
|
<Array data="@softwares">
|
||||||
|
<Center>
|
||||||
|
<firm:Fixed width="300">
|
||||||
|
<Panel background="VANILLA" insets="8">
|
||||||
|
<Column>
|
||||||
|
<Scale scale="1.2">
|
||||||
|
<Text text="@projectName"/>
|
||||||
|
</Scale>
|
||||||
|
<When condition="@hasWebPresence">
|
||||||
|
<Row>
|
||||||
|
<firm:Button onClick="@open">
|
||||||
|
<Text text="Navigate to WebSite"/>
|
||||||
|
</firm:Button>
|
||||||
|
</Row>
|
||||||
|
<Spacer/>
|
||||||
|
</When>
|
||||||
|
<Text text="@projectDescription" width="280"/>
|
||||||
|
<Array data="@developers">
|
||||||
|
<Row>
|
||||||
|
<Text text="by "/>
|
||||||
|
<Text text="@name"/>
|
||||||
|
</Row>
|
||||||
|
</Array>
|
||||||
|
<Array data="@licenses">
|
||||||
|
<When condition="@hasUrl">
|
||||||
|
<firm:Button onClick="@open">
|
||||||
|
<Center>
|
||||||
|
<Row>
|
||||||
|
<Text text="License: "/>
|
||||||
|
<Text text="@name"/>
|
||||||
|
</Row>
|
||||||
|
</Center>
|
||||||
|
</firm:Button>
|
||||||
|
<Row>
|
||||||
|
<Text text="License: "/>
|
||||||
|
<Text text="@name"/>
|
||||||
|
</Row>
|
||||||
|
</When>
|
||||||
|
</Array>
|
||||||
|
</Column>
|
||||||
|
</Panel>
|
||||||
|
</firm:Fixed>
|
||||||
|
</Center>
|
||||||
|
</Array>
|
||||||
|
</Panel>
|
||||||
|
</ScrollPanel>
|
||||||
|
</Column>
|
||||||
|
</Panel>
|
||||||
|
</Center>
|
||||||
|
</Root>
|
||||||
Reference in New Issue
Block a user