kagamihogeの日記

kagamihogeの日記です。

DataGrid からのドラッグ操作中に表示するオブジェクトを変更

Flex でドラッグ&ドロップを実現する方法は、自分が知る限り 2 通りある。1 つは DragManager を使用して自前でドラッグ&ドロップ操作を作るやり方。ウチのエントリだと http://d.hatena.ne.jp/kagamihoge/20080214/1203002949 がそれに相当する。もう 1 つは、DataGrid などの ListBase 系コントロールの dragEnabled プロパティを true にするやり方。こちらはプロパティを true にするだけなのでかなり簡単。ただし、このやり方はデフォルトの動作を変えたい場合は、前者のやり方なみにいろいろと作りこむ必要が出てくる。

DataGrid の dragEnabled プロパティを true にして、ドラッグ操作を行う場合、ドラッグ中に表示されるオブジェクトはデフォルトでは行の内容を繋げたものになる。これを変更したい場合どうするか。ドラッグの開始を DragManager.doDrag で行う場合は引数にドラッグするイメージを指定すればよい。しかし、DataGrid の場合は dragEnabled を true にするだけでドラッグ可能になるので、この方法は使えないようだ。

色々調べた結果、DataGrid の dragImage *1をオーバーライドすれば良い、ということがわかった。

というわけなので、dragImage をオーバーライドして適当なコンポーネントを表示する動作に変更した DataGrid を作ってみる。

package mycomponent
{
    import mx.controls.DataGrid;
    import mx.controls.Label;
    import mx.core.IUIComponent;

    public class MyDataGrid extends DataGrid
    {
        override protected function get dragImage():IUIComponent {
            var l:Label = new Label();
            l.text = "test test";
            l.setStyle("fontSize", 20);
            return l;
        }
    }
}

すると、こうなる。

ドラッグ中のイメージ変更はこの方法で出来ることがわかった。しかし、ドラッグ中のイメージの初期出現箇所は DataGrid の左上に固定されているようで、マウスの位置とドラッグ中のイメージの場所の関係がおかしくなってしまう。

デフォルトのドラッグ動作は不自然な動きをしていないので、DataGrid の dragImage のソースを見てみる。このメソッドは mx.controls.dataGridClasses.DataGridDragProxy に処理を委譲しており、150 行目あたりで下記のように座標をゴニョゴニョしてるっぽいのが読み取れる。

o.setActualSize(ww, src.height);
var pt:Point = new Point(0, 0);
pt = DisplayObject(src).localToGlobal(pt);
pt = DataGridBase(owner).globalToLocal(pt);
o.y = pt.y;

ということは、表示するコンポーネントの座標を適当なものを指定してやれば上手くいくだろうと推測。とりあえずマウスの位置を基点にする感じでやってみる。ついでにラベルの中身を選択行の列 3 の中身を表示する。

package mycomponent
{
    import mx.controls.DataGrid;
    import mx.controls.Label;
    import mx.core.IUIComponent;

    public class MyDataGrid extends DataGrid
    {
        override protected function get dragImage():IUIComponent {
            var l:Label = new Label();
            l.text = "**" + this.selectedItem.col3 + "**";
            l.setStyle("fontSize", 20);

            l.x = this.mouseX + 20;
            l.y = this.mouseY;

            return l;
        }
    }
}

こんな感じになる。

*1:実際には ListBase の dragImage プロパティ