目次 | 前の項目 | 次の項目 | ドラッグ&ドロップ |
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 を発行します。
setDropTarget() メソッドの呼び出し元には、AWTPermission: setDropTarget が必要です。呼び出し元にこのアクセス権がない場合は、setDropTarget() は SecurityException を発行します。
DropTarget は、操作の受け側、つまりドロップ先の役割に関連する、ドラッグ&ドロッププロトコルのプラットフォーム固有の処理をすべてカプセル化します。一般に、単一の DropTarget インスタンスは、java.awt.Component の任意のインスタンスに関連付けられます。このような関係を確立すると、関連付けられた Component の可視ジオメトリに論理カーソルの座標が交差したときに、ドラッグ&ドロップ操作の受け取りが可能であるとして、このジオメトリがクライアントのデスクトップにエクスポートされます。
DropTarget クラスは、次のように定義されています。
public class java.awt.dnd.DropTarget implements DropTargetListener, Serializable { 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(); protected DropTargetContext createDropTargetContext(); public void addNotify(ComponentPeer cp); public void removeNotify(ComponentPeer cp); }
Component の実パラメータが DropTarget のこのクラスまたはインスタンスとともに使うことが不適切な場合は、setComponent() メソッドは、IllegalArgumentException を発行します。また、このメソッドは、指定された Component で、DropTarget の外部設定が許可されていない場合も、UnsupportedOperationException を発行します。セキュリティ上の理由から、setComponent() の呼び出し元は、AWTPermission setDropTarget を必要とします。そうでない場合は、SecurityException が発行されます。
addDropTargetListener() および removeDropTargetListener() メソッドを使って、ユニキャスト DropTargetListener を変更できます。
setActive() および isActive() メソッドを使って、DropTarget をアクティブまたは非アクティブにしたり、DropTarget の現在の状態を知ることができます。
getFlavorMap() メソッドは、プラットフォームに依存した型名と、それに対応するプラットフォームに依存しない DataFlavors との間のマッピングを行う目的で、この DropTarget に関連付けられた FlavorMap を取得するために使います。
通常、createDropTargetContext() メソッドは、ドラッグ操作で最初に DropTarget に関連付けられた Component に遭遇したときに、背後のプラットフォームに依存したピアに、新しい DropTargetContext のインスタンスを提供するためだけに呼び出されます。現在 DropTarget に関連付けられている DropTargetContext がない場合は、getDropTargetContext() の呼び出しに許可されている副作用によって、新しい DropTargetContext のインスタンスが生成されます。
addNotify() および removeNotify() メソッドは、Component の ComponentPeer への関連付けを DropTarget に通知するためだけに、Component から呼び出されます。
進行中のドラッグ&ドロップ操作に関連付けられた論理カーソルが、DropTarget に関連付けられた Component の可視ジオメトリと最初に交差すると、DropTarget に関連付けられた DropTargetContext がインタフェースになります。このインタフェースを介して、DropTargetListener から受け側のプロトコルの状態の制御にアクセスできます。DropTargetContext インタフェースは、次のように定義されています。
public class DropTargetContext { public DropTarget getDropTarget(); public Component getComponent(); public DataFlavor[] getDataFlavors(); public void getTransferable() throws InvalidDnDOperationException; public void dropComplete(boolean success) throws InvalidDnDOperationException; protected void acceptDrop(int action); protected void rejectDrop(); public void addNotify(DropTargetContextPeer dtcp); public void removeNotify(); protected Transferable createTransferableProxy(Transferable t, boolean isLocal ); }
getDataFlavors() メソッドは、DragSource で利用できる DataFlavors の配列を返します。getTransferable() メソッドは、Transferable を返し、getTransferData() メソッドを介したデータ転送を可能にします。返される Transferable は、必ずしも DragSource が登録したものではなく、プロキシの可能性もあります (JVM 間の転送ではプロキシ)。最初に acceptDrag() を呼び出さずに getTransferData() を呼び出すことは不正です。
addNotify() および removeNotify() メソッドは、背後のプラットフォームの DropTargetContextPeer によって排他的に呼び出され、DropTargetContext およびそれと関連付けられた DropTarget で発生または終了したドラッグ&ドロップ操作を DropTargetContext に通知します。
createTransferableProxy() メソッドにより、DropTargetContext の実装で、DropTargetListener と呼び出し元から提供された Transferable との間に Transferable を挿入できるようになります。一般に、呼び出し元は背後のプラットフォームの DropTargetContextPeer です。
適切な 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 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() の呼び出しによって応答します。
getCursorLocation() メソッドは、関連付けられた Component を原点として、論理 Drag カーソルのホットスポットの現在の相対座標を返します。
getSourceActions() メソッドは、現在の「動作」、つまり DragSource によって現在のドラッグ&ドロップのジェスチャーに関連付けられた操作 (ACTION_MOVE、ACTION_COPY、または ACTION_REFERENCE) を返します。
DropTargetListener の dragExit() メソッドは、論理 Drag カーソルのホットスポットが、DropTarget に関連付けられた Component のジオメトリの可視部分と交差しなくなったときに呼び出されます。この通知を受け取ると、DropTargetListener は、それまでに適用したすべての Drag-under フィードバック効果を取り消します。
DropTargetListener の drop() メソッドは、DragSource が commitDrop() メソッドを呼び出した結果として呼び出されます。この通知を受け取ると、DropTargetListener は、DropTargetDropEvent オブジェクト上の getSourceActions() メソッドの戻り値によって指定された操作を、getTransferable() メソッドから返された Transferable オブジェクト上で実行します。その後、関連付けられた DropTargetContext の dropComplete() メソッドを呼び出して、操作の成功または失敗を示します。
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(); Point getCursorLocation(); public int getSourceActions(); public void acceptDrag(int operations); public void rejectDrag(); public boolean isTransferableLocal(); }
DropTargetDragEvent は、DropTargetListener の dragEnter() および dragOver() メソッドに渡されます。getCursorLocation() メソッドは、関連付けられた Component を原点として、論理 Drag カーソルのホットスポットの現在の相対座標を返します。
getSourceActions() メソッドは、現在の「動作」、つまり DragSource によって現在のドラッグ&ドロップのジェスチャーに関連付けられた操作 (ACTION_MOVE、ACTION_COPY、または ACTION_REFERENCE) を返します。
getDataFlavors() メソッドは、ドラッグ&ドロップ操作の対象データとして優先順位の高い順に、利用可能なデータ型を返します。
DropTargetDropEvent は、次のように定義されています。
public class java.awt.dnd.DropTargetDropEvent extends java.awt.dnd.DropTargetEvent { Point getCursorLocation(); public int getSourceActions(); public void acceptDrop(int dropAction); public void rejectDrop(); public boolean isTransferableLocal(); public Transferable getTransferable(); }
DropTargetDropEvent は、commitDrop() の呼び出しにより DragSource がドロップを開始したときに、DropTargetListener の drop() メソッドに渡されます。DropTargetDropEvent は DropTargetListener に対して、getTransferable() メソッドから返される Transferable を介して、この操作に関連付けられたデータへのアクセスを提供します。getSourceActions() の戻り値は、ドロップの発生時に転送元によって定義された動作であると定義されています。
getCursorLocation() メソッドの戻り値は、ドロップが発生した位置であると定義されています。
DropTargetListener.drop() メソッドは、ドロップに関連付けられた Transferable で getTransferData() を呼び出す前に、選択された操作を実パラメータとして、acceptDrop() を呼び出します。
rejectDrop() を呼び出して、ドロップ操作を拒否することも可能です。
多くの GUI コンポーネントは、大規模な (大規模になり得る) データセットに対し、スクロール可能な「ビューポート」を提供します。ドロップ&ドラッグ操作時には、これらのビューポートを自動スクロールできることが望ましいでしょう。そうすれば、操作の対象物をドロップしたい特定の (最初はビューポートに表示されていない) メンバの位置までスクロールしながら、データセット上を移動することができます。スクロール可能なコンポーネントは、次のインタフェースを実装することによって、DropTarget にドラッグの「自動スクロール」機能を提供します。
public interface DragAutoScrollingSupport { Insets getAutoscrollInsets(); void autoScrollContent(Point cursorLocn); }
次の条件が満たされた場合、実装する DropTarget は、少なくとも Toolkit.getAutoscrollRepeatDelay() ミリ秒ごとに、関連付けられたコンポーネント (存在する場合) の autoScrollContent() メソッドを呼び出し、コンポーネントの座標で表した現在の論理カーソルの位置を渡します。
上のいずれかの条件が満たされなくなると、次にトリガとなる条件が発生するまで自動スクロール機能は終了します。自動スクロールをサポートするために、Toolkit クラスは次のようになりました。
public class Toolkit { // ... public int getAutoscrollInitialDelay(); // ms public int getAutoscrollRepeatDelay(); // ms public Rectangle getAutoscrollCursorHysteresis(Point cc); // ... }
getAutoscrollCursorHysteresis() メソッドは、現在のカーソル位置として指定された点を囲むヒステリシスの長方形を返します。この長方形は、自動スクロール中のヒステリシス検出時の当たり判定に使われます。