目次 | 前の項目 | 次の項目 ドラッグ&ドロップ


2.4 ドロップターゲット


2.4.1 DropTarget の登録および登録解除のための java.awt.Component の追加

Java.awt.Component クラスには、DropTarget との関連付けおよび関連付け解除を可能にするために、メソッドが 2 つ追加されました。特に次の点が重要です。

public class java.awt.Component /* ... */ {
	// ...

	public synchronized
			void       setDropTarget(DropTarget dt);

	public synchronized
			DropTarget getDropTarget(DropTarget df);

	//
}

DropTarget を Component に関連付けるには、DropTarget.setCompononent() または Component.setDropTarget() のどちらのメソッドを呼び出すこともできます。このため、相互再帰呼び出しを防ぐために、両方のメソッドの実装に準拠する必要があります。

DropTarget の Component への関連付けを解除するには、DropTarget.setCompononent(null) メソッドと Component.setDropTarget(null) メソッドのどちらでも呼び出すことができます。

これら 2 つのメソッドが相互の状態を適切に管理するために、各メソッドを、DropTarget と Component の両方に準拠するように実装する必要があります。

DropTarget の実パラメータが Component のこのクラスまたはインスタンスとともに使うことが不適切な場合は、setDropTarget() メソッドは、IllegalArgumentException を発行します。また、Component が DropTarget の外部設定をサポートしていない場合なども、このメソッドは UnsupportedOperationException を発行します。


2.4.2 DropTarget の定義

DropTarget は、操作の受け側、つまりドロップ先の役割に関連する、ドラッグ&ドロッププロトコルのプラットフォーム固有の処理をすべてカプセル化します。

一般に、単一の DropTarget インスタンスを、java.awt.Component の任意のインスタンスに関連付けることができます。このような関係を確立すると、関連付けられた Component の可視ジオメトリに論理カーソルの座標が交差したときに、ドラッグ&ドロップ操作の受け取りが可能であるとして、このジオメトリがクライアントのデスクトップにエクスポートされます。

DropTarget クラスは、次のように定義されています。

public class java.awt.dnd.DropTarget
       implements DropTargetListener, Serializable {

     public DropTarget(Component          c,
                       int                actions,
                       DropTargetListener dsl,
                       boolean            isActive,
                       FlavorMap          fm
     );

	public DropTarget();

	public DropTarget(Component c);
	public DropTarget(Component c, DropTargetListener dsl);

	public Component getComponent();
	public void      setComponent(Component c);

	public DropTargetContext getDropTargetContext();


	public void
	    addDropTargetListener(DropTargetListener dte)
		  throws TooManyListenersException;

	public void
	    removeDropTargetListener(DropTargetListener dte);

	public void	    setActive(boolean active);
	public boolean isActive();

	public FlavorMap getFlavorMap();
     public void      setFlavorMap(FlavorMap fm);

     public void setDefaultActions(int actions);
     public int  getDefaultActions();

	protected DropTargetContext createDropTargetContext();

	public void addNotify(ComponentPeer cp);
	public void removeNotify(ComponentPeer cp);
}

Component の実パラメータが DropTarget のこのクラスまたはインスタンスとともに使うことが不適切な場合は、setComponent() メソッドは、IllegalArgumentException を発行します。 また、このメソッドは、指定された Component で、DropTarget の外部設定が許可されていない場合も、UnsupportedOperationException を発行します。

addDropTargetListener() および removeDropTargetListener() メソッドを使って、ユニキャスト DropTargetListener を変更できます。

setActive() および isActive() メソッドを使って、DropTarget をアクティブまたは非アクティブにしたり、DropTarget の現在の状態を知ることができます。

getFlavorMap() メソッドは、プラットフォームに依存した型名と、それに対応するプラットフォームに依存しない DataFlavors との間のマッピングを行う目的で、この DropTarget に関連付けられた FlavorMap を取得するために使います。

setFlavorMap() メソッドは、新しい FlavorMap を DropTarget に割り当てます。 パラメータに null が指定された場合は、「デフォルトの」 FlavorMap を DropTarget にインストールします。

createDropTargetContext() メソッドは、ドラッグ操作で最初に DropTarget に関連付けられた Component に遭遇したときに、背後のプラットフォームに依存したピアに、新しい DropTargetContext のインスタンスを提供するためだけに呼び出されます。現在 DropTarget に関連付けられている DropTargetContext がない場合は、getDropTargetContext() の呼び出しに許可されている副作用によって、新しい DropTargetContext のインスタンスが生成されます。

addNotify() および removeNotify() メソッドは、Component の ComponentPeer への関連付けを DropTarget に通知するためだけに、Component から呼び出されます。

DropTarget 自体が DragTargetListener を実装することに注目してください。 これにより、プラットフォームによって作成されたプラットフォームのピアである DropTargetContextPeer のインスタンスは、DropTarget に進行中の操作状態の変化について通知できるようになり、したがって DropTarget は、プラットフォームと DropTarget に登録されている DropTargetListener の間に割り込むことができるようになります。


2.4.3 DropTargetContext の定義

進行中のドラッグ&ドロップ操作に関連付けられた論理カーソルが、DropTarget に関連付けられた Component の可視ジオメトリと最初に交差すると、DropTarget に関連付けられた DropTargetContext がインタフェースになります。 このインタフェースを介して、DropTargetListener から受け側のプロトコルの状態の制御にアクセスできます。

DropTarget の DropTargetContext が存在しない場合は、DropTarget の getDropTargetContext() メソッドが呼び出されたときに、DropTarget の createDropTargetContext() メソッドによって DropTargetContext が作成されます。

DropTargetContext インタフェースは、次のように定義されています。

public class DropTargetContext {
	public DropTarget getDropTarget();

	public Component		 getComponent();

	public void		 dropComplete(boolean success)
				throws InvalidDnDOperationException;

	public void acceptDrag(int dropAction);
	public void rejectDrag();

	public void acceptDrop(int dropAction);
	public void rejectDrop();

	public void addNotify(DropTargetContextPeer dtcp);
	public void removeNotify();

	protected Transferable
		createTransferableProxy(Transferable t,
		                        boolean      isLocal
		);

     protected void setTargetActions(int actions);
     protected int  getTargetActions();

     protected DataFlavor[] getCurrentDataFlavors();
     protected List         getCurrentDataFlavorsAsList();
    
     protected boolean isDataFlavorSupported(DataFlavor df);

     protected Transferable getTransferable();
    
}


アクセスおよび制御を行うメソッドは、ほとんどが protected です。 これらのメソッドの状態に public アクセスするときは、通常、特定の DropTargetEvent サブクラスを使用して呼び出し、要求を DropTargetContext に委譲するためです。

getDropTarget() メソッドは、この DropTargetContext を作成した DropTarget を返します。

getComponent() メソッドは、この DropTargetContext を作成した DropTarget に関連付けられた Component を返します。

acceptDrag() メソッドは、DropTargetDragEvent の類似のメソッドから委譲されており、DropTargetListener のメソッド dragEnter()、dragOver()、または dropActionChanged() から呼び出されます。 acceptDrag() の呼び出しは、受け側では指定されたオペレーションを含むドロップの受け取りの準備ができていることを意味します。 通常は、現在ユーザが選択しているアクションがオペレーションとして指定されます。

rejectDrag() メソッドは、DropTargetDragEvent の類似のメソッドから委譲されており、DropTargetListener のメソッド dragEnter()、dragOver()、または dropActionChanged() から呼び出されます。 rejectDrag() の呼び出しは、受け側では現在ユーザが選択しているアクションを含むドロップの受け取りが不可能であることを意味します。

acceptDrop() メソッドは、DropTargetDropEvent の類似のメソッドから委譲されており、DropTargetListener の drop() メソッドから呼び出されます。 acceptDrop() の呼び出しは、受け側では指定されたオペレーションを含むドロップの受け取りの準備ができていることを意味します。 通常は、現在ユーザが選択しているアクションがオペレーションとして指定されます。

rejectDrop() メソッドは、DropTargetDropEvent の類似のメソッドから委譲されており、DropTargetListener の drop() メソッドから呼び出されます。 rejectDrop() の呼び出しは、受け側では現在ユーザが選択しているアクションを含むドロップの受け取りが不可能であることを意味します。このメソッドにより、ドラッグ&ドロップ操作が終了し、データは転送されません。

dropComplete() メソッドは、DropTargetListener がドラッグ&ドロップオペレーションの対象を含む転送を完了したこと、およびオペレーションが完了したことを、転送元の DragSource に通知します。転送の成功 (または失敗) および指定されたオペレーションのそれ以降の適用が、実際のパラメータの値によって通知されます。

getDataFlavors() メソッドは、DragSource で利用できる DataFlavors の配列を返します。

getTransferable() メソッドは、Transferable を返し、getTransferData() メソッドを介したデータ転送を可能にします。 返される Transferable は、必ずしも DragSource が登録したものではなく、プロキシの可能性もあります (JVM* 間の転送ではプロキシ)。最初に acceptDrop() を呼び出さずに getTransferData() を呼び出すことは不正です。

addNotify() および removeNotify() メソッドは、基本的なプラットフォームの DropTargetContextPeer によって排他的に呼び出され、DropTargetContext およびそれと関連付けられた DropTarget で発生または終了したドラッグ&ドロップ操作を DropTargetContext に通知します。

createTransferableProxy() メソッドにより、DropTargetContext の実装で、DropTargetListener と呼び出し元から提供された Transferable との間に Transferable を挿入できるようになります。 一般に、呼び出し元は基本的なプラットフォームの DropTargetContextPeer です。


2.4.4 DropTargetListener の定義

適切な Drag-under フィードバックセマンティクスの提供、およびその後のドロップの処理は、DropTarget に関連付けられた DropTargetListener を使って可能になります。

DropTargetListener は、転送元によって提案された動作、および利用可能なデータ型を検査することによって、ドロップが可能かどうかに関する適切な Drag-under フィードバックおよび DragSource への応答を決定します。

特定の DropTargetListener インスタンスは、addDropTargetListener() メソッドを介して DropTarget に関連付けられ、removeDropTargetListener() メソッドを介して削除されます。

public interface java.awt.dnd.DropTargetListener
	  extends java.util.EventListener {
	void dragEnter            (DropTargetDragEvent dtde);
	void dragOver             (DropTargetDragEvent dtde);
     void dropActionChanged    (DropTargetDragEvent dtde);
	void dragExit             (DropTargetDragEvent dtde);
	void drop                 (DropTargetDropEvent dtde);
}

DropTargetListener の dragEnter() メソッドは、論理 Drag カーソルのホットスポットが、DropTarget に関連付けられた Component のジオメトリの可視部分と交差したときに呼び出されます。この通知を受け取ると、DropTargetListener は、DragSource から提供される動作、およびデータ型 (DataFlavors) を調べて、適切な動作および Drag-under フィードバックを決定し、acceptDrag() または rejectDrag() を呼び出します。

DropTargetListener の dragOver() メソッドは、動いている論理 Drag カーソルのホットスポットが、DropTarget に関連付けられた Component のジオメトリの可視部分と交差している間、呼び出されます。この通知を受け取ると、DropTargetListener は、DragSource から提供される「動作」およびデータの型を調べて、適切な動作および Drag-under フィードバックを決定し、acceptDrag() または rejectDrag() の呼び出しによって応答します。

getLocation() メソッドは、関連付けられた Component を原点として、論理 Drag カーソルのホットスポットの現在の相対座標を返します。

getSourceActions() メソッドは、現在の「動作」、つまり DragSource によって現在のドラッグ&ドロップのジェスチャーに関連付けられた操作 (ACTION_MOVEACTION_COPY、または ACTION_LINK) を返します。

DropTargetListener の dragExit() メソッドは、論理 Drag カーソルのホットスポットが、DropTarget に関連付けられた Component のジオメトリの可視部分と交差しなくなったとき、または drop() による通知が行われる直前に呼び出されます。この通知を受け取ると、DropTargetListener は、それまでに適用したすべての Drag-under フィードバック効果を取り消します。このとき、DropTarget に関連付けられた DropTargetContext が無効になることに注意してください。

交差している間にユーザがドラッグジェスチャーを終了すると、DropTargetListener の drop() メソッドが呼び出されます。この通知を受け取ると、DropTargetListener は、DropTargetDropEvent オブジェクト上の getSourceActions() メソッドの戻り値によって指定された操作を、getTransferable() メソッドから返された Transferable オブジェクト上で実行します。 その後、関連付けられた DropTargetContext の dropComplete() メソッドを呼び出して、操作の成功または失敗を示します。


2.4.5 DropTargetDragEvent および DropTargetDropEvent の定義

DropTargetEvent および DropTargetDragEvent は次のように定義されています。

public abstract class java.awt.dnd.DropTargetEvent
	  extends java.util.EventObject1 {

	public DropTargetContext getDropTargetContext();

}

DropTargetEvent は、DropTargetListener の dragExit() メソッドに渡されます。


public class   java.awt.dnd.DropTargetDragEvent
	  extends java.awt.dnd.DropTargetEvent {
	public DataFlavor[] getDataFlavors();

	public Point	  getLocation();

	public int getSourceActions();

     public getDropAction();

     public DataFlavor[] getCurrentDataFlavors();
	public List         getCurrentDataFlavorsAsList();

     public boolean isDataFlavorSupported();

	public void acceptDrag(int operation);
	public void rejectDrag();

}

DropTargetDragEvent は、DropTargetListener の dragEnter()、dragOver()、および dropActionChanged() メソッドに渡されます。

getLocation() メソッドは、関連付けられた Component を原点として、論理 Drag カーソルのホットスポットの現在の相対座標を返します。

getSourceActions() メソッドは、現在の「動作」、つまり DragSource によって現在のドラッグ&ドロップのジェスチャーに関連付けられた操作 (ACTION_MOVEACTION_COPY、または ACTION_REFERENCE) を返します。

getCurrentDataFlavors()、getCurrentDataFlavorsAsList()、および isDataFlavorSupported() メソッドは、転送元のデータ型を受け側で調べるときに使用します。

このメソッドは、次のように定義します。

public class java.awt.dnd.DropTargetDropEvent
	  extends java.awt.dnd.DropTargetEvent {

	public Point	  getLocation();

	public int getSourceActions();

     public int getDropAction();

	public void acceptDrop(int dropAction);
	public void rejectDrop();	

	public boolean isLocalTransfer();

     public DataFlavor[] getCurrentDataFlavors();
     public List         getCurrentDataFlavorsAsList();

     public boolean isDataFlavorSupported(DataFlavor df);

	public Transferable getTransferable();
 
     public void dropComplete(boolean success);
}

ドロップが発生すると、DropTargetDropEvent が DropTargetListener の drop() メソッドに渡されます。DropTargetDropEvent は DropTargetListener に対して、getTransferable() メソッドから返される Transferable を介して、この操作に関連付けられたデータへのアクセスを提供します。

getSourceActions() の戻り値は、ドロップの発生時に転送元によって定義された動作であると定義されています。

getDropAction() メソッドの戻り値は、ユーザのジェスチャーによって選択されたドロップアクションおよび転送元でサポートされるアクションの共通部分として、ドロップ実行時に定義されます。また、結果のアクションは、通常、この戻り値とドロップ実行時のターゲットでサポートされるアクションの共通部分になります。

getLocation() メソッドの戻り値は、ドロップが発生した位置であると定義されています。

getCurrentDataFlavors()、getCurrentDataFlavorsAsList()、および isDataFlavorSupported() メソッドは、Transferable の getTransferData() メソッドによって後続の転送が行われるときに、転送元のデータ型を受け側で調べるときに使用されます。

drop() メソッドの標準の実装は、アクションおよび利用可能な DataFlavors を検査し、交換が正常に終了するかどうかを判定します。

交換が発生すると、DropTargetListener.drop() 実装は、getTransferable() を呼び出す前に、選択されたオペレーションを実パラメータとして acceptDrop() を呼び出します。acceptDrop() の前に getTransferable() を呼び出すと、InvalidDnDOperationException が発生します。

rejectDrop() を呼び出して、ドロップ操作を拒否することも可能です。rejectDrop() を呼び出すと、転送元と受け側の間の対話が停止します。このため、通常は、rejectDrop() を呼び出したら、ただちに drop() メソッドから戻ります。

ドラッグ&ドロップ操作の転送元が、drop() による通知の受け側と同一の物理 JVM に存在する場合は、isLocalTransfer() メソッドから true が返されます。 同一の物理 JVM に存在しない場合は、false が返されます。

ローカルの物理 JVM で呼び出された Transferable.getTransferData() からオブジェクト参照を受け取る場合は、この違いが重要になります。 この場合、受け取ったオブジェクト参照は、転送元で保持されているものと同じです (コピー、プロキシ、および異なるオブジェクトではない)。 このため、受け側では共有オブジェクト参照を、次のような特別な方法で処理する必要があります。

dropComplete() メソッドは、関連付けられたドラッグ&ドロップ操作の終了を通知し、受け側で実行された転送の成功 (または失敗) を返します。このメソッドを呼び出すと、DragSourceListener の dragDropEnd() メソッドが、DragSourceDropEvent で使用できる適切な状態で呼び出されます。このメソッドの呼び出しに失敗すると、ドラッグ&ドロップ操作が正常に終了しなくなります。


2.4.6 自動スクロールのサポート

多くの GUI コンポーネントは、大規模な (大規模になり得る) データセットに対し、スクロール可能な「ビューポート」を提供します。ドラッグ&ドロップ操作時には、これらのビューポートを自動スクロールできることが望ましいでしょう。 そうすれば、操作の対象物をドロップしたい特定の (最初はビューポートに表示されていない) メンバの位置までスクロールしながら、データセット上を移動することができます。

スクロール可能なコンポーネントは、次のインタフェースを実装することによって、DropTarget にドラッグの「自動スクロール」機能を提供します。

public interface Autoscroll {
	Insets getAutoscrollInsets();

	void autoScrollContent(Point cursorLocn);
}

次の条件が満たされた場合、実装する DropTarget は、関連付けられたコンポーネント (存在する場合) の autoScroll() メソッドを定期的に呼び出し、コンポーネントの座標で表した現在の論理カーソルの位置を渡します。

上のいずれかの条件が満たされなくなると、次にトリガーとなる条件が発生するまで自動スクロール機能は終了します。

自動スクロール開始前の初期遅延、自動スクロール通知の間隔、およびピクセルのヒステリシス値はすべて、外部で設定でき、Toolkit.getDesktopProperty() メソッドから問い合わせることができます。

* この Web サイトで使用されている用語「Java Virtual Machine」または「JVM」は、Java プラットフォーム用の仮想マシンを表します。


目次 | 前の項目 | 次の項目
Copyright © 1997, 1998 Sun Microsystems, Inc. All Rights Reserved.