gallu’s blog

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

Drag and Drop 調査:toオブジェクト変

次はtoオブジェクトに実装かけて移動完了とする必要がある。
えと…長いんで、ふくしぅ。

・移動中のfromオブジェクトがtoオブジェクトの上空にいる
・その状態でマウスアップ(クリックの指を外す)が発生する
・fromオブジェクトを受け入れる準備が整ったので「かも〜ん」

ふむり。
次に、イベント系の確認。DragEventをチェック。
http://livedocs.adobe.com/flex/3_jp/langref/mx/events/DragEvent.html
DRAG_DROP、DRAG_ENTER、DRAG_EXITあたりがポイントかしらん。
とりあえずイベントを出すクラス(UIComponentクラス)のイベントを確認。
http://livedocs.adobe.com/flex/3_jp/langref/mx/core/UIComponent.html


dragDrop イベント

ユーザーがドロップターゲット上でマウスを離したとき、ドロップターゲットによって送出されます。


このイベントハンドラは、ドラッグデータをドロップターゲットに追加するために使用します。


ある Tree コントロールから別の Tree コントロールにデータをドラッグするときに、Event.preventDefault() を Tree コントロールの dragDrop イベントのイベントハンドラで呼び出すと、ドロップは行われません。
DragEvent.DRAG_DROP 定数により、イベントオブジェクトの type プロパティ値が dragDrop イベント用に定義されます。


dragEnter イベント

ドラッグ操作時に、コンポーネント上でマウスを移動したとき、コンポーネントによって送出されます。Flash Player で実行しているアプリケーションの場合、コンポーネント上にマウスを移動するたびに何度もこのイベントが送出されます。AIR で実行しているアプリケーションの場合、このイベントは 1 回だけ送出されます。


コンポーネントを有効なドロップターゲットとするには、このイベントのハンドラを定義する必要があります。ハンドラ内では、コンポーネントがドラッグを受け付けることができることを示す視覚的なフィードバックをユーザーに提供するために、ドロップターゲットの外観を変更できます。例えば、ドロップターゲットの周囲に境界線を表示したり、ドロップターゲットにフォーカスを移すことができます。


ドラッグを受け入れる場合は、DragManager.acceptDragDrop() メソッドを呼び出す必要があります。acceptDragDrop() を呼び出さないと、他のドラッグイベントがすべて取得されなくなります。


Flash Player では、action プロパティの値は、コピーの実行中も常に DragManager.MOVE です。 これは、Control キーが押され、コピーが通知されたことをコントロールが認識する前に dragEnter イベントが発生するためです。 action プロパティ(dragOver イベントのイベントオブジェクト)には、ドラッグ操作の種類を示した値が含まれています。DragManager.showFeedback() メソッドを呼び出してドラッグアクションの種類を変更することもできます。


dragCompleteイベント

ドラッグ操作が完了したとき(ドラッグデータをドロップターゲットにドロップするか、ドロップを実行せずにドラッグ&ドロップ操作を終了したときのいずれか)、ドラッグイニシエータ(ドラッグしたデータのソースであるコンポーネント)によって送出されます。
このイベントは、ドラッグ&ドロップ操作の最終的なクリーンアップを行うために使用できます。例えば、List コントロールアイテムをあるリストから別のリストにドラッグする場合、List コントロールアイテムがそれ以降必要でなければソースから削除することができます。

ふむり…acceptDragDropあたり不明だし無視してみようかと思ったけど、しっかり釘刺されてる(苦笑


とりあえず実装してみまっしょ。
ついでに、ちょいと遊び入れてます。えと…「括弧の演算子ってインスタンスreferer返すよねぇ普通」に基づく、かなり省略チックな記述です…ってのを先に。
一番わかりやすくてわかりにくいところを一例にとって。


通常

  // 変数宣言して
  var ui_to:UIComponent;
  var ui_from:UIComponent;
  // 型変えて
  ui_to = e.currentTarget as UIComponent;
  ui_from = e.dragInitiator as UIComponent;
  // メソッドcall
  ui_to.addChild(ui_from);

って書くと思うのですが、ぢつはこれ

(e.currentTarget as UIComponent).addChild(e.dragInitiator as UIComponent);

って省略できます。ので、これ使ってます。


で、ソース。


mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="onComplete()">

<!-- ********************************** -->
<mx:Script source="base.as" />


<!-- ********************************** -->
<mx:Panel>
	
<mx:Panel>
  <mx:HBox id="h_from" />
</mx:Panel>

<mx:Panel>
  <mx:HBox id="h_area" />
</mx:Panel>


</mx:Panel>
	
</mx:Application>


Script

//
import flash.events.MouseEvent;

import mx.containers.Panel;
import mx.controls.Button;
import mx.core.DragSource;
import mx.core.UIComponent;
import mx.events.DragEvent;
import mx.managers.DragManager;


private function onComplete():void{
  var btn:Button;
  var pl:Panel;
  for (var i:int = 0; i < 3; i ++) {
    // 置き場所
    pl = new Panel;
    pl.id = "pl_" + i.toString();
    //
    pl.addEventListener(DragEvent.DRAG_ENTER, d_in);
    pl.addEventListener(DragEvent.DRAG_DROP, d_drop);
    //
    h_from.addChild(pl);

    // ボタン
    btn = new Button;
    btn.label = "● " + i.toString();
    btn.id = "btn_" + i.toString();
    //
    btn.addEventListener(MouseEvent.MOUSE_DOWN, m_down);
    //
    h_area.addChild(btn);
  }

}

// マウスダウン
private function m_down(e:MouseEvent):void{
  DragManager.doDrag(e.currentTarget as UIComponent, new DragSource(), e);
}

// 上空におこしやす
private function d_in(e:DragEvent):void {
//trace (e.currentTarget);
//trace (event.dragInitiator);
  DragManager.acceptDragDrop(e.currentTarget as UIComponent);   // ドロップの受け入れ可能
}

// 落下!
private function d_drop(e:DragEvent):void {
//trace (e.currentTarget);
//trace (e.dragInitiator);
  (e.currentTarget as UIComponent).addChild(e.dragInitiator as UIComponent);
}


//private

こげな感じ。


ふむり…なんとかD&D出来るようになったかな。