<commit_before>@file:Suppress("IMPLICIT_CAST_TO_ANY")

package tornadofx

import javafx.beans.binding.BooleanExpression
import javafx.beans.property.SimpleBooleanProperty
import javafx.beans.property.SimpleObjectProperty
import javafx.beans.property.SimpleStringProperty
import javafx.collections.FXCollections
import javafx.scene.Node
import javafx.scene.control.ButtonBar
import javafx.scene.layout.BorderStrokeStyle
import javafx.scene.paint.Color
import javafx.scene.text.FontWeight

abstract class Wizard(title: String? = null, heading: String? = null) : View(title), InstanceScoped {
    val pages = FXCollections.observableArrayList<UIComponent>()

    val currentPageProperty = SimpleObjectProperty<UIComponent>()
    var currentPage by currentPageProperty

    val hasNext = booleanBinding(currentPageProperty, pages) { value != null && pages.indexOf(value) < pages.size - 1 }
    val hasPrevious = booleanBinding(currentPageProperty, pages) { value != null && pages.indexOf(value) > 0 }
    val allPagesComplete: BooleanExpression get() = booleanListBinding(pages) { complete }

    open val canFinish: BooleanExpression = SimpleBooleanProperty(true)
    open val canGoNext: BooleanExpression = hasNext
    open val canGoBack: BooleanExpression = hasPrevious

    val stepsTextProperty = SimpleStringProperty("Steps")
    val backButtonTextProperty = SimpleStringProperty("< Back")
    val nextButtonTextProperty = SimpleStringProperty("Next >")
    val finishButtonTextProperty = SimpleStringProperty("Finish")
    val cancelButtonTextProperty = SimpleStringProperty("Cancel")

    val showStepsHeaderProperty = SimpleBooleanProperty(true)
    var showStepsHeader by showStepsHeaderProperty

    val showStepsProperty = SimpleBooleanProperty(true)
    var showSteps by showStepsProperty

    val numberedStepsProperty = SimpleBooleanProperty(true)
    var numberedSteps by numberedStepsProperty

    val enableStepLinksProperty = SimpleBooleanProperty(false)
    var enableStepLinks by enableStepLinksProperty

    val showHeaderProperty = SimpleBooleanProperty(true)
    var showHeader by showHeaderProperty

    val graphicProperty = SimpleObjectProperty<Node>()
    var graphic by graphicProperty

    open fun getNextPage() = pages.indexOf(currentPage) + 1
    open fun getPreviousPage() = pages.indexOf(currentPage) - 1

    fun next() {
        currentPage.onSave()
        if (currentPage.isComplete) {
            currentPage = pages[getNextPage()]
        }
    }

    fun back() {
        currentPage = pages[getPreviousPage()]
    }

    override val root = borderpane {
        addClass(WizardStyles.wizard)
        top {
            hbox {
                addClass(WizardStyles.header)
                removeWhen { showHeaderProperty.not() }
                vbox(5) {
                    label(titleProperty)
                    label(headingProperty) {
                        addClass(WizardStyles.heading)
                        visibleWhen { titleProperty.isEqualTo(headingProperty).not() }
                    }
                }
                spacer()
                label {
                    addClass(WizardStyles.graphic)
                    graphicProperty().bind(this@Wizard.graphicProperty)
                }
            }
        }
        center {
            stackpane {
                addClass(WizardStyles.content)
                bindChildren(pages) { page ->
                    val isPageActive = currentPageProperty.isEqualTo(page)
                    page.root.apply {
                        visibleWhen { isPageActive }
                    }
                }
            }
        }
        left {
            vbox {
                addClass(WizardStyles.stepInfo)
                removeWhen { showStepsProperty.not() }
                label(stepsTextProperty) {
                    addClass(WizardStyles.stepsHeading)
                    removeWhen { showStepsHeaderProperty.not() }
                }
                vbox(5) {
                    bindChildren(pages) { page ->
                        val isPageActive = currentPageProperty.isEqualTo(page)

                        hyperlink("") {
                            textProperty().bind(stringBinding(numberedStepsProperty) { "${if (numberedSteps) (pages.indexOf(page) + 1).toString() + ". " else ""}${page.title}" })
                            toggleClass(WizardStyles.bold, isPageActive)
                            action { currentPage = page }
                            enableWhen { enableStepLinksProperty }
                        }
                    }
                }
            }
        }
        bottom {
            buttonbar {
                addClass(WizardStyles.buttons)
                button(type = ButtonBar.ButtonData.BACK_PREVIOUS) {
                    textProperty().bind(backButtonTextProperty)
                    enableWhen { canGoBack }
                    action { back() }
                }
                button(type = ButtonBar.ButtonData.NEXT_FORWARD) {
                    textProperty().bind(nextButtonTextProperty)
                    enableWhen { canGoNext }
                    action { next() }
                }
                button(type = ButtonBar.ButtonData.CANCEL_CLOSE) {
                    textProperty().bind(cancelButtonTextProperty)
                    action { close() }
                }
                button(type = ButtonBar.ButtonData.FINISH) {
                    textProperty().bind(finishButtonTextProperty)
                    enableWhen { canFinish }
                    action {
                        currentPage.onSave()
                        if (currentPage.isComplete) {
                            onSave()
                            if (isComplete) close()
                        }
                    }
                }
            }
        }
    }

    init {
        importStylesheet(WizardStyles::class)
        this.heading = heading ?: ""
    }<commit_msg>Wizard.onComplete callback<commit_after>@file:Suppress("IMPLICIT_CAST_TO_ANY")

package tornadofx

import javafx.beans.binding.BooleanExpression
import javafx.beans.property.SimpleBooleanProperty
import javafx.beans.property.SimpleObjectProperty
import javafx.beans.property.SimpleStringProperty
import javafx.collections.FXCollections
import javafx.scene.Node
import javafx.scene.control.ButtonBar
import javafx.scene.layout.BorderStrokeStyle
import javafx.scene.paint.Color
import javafx.scene.text.FontWeight

abstract class Wizard(title: String? = null, heading: String? = null) : View(title), InstanceScoped {
    val pages = FXCollections.observableArrayList<UIComponent>()

    val currentPageProperty = SimpleObjectProperty<UIComponent>()
    var currentPage by currentPageProperty

    val hasNext = booleanBinding(currentPageProperty, pages) { value != null && pages.indexOf(value) < pages.size - 1 }
    val hasPrevious = booleanBinding(currentPageProperty, pages) { value != null && pages.indexOf(value) > 0 }
    val allPagesComplete: BooleanExpression get() = booleanListBinding(pages) { complete }

    override val complete = SimpleBooleanProperty(false)

    open val canFinish: BooleanExpression = SimpleBooleanProperty(true)
    open val canGoNext: BooleanExpression = hasNext
    open val canGoBack: BooleanExpression = hasPrevious

    val stepsTextProperty = SimpleStringProperty("Steps")
    val backButtonTextProperty = SimpleStringProperty("< Back")
    val nextButtonTextProperty = SimpleStringProperty("Next >")
    val finishButtonTextProperty = SimpleStringProperty("Finish")
    val cancelButtonTextProperty = SimpleStringProperty("Cancel")

    val showStepsHeaderProperty = SimpleBooleanProperty(true)
    var showStepsHeader by showStepsHeaderProperty

    val showStepsProperty = SimpleBooleanProperty(true)
    var showSteps by showStepsProperty

    val numberedStepsProperty = SimpleBooleanProperty(true)
    var numberedSteps by numberedStepsProperty

    val enableStepLinksProperty = SimpleBooleanProperty(false)
    var enableStepLinks by enableStepLinksProperty

    val showHeaderProperty = SimpleBooleanProperty(true)
    var showHeader by showHeaderProperty

    val graphicProperty = SimpleObjectProperty<Node>()
    var graphic by graphicProperty

    open fun getNextPage() = pages.indexOf(currentPage) + 1
    open fun getPreviousPage() = pages.indexOf(currentPage) - 1

    fun next() {
        currentPage.onSave()
        if (currentPage.isComplete) {
            currentPage = pages[getNextPage()]
        }
    }

    fun back() {
        currentPage = pages[getPreviousPage()]
    }

    override val root = borderpane {
        addClass(WizardStyles.wizard)
        top {
            hbox {
                addClass(WizardStyles.header)
                removeWhen { showHeaderProperty.not() }
                vbox(5) {
                    label(titleProperty)
                    label(headingProperty) {
                        addClass(WizardStyles.heading)
                        visibleWhen { titleProperty.isEqualTo(headingProperty).not() }
                    }
                }
                spacer()
                label {
                    addClass(WizardStyles.graphic)
                    graphicProperty().bind(this@Wizard.graphicProperty)
                }
            }
        }
        center {
            stackpane {
                addClass(WizardStyles.content)
                bindChildren(pages) { page ->
                    val isPageActive = currentPageProperty.isEqualTo(page)
                    page.root.apply {
                        visibleWhen { isPageActive }
                    }
                }
            }
        }
        left {
            vbox {
                addClass(WizardStyles.stepInfo)
                removeWhen { showStepsProperty.not() }
                label(stepsTextProperty) {
                    addClass(WizardStyles.stepsHeading)
                    removeWhen { showStepsHeaderProperty.not() }
                }
                vbox(5) {
                    bindChildren(pages) { page ->
                        val isPageActive = currentPageProperty.isEqualTo(page)

                        hyperlink("") {
                            textProperty().bind(stringBinding(numberedStepsProperty) { "${if (numberedSteps) (pages.indexOf(page) + 1).toString() + ". " else ""}${page.title}" })
                            toggleClass(WizardStyles.bold, isPageActive)
                            action { currentPage = page }
                            enableWhen { enableStepLinksProperty }
                        }
                    }
                }
            }
        }
        bottom {
            buttonbar {
                addClass(WizardStyles.buttons)
                button(type = ButtonBar.ButtonData.BACK_PREVIOUS) {
                    textProperty().bind(backButtonTextProperty)
                    enableWhen { canGoBack }
                    action { back() }
                }
                button(type = ButtonBar.ButtonData.NEXT_FORWARD) {
                    textProperty().bind(nextButtonTextProperty)
                    enableWhen { canGoNext }
                    action { next() }
                }
                button(type = ButtonBar.ButtonData.CANCEL_CLOSE) {
                    textProperty().bind(cancelButtonTextProperty)
                    action { close() }
                }
                button(type = ButtonBar.ButtonData.FINISH) {
                    textProperty().bind(finishButtonTextProperty)
                    enableWhen { canFinish }
                    action {
                        currentPage.onSave()
                        if (currentPage.isComplete) {
                            onSave()
                            if (isComplete) close()
                        }
                    }
                }
            }
        }
    }

    private val completeListeners = arrayListOf<() -> Unit>()

    fun onComplete(resultListener: () -> Unit) {
        completeListeners.add(resultListener)
    }

    init {
        importStylesheet(WizardStyles::class)
        this.heading = heading ?: ""
    }

    override fun onDock() {
        complete.onChange {
            if (it) completeListeners.forEach { it()}
        }
    }
{'fraction_non_alphanumeric': 0.07807538874867703, 'fraction_numerical': 0.0011397866970609787, 'mean_word_length': 1.8039260442821274, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5196194', 'n_tokens_mistral': 3033, 'n_tokens_neox': 2877, 'n_words': 542}