Java 2 Platform Standard Edition 5.0 のドラッグ&ドロップサブシステム

このドキュメントには次のセクションがあります。

1.0 要件

この仕様では、Java 2 プラットフォームのドラッグ&ドロップ機能の API を定義します。

この仕様で規定するプライマリ要件は、次のとおりです。

  1. AWT および Swing クラスによって実装される Java GUI クライアントに対して、プラットフォームに依存しないドラッグ&ドロップ機能を提供する。
  2. プラットフォームに依存するドラッグ&ドロップ機能を統合し、次のような機能を使うネイティブアプリケーション間で行われるドラッグ&ドロップ操作に Java クライアントが参加できるようにする。
    • OLE (Win32) ドラッグ&ドロップ
    • XDND プロトコル
    • CDE/Motif 動的プロトコル
    • MacOS
    • OS/2
  3. 100% Pure JavaOS/Java の実装サポート。
  4. 既存の java.awt.datatransfer.* パッケージを活用して、MIME 標準ベースの拡張可能なデータ型システムに記述されている、データの転送を使用可能にする。
  5. ユーザー補助機能が利用できる場合に、その機能の使用を除外しないこと。
  6. さまざまな入力デバイスのサポートが可能な拡張性。

この仕様は、上で言及した以前の研究から派生していますが、JavaBeans イベントモデルや軽量 (Swing) コンポーネントが出現し、クロスプラットフォームの統合と相互運用性の問題の理解が深まってきた結果、元の研究とはかなり異なった仕様が組み入れられています。

2.0 API

以降のセクションでは、ドラッグ&ドロップ API について説明します。

2.1 概要

ドラッグ&ドロップは、多くのグラフィカルユーザーインタフェース (GUI) システムにみられる直接的な操作のジェスチャーで、GUI 内の表現要素に論理的に関連付けられた 2 つの構成要素間で情報を転送するためのメカニズムを提供します。通常、ドラッグ&ドロップは、ユーザーが適切な入力デバイスを使用して行う物理的なジェスチャーによって生じます。ドラッグ&ドロップは、GUI の表現要素上でデータ転送の結果がわかるように、ナビゲーション中に、ユーザーに継続的にフィードバックするメカニズムと、続いて行われるデータのネゴシエーションおよび転送を容易にする機能を提供します。

一般的なドラッグ&ドロップ操作は、次のようにいくつかの状態に分けることができます (この順番どおり行われるわけではない)。

このドキュメントの以降の部分では、このモデルをサポートするために提案された API の変更の詳細について説明します。

2.2 ドラッグジェスチャーの認識

ドラッグ&ドロップ操作を開始できるジェスチャーは、プラットフォーム、Component、およびデバイスごとに異なります。このため、操作の依存性をカプセル化するためのメカニズムが必要です。このメカニズムがあれば、ドラッグ&ドロップ操作を開始する Component の作成が簡単になります。

2.2.1 DragGestureRecognizer

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 クラスのセマンティクスをサポートするために、プラットフォームによってほかの抽象サブクラスが提供されることがあります。この 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 によって、直前に認識されたジェスチャーの特性に関する情報がすべてカプセル化されます。次の情報がカプセル化されます。

2.3 ドラッグソース

DragSource (ドラッグ元) は、ドラッグ&ドロップ操作を開始する構成要素です。

2.3.1 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 は、数多くの状況で使用される可能性があります。

制御オブジェクトは、ドラッグ操作を処理するために、ユーザーのジェスチャーの前に DragSource のインスタンスを取得して、関連する Component を有効にします。インスタンスを取得したら、DragGestureRecognizer を取得して、DragSourceComponent に関連付ける必要があります。

ユーザーのジェスチャーの最初の解釈、および以降のドラッグ操作の開始は、通常は DragGestureRecognizer によって実装される実装側の Component の役割です。

ジェスチャーが発生すると、ユーザーによる操作ジェスチャーを処理し、ドラッグ&ドロッププロトコルの通知を配布するために、DragSourcestartDrag メソッドが呼び出されます。DragSource は、どの時点においても現在の操作として 1 つのドラッグ&ドロップ操作のみを許可し、それ以上の startDrag 要求はすべて、現在の操作が完了するまで IllegalDnDOperationException をスローすることによって拒否します。

ドラッグ操作を開始するために、startDrag メソッドの呼び出し元は、次のパラメータを提供します。

前述したように、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 は、DragSourcestartDrag() メソッドに渡すことができます。null も渡すことができますが、この場合は、DragSource クラスまたはインスタンスの「デフォルト」の FlavorMap が使用されます。

2.3.2 DragSourceContext の定義

DragSourcestartDrag メソッドが正常に呼び出された結果、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 サブインタフェースを介して、startDragDragSource に登録された DragSourceListener を実装する任意のオブジェクトに委譲します。

DragSourceListener のプライマリの役目は、ドラッグ&ドロップ操作中にユーザー操作の進行を監視して、Drag-Over 効果をユーザーにフィードバックすることです。一般的に、フィードバックは、Drag Cursor を変更することで行われます。

各ドラッグ操作には、次の 2 種類の論理カーソル (ドラッグカーソル) の状態が関連付けられています。

Cursor の状態は、DragSourceContextsetCursor メソッドを呼び出すことによって変更できます。

2.3.3 DragSourceListener の定義

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);
}

ドラッグ操作が進行するに従って、DragSourceListenerdragEnterdragOver、および dragExit メソッドが呼び出されます。これは、DropTarget が関連付けられている GUI Component のジオメトリに交差するように、論理 Drag カーソルの位置をユーザーがナビゲートした結果です (DropTarget のプロトコルの相互作用に関する詳細は次を参照)。

DragSourceListenerdragEnter メソッドは、次の条件が満たされたときに呼び出されます。

DropTarget に登録された DropTargetListener dragEnter メソッドが呼び出され、正常に処理を返す。

登録された DropTargetListener が、DropTargetDragEventacceptDrag メソッドを呼び出して、転送元が実行する可能性のあるドロップアクション、および利用可能なデータ型 (DataFlavors) を調べた上で、ドラッグを受け入れます。

DragSourceListener の dragOver メソッドは、次の条件が満たされたときに呼び出されます。

DragSourceListenerdragExit メソッドは、次の条件のうちの 1 つが満たされたときに呼び出されます。

DragSourceListenerdropActionChanged() メソッドは、ドラッグ操作を実行するためにユーザーが使用している、マウスボタンやキーボードのキーなどの入力デバイスの状態が変わったときに呼び出されます。

dragDropEnd() メソッドは、操作が完了したことを示すために呼び出されます。DragSourceDropEventgetDropSuccess メソッドは、終了状態を確認するために使用されます。getDropAction メソッドは、DropTargetDropTargetDropEventacceptDrop パラメータを介してドロップ操作に適用するために選択した操作を返します。

このメソッドが完了すると、現在の DragSourceContext および関連付けられたリソースが無効になります。

2.3.4 DragSourceEvent の定義

DragSourceEvent クラスは、DragSource に属するすべてのイベントのルート Event クラスで、次のように定義されています。

public class   java.awt.dnd.DragSourceEvent extends java.util.EventObject {
        public DragSourceEvent(DragSourceContext dsc);
        public DragSourceContext getDragSourceContext();
        //...
};

このイベントのインスタンスは、DragSourceListenerdragExit メソッドに渡されます。

2.3.5 DragSourceDragEvent の定義

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


public class java.awt.dnd.DragSourceDragEvent extends DragSourceEvent {
        public int getTargetActions();
        public int getUserAction();
        public int getGestureModifiers();
        public int getGestureModifiersEx();
        public int getDropAction();
}

このクラスのインスタンスは、DragSourceListenerdragEnterdragOver、および dragGestureChanged の各メソッドに渡されます。

getDragSourceContext メソッドは、現在のドラッグ&ドロップ操作に関連付けられた DragSourceContext を返します。

getUserAction メソッドは、ユーザージェスチャーによって現在選択されているアクションを返します。

getTargetActions メソッドは、ドロップアクションがドラッグソースによってサポートされている場合には、現在のドロップターゲットにより選択されているドロップアクションを返し、ドロップアクションがドラッグソースによりサポートされていない場合には DnDConstants.ACTION_NONE を返します。

これら 2 つの結果とドラッグソースによりサポートされる一連のドロップアクションの論理的な相互作用が、ドロップによる実際の効果を定義し、getDropAction を介して返されます。

getGestureModifiers メソッドは、入力デバイスの修飾子の現在の状態を返します。通常、入力デバイスの修飾子は、ユーザーのジェスチャーに関連付けられたマウスボタンおよびキーボードのキーです。

getGestureModifiersEx メソッドは、ユーザーのジェスチャーに関連付けられた入力デバイスの拡張修飾子の現在の状態を返します。

2.3.6 DragSourceDropEvent の定義

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();
}

このクラスのインスタンスは、DragSourceListenerdragDropEnd メソッドに渡されます。このイベントはドラッグ&ドロップ操作の終了状態を DragSource のためにカプセル化します。

ドロップが発生して、ドロップに関係した DropTargetDropTargetContextdropComplete メソッドを介してデータ転送の成功または失敗を示し、イニシエータは getDropSuccess メソッドを介してこのステータスを取得できます。ドロップ先である DropTarget がドラッグの対象に対して実行する操作は、(DropTargetacceptDrop メソッドにより渡された) getDropAction メソッドを介して返されます。

ユーザーが DropTarget の外部でジェスチャーを終了するか、DropTargetrejectDrop を呼び出した場合など、何らかの理由でドロップが発生する前にドラッグ操作が中止された場合は、getDropSuccess メソッドは false を返します。そうでない場合は true を返します。

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);
        //...
}

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

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

DropTargetComponent の両方の設定メソッドの仕様に準拠する実装は、互いの状況を適切に管理するように実装する必要があります。

DropTarget の実パラメータが Component の、このクラスまたはインスタンスとともに使うことが不適切な場合は、setDropTarget メソッドは、IllegalArgumentException をスローします。また、ComponentDropTarget の外部設定をサポートしていない場合なども、このメソッドは 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 メソッドは、新しい FlavorMapDropTarget に割り当てます。パラメータに null が指定された場合は、「デフォルト」の FlavorMapDropTarget にインストールします。

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

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

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

2.4.3 DropTargetContext の定義

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

DropTarget の <>DropTargetContext が存在しない場合は、DropTargetgetDropTargetContext メソッドが呼び出されたときに、副作用として DropTargetcreateDropTargetContext メソッドによって 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 のメソッド dragEnterdragOver、または dropActionChanged から呼び出されます。rejectDrag の呼び出しは、現在ユーザーが選択しているアクションを受け取れないことを意味します。

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

rejectDrop メソッドは、DropTargetDropEvent の類似のメソッドから委譲されていて、DropTargetListenerdrop メソッドから呼び出されます。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 です。

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);
}

次のコンテキストでこのグラフィックスを説明します。

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

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

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

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

2.4.5 DropTargetDragEvent および DropTargetDropEvent の定義

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

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

        public DropTargetContext getDropTargetContext();
        //...
}

DropTargetEvent は、DropTargetListenerdragExit メソッドに渡されます。

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 は、DropTargetListenerdragEnterdragOver、および dropActionChanged メソッドに渡されます。

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

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

getDropAction メソッドの戻り値は、ユーザージェスチャーによって現在選択されているアクションを返します。

getCurrentDataFlavorsgetCurrentDataFlavorsAsList、および 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);
        //...
}

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

getSourceActions メソッドの戻り値は、ドロップの発生時に転送元によって定義されたアクションを返すように定義されています。

getDropAction メソッドの戻り値は、ユーザージェスチャーによって現在選択されているアクションを返します。

getLocation メソッドの戻り値は、ドロップが発生した位置を返すように定義されています。

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

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

交換が発生すると、DropTargetListener.drop 実装は、getTransferable を呼び出す前に、選択された操作で実パラメータとして acceptDrop を呼び出します。acceptDrop の前に getTransferable を呼び出すと、InvalidDnDOperationException が発生します。

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

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

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

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

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

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

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

public interface Autoscroll {
        Insets getAutoscrollInsets();
        void autoScrollContent(Point cursorLocn);
}

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

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

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

2.5 データ転送段階

有効なドロップが発生した場合は、DropTargetListenerdrop メソッドは、ジェスチャーに関連付けられたデータの転送に取りかかります。DropTargetDropEvent は、転送されるデータオブジェクトを表す Transferable オブジェクトを取得するための手段を提供します。

まず、drop メソッドにより、DropTargetListener が、rejectDrop を呼び出してドロップを拒否するか (この場合はすぐに復帰する)、または getSourceActions によって返された操作から選択された操作を指定する acceptDrop を呼び出してドロップを受け入れます。

acceptDrop のあとは、getTransferable が呼び出され、返された TransferablegetTransferData メソッドを介してデータ転送が行われます。最後に、ドロップの転送先で転送元からのオブジェクトの転送が完了すると、DropTargetContext.dropComplete が呼び出され、転送の成功または即時失敗が通知されます。

DropTargetContext.dropComplete メソッドから復帰すると同時に、Transferable および DragSourceContext のインスタンスが有効であるという保証がなくなるため、あとでガベージコレクトできるように、受け側によりインスタンスへのすべての参照が破棄されます。

ACTION_REFERENCE 操作を使う場合は、転送元と転送先でオブジェクトおよび関連付けられた転送のセマンティクスに合意が必要です。一般に、JVM 内の転送では、転送元と転送先の間でライブオブジェクト参照が渡されますが、JVM 間の転送、またはネイティブアプリケーションと Java アプリケーションの間では、ライブオブジェクト参照は無意味で、URI などのほかの種類の参照が交換されます。転送が JVM 内の転送かどうかは、DragSourceDropTarget の両方で検出できます。

2.5.1 FlavorMap および SystemFlavorMap

ターゲットとなるすべてのドラッグ&ドロッププラットフォームは、同様のメカニズムを使って転送データの型を表しますが、この表現方法には違いがあります。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 を返します。

2.5.2 JVM 境界を越えるデータの転送

この 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 サブクラスによって、次のセマンティクスが実装されます。

このメソッドの提供 (またはスーパークラス実装の継承) によって、DragSource に関連付けられたドラッグ&ドロップシステムでは、カプセル化されたデータのエンコードされたストリームが Transferable から自動的に抽出されます。この結果、このデータは JVM の境界を越えて、DataFlavor のリクエスタに単純なバイトストリームとして転送されます。

2.5.3 JVM 境界を越えるファイルリストの転送

ドラッグ&ドロップ転送の典型的な対象として、プラットフォームに依存する 1 つ以上のファイル名のリストを挙げることができます。ファイル名リストの作成または処理を行うプログラムを簡単に開発できるように、ドラッグ&ドロップシステムでは、ファイル名リストは独自に処理されます。

DataFlavorapplication/x-java-file-list;class=java.util.List という MIME「Content-Type」に指定されている場合、ドラッグ&ドロップシステムでは、リストの要素が java.io.File 型のオブジェクトのリストと同質であることを前提としています。したがって、ファイルリストの転送がサポートされている場合は、この DataFlavor が要求されると、転送元では、その File オブジェクトの List が構築されます。また、受け側が、有効な DataFlavor を要求した場合は、その File オブジェクトの List を転送元から受け取ります。転送元とターゲット間でファイルリストを転送するときは、この独自の処理による簡単なメカニズムが使用されます。

2.5.4 JVM 境界を越える java.rmi.Remote 参照の転送

RMI メカニズムの機能を使用すれば、JVM 間でオブジェクト参照をドラッグ&ドロップすることができます。ドラッグ&ドロップシステムでは、次の要件を満たすように、オブジェクト参照の転送が自動的に構成されます。

これらの条件が満たされている場合は、適切な DataFlavor が要求されると、要求元 (転送元と異なる JVM に存在する場合) に返されるオブジェクトは、DataFlavor の表現クラスとして指定されている Remote オブジェクトサブインタフェースのインスタンスへの RMI 参照になります。

3.0 問題点

3.0.1 さまざまなプラットフォームプロトコルエンジンに関する問題点

特定の基本的なプラットフォームのドラッグ&ドロップ、およびウィンドウシステムの実装には制限があるため、ドラッグ操作の対話、および AWT Component へのイベント送信のセマンティクスは、プラットフォームに依存しています。このため、ドラッグ操作中に DragSource がそのドラッグに属するプラットフォームのウィンドウシステムイベントの処理を行い、通常のイベント処理が排除されることがあります。

プラットフォームネイティブなドラッグ&ドロップシステムのシングルスレッドの処理部と、AWT 内の実装を担当するネイティブなウィンドウシステムイベントの対話により、DropTargetListener、および DragSourceListener への「コールバック」は、AWT システムイベントを処理するスレッド上か、またはスレッドと同期して発生します。これは、セキュリティーの面で望ましくない動作ですが、構造ではなく実装上の特徴なので、避けることができません。

3.0.2 VM 間の転送か、それとも VM 内の転送か

JVM 内のドラッグ&ドロップ転送を可能にするため、既存の DataFlavor クラスは、直列化された固定表現ではなく、「ライブ」オブジェクト参照の型を表現できるように拡張されます。このようなオブジェクトは、同じ JVM、および ClassLoader コンテキスト内にある転送元と転送先の間で転送されます。

MIME コンテンツタイプは、application/x-java-local-objectref になります。

3.0.3 Transferable のライフタイム

Transferable オブジェクト、それに関連付けられた DataFlavor、およびドラッグ&ドロップ操作のオペランドに指定された基本的なデータをカプセル化するオブジェクトは、少なくとも、操作を制御する DragSource に関連付けられた DragSourceListenerdragDropEnd イベントを受け取るまで有効です。転送元と転送先の間での操作対象のライフタイムは、その時点を過ぎて定義される実装です。

3.0.4 Transferable を介して公開される転送元オブジェクトの ACTION_MOVE セマンティクス

正常に終了したドラッグ&ドロップ (ACTION_MOVE) 操作の「転送元」は、転送が正常に完了したあと、すぐに Transferable の対象であるオブジェクトへの参照を削除または放棄する必要があります。これは、DragSourceListener.dragDropEnd 通知から戻る前に行う必要があります。

3.0.5 ACTION_REFERENCE 操作のセマンティクス

以前のバージョンの仕様に対する開発者からのフィードバックの結果、動作タグ ACTION_REFERENCE が追加されました。このタグにより、既存のプラットフォームのドラッグ&ドロップ「リンク」セマンティクスを含めることができます。

参照、つまりリンクのセマンティクスは、プラットフォームネイティブのドラッグ&ドロップにとって非常に不都合なものであるため、ネイティブなアプリケーション間でさえも本質的に使い物にならなくなっていると言えます。このため、ネイティブと、プラットフォームに依存しない Java アプリケーションとの間では、このセマンティクスの使用は推奨されません。

Java 対 Java で使用する場合、求められるセマンティクス (同一の JVM および ClassLoader 内) は、転送先が転送対象への Java オブジェクト参照を取得するように定義されています。JVM または ClassLoader 間では、セマンティクスの実装は定義済みですが、転送元から転送先に URL を送るか、RMI Remote 参照によって実装することもできます。

付録 A: DropTargetPeer 定義

この定義は、この仕様の標準的な部分ではありませんが、仕様をわかりやすくするために含められています。

public interface DropTargetPeer {
        void addDropTarget(DropTarget dt);
        void removeDropTarget(DropTarget dt);
}

付録 B: DragSourceContextPeer 定義

この定義は、この仕様の標準的な部分ではありませんが、仕様をわかりやすくするために含められています。

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();
}

付録 C: DropTargetContextPeer 定義

この定義は、この仕様の標準的な部分ではありませんが、仕様をわかりやすくするために含められています。

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);
}

Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.