2017-06-22 9 views
1

私はjavafxコンポーネント用のKotlinのビルダーパターンを考え出しています。パターンは私がこれまで行ってきた何 KotlinのJavaFXコンポーネントのビルダーパターンを構築する方法

以下
fun main(args: Array<String>) { 
    val vb = vbox { 
     child { 
      hbox { 
       child { 
        label { 
         prefWidth = 20.0 
        } 
        button { 
         text = "Click" 
        } 
       } 
      } 
      label { 
       prefHeight = 80.0 
      } 
     } 
    } 
} 

のようになります。以下の通りですが、childlabelまたはChildクラスで宣言buttonメソッドを公開されていません。すべてのポインタ?

fun Pane.child(init: (Pane.() -> Unit)? = null): Child { 
    val ch = Child() 
    init?.invoke(this) 
    ch.parent = this 
    return ch 
} 

class Child { 
    var parent: Pane? = null 

    fun <T : Node> initChildNode(styleClass: String? = null, tag: T, init: (T.() -> Unit)? = null): T { 
     init?.invoke(tag) 
     tag.styleClass.add(styleClass) 
     parent?.children?.add(tag) 
     return tag 
    } 

    fun region(styleClass: String? = null, init: (Region.() -> Unit)? = null) = initChildNode(styleClass, Region(), init) 
    fun vbox(styleClass: String? = null, init: (VBox.() -> Unit)? = null) = initChildNode(styleClass, VBox(), init) 
    fun hbox(styleClass: String? = null, init: (HBox.() -> Unit)? = null) = initChildNode(styleClass, HBox(), init) 
    fun label(styleClass: String? = null, init: (Label.() -> Unit)? = null) = initChildNode(styleClass, Label(), init) 
    fun button(styleClass: String? = null, init: (Button.() -> Unit)? = null) = initChildNode(styleClass, Button(), init) 

} 

fun vbox(styleClass: String? = null, init: (VBox.() -> Unit)? = null) = initNode(styleClass, VBox(), init) 
fun hbox(styleClass: String? = null, init: (HBox.() -> Unit)? = null) = initNode(styleClass, HBox(), init) 

fun <T : Node> initNode(styleClass: String? = null, tag: T, init: (T.() -> Unit)? = null): T { 
    init?.invoke(tag) 
    tag.styleClass.add(styleClass) 
    return tag 
} 

注:私はTornadoFXライブラリに見てきましたが、私は目的を学習に主に起因する私自身の解決策を考え出すのが好き。

+1

あなたはこれらの関数がスコープになりたい場合は、 'あなた' init'パラメータは延長すべきです「ペイン」の代わりに「チャイルド」を選択します。 – zsmb13

+0

ここで必要なのはhttps://kotlinlang.org/docs/reference/type-safe-builders.htmlです – Calin

答えて

0

私は最終的に@ zsmb13のアドバイスを使って解決策を考え出しました。ここで

それは相手の参照

fun <T : Pane> T.children(init: (Children.() -> Unit)? = null): Children { 
    val ch = Children() 
    ch.parent = this 
    init?.invoke(ch) 
    return ch 
} 

class Children : Layout() { 
    var parent: Pane? = null 

    override fun <T : Node> initNode(styleClass: String?, tag: T, init: (T.() -> Unit)?): T { 
     val node: T = super.initNode(styleClass, tag, init) 
     parent?.children?.add(node) 
     return node 
    } 
} 

open class Layout { 
    var pane: Pane? = null 

    open fun <T : Node> initNode(styleClass: String? = null, tag: T, init: (T.() -> Unit)? = null): T { 
     init?.invoke(tag) 
     tag.styleClass.add(styleClass) 
     return tag 
    } 

    fun region(styleClass: String? = null, init: (Region.() -> Unit)? = null) = initNode(styleClass, Region(), init) 
    fun vbox(styleClass: String? = null, init: (VBox.() -> Unit)? = null) = initNode(styleClass, VBox(), init) 
    fun hbox(styleClass: String? = null, init: (HBox.() -> Unit)? = null) = initNode(styleClass, HBox(), init) 
    fun label(styleClass: String? = null, init: (Label.() -> Unit)? = null) = initNode(styleClass, Label(), init) 
    fun button(styleClass: String? = null, init: (Button.() -> Unit)? = null) = initNode(styleClass, Button(), init) 
    fun progressBar(styleClass: String? = null, init: (ProgressBar.() -> Unit)? = null) = initNode(styleClass, ProgressBar(), init) 
} 

fun <T : Pane> layout(styleSheet: String = "", init: Layout.() -> T): T { 
    val layout = Layout() 
    val pane = layout.init() 
    layout.pane = pane 
    pane.stylesheets.add(layout.javaClass.classLoader.getResource(styleSheet).toExternalForm()) 
    return pane 
} 

のためのものであり、使い方は以下のようなものです:

private var loadProgress: ProgressBar? = null 
private var progressText: Label? = null 

val layout = layout("xyz.css") { 
      vbox("screen") { 
       prefWidth = 500 
       prefHeight = 450 
       children { 
        region { minHeight = 250.0 } 
        hbox { 
         children { 
          region { minWidth = 30.0 } 
          label("large-label") { 
           text = "Foo" 
          } 
          label("large-label") { 
           text = "Bar" 
          } 
          region { minWidth = 20.0 } 
          label("small-label") { 
           text = "xyz" 
          } 
         } 
        } 
        region { minHeight = 10.0 } 
        loadProgress = progressBar("progress") { minWidth = [email protected] } 
        hbox { 
         children { 
          region { minWidth = 30.0 } 
          progressText = label("progress-label") 
         } 
        } 
       } 
      } 
     } 
関連する問題