このドキュメントには次のセクションがあります。
この仕様では、Java 2プラットフォームのドラッグ・アンド・ドロップ機能のAPIを定義します。
この仕様で規定するプライマリ要件は、次のとおりです。
java.awt.datatransfer.*
パッケージを活用して、MIME標準ベースの拡張可能なデータ型システムに記述されている、データの転送を使用可能にする。この仕様は、上で言及した以前の研究から派生していますが、JavaBeansイベント・モデルや軽量(Swing)コンポーネントが出現し、クロス・プラットフォームの統合と相互運用性の問題の理解が深まってきた結果、元の研究とはかなり異なった仕様が組み入れられています。
以降のセクションでは、ドラッグ・アンド・ドロップAPIについて説明します。
ドラッグ・アンド・ドロップは、多くのグラフィカル・ユーザー・インタフェース(GUI)システムにみられる直接的な操作のジェスチャで、GUI内の表現要素に論理的に関連付けられた2つの構成要素間で情報を転送するためのメカニズムを提供します。通常、ドラッグ・アンド・ドロップは、ユーザーが適切な入力デバイスを使用して行う物理的なジェスチャによって生じます。ドラッグ・アンド・ドロップは、GUIの表現要素上でデータ転送の結果がわかるように、ナビゲーション中に、ユーザーに継続的にフィードバックするメカニズムと、続いて行われるデータのネゴシエーションおよび転送を容易にする機能を提供します。
一般的なドラッグ・アンド・ドロップ操作は、次のようにいくつかの状態に分けることができます(この順番どおり行われるわけではない)。
Transferable
(転送可能になり得る)データのドラッグ・アンド・ドロップを開始するために、GUIの表現要素(Component
)に関連付けられたDragSource
(ドラッグ・ソース)が作成されます。Transferable
データ型を消費できる可能性のある、GUIの表現要素(Components
)に関連付けられた1つ以上のDropTarget
が生成または削除されます。DragGestureRecognizer
がDragSource
から取得され、ユーザーのドラッグ開始ジェスチャをComponent
上で追跡し識別するために、Component
と関連付けられます。Component
上でドラッグ・ジェスチャを行うと、登録されたDragGestureRecognizer
がそれを検出し、そのDragGestureListener
に通知します。
注: このドキュメントでは、ドラッグ・アンド・ドロップ操作の開始要因が、人間であるユーザーによる物理的なジェスチャであることを繰り返し言及していますが、これには、DragSource
が適切に実装されている場合の、プログラムによるドラッグ・アンド・ドロップ操作も含まれています。
DragGestureListener
によって、DragSource
がユーザーの代わりにドラッグ・アンド・ドロップ操作を開始します。このとき、GUI Cursor
がアニメーション化されたり、操作の対象である項目のImage
がレンダリングされたりすることがあります。DropTarget
が関連付けられているGUIのComponent
の上を移動すると、サポートされる操作および関連するデータ型に基づいて、DragSource
は「ドラッグオーバー」フィードバック効果を提供するために通知を受信し、DropTarget
は「ドラッグ・アンダー」フィードバック効果を提供するために通知を受け取ります。
ジェスチャ自体は、論理カーソルをGUI階層全体にわたって移動し、GUI Component
の幾何学的図形と交差します。これにより、論理的なDragカーソルがComponent
とそれに関連付けられたDropTarget
に入り、横切り、その後離れる可能性があります。
DragSource
オブジェクトはユーザーに「ドラッグオーバー」フィードバックを示します。通常の場合、論理カーソルに関連したGUI Cursor
を動画化します。
DropTarget
オブジェクトは、通常は関連付けられたGUI Component
のGUI Cursor
にアニメーションをレンダリングすることによって、「ドラッグ・アンダー」フィードバックをユーザーに示します。
DragSource
とDropTarget
の両方がサポートする変換「操作」、つまりCopy、MoveまたはReference(link)によって、パラメータ化される。DragSource
が提供するデータ型のセットと、DropTarget
が包括できるデータ型のセットとの共通部分によって、パラメータ化される。DragSource
およびDropTarget
は、DragSource
に関連した情報を含みその情報の型のネゴシエーションおよび変換となる通知を、Transferable
オブジェクトを介して受け取る。このドキュメントの以降の部分では、このモデルをサポートするために提案されたAPIの変更の詳細について説明します。
ドラッグ・アンド・ドロップ操作を開始できるジェスチャは、プラットフォーム、Component
およびデバイスごとに異なります。このため、操作の依存性をカプセル化するためのメカニズムが必要です。このメカニズムがあれば、ドラッグ・アンド・ドロップ操作を開始するComponent
の作成が簡単になります。
DragGestureRecognizer
は、すべてのデバイス、プラットフォーム、およびComponent
固有のドラッグ・アンド・ドロップ・ジェスチャ・レコグナイザ用の抽象基底クラスで、次のように定義されています。
public abstract DragGestureRecognizer { protected DragGestureRecognizer( DragSource ds, Component c, int srcActions, DragGestureListener dgl ); public Component getComponent(); public void setComponent(Component c); public int getSourceActions(); public void setSourceActions(int actions); public java.awt.InputEvent getTriggerEvent(); public void resetRecognizer(); public void addDragGestureListener( DragGestureListener dgl ) throws TooManyListenerExceptions; public void removeDragGestureListener( DragGestureListener dgl ); protected abstract void registerListeners(); protected abstract void unregisterListeners(); protected void fireDragGestureRecognized( int dragAction ); protected void appendEvent(InputEvent awtie); }
DragGestureRecognizer
に適した特定の具象サブクラスは、DragSource
インスタンス、Toolkit
など、様々な方法で取得できます。具象実装サブクラスは、Class
参照を抽象DragGestureRecognizer
スーパー・クラスに指定することによって、標準APIから取得できます。この実パラメータの具象サブクラスは、インスタンス化されてリクエスタに返されます。
DragGestureRecognizer
インスタンスがComponent
およびDragSource
に関連付けられると、そのインスタンスの特定のEventListener
セットがターゲットComponent
とともに登録されて、そのComponent
に提供されたイベントのいくつかがモニターされ、開始ジェスチャが検出されます。registerListeners
およびunregisterListeners
を使用して、これらのモニタリングEventListener
の追加および削除を行うことができます。
指定されたComponent
またはDragSource
が、そのDragGestureRecognizer
に対して正しい状態にないか、そのDragGestureRecognizerと相互運用性がない場合は、DragGestureRecognizer
によって、IllegalStateException
またはIllegalArgumentException
がスローされる可能性があります。
DragGestureRecognizer
の具象インスタンスによって、関連するComponent
上でドラッグを開始するユーザー・ジェスチャが検出されたときは、DragGestureListener
イベントのユニキャスト・イベント・ソース上に登録されているDragGestureListener
に対してDragGestureEvent
が発生します。このDragGestureListener
は、関連付けられたDragSource
に(必要に応じて)ドラッグ・アンド・ドロップ操作の開始を促します。
実装は、マウス・デバイス・ジェスチャを認識するために(少なくとも)抽象サブクラスMouseDragGestureRecognizer
を提供します。その他の入力デバイスや、Componentクラスの特定のセマンティックスをサポートするために、プラットフォームによってその他のabstractサブクラスが提供されることがあります。このMouseDragGestureRecognizer
の具象スーパー・クラスでは、プラットフォームに依存するマウスベースのジェスチャがカプセル化されます。この具象スーパー・クラスは、createDragGestureRecognizer(Class adgrc, DragSource ds, Component c, int sa, DragGestureListener dgl)
メソッドを介してToolkit
オブジェクトから取得できます。このToolkit
のAPIから、プラットフォームに依存する具象実装が提供されます。この実装は、プラットフォームに依存しない特定の抽象定義(クラス)が継承されています。
MouseDragGestureRecognizer
抽象クラスは、次のように定義されています。
public abstract MouseDragGestureRecognizer extends DragGestureRecognizer implements MouseListener, MouseMotionListener { public MouseDragGestureRecognizer( DragSource ds, Component c, int sa, DragGestureListener dsl ); //... }
DragGestureListener
は、次のように定義されます。
public interface DragGestureListener extends EventListener { void dragGestureRecognized(DragGestureEvent dge); }
通常、dragGestureRecognized()
メソッドは単に、DragGestureEvent
の簡易API startDrag
を使って、関連するDragSource
上でドラッグ・アンド・ドロップ操作を開始します。
開始ジェスチャに影響する各Component
(クラスまたはインスタンス)の動作は、通常、このDragGestureListener
メソッドに実装されるか、適切または可能な場合はDragGestureRecognizer
サブクラスに実装されます。
DragGestureEvent
は、次のように定義されます。
publc class DragGestureEvent extends EventObject { public DragGestureEvent(DragGestureRecognizer dgr, int dragAction, java.util.List events ); public DragGestureRecognizer getSourceAsDragGestureRecognizer(); public Component getComponent(); public DragSource getDragSource(); public java.util.Iterator iterator(); public Object[] toArray(); public Object[] toArray(Object[] array); public int getDragAction(); public startDrag(Cursor dragCursor, Transferable t, DragSourceListener dsl ); public startDrag(Cursor dragCursor, Image dragImage, Point imageOffset, Transferable t, DragSourceListener dsl ); //... }
DragGestureEvent
によって、直前に認識されたジェスチャの特性に関する情報がすべてカプセル化されます。次の情報がカプセル化されます。
DragGestureRecognizer
Component
DragSource
InputEvent
オブジェクトのリスト。DragSource
(ドラッグ元)は、ドラッグ・アンド・ドロップ操作を開始する構成要素です。
DragSource
および関連付けられた定数のインタフェースは、次のように定義されています。
DnDConstants
クラスは、転送対象に適用される可能性のある操作を定義しています。
public final class java.awt.dnd.DnDConstants { public static int ACTION_NONE = 0x0; public static int ACTION_COPY = 0x1; public static int ACTION_MOVE = 0x2; public static int ACTION_COPY_OR_MOVE= ACTION_COPY | ACTION_MOVE; public static int ACTION_REFERENCE = 0x40000000; } public class java.awt.dnd.DragSource { public static Cursor DefaultCopyDrop; public static Cursor DefaultMoveDrop; public static Cursor DefaultLinkDrop; public static Cursor DefaultCopyNoDrop; public static Cursor DefaultMoveNoDrop; public static Cursor DefaultLinkNoDrop; public static DragSource getDefaultDragSource(); public static boolean isDragImageSupported(); public void startDrag(DragGestureEvent trigger, Cursor dragCursor, Image dragImage, Point dragImageOffset, Transferable transferable, DragSourceListener dsl, FlavorMap fm) throws InvalidDnDOperationException; protected DragSourceContext createDragSourceContext( DragSourceContextPeer dscp, DragGestureEvent trigger, Cursor dragCursor, Image dragImage, Point dragImageOffset, Transferable transferable, DragSourceListener dsl ); public FlavorMap getFlavorMap(); public DragGestureRecongizer createDragGestureRecognizer( Class abstractRecognizerClass, Component c, int srcActions, DragGestureListener dgl ); public DragGestureRecongizer createDefaultDragGestureRecognizer( Component c, int srcActions, DragGestureListener dgl ); //... }
DragSource
は、数多くの状況で使用される可能性があります。
TextField
など)のクラスごとに1インスタンス。実装により異なるComponent
のインスタンス、またはComponent
インスタンスに関連付けられているアプリケーション固有のオブジェクトごとに1つ。実装により異なる制御オブジェクトは、ドラッグ操作を処理するために、ユーザーのジェスチャの前にDragSource
のインスタンスを取得して、関連するComponent
を有効にします。インスタンスを取得したら、DragGestureRecognizer
を取得して、DragSource
をComponent
に関連付ける必要があります。
ユーザーのジェスチャの最初の解釈、および以降のドラッグ操作の開始は、通常はDragGestureRecognizer
によって実装される実装側のComponent
の役割です。
ジェスチャが発生すると、ユーザーによる操作ジェスチャを処理し、ドラッグ・アンド・ドロップ・プロトコルの通知を配布するために、DragSource
のstartDrag
メソッドが呼び出されます。DragSource
は、どの時点においても現在の操作として1つのドラッグ・アンド・ドロップ操作のみを許可し、それ以上のstartDrag
要求はすべて、現在の操作が完了するまでIllegalDnDOperationException
をスローすることによって拒否します。
ドラッグ操作を開始するために、startDrag
メソッドの呼出し元は、次のパラメータを提供します。
DragGestureEvent
。Cursor
(ユーザーに対してNo Dropの視覚的なフィードバックを提供するCursor
)。Image
(オプション)。この機能をサポート可能なプラットフォーム上では、ドラッグ・イメージを操作に関連付けて、より忠実にDrag Overをフィードバックできます。このイメージは、通常は、ドラッグされる1つまたは複数のオブジェクトの小さな「アイコン」の表示で、背後のシステムは、Cursor
アニメーションの動きを追跡しながらこのイメージを読み込みます。イメージは、Cursorアニメーションと同時に動きますが、通常は、Cursorアニメーションとは別のものです。
この機能が利用できない箇所、または背後のシステムがレンダリングするのに適切でない種類のイメージの場合、このパラメータは無視され、結果的にCursor
の「Drag Over」アニメーションだけになるので、アプリケーションは、この機能に依存しません。特定のプラットフォーム上にこの機能が存在するかどうかは、staticメソッドisDragImageSupported
を呼び出すことによってテストできます。
Image
が渡された場合にはPoint
(Component
の座標空間内)は、ドラッグ「Cursor」の「ホット・スポット」の座標に対する相対位置でImage
の起点が指定される。Component
の座標空間内において、最初のジェスチャの時点で、その「ホット・スポット」に対する相対位置に、Image
の「Drag Over」アニメーションを適切に配置して開始するためにある。DataFlavor
(データの型)を記述した、Transferable
のインスタンス。
Transferable
のインスタンスは、ドラッグ操作の開始時にDragSource
に関連付けられ、ドラッグ・アンド・ドロップのオペランドまたは対象である、オブジェクトまたはデータを表しています。これは、ドラッグ操作のあと、DropTarget
に関連付けられたComponent
上でドロップが成功した結果として、DragSource
からDropTarget
に渡される情報です。
コンテナ・オブジェクトを作成し、転送の対象にしてTransferable
を実装することによって、同じ種類または異なる種類のオブジェクトの複数コレクションをドラッグ・アンド・ドロップ操作の対象にすることも可能です。ただし、ターゲットとなるどのネイティブ・プラットフォーム・システムでも、このようなコレクションを記述および転送するメカニズムは標準ではサポートされていません。そのため、透過的かつプラットフォーム移植性の高い方法では、このような転送を実装することはできません。
DragSourceListener
のインスタンス。前述したように、startDrag
メソッドの主な役割は、ユーザーのためにドラッグを開始することです。このためには、startDrag
メソッドは、操作そのものを追跡するためのDragSourceContext
のインスタンスを作成する必要があります。さらに重要なことは、このメソッドは、基本的なプラットフォーム実装内で、操作そのものを開始しなければならないことです。これを行うために、DragSource
は、まず基本的なシステムから(通常はjava.awt.Toolkit.createDragSourceContextPeer
メソッドの呼出しにより) DragSourceContextPeer
を取得してから、新しく作成されたDragSourceContextPeer
(基本的なシステムの機能に対してプラットフォームに依存しないインタフェースを提供する)をDragSourceContext
に関連付ける必要があります。startDrag
メソッドは、createDragSourceContext
メソッドを呼び出して、適切なDragSourceContext
のインスタンスを生成し、DragSourceContextPeer
を関連付けます。
ドラッグ・アンド・ドロップ・システムが、何らかの理由でドラッグ操作を開始できない場合は、startDrag
メソッドは、java.awt.dnd.InvalidDnDOperationException
をスローしてその状態を示します。この例外は通常、基礎になるプラットフォーム・システムがドラッグを開始する状態にないか、あるいは指定されたパラメータが無効な場合にスローされます。
ドラッグ操作中には、ソースがドラッグ操作の開始時に公開した操作のセットは、変更できないことに注意してください。つまり、ドラッグ操作中は、DragSource
に関する操作が一定である必要があります。
getFlavorMap
メソッドは、Transferable
によって公開されたDataFlavors
を、基盤のドラッグ・アンド・ドロップ・プラットフォームのデータ型名にマップするために、基本的なシステムによるFlavorMap
オブジェクトの取得に使われます。(FlavorMap
の詳細は、以降を参照)
「private」FlavorMap
は、DragSource
のstartDrag()
メソッドに渡すことができます。nullも渡すことができますが、この場合は、DragSource
クラスまたはインスタンスの「デフォルト」のFlavorMap
が使用されます。
DragSource
のstartDrag
メソッドが正常に呼び出された結果、DragSourceContext
クラスのインスタンスが作成されます。このインスタンスは、DragSource
のために操作の状態を追跡し、状態の変化をDragSourceListener
に配布する役割を果たします。
DragSourceContext
クラスは、次のように定義されます。
public class DragSourceContext implements DragSourceListener { public DragSourceContext( DragSourceContextPeer dscp, DragGestureEvent trigger, Cursor dragCursor, Image dragImage, Point dragOffset, Transferable transferable, DragSourceListener dsl ); public DragSource getDragSource(); public Component getComponent(); public DragGestureEvent getTrigger(); public Image getDragImage(); public Point getDragImageOffset(); public void transferablesFlavorsChanged(); public int getSourceActions(); public Cursor getCursor(); pbulic void setCursor(Cursor Cursor) throws InvalidDnDOperationException; public void addDragSourceListener(DragSourceListener dsl) throws TooManyListenersException; public void removeDragSourceListener(DragSourceListener dsl); protected updateCurrentCursor(int dropOperation, int targetActions, int status ); // values for status parameter above. protected static final int DEFAULT = 0; protected static final int ENTER = 1; protected static final int OVER = 2; protected static final int CHANGED = 3; //... }
DragSourceContext
自体がDragSourceListener
を実装することに注目してください。これにより、DragSource
によって作成されたプラットフォームのピアであるDragSourceContextPeer
のインスタンスは、DragSourceContext
に進行中の操作状態の変化について通知できるようになります。したがってDragSourceContext
は、プラットフォームと、操作のイニシエータによって提供されたDragSourceListener
の間に割り込むことができるようになります。
転送元、またはドラッグ・アンド・ドロップ操作のイニシエータに関してプラットフォームが公開する状態の変化の詳細は、次のとおりです。
ドラッグ・アンド・ドロップ操作中のイニシエータに関する状態の変化の通知は、上に示したように、DragSourceContextPeer
から適切なDragSourceContext
に配布されます。DragSourceContextは通知を、ユニキャストJavaBeansに準拠したEventListener
サブインタフェースを介して、startDrag
でDragSource
に登録されたDragSourceListener
を実装する任意のオブジェクトに委譲します。
DragSourceListener
のプライマリの役目は、ドラッグ・アンド・ドロップ操作中にユーザー操作の進行をモニターして、Drag-Over効果をユーザーにフィードバックすることです。一般的に、フィード・バックは、Drag Cursorを変更することで行われます。
各ドラッグ操作には、次の2種類の論理カーソル(ドラッグ・カーソル)の状態が関連付けられています。
Cursor
。有効なDropTarget
上にドラッグしているときに表示されるカーソル。Cursor
。それ以外のものの上にドラッグしているときに表示されるカーソル(ドラッグ開始時のカーソルの初期状態)。Cursor
の状態は、DragSourceContext
のsetCursor
メソッドを呼び出すことによって変更できます。
DragSourceListener
インタフェースは、次のように定義されます。
public interface java.awt.dnd.DragSourceListener extends java.util.EventListener { void dragEnter (DragSourceDragEvent dsde); void dragOver (DragSourceDragEvent dsde); void dropActionChanged (DragSourceDragEvent dsde); void dragExit (DragSourceEvent dse); void dragDropEnd (DragSourceDropEvent dsde); }
ドラッグ操作が進行するに従って、DragSourceListener
のdragEnter
、dragOver
、およびdragExit
メソッドが呼び出されます。これは、DropTarget
が関連付けられているGUI Component
のジオメトリに交差するように、論理Dragカーソルの位置をユーザーがナビゲートした結果です(DropTarget
のプロトコルの相互作用に関する詳細は次を参照)。
DragSourceListener
のdragEnter
メソッドは、次の条件が満たされたときに呼び出されます。
Component
の可視ジオメトリに最初に交わった。Component
に、アクティブなDropTarget
が関連付けられている。DropTarget
に登録されたDropTargetListener
dragEnter
メソッドが呼び出され、正常に処理を返す。
登録されたDropTargetListener
が、DropTargetDragEvent
のacceptDrag
メソッドを呼び出して、転送元が実行する可能性のあるドロップ・アクション、および利用可能なデータ型(DataFlavors
)を調べた上で、ドラッグを受け入れます。
DragSourceListenerのdragOver
メソッドは、次の条件が満たされたときに呼び出されます。
dragEnter
の呼出しに関連付けられたComponent
の可視ジオメトリに、まだ交差している。Component
に、DropTarget
が関連付けられている。DropTarget
がまだアクティブである。DropTarget
に登録されたDropTargetListener
dragOver
メソッドが呼び出され、正常に処理を返す。DropTarget
が、rejectDrag
を介してドラッグ拒否しない。DragSourceListener
のdragExit
メソッドは、次の条件のうちの1つが満たされたときに呼び出されます。
dragEnter
の呼出しに関連付けられたComponent
の可視ジオメトリと、もはや交差していない。
または:
Component
(これが直前のdragEnter
の呼出しにつながった)に、アクティブなDropTarget
(またはDropTargetListener
)が関連付けられていない。
または:
dragEnter
またはdragOver
が最後に呼び出されてから、現在のDropTarget
のDropTargetListener
がrejectDrag
を呼び出した。DragSourceListener
のdropActionChanged()
メソッドは、ドラッグ操作を実行するためにユーザーが使用している、マウス・ボタンやキーボードのキーなどの入力デバイスの状態が変わったときに呼び出されます。
dragDropEnd()
メソッドは、操作が完了したことを示すために呼び出されます。DragSourceDropEvent
のgetDropSuccess
メソッドは、終了状態を確認するために使用されます。getDropAction
メソッドは、DropTarget
がDropTargetDropEvent
のacceptDrop
パラメータを介してドロップ操作に適用するために選択した操作を返します。
このメソッドが完了すると、現在のDragSourceContext
および関連付けられたリソースが無効になります。
DragSourceEvent
クラスは、DragSource
に属するすべてのイベントのルートEvent
クラスで、次のように定義されています。
public class java.awt.dnd.DragSourceEvent extends java.util.EventObject { public DragSourceEvent(DragSourceContext dsc); public DragSourceContext getDragSourceContext(); //... };
このイベントのインスタンスは、DragSourceListener
のdragExit
メソッドに渡されます。
DragSourceDragEvent
クラスは、次のように定義されます。
public class java.awt.dnd.DragSourceDragEvent extends DragSourceEvent { public int getTargetActions(); public int getUserAction(); public int getGestureModifiers(); public int getGestureModifiersEx(); public int getDropAction(); }
このクラスのインスタンスは、DragSourceListener
のdragEnter
、dragOver
、およびdragGestureChanged
の各メソッドに渡されます。
getDragSourceContext
メソッドは、現在のドラッグ・アンド・ドロップ操作に関連付けられたDragSourceContext
を返します。
getUserAction
メソッドは、ユーザー・ジェスチャによって現在選択されているアクションを返します。
getTargetActions
メソッドは、ドロップ・アクションがドラッグ・ソースによってサポートされている場合には、現在のドロップ・ターゲットにより選択されているドロップ・アクションを返し、ドロップ・アクションがドラッグ・ソースによりサポートされていない場合にはDnDConstants.ACTION_NONE
を返します。
これら2つの結果とドラッグ・ソースによりサポートされる一連のドロップ・アクションの論理的な相互作用が、ドロップによる実際の効果を定義し、getDropAction
を介して返されます。
getGestureModifiers
メソッドは、入力デバイスの修飾子の現在の状態を返します。通常、入力デバイスの修飾子は、ユーザーのジェスチャに関連付けられたマウス・ボタンおよびキーボードのキーです。
getGestureModifiersEx
メソッドは、ユーザーのジェスチャに関連付けられた入力デバイスの拡張修飾子の現在の状態を返します。
DragSourceDropEvent
クラスは、次のように定義されます。
public public class java.awt.dnd.DragSourceDropEvent extends java.util.EventObject { public DragSourceDropEvent(DragSourceContext dsc); public DragSourceDropEvent(DragSourceContext dsc, int action, boolean success); public boolean getDropSuccess(); public int getDropAction(); }
このクラスのインスタンスは、DragSourceListener
のdragDropEnd
メソッドに渡されます。このイベントはドラッグ・アンド・ドロップ操作の終了状態をDragSource
のためにカプセル化します。
ドロップが発生して、ドロップに関係したDropTarget
がDropTargetContext
のdropComplete
メソッドを介してデータ転送の成功または失敗を示し、イニシエータはgetDropSuccess
メソッドを介してこのステータスを取得できます。ドロップ先であるDropTarget
がドラッグの対象に対して実行する操作は、(DropTarget
のacceptDrop
メソッドにより渡された) getDropAction
メソッドを介して返されます。
ユーザーがDropTarget
の外部でジェスチャを終了するか、DropTarget
がrejectDrop
を呼び出した場合など、何らかの理由でドロップが発生する前にドラッグ操作が中止された場合は、getDropSuccess
メソッドはfalseを返します。そうでない場合はtrueを返します。
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)
のどちらのメソッドを呼び出すこともできます。
DropTarget
とComponent
の両方の設定メソッドの仕様に準拠する実装は、互いの状況を適切に管理するように実装する必要があります。
DropTarget
の実パラメータがComponent
の、このクラスまたはインスタンスとともに使うことが不適切な場合は、setDropTarget
メソッドは、IllegalArgumentException
をスローします。また、Component
がDropTarget
の外部設定をサポートしていない場合なども、このメソッドはUnsupportedOperationException
をスローします。
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
自体がDropTargetListener
を実装することに注目してください。これにより、プラットフォームによって作成されたプラットフォームのピアであるDropTargetContextPeer
のインスタンスは、DropTarget
に進行中の操作状態の変化について通知できるようになり、したがってDropTarget
は、プラットフォームとDropTarget
に登録されているDropTargetListener
の間に割り込むことができるようになります。
進行中のドラッグ・アンド・ドロップ操作に関連付けられた論理カーソルが、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アクセスするときは、通常、要求をDropTargetContext
に委譲する特定のDropTargetEvent
サブクラスの呼出しにより行います。
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
を呼び出さずにgetTransferable
を呼び出すことは不正です。
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 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
を呼び出します。
DropTargetListener
のdragExit
メソッドは、論理Dragカーソルのホット・スポットが、DropTarget
に関連付けられたComponent
のジオメトリの可視部分と交差しなくなったとき、またはdrop
による通知が行われる直前に呼び出されます。この通知を受け取ると、DropTargetListener
は、それまでに適用したすべてのDrag-underフィードバック効果を取り消します。このときの副作用として、DropTarget
に関連付けられたDropTargetContext
が無効になることに注意してください。
交差している間にユーザーがドラッグ・ジェスチャを終了すると、DropTargetListener
のdrop
メソッドが呼び出されます。この通知を受け取ると、DropTargetListener
は、DropTargetDropEvent
オブジェクト上のgetSourceActions
メソッドの戻り値によって指定された操作を、getTransferable
メソッドから返されたTransferable
オブジェクト上で実行します。その後、関連付けられたDropTargetContext
のdropComplete
メソッドを呼び出して、操作の成功または失敗を示します。
DropTargetEvent
およびDropTargetDragEvent
は次のように定義されています。
public abstract class java.awt.dnd.DropTargetEvent extends java.util.EventObject { public DropTargetContext getDropTargetContext(); //... }
DropTargetEvent
は、DropTargetListener
のdragExit
メソッドに渡されます。
public class java.awt.dnd.DropTargetDragEvent extends java.awt.dnd.DropTargetEvent { public Transferable getTransferable(); 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_MOVE、ACTION_COPY、またはACTION_REFERENCE)を返します。
getDropAction
メソッドの戻り値は、ユーザー・ジェスチャによって現在選択されているアクションを返します。
getCurrentDataFlavors
、getCurrentDataFlavorsAsList
、およびisDataFlavorSupported
メソッドは、転送元のリスト型を受け側で調べるときに使用します。
getTransferable
メソッドは、転送元のデータを受け側で調べるときに使用します。DropTargetDragEvent
インスタンス上のgetTransferable
はそれぞれのDropTargetListener
のメソッド内でのみ呼び出され、すべての必要なデータはメソッドが返される前に、返されたTransferable
から取り出されることに注目してください。
DropTargetDropEvent
は、次のように定義されます。
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
メソッドの標準の実装は、アクションおよび利用可能なDataFlavor
を検査し、交換が正常に終了するかどうかを判定します。
交換が発生すると、DropTargetListener.drop
実装は、getTransferable
を呼び出す前に、選択された操作で実パラメータとしてacceptDrop
を呼び出します。acceptDrop
の前にgetTransferable
を呼び出すと、InvalidDnDOperationException
が発生します。
rejectDrop
を呼び出して、ドロップ操作を拒否することも可能です。呼び出すと、転送元と受け側の間の対話が停止します。このため、通常は、rejectDropを呼び出すと、ただちにdrop
メソッドから戻ります。
ドラッグ・アンド・ドロップ操作の転送元が、drop
による通知の受け側と同一の物理JVMに存在する場合は、isLocalTransfer
メソッドからtrueが返されます。同一の物理JVMに存在しない場合は、falseが返されます。
ローカルで呼び出されたTransferable.getTransferData
からオブジェクト参照を受け取る場合は、この違いが重要になります。この場合、受け取ったオブジェクト参照は、転送元で保持されているものと同じです(コピー、プロキシ、および異なるオブジェクトではない)。このため、受け側では共有オブジェクト参照を、次のような特別な方法で処理する必要があります。
dropCompete
が呼び出されて転送の完了が転送元に通知されるまで、オブジェクトまたはカプセル化されたデータの状態を変更できません。また、転送元は、getTransferData
メソッドからこれらのオブジェクトを返したあとでも、dragDropEnd
による通知を受け取るまで、オブジェクトの状態を変更できません。dropComplete
およびdragDropEnd
メソッドが処理されるまでは、交換されたオブジェクトまたはそのオブジェクトに含まれるデータの状態を変更することはできません。その後、共有セマンティックスは、共有されているオブジェクトに依存した実装になります。dropComplete
メソッドは、関連付けられたドラッグ・アンド・ドロップ操作の終了を通知し、受け側で実行された転送の成功(または失敗)を返します。このメソッドを呼び出すと、DragSourceListener
のdragDropEnd
メソッドが、DragSourceDropEvent
で使用できる適切な状態で呼び出されます。このメソッドの呼出しに失敗すると、ドラッグ・アンド・ドロップ操作が正常に終了しません。
多くのGUI Component
は、大規模な(大規模になり得る)データ・セットに対し、スクロール可能な「ビューポート」を提供します。ドラッグ・アンド・ドロップ操作時には、これらのビューポートを自動スクロールできることが望ましいでしょう。そうすれば、操作の対象物をドロップしたい特定の(最初はビューポートに表示されていない)メンバーの位置までスクロールしながら、データ・セット上を移動できます。
スクロール可能なComponent
は、次のインタフェースを実装することによって、DropTarget
にドラッグの「自動スクロール」機能を提供します。
public interface Autoscroll { Insets getAutoscrollInsets(); void autoScrollContent(Point cursorLocn); }
次の条件が満たされた場合、実装するDropTarget
は、関連付けられたComponent
(存在する場合)のautoscroll
メソッドを定期的に呼び出し、Component
の座標で表した現在の論理カーソルの位置を渡します。
Component
の可視ジオメトリ、およびgetAutoscrollInsets
メソッドが返すInsets
によって記述された境界領域と交差した場合。上のいずれかの条件が満たされなくなると、次にトリガーとなる条件が発生するまで自動スクロール機能は終了します。
自動スクロール開始前の初期遅延、自動スクロール通知の間隔、およびピクセルのヒステリシス値はすべて、外部で構成でき、Toolkit.getDesktopProperty
メソッドから問い合わせることができます。
有効なドロップが発生した場合は、DropTargetListener
のdrop
メソッドは、ジェスチャに関連付けられたデータの転送に取りかかります。DropTargetDropEvent
は、転送されるデータ・オブジェクトを表すTransferable
オブジェクトを取得するための手段を提供します。
まず、drop
メソッドにより、DropTargetListener
が、rejectDrop
を呼び出してドロップを拒否するか(この場合はすぐに復帰する)、またはgetSourceActions
によって返された操作から選択された操作を指定するacceptDrop
を呼び出してドロップを受け入れます。
acceptDrop
のあとは、getTransferable
が呼び出され、返されたTransferable
のgetTransferData
メソッドを介してデータ転送が行われます。最後に、ドロップの転送先で転送元からのオブジェクトの転送が完了すると、DropTargetContext.dropComplete
が呼び出され、転送の成功または即時失敗が通知されます。
DropTargetContext.dropComplete
メソッドから復帰すると同時に、Transferable
およびDragSourceContext
のインスタンスが有効であるという保証がなくなるため、あとでガベージ・コレクトできるように、受け側によりインスタンスへのすべての参照が破棄されます。
ACTION_REFERENCE操作を使う場合は、転送元と転送先でオブジェクトおよび関連付けられた転送のセマンティックスに合意が必要です。一般に、JVM内の転送では、転送元と転送先の間でライブ・オブジェクト参照が渡されますが、JVM間の転送、またはネイティブ・アプリケーションとJavaアプリケーションの間では、ライブ・オブジェクト参照は無意味で、URIなどのほかの種類の参照が交換されます。転送がJVM内の転送かどうかは、DragSource
とDropTarget
の両方で検出できます。
ターゲットとなるすべてのドラッグ・アンド・ドロッププラットフォームは、同様のメカニズムを使用して転送データの型を表しますが、この表現方法には違いがあります。Javaプラットフォームでは、DataFlavor
内にカプセル化されたMIME形式を使用してデータ型を表します。Javaと、プラットフォームにネイティブなアプリケーションとの間でのデータ転送を許可するには、これらのプラットフォーム名の存在が公開される必要があります。このため、これらのプラットフォームに依存する型名、それらの表現方法、およびJava MIMEベースのDataFlavor
間で、プラットフォームに依存しない拡張可能なマッピングを作成するためのメカニズムが必要です。
この実装は、プラットフォームにネイティブなデータ型(文字列)とDataFlavor
の構築に使われるMIME形式(文字列)との間のマッピングを外部で指定するメカニズムを提供します。この外部マッピングは、背後のプラットフォームのドラッグ・アンド・ドロップ・メカニズムによって転送元から転送先にエクスポートされる適切なDataFlavors
(MIME形式)を公開するために、背後のプラットフォーム固有の実装コードで使われます。
背後のシステムは、DragSource
クラスおよびDropTarget
クラスのどちらを使っても、プラットフォームに依存する名前とDataFlavors
間のマッピングにアクセスできます。
public interface java.awt.datatransfer.FlavorMap { java.util.Map getNativesForFlavors(DataFlavor[] dfs); java.util.Map getFlavorsForNatives(String[] natives); }
getNativesForFlavors
メソッドは、DataFlavor
の配列をパラメータにとり、実パラメータdfs
から、関連付けられたString
型の値(そのMIME形式に対応するプラットフォームに依存する型名に一致)とともに、DataFlavor
型のゼロ個以上のキーを含むMap
オブジェクトを返します。
getFlavorsForNatives
メソッドは、String
型の配列をパラメータにとり、実パラメータnativesから、関連付けられたDataFlavor
型の値(そのプラットフォームに依存する型名に対応するプラットフォームに依存しない型に一致)とともに、String
型のゼロ個以上のキーを含むMap
オブジェクトを返します。
これらのメソッドによって返されるMap
オブジェクトは可変の場合もありますが、必ずしもその必要はありません。
nullがこれらのメソッドのうちのいずれかに渡されると、呼出しの時点で実装にとって既知であるすべてのキーと値の現在のマップが返されます。
たとえば、Win32では、シンプル・テキストのクリップボード形式の名前は、CF_TEXT (実際にはこれは整数1)ですが、Motifでは、STRINGという名前のX11 Atomです。MIME形式を使用してこれを表現する場合は、text/plain charset=us-asciiです。プラットフォームに対する移植性のあるFlavorMap
は、Win32上のCF_TEXTとMotif/X11上のSTRING間のマッピングを行います。
一般に、これらのマッピングは、SystemFlavorMap
に実装するときに、外部の固定された構成形式(プロパティ・ファイルまたはURL)に保持し、プラットフォームからロードして、特定のプラットフォームに適切にFlavorMap
を設定するようにします。
SystemFlavorMap
クラスは、全システムに共通なマッピングのセットを指定するための、プラットフォームで構成が可能な単純なメカニズムを実装するために提供されています。次のように定義されています。
public class java.awt.datatransfer.SystemFlavorMap implements FlavorMap, FlavorTable { public static FlavorMap getSystemFlavorMap(); public synchronized Map getNativesForFlavors(DataFlavor[] dfs); public synchronized Map getFlavorsForNatives(String[] natives); public static String encodeDataFlavor(DataFlavor flav); public static String encodeJavaMIMEType(String mimeType); public static boolean isJavaMIMEType(String mimeStr); public static String decodeJavaMIMEType(String nat); public static DataFlavor decodeDataFlavor(String nat); //... }
SystemFlavorMap
クラスは、プラットフォーム固有のFlavorMap
のプロパティ・ファイル(java.awt.Properties
を参照)を使った単純な実装を提供します。このクラスは、AWTのプロパティであるAWT.flavorMapFileURL (Toolkit.getProperty
を参照)の値か、またはSystem.getProperty("java.home")+File.separator+"lib"+File.separator+"flavormap.properties"
のデフォルトのファイル位置を使って、そのプロパティから適切なMap
を作成します。
さらに、このクラスは、Java MimeType
とプラットフォームに依存した名前空間のエンコードまたはデコードに使う、いくつかのstaticな簡易関数を提供します。プロパティ・ファイルの構文は、次のとおりです。
{ <platform_type_name> ‘=' <IETF_MIME_RFC_conformant_specification> <nl> } *
DragSource
およびDropTarget
のデフォルト実装は、その他の実装によってオーバーライドされていなければ、getFlavorMap
メソッドからSystemFlavorMap
を返します。
このAPIでは、Javaとネイティブ・アプリケーションの間でデータをドラッグ・アンド・ドロップできることがプライマリの目標です。このことが、Java仮想マシンの境界を越えてデータが渡されたときに行われる、実際のデータ・エンコードおよびデータ交換の方法およびメカニズムに大きく影響しています。
このようなデータ交換では、転送元または受け側がJavaのデータ型を認識しないネイティブ・アプリケーションであるため、このドラッグ・アンド・ドロップのシステムでは単純にJavaオブジェクトの参照を渡すことができません。転送元または受け側でJavaのデータ型の認識または操作を行うことができない可能性があるためです。
データ交換が発生すると、転送元と受け側の実装に関係なく、データ型およびエンコードの方式に双方が合意しているときにかぎり、データ交換が実現されます。つまり残念なことに、交換で発生する問題は、ほとんどの場合、転送元および受け側のアプリケーションが原因です。
実質的には、プラットフォームに依存したイメージ、ドキュメント、その他の「Content-Type」など、「ネイティブ」なデータ形式の場合において、関連する外部形式のエンコードとデコードは、転送を行う転送元と転送先の責任によって行われます。
このドラッグ・アンド・ドロップ・システムでは、そのようなJava仮想マシンの境界を越える「ネイティブ」なデータ型の外部表現が、java.io.InputStream
またはそのサブクラス内にカプセル化されて公開されます。
つまり、java.io.InputStream
を継承する表現クラスを含むすべてのDataFlavor
が、Java仮想マシンの境界を越えて転送可能であり、転送のために公開されることになります。
このようなネイティブなデータ型の交換を実装するには、DataFlavor
をMIMEの「Content-Type」に定義します。MIMEの「Content-Type」には、「ネイティブ」なデータ型の特性が、java.io.InputStream
クラスを継承する表現クラスを使って記述されています。java.io.InputStreamクラスによって、カプセル化されたデータがバイト・ストリームにエンコードされます。
特に、このようなInputStream
サブクラスによって、次のセマンティックスが実装されます。
java.io.InputStream
型の引数を1つ取るpublicコンストラクタの提供。
java.io.InputStream
のサブクラスによってこのコンストラクタが提供されるため、DropTarget
に関連付けられたドラッグ・アンド・ドロップ・システムでは、要求されたDataFlavor
に指定されている表現クラスのインスタンスが自動的に再構築されます。そのインスタンスは、サブクラスの要求に応じてフォーマットされたカプセル化データを含むInputStream
によって初期化されます。このインスタンスは、初期化されると、Transferable.getTransferData
メソッドの呼出し側に返されます。次に、呼出し側では、データ・ストリームが転送されると、フォーマットされた内容が読み取られ解釈されます。
InputStream.read(byte b[], int off, int len)
の実装の提供。このメソッドの提供(またはスーパー・クラス実装の継承)によって、DragSource
に関連付けられたドラッグ・アンド・ドロップ・システムでは、カプセル化されたデータのエンコードされたストリームがTransferable
から自動的に抽出されます。この結果、このデータはJVMの境界を越えて、DataFlavor
のリクエスタに単純なバイト・ストリームとして転送されます。
ドラッグ・アンド・ドロップ転送の典型的な対象として、プラットフォームに依存する1つ以上のファイル名のリストを挙げることができます。ファイル名リストの作成または処理を行うプログラムを簡単に開発できるように、ドラッグ・アンド・ドロップ・システムでは、ファイル名リストは独自に処理されます。
DataFlavor
がapplication/x-java-file-list;class=java.util.List
というMIME「Content-Type」に指定されている場合、ドラッグ・アンド・ドロップ・システムでは、リストの要素がjava.io.File
型のオブジェクトの同一種リストであることを前提としています。したがって、ファイル・リストの転送がサポートされている場合は、このDataFlavor
が要求されると、転送元では、そのFile
オブジェクトのList
が構築されます。また、受け側が、有効なDataFlavor
を要求した場合は、そのFile
オブジェクトのList
を転送元から受け取ります。転送元とターゲット間でファイル・リストを転送するときは、この独自の処理による簡単なメカニズムが使用されます。
RMIメカニズムの機能を使用すれば、JVM間でオブジェクト参照をドラッグ・アンド・ドロップすることができます。ドラッグ・アンド・ドロップ・システムでは、次の要件を満たすように、オブジェクト参照の転送が自動的に構成されます。
DataFlavor
に関連付けられたインタフェースの表現クラスが、java.rmi.Remote
とjava.io.Serializable
の両方を実装している。
(MIMEの「Content-Type」には、任意の適合したデータ型、またはapplication/x-java-remote-objectを指定できる)
(効果的に実装するには、転送されたオブジェクト実装クラスは、java.rmi.server.UnicastRemoteObject
から継承されていなければならない。RMIシステムには必要な初期化がいくつか実装されているためである。その初期化が実装されていない場合は、転送は正常に完了しない)。
これらの条件が満たされている場合は、適切なDataFlavor
が要求されると、要求元(転送元と異なるJVMに存在する場合)に返されるオブジェクトは、DataFlavor
の表現クラスとして指定されているRemote
オブジェクト・サブインタフェースのインスタンスへのRMI参照になります。
特定の基本的なプラットフォームのドラッグ・アンド・ドロップ、およびウィンドウ・システムの実装には制限があるため、ドラッグ操作の対話、およびAWT Component
へのイベント送信のセマンティックスは、プラットフォームに依存しています。このため、ドラッグ操作中にDragSource
がそのドラッグに属するプラットフォームのウィンドウ・システム・イベントの処理を行い、通常のイベント処理が排除されることがあります。
プラットフォーム・ネイティブなドラッグ・アンド・ドロップ・システムのシングル・スレッドの処理部と、AWT内の実装を担当するネイティブなウィンドウ・システム・イベントの対話により、DropTargetListener
、およびDragSourceListener
への「コールバック」は、AWTシステム・イベントを処理するスレッド上か、またはスレッドと同期して発生します。これは、セキュリティの面で望ましくない動作ですが、構造ではなく実装上の特徴なので、避けることができません。
JVM内のドラッグ・アンド・ドロップ転送を可能にするため、既存のDataFlavor
クラスは、直列化された固定表現ではなく、「ライブ」オブジェクト参照の型を表現できるように拡張されます。このようなオブジェクトは、同じJVM、およびClassLoader
コンテキスト内にある転送元と転送先の間で転送されます。
MIMEコンテンツ・タイプは、application/x-java-local-objectrefになります。
Transferable
オブジェクト、それに関連付けられたDataFlavor
、およびドラッグ・アンド・ドロップ操作のオペランドに指定された基本的なデータをカプセル化するオブジェクトは、少なくとも、操作を制御するDragSource
に関連付けられたDragSourceListener
がdragDropEnd
イベントを受け取るまで有効です。転送元と転送先の間での操作対象のライフ・タイムは、その時点を過ぎて定義される実装です。
正常に終了したドラッグ・アンド・ドロップ(ACTION_MOVE)操作の「転送元」は、転送が正常に完了したあと、すぐにTransferable
の対象であるオブジェクトへの参照を削除または放棄する必要があります。これは、DragSourceListener.dragDropEnd
通知から戻る前に行う必要があります。
以前のバージョンの仕様に対する開発者からのフィード・バックの結果、動作タグACTION_REFERENCEが追加されました。このタグにより、既存のプラットフォームのドラッグ・アンド・ドロップ「リンク」セマンティックスを含めることができます。
参照、つまりリンクのセマンティックスは、プラットフォーム・ネイティブのドラッグ・アンド・ドロップにとって非常に不都合なものであるため、ネイティブなアプリケーション間でさえも本質的に使い物にならなくなっていると言えます。このため、ネイティブと、プラットフォームに依存しないJavaアプリケーションとの間では、このセマンティックスの使用は非推奨です。
Java対Javaで使用する場合、求められるセマンティックス(同一のJVMおよびClassLoader
内)は、転送先が転送対象へのJavaオブジェクト参照を取得するように定義されています。JVMまたはClassLoader
間では、セマンティックスの実装は定義済みですが、転送元から転送先にURLを送るか、RMI Remote
参照によって実装することもできます。
この定義は、この仕様の標準的な部分ではありませんが、仕様をわかりやすくするために含められています。
public interface DropTargetPeer { void addDropTarget(DropTarget dt); void removeDropTarget(DropTarget dt); }
この定義は、この仕様の標準的な部分ではありませんが、仕様をわかりやすくするために含められています。
public interface DragSourceContextPeer { void startDrag(DragSourceContext dsc, Cursor c, Image di, Point ioff ) throws InvalidDnDOperationException; Cursor getCursor(); void setCursor(Cursor c) throws InvalidDnDOperationException; void transferablesFlavorsChanged(); }
この定義は、この仕様の標準的な部分ではありませんが、仕様をわかりやすくするために含められています。
public interface DropTargetContextPeer { int getTargetActions(); void setTargetActions(int actions); DropTarget getDropTarget(); DataFlavor[] getTransferDataFlavors(); Transferable getTransferable() throws InvalidDnDOperationException; boolean isTransferableJVMLocal(); void acceptDrag(int dragAction); void rejectDrag(); void acceptDrop(int dropAction); void rejectDrop(); void dropComplete(boolean success); }