【注意】Viewにクロージャを引数とするbindメソッドでenable、visible設定をバインドした際の注意

Griffon

タイトルのままです。
絶対ハマると思います。
View内のボタンの活性・非活性制御にbindメソッドを使った場合注意が必要。
通常のbindメソッドなら良いのですが、クロージャを引数に受けとるタイプで注意が必要。

例えば、保存するボタンがあるとする。
保存するボタンはModelのisInsertModeプロパティかisUpdateModeプロパティがtrueの場合のみ、押せるようにしたい。
この2つの設定は、Model内で@Bindableアノテーション付きで宣言されている。

    // ...
button(
        text:"保存する",
        actionPerformed:confirmAndExecute(
view.mainFrame,
"設定を保存します。\nよろしいですか?",
"はい",
controller.updateTwitterAccount,
),
        visible:bind{
model.isInsertMode || model.isUpdateMode
},
)
// ...

ここで、Controllerにてmodel.isInsertMode、model.isUpdateModeを色々変更してみるのだが、
変更内容がうまく反映されない。
どうもmodel.isUpdateModeを変更した場合にうまく変更が反映されてくれない。

解決策

いろいろもがいているうちに、2行追加することで問題が解決した。

    // ...
button(
        text:"保存する",
        actionPerformed:confirmAndExecute(
view.mainFrame,
"設定を保存します。\nよろしいですか?",
"はい",
controller.updateTwitterAccount,
),
        visible:bind{
model.isInsertMode  // <=ここ
model.isUpdateMode  // <=ここ
model.isInsertMode || model.isUpdateMode
},
)
// ...

どうもクロージャの最終行の値評価が行われる前に一度プロパティの呼び出しをしておく必要があるようだ。
解決方法としてはかなりかっこ悪いがこれで対応できる。

追記

例えば既存処理で一度別変数にセットしてから評価しているようなプログラムでは当然問題がでないので本当にハマった。

ex

    // ...
button(
        text:"保存する",
        actionPerformed:confirmAndExecute(
view.mainFrame,
"設定を保存します。\nよろしいですか?",
"はい",
controller.updateTwitterAccount,
),
        visible:bind{
// 一度プロパティの呼び出しをしているため問題は発生しない。
def insert = model.isInsertMode
def update = model.isUpdateMode
insert || update
},
)
// ...

実行環境

$ uname -vs
Linux #50-Ubuntu SMP Fri Sep 7 16:16:45 UTC 2012
$ groovy -version
Groovy Version: 2.0.0 JVM: 1.7.0_07 Vendor: Oracle Corporation OS: Linux
$ griffon -version
------------------------------------------------------------
Griffon 1.0.0
------------------------------------------------------------
Build: 04-Jun-2012 08:53 PM
Groovy: 1.8.6
Ant: 1.8.2
Slf4j: 1.6.4
Spring: 3.1.1.RELEASE
JVM: 1.7.0_07 (Oracle Corporation 23.2-b09)
OS: Linux 3.2.0-31-generic amd64

Griffon

Posted by genzouw