Drag and Drop on JavaFX Part 2

Drag and Drop on JavaFX Part1 』から 早いもので 2ヶ月 もの月日が流れました。 つくづく 時の流れの早さに驚かされる今日この頃です。
本当は いろいろと書きたいネタはあったのですが、結局、Drag and Drop ネタに落ち着くことに...

と言うことで、今回は Part 1 で 紹介した Draggable を改善してみました。
ところで、なぜ Part 1 の Draggable を改善しなくてはならないかというと...

Node をドラッグできるようにするために、シーングラフの構造を変更しなくてはならない
からです。
例えば...
var vbox = VBox {
    content: [
        Rectangle { ... }
        Rectangle { ... }
        Rectangle { ... }
    ]
}
という VBox の子ノードをドラッグできるようにするために、
var vbox = VBox {
    content: [
        Draggable {
            node: Rectangle { ... }
        }
        Draggable {
            node: Rectangle { ... }
        }
        Draggable {
            node: Rectangle { ... }
        }
    ]
}
のようにシーングラフの構造を変更しなくてはならないのです。

それが何か?
と思われるかもしれませんが...
実は次回のテーマでもある Sortable では、これが非常に重要な意味を持つことになるのです。
ポイントは 構造と処理の分離!!

今回の改善によって上記のコードは

var vbox = VBox {
    content: [
        Rectangle { ... }
        Rectangle { ... }
        Rectangle { ... }
    ]
}

// Drag 機能 追加
for (node: vbox.content) {
    Draggable { node: node }
}
のように、ノードの構造を変更することなく、Drag 機能を追加することができます。Drag 機能 追加部分のコードは、構造と分離しており、別のクラスに記述することも可能です。改善前の Draggable では 構造と一体化していたため、別のクラスに記述することは非常に難しいのです。これはライブラリ開発にとってはとても重要なことです。

前回の Draggable.fx からの変更点は以下です。ソースを載せるほどの変更でもないので、今回は説明だけです。

  1. CustomNode を拡張するのを止めました。
  2. マウスイベントを捕捉するために Scene の再上面に scene と同じ大きさの Rectangle を追加しました。
    →構造を変更しないといいながら、実はこっそりと構造を変更していたりして...

実は 2については、node 属性で指定した Node の onMouseXxxxxx 属性を直接変更する

var _onMousePressed = node.onMousePressed;    // あらかじめ node に設定された onMousePressed 属性
node.onMousePressed = function(e: MouseEvent) {
    // Draggable に関する処理
    _onMousePressed(e);
}
というような方法も考えられますが、あらかじめ Node に設定された関数を変更してしまうのはどうかと思い、2の方法にしてみました。

次回は、いよいよ Sortable (Drag and Drop で並び替え可能なリスト) を JavaFX で実装してみたいと思います。
今回は、その前フリでした...