このセクションでは、クリップボードを使った切り取り、コピー、貼り付けに関する情報を提供します。
コンポーネント '@mozilla.org/widget/clipboard' とインターフェース nsIClipboard によって、システムクリップボードへアクセスができます。これは、アプリケーションからクリップボードへデータをコピーしたり、貼り付けることができるということです。クリップボードを操作するには、3 つの XPCOM オブジェクトが必要です。まず、クリップボードに置くデータを保持するオブジェクトです。2 番目は、クリップボードオブジェクト、3 番目は、データを最初のオブジェクトからクリップボードに転送するオブジェクトです。Mozilla のクリップボードモデルでは、データをコピーするのに次のステップを行なう必要があります。
クリップボードに直接オブジェクトを置くのではなく、どうして転送オブジェクトが必要なのか戸惑っているかもしれません。一つの理由は、システムによっては、データがすぐにコピーされないからです。そこでは、コピーは後になって行なわれるか、データが貼り付けられるまで待たされます。別の理由は、転送オブジェクトは、同じデータであっても、複数の表現をもつ場合があるからです。例えば、HTML の一部分は、オリジナルの HTML 形式でも、プレーンテキストでも表現できます。アプリケーションがクリップボードからデータを取得したいが、それが HTML を理解しない場合には、プレーンテキストバージョンを使うことができます。つまり、アプリケーションが HTML を理解しない場合には、そのバージョンが取得できるということです。転送オブジェクトは、クリップボードの内容を、アプリケーションがそれが必要だと判断するまで保持しています。これによって、クリップボードは、別のアプリケーションからすぐに使えるのです。
クリップボードにコピーするステップをコードにしてみましょう。まず、コピーしたいものをラップする(wrap) XPCOM オブジェクトを作る必要があります。ここでは、テキストをコピーしたいとします。インターフェース nsISupportsWString を使います。これは、文字列(具体的に言うと、Unicode 文字列) を表現するのに使うことができます 。
var copytext="Text to copy"; var str = Components.classes["@mozilla.org/supports-wstring;1"].createInstance(Components.interfaces.nsISupportsWString); str.data=copytext; |
最初の行は、コピーしたいテキストを指定しています。次に、変数 str が、文字列を保持するのに使えるコンポーネントに割り当てられています。2 行目は、data を使って、コンポーネントにそれを割り当てています。ここで、文字列 "Text to copy" がコピーされますが、これは、コピーしたいテキスト文字列で置き換えることができます。コピーするオブジェクトができたので、今度は転送オブジェクトを作る必要があります。
var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
trans.addDataFlavor("text/unicode");
trans.setTransferData("text/unicode",str,copytext.length*2);
|
最初の行で、nsITransferable を実装する転送コンポーネントを取得します。次に、転送オブジェクトに使いたいデータの型を指示する必要があります。データの型は、データのフレーバー (flavor 訳注: 「特色」とか「基本となる性質」といった意味です。適切な訳語を思い付かなかったので音訳するだけにします) として参照されます。あるフレーバーのデータを転送するのに必要な転送オブジェクトに指示するのに、関数 addDataFlavor を使います。この場合は、"text/unicode" フレーバーのデータを転送します。これは Unicode 文字列です。次に、関数 setTransferData を呼び出します。これは、データを文字列から転送オブジェクトにコピーします。この関数は、引数を 3 つ取ります。最初の引数は設定したフレーバー、2 番目は文字列を保持しているオブジェクト、3 番目はデータの長さで、これは byte で指定します。ここで、この長さは 2 倍しています。文字ごとに 2 byte が必要な Unicode 文字列を使っているからです。
最後の 2 行は繰返し可能です。複数のフレーバーのために addDataFlavor と setTransferData を呼び出します。このようにして、内容のテキストバージョンと HTML バージョンを作ることができます。転送オブジェクトは、データのコピーをもっています。必要なフレーバーすべてを追加したら、それらすべてを一度にクリップボードに置くことができます。それらすべてをクリップボードに置く準備ができるまで、転送オブジェクトは、必要なデータを保持しつづけます。
次に、システムクリップボードを参照するクリップボードオブジェクトを作る必要があります。
var clip = Components.classes["@mozilla.org/widget/clipboard;1"].createInstance(Components.interfaces.nsIClipboard); clip.emptyClipboard(clip.kGlobalClipboard); clip.setData(trans,null,clip.kGlobalClipboard); |
システムクリップボードオブジェクトを取得し、それを clip 変数に保存します。クリップボードにコピーする前に、emptyClipboard 関数を使ってクリップボードの現在の内容を空にします。最後に、関数 setData を呼び出すことにより、データをクリップボードにコピーできます。この関数の最初の引数は転送オブジェクトです。2 番目のパラメータは通常 null にしますが、nsIClipboardOwner にすることもできます。こうすると、既にコピーしたデータが別のコピー操作で上書きされる時期を指定できます。システムクリップボードにコピーする準備ができて始めて setData を呼び出します。
setData への 3 番目のパラメータ (と、emptyClipboard へのパラメータ) は、どのクリップボードバッファーを使うか指示します。上のコードは、このために、定数 kGlobalConstant を使っています。これは、グローバルクリップボードを表します。これは、多くの場合、編集メニューの切り取りと貼り付け操作で使われるものと同じです。この代わりに kSelectionClipboard を使うと、選択バッファーにコピーします。これは、一般に、Unix システムだけで利用できるものです。
この多段階のステップからなるプロセスによって、テキストはクリップボードにコピーされます。オリジナルのデータをコピーしそれを削除すると、コピーではなく、クリップボードへの切り取りができます。通常、テキストは文書かテキストボックス内にあります。下のコードは上のコードをひとまとめにし、エラーチェックを追加したものです。
var copytext="Text to copy";
var str = Components.classes["@mozilla.org/supports-wstring;1"].createInstance(Components.interfaces.nsISupportsWString);
if (!str) return false;
str.data=copytext;
var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
if (!trans) return false;
trans.addDataFlavor("text/unicode");
trans.setTransferData("text/unicode",str,copytext.length*2);
var clip = Components.classes["@mozilla.org/widget/clipboard;1"].createInstance(Components.interfaces.nsIClipboard);
if (!clip) return false;
clip.emptyClipboard(clip.kGlobalClipboard);
clip.setData(trans,null,clip.kGlobalClipboard);
|
クリップボードからデータを貼り付けるには、上と同様なプロセスを使います。違うのは、setData の代わりに getData を使うことと、setTransferData の代わりに getTransferData を使うことです。ここで興味深いのは、転送オブジェクトのデータのフレーバーが、可能な場合、必要なフレーバーに変換されることです。以下は貼り付けを行なうためのステップです。
最初のステップは、コピーで使われたステップと似ています。
var clip = Components.classes["@mozilla.org/widget/clipboard;1"].createInstance(Components.interfaces.nsIClipboard);
if (!clip) return false;
var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
if (!trans) return false;
trans.addDataFlavor("text/unicode");
|
このコードはクリップボードオブジェクトと転送オブジェクトを取得します。フレーバーを転送オブジェクトに追加します。次いで、クリップボードからデータを取得しなければなりません。
clip.getData(trans,clip.kGlobalClipboard);
var str=new Object();
var strLength=new Object();
trans.getTransferData("text/unicode",str,strLength);
|
最初の行は、setData の反対のことを行ないます。現在システムクリップボードにあるデータは、転送オブジェクトに置かれます。次に、JavaScript オブジェクトを 2 つ作ります。これは、データとデータの長さを保持します。現在クリップボードにあるデータの型が何か分からないということに注意して下さい。それは、別のアプリケーションが置いたものかもしれません。このため、str と strLength には、汎用オブジェクト (generic Object) を使います。
次に、転送オブジェクトからデータを検索するため、getTransferData を使います。取得したいフレーバーを指定します。データは、それが指定のフレーバーのものではなく、実際のフレーバーと指定のフレーバーとの間で変換が可能な場合には、変換されます。もともと複数のフレーバーでデータをクリップボードにコピーした場合、必要な最適のフォーマットを基にデータの検索ができます。例えば、テキストボックスは text/unicode (あるいは text/plain) を取るでしょうし、コンポーザーウィンドウは HTML とイメージデータを取るでしょう。
変数 str は、クリップボードのデータを保持しています。次に、XPCOM オブジェクトを変換して JavaScript 文字列に戻す必要があります。以下のコードは、この目的で利用できます。
if (str) str=str.value.QueryInterface(Components.interfaces.nsISupportsWString); if (str) pastetext=str.data.substring(0,strLength.value / 2); |
まず、インターフェース nsISupportsWString に立ち戻ります。これによって、文字列が取得できます。getTransferData によって内容を与えられたオブジェクト、この場合はstr、のプロパティー value が実際の値を提供します。
文字列を変数 pastetext に代入します。その結果、これをテキストボックスや必要に応じてその他の場所に置くことができます。
(進む) 次のセクションでは、ドラッグとドロップをサポートする要素の作り方を見ることにしましょう。