Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repo-based creator templates #2304

Merged
merged 118 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
10d4ca6
Initial custom template system
RedNesto Apr 30, 2024
e1c1dc5
Add remember, editable and property derivation
RedNesto May 3, 2024
d56284a
Add hidden properties
RedNesto May 3, 2024
2e79118
Implement property derivation for all types
RedNesto May 3, 2024
1486196
Actual types implementation
RedNesto May 4, 2024
bf48447
Some more stuff
RedNesto May 6, 2024
5386102
Some more refactoring to get things working nicely
RedNesto May 10, 2024
b7ab23d
Move CreatorProperties to an EP
RedNesto May 10, 2024
11256de
Add property UI order
RedNesto May 12, 2024
f6e3682
Move custom template to a separate module builder
RedNesto May 13, 2024
120a66f
Add default values to template descriptor
RedNesto May 13, 2024
0bf51a1
Add option to output null value if default
RedNesto May 13, 2024
bc88e1f
Add group/collapsibleGroup support
RedNesto May 13, 2024
0b35944
Dropdown labels
RedNesto May 13, 2024
334f388
Use segmented buttons for options by default
RedNesto May 13, 2024
28c9150
Support comma separated string lists
RedNesto May 13, 2024
3e43015
Add TemplateProviders
RedNesto May 14, 2024
9f1eb1e
WIP Sponge creator
RedNesto May 16, 2024
b84751a
Support built-in templates
RedNesto May 19, 2024
217fd08
Support multiple templates per provider
RedNesto May 19, 2024
82781eb
Remove commented code
RedNesto May 19, 2024
a272f5b
Remember used templates
RedNesto May 19, 2024
ccbc8df
Move CustomPlatformStep to the appropriate package
RedNesto May 19, 2024
c40b286
Fix recent template provider being saved in the recent list
RedNesto May 26, 2024
93623e3
Switch BuiltInTemplateProvider to flat dir
RedNesto May 26, 2024
4e512e6
Add NeoForge specific stuff
RedNesto May 27, 2024
427d241
Add TemplateApi marker annotation for template models
RedNesto May 27, 2024
68c563e
Move RecentProjectTemplates out of the models package
RedNesto May 27, 2024
b7c0af6
Remove old commented code
RedNesto May 27, 2024
b79a833
Replace usage of kotlin plugin function by stdlib one
RedNesto May 28, 2024
37c12e3
Always refresh template files
RedNesto May 29, 2024
fe76265
Add fabric_versions
RedNesto May 29, 2024
445a36b
Add license property
RedNesto May 30, 2024
3e245fd
Handle template descriptor deserialization errors
RedNesto May 30, 2024
e10f27a
Basic template inheritance and template labels
RedNesto May 30, 2024
1f7a0fe
Add basic versioning
RedNesto May 31, 2024
e5075da
Display all yarn/fabric api versions if none match the selected game …
RedNesto May 31, 2024
22eee06
Add property validation support
RedNesto May 31, 2024
c3c3edc
Don't even call buildUi if property is hidden
RedNesto Jun 1, 2024
a2e7e29
Add "select" derivation
RedNesto Jun 1, 2024
fa597e9
Fix templates not getting access to builtin properties
RedNesto Jun 1, 2024
951aaea
Include license displayname in LicenseData
RedNesto Jun 1, 2024
335a6b6
Add 1.16 & 1.20.6 to MinecraftVersions
RedNesto Jun 1, 2024
e4836ef
Remove unused class
RedNesto Jun 1, 2024
897baf7
Some ClassFqn doc & withClassName
RedNesto Jun 1, 2024
f7f3894
Add ForgeVersions
RedNesto Jun 1, 2024
79617ba
Allow to get template from outside the template root
RedNesto Jun 2, 2024
1a992c0
Builtin templates update
RedNesto Jun 2, 2024
469fcc4
Add templates repo as resource modules
RedNesto Jun 2, 2024
d6b9ccb
Flatten a bit the builtin template update code
RedNesto Jun 2, 2024
693a691
Ktlint fixes
RedNesto Jun 2, 2024
f539be0
Add licenses
RedNesto Jun 2, 2024
59dcc86
Revert unneeded change
RedNesto Jun 2, 2024
25d904a
Make properties & files properly optional
RedNesto Jun 2, 2024
f7e49a7
Restore required nonnull assert
RedNesto Jun 2, 2024
39f3795
Run gradle wrapper task after project import
RedNesto Jun 2, 2024
9162a77
Add .gitignore and git add generated files after gradle wrapper task
RedNesto Jun 2, 2024
e67ee3c
Architectury template
RedNesto Jun 3, 2024
fd2f51c
Add paper manifest warning
RedNesto Jun 3, 2024
83e216a
Fix ktlint warnings
RedNesto Jun 3, 2024
ac172c7
Include templates repo as submodule
RedNesto Jun 3, 2024
02d85e7
Include templates in publish workflow
RedNesto Jun 3, 2024
1be51a3
Bump templates submodule
RedNesto Jun 3, 2024
2e7c24a
Switch builtin url to org repo
RedNesto Jun 3, 2024
dfb519c
Fix directory name in builtin provider
RedNesto Jun 3, 2024
dda1678
Explicitly import Gradle and Maven projects
RedNesto Jun 4, 2024
a507579
Remove unused imports
RedNesto Jun 4, 2024
8766ca8
Use org repo
RedNesto Jun 6, 2024
28f38c5
Promote new wizard
RedNesto Jun 6, 2024
e17a4f7
Actually use the correct org name
RedNesto Jun 6, 2024
a29a4f4
Get rid of AbstractLongRunningAssetsStep usage
RedNesto Jun 6, 2024
b027601
Reformat and open main files
RedNesto Jun 6, 2024
78d344d
Remove unused import
RedNesto Jun 6, 2024
e9f1638
Specify TemplateApi target and retention
RedNesto Jun 6, 2024
48421e9
Improve loading UI/UX
RedNesto Jun 7, 2024
e1ab3ae
Localization support
RedNesto Jun 9, 2024
7387383
Display validation and unhandled errors to user
RedNesto Jun 11, 2024
a23e85c
Split templates into groups
RedNesto Jun 11, 2024
01a3f01
Bump templates
RedNesto Jun 14, 2024
2523e1c
Add user-configurable repositories instead of raw providers
RedNesto Jun 15, 2024
1282557
Add back builtin provider
RedNesto Jun 15, 2024
4999c5c
Remove recent templates related code
RedNesto Jun 15, 2024
11d9701
Convert recursive virtualfile loop into visitor
RedNesto Jun 15, 2024
bb93e27
Make provider label a property and localize it
RedNesto Jun 15, 2024
226d986
Move repo table code outside of MinecraftConfigurable
RedNesto Jun 15, 2024
d859d81
Fix differences in creator properties naming and ctor parameters order
RedNesto Jun 15, 2024
fb2b6cb
Some work towards more extensible derivations
RedNesto Jun 16, 2024
3d6927a
Add missing licenses
RedNesto Jun 16, 2024
0a769af
Remove unused imports
RedNesto Jun 16, 2024
d8b0103
Get rid of builtin sponge specific derivation
RedNesto Jun 16, 2024
fc2d756
Rework how all derivations work, with validation now!
RedNesto Jun 16, 2024
d6c6aaf
Fix imports, again
RedNesto Jun 16, 2024
119636b
MavenArtifactVersion should load versions in setupProperty
RedNesto Jun 17, 2024
ba5c7e6
Invert hidden -> visible and added custom visibility conditions
RedNesto Jun 17, 2024
31ffbbf
Add build coords default group and version
RedNesto Jun 17, 2024
8a1efc2
Add rawVersionFilter to maven artifact version property
RedNesto Jun 18, 2024
8a755b4
Add versionFilter to maven artifact version property
RedNesto Jun 20, 2024
8080e21
Fix dropdown default values and add validation to ensure selection is…
RedNesto Jun 21, 2024
fa6b944
Add Bungeecord and Spigot Kotlin templates
RedNesto Jun 24, 2024
f8a0dd3
Fix Parchment property not matching first release of a major mc version
RedNesto Jun 25, 2024
84375b6
NeoForge Kotlin templates
RedNesto Jun 29, 2024
dcc5ca2
Add $version placeholder to remote url
RedNesto Jun 29, 2024
174fec9
Fixup github archive matcher
RedNesto Jun 29, 2024
3c3b5ba
Add Fabric split sources
RedNesto Jun 30, 2024
ae4be36
Use Neo's ModDev plugin in 1.21
RedNesto Jun 30, 2024
fad2ebb
Improve template error reporting
RedNesto Jun 30, 2024
dc58e6b
Fix Loom's default version selection
RedNesto Jul 2, 2024
1c64ab4
No longer unzip remote templates
RedNesto Jul 2, 2024
4a1d63c
Cache downloaded versions
RedNesto Jul 8, 2024
55cbc54
Remove superfluous blank line
RedNesto Jul 8, 2024
cba685f
Actually add the builtin repo by default
RedNesto Jul 11, 2024
1ce67eb
Hide the repositories row if only one repo is configured
RedNesto Jul 11, 2024
4e61b15
Proper module generation for finalizers
RedNesto Jul 11, 2024
c6ad8d0
Update templates submodule
RedNesto Jul 11, 2024
d61a9bc
Add customizable storage keys
RedNesto Jul 12, 2024
4b637f7
Rename FabricApi -> Fabric API and ArchitecturyApi -> Architectury API
RedNesto Jul 12, 2024
36b34ae
Remove dead code
RedNesto Jul 12, 2024
e5e5832
Add versions download indicator
RedNesto Jul 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: true
- name: Fetch latest submodule updates
run: git submodule update --remote
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
Expand Down
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule "templates"]
path = templates
branch = main
url = https://github.com/minecraft-dev/templates
27 changes: 25 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,26 @@ val gradleToolingExtensionJar = tasks.register<Jar>(gradleToolingExtensionSource
archiveClassifier.set("gradle-tooling-extension")
}

val templatesSourceSet: SourceSet = sourceSets.create("templates") {
resources {
srcDir("templates")
compileClasspath += sourceSets.main.get().output
}
}

val templateSourceSets: List<SourceSet> = (file("templates").listFiles() ?: emptyArray()).mapNotNull { file ->
if (file.isDirectory() && (file.listFiles() ?: emptyArray()).any { it.name.endsWith(".mcdev.template.json") }) {
sourceSets.create("templates-${file.name}") {
resources {
srcDir(file)
compileClasspath += sourceSets.main.get().output
}
}
} else {
null
}
}

val externalAnnotationsJar = tasks.register<Jar>("externalAnnotationsJar") {
from("externalAnnotations")
destinationDirectory.set(layout.buildDirectory.dir("externalAnnotations"))
Expand Down Expand Up @@ -381,6 +401,9 @@ tasks.withType<PrepareSandboxTask> {
from(externalAnnotationsJar) {
into("Minecraft Development/lib/resources")
}
from("templates") {
into("Minecraft Development/lib/resources/builtin-templates")
}
}

tasks.runIde {
Expand All @@ -391,8 +414,8 @@ tasks.runIde {
systemProperty("idea.debug.mode", "true")
}
// Set these properties to test different languages
// systemProperty("user.language", "en")
// systemProperty("user.country", "US")
systemProperty("user.language", "fr")
systemProperty("user.country", "FR")
}

tasks.buildSearchableOptions {
Expand Down
15 changes: 15 additions & 0 deletions src/main/kotlin/MinecraftConfigurable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package com.demonwav.mcdev

import com.demonwav.mcdev.asset.MCDevBundle
import com.demonwav.mcdev.asset.PlatformAssets
import com.demonwav.mcdev.creator.custom.templateRepoTable
import com.demonwav.mcdev.update.ConfigurePluginUpdatesDialog
import com.intellij.ide.projectView.ProjectView
import com.intellij.openapi.options.Configurable
Expand All @@ -31,6 +32,7 @@ import com.intellij.ui.EnumComboBoxModel
import com.intellij.ui.components.Label
import com.intellij.ui.dsl.builder.AlignX
import com.intellij.ui.dsl.builder.BottomGap
import com.intellij.ui.dsl.builder.MutableProperty
import com.intellij.ui.dsl.builder.bindItem
import com.intellij.ui.dsl.builder.bindSelected
import com.intellij.ui.dsl.builder.panel
Expand Down Expand Up @@ -91,6 +93,19 @@ class MinecraftConfigurable : Configurable {
}
}

group(MCDevBundle("minecraft.settings.creator")) {
row(MCDevBundle("minecraft.settings.creator.repos")) {}

row {
templateRepoTable(
MutableProperty(
{ settings.creatorTemplateRepos.toMutableList() },
{ settings.creatorTemplateRepos = it }
)
)
}.resizableRow()
}

onApply {
for (project in ProjectManager.getInstance().openProjects) {
ProjectView.getInstance(project).refresh()
Expand Down
34 changes: 34 additions & 0 deletions src/main/kotlin/MinecraftSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@

package com.demonwav.mcdev

import com.demonwav.mcdev.asset.MCDevBundle
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.editor.markup.EffectType
import com.intellij.util.xmlb.annotations.Attribute
import com.intellij.util.xmlb.annotations.Tag
import com.intellij.util.xmlb.annotations.Text

@State(name = "MinecraftSettings", storages = [Storage("minecraft_dev.xml")])
class MinecraftSettings : PersistentStateComponent<MinecraftSettings.State> {
Expand All @@ -37,8 +41,29 @@ class MinecraftSettings : PersistentStateComponent<MinecraftSettings.State> {
var underlineType: UnderlineType = UnderlineType.DOTTED,

var isShadowAnnotationsSameLine: Boolean = true,

var creatorTemplateRepos: List<TemplateRepo> = listOf(TemplateRepo.makeBuiltinRepo()),
)

@Tag("repo")
data class TemplateRepo(
@get:Attribute("name")
var name: String,
@get:Attribute("provider")
var provider: String,
@get:Text
var data: String
) {
constructor() : this("", "", "")

companion object {

fun makeBuiltinRepo(): TemplateRepo {
return TemplateRepo(MCDevBundle("minecraft.settings.creator.repo.builtin_name"), "builtin", "true")
}
}
}

private var state = State()

override fun getState(): State {
Expand All @@ -47,6 +72,9 @@ class MinecraftSettings : PersistentStateComponent<MinecraftSettings.State> {

override fun loadState(state: State) {
this.state = state
if (state.creatorTemplateRepos.isEmpty()) {
state.creatorTemplateRepos = listOf()
}
}

// State mappings
Expand Down Expand Up @@ -86,6 +114,12 @@ class MinecraftSettings : PersistentStateComponent<MinecraftSettings.State> {
state.isShadowAnnotationsSameLine = shadowAnnotationsSameLine
}

var creatorTemplateRepos: List<TemplateRepo>
get() = state.creatorTemplateRepos.map { it.copy() }
set(creatorTemplateRepos) {
state.creatorTemplateRepos = creatorTemplateRepos.map { it.copy() }
}

enum class UnderlineType(private val regular: String, val effectType: EffectType) {

NORMAL("Normal", EffectType.LINE_UNDERSCORE),
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/creator/MinecraftModuleBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import com.intellij.openapi.roots.ModifiableRootModel

class MinecraftModuleBuilder : AbstractNewProjectWizardBuilder() {

override fun getPresentableName() = "Minecraft"
override fun getPresentableName() = "Minecraft (Old Wizard)"
override fun getNodeIcon() = PlatformAssets.MINECRAFT_ICON
override fun getGroupName() = "Minecraft"
override fun getBuilderId() = "MINECRAFT_MODULE"
Expand Down
4 changes: 3 additions & 1 deletion src/main/kotlin/creator/ProjectSetupFinalizerWizardStep.kt
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ class JdkProjectSetupFinalizer(
private var preferredJdkLabel: Placeholder? = null
private var preferredJdkReason = MCDevBundle("creator.validation.jdk_preferred_default_reason")

var preferredJdk: JavaSdkVersion = JavaSdkVersion.JDK_17
val preferredJdkProperty = propertyGraph.property(JavaSdkVersion.JDK_17)

var preferredJdk: JavaSdkVersion by preferredJdkProperty
private set

fun setPreferredJdk(value: JavaSdkVersion, reason: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ abstract class AbstractBuildSystemStep(

override val self get() = this
override val label
get() = MCDevBundle("creator.ui.build_system.label.generic")
get() = MCDevBundle("creator.ui.build_system.label")

override fun initSteps(): LinkedHashMap<String, NewProjectWizardStep> {
context.putUserData(PLATFORM_NAME_KEY, platformName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class BuildSystemPropertiesStep<ParentStep>(private val parent: ParentStep) : Ab
val groupIdProperty = propertyGraph.property("org.example")
.bindStorage("${javaClass.name}.groupId")
val artifactIdProperty = propertyGraph.lazyProperty(::suggestArtifactId)
private val versionProperty = propertyGraph.property("1.0-SNAPSHOT")
val versionProperty = propertyGraph.property("1.0-SNAPSHOT")
.bindStorage("${javaClass.name}.version")

var groupId by groupIdProperty
Expand Down
16 changes: 16 additions & 0 deletions src/main/kotlin/creator/creator-utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,15 @@ import com.demonwav.mcdev.creator.step.LicenseStep
import com.demonwav.mcdev.util.MinecraftTemplates
import com.intellij.ide.fileTemplates.FileTemplateManager
import com.intellij.ide.starters.local.GeneratorTemplateFile
import com.intellij.ide.util.projectWizard.WizardContext
import com.intellij.ide.wizard.AbstractNewProjectWizardStep
import com.intellij.ide.wizard.AbstractWizard
import com.intellij.ide.wizard.GitNewProjectWizardData
import com.intellij.ide.wizard.NewProjectWizardStep
import com.intellij.notification.Notification
import com.intellij.notification.NotificationType
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.openapi.observable.properties.ObservableMutableProperty
import com.intellij.openapi.observable.properties.ObservableProperty
import com.intellij.openapi.project.Project
Expand Down Expand Up @@ -160,3 +164,15 @@ fun notifyCreatedProjectNotOpened() {
NotificationType.ERROR,
).notify(null)
}

val WizardContext.modalityState: ModalityState
get() {
val contentPanel = this.getUserData(AbstractWizard.KEY)?.contentPanel

if (contentPanel == null) {
thisLogger().error("Wizard content panel is null, using default modality state")
return ModalityState.defaultModalityState()
}

return ModalityState.stateForComponent(contentPanel)
}
78 changes: 78 additions & 0 deletions src/main/kotlin/creator/custom/BuiltinValidations.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Minecraft Development for IntelliJ
*
* https://mcdev.io/
*
* Copyright (C) 2024 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, version 3.0 only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.demonwav.mcdev.creator.custom

import com.demonwav.mcdev.asset.MCDevBundle
import com.demonwav.mcdev.platform.fabric.util.FabricVersions
import com.demonwav.mcdev.util.SemanticVersion
import com.intellij.openapi.ui.ComboBox
import com.intellij.openapi.ui.ValidationInfo
import com.intellij.openapi.ui.validation.DialogValidation
import com.intellij.openapi.ui.validation.validationErrorIf
import com.intellij.openapi.util.text.StringUtil
import javax.swing.JComponent

object BuiltinValidations {
val nonBlank = validationErrorIf<String>(MCDevBundle("creator.validation.blank")) { it.isBlank() }

val validVersion = validationErrorIf<String>(MCDevBundle("creator.validation.semantic_version")) {
SemanticVersion.tryParse(it) == null
}

val nonEmptyVersion = DialogValidation.WithParameter<ComboBox<SemanticVersion>> { combobox ->
DialogValidation {
if (combobox.item?.parts.isNullOrEmpty()) {
ValidationInfo(MCDevBundle("creator.validation.semantic_version"))
} else {
null
}
}
}

val nonEmptyYarnVersion = DialogValidation.WithParameter<ComboBox<FabricVersions.YarnVersion>> { combobox ->
DialogValidation {
if (combobox.item == null) {
ValidationInfo(MCDevBundle("creator.validation.semantic_version"))
} else {
null
}
}
}

val validClassFqn = validationErrorIf<String>(MCDevBundle("creator.validation.class_fqn")) {
it.isBlank() || it.split('.').any { part -> !StringUtil.isJavaIdentifier(part) }
}

fun byRegex(regex: Regex): DialogValidation.WithParameter<() -> String> =
validationErrorIf<String>(MCDevBundle("creator.validation.regex", regex)) { !it.matches(regex) }

fun <T> isAnyOf(
selectionGetter: () -> T,
options: Collection<T>,
component: JComponent? = null
): DialogValidation = DialogValidation {
if (selectionGetter() !in options) {
return@DialogValidation ValidationInfo(MCDevBundle("creator.validation.invalid_option"), component)
}

return@DialogValidation null
}
}
58 changes: 58 additions & 0 deletions src/main/kotlin/creator/custom/CreatorProgressIndicator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Minecraft Development for IntelliJ
*
* https://mcdev.io/
*
* Copyright (C) 2024 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, version 3.0 only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.demonwav.mcdev.creator.custom

import com.intellij.openapi.observable.properties.GraphProperty
import com.intellij.openapi.progress.TaskInfo
import com.intellij.openapi.progress.util.ProgressIndicatorBase

class CreatorProgressIndicator(
val loadingProperty: GraphProperty<Boolean>? = null,
val textProperty: GraphProperty<String>? = null,
val text2Property: GraphProperty<String>? = null,
) : ProgressIndicatorBase(false, false) {

init {
loadingProperty?.set(false)
textProperty?.set("")
text2Property?.set("")
}

override fun start() {
super.start()
loadingProperty?.set(true)
}

override fun finish(task: TaskInfo) {
super.finish(task)
loadingProperty?.set(false)
}

override fun setText(text: String?) {
super.setText(text)
textProperty?.set(text ?: "")
}

override fun setText2(text: String?) {
super.setText2(text)
text2Property?.set(text ?: "")
}
}
Loading
Loading