xulfr.org

8.4 Utilisation du presse-papiers

Écrit par Neil Deakin. Traduit par Nadine Henry (22/07/2004).
Page originale : http://www.xulplanet.com/tutorials/xultu/clipboard.html xulplanet.com

Cette section fournit des informations au sujet du coupé, copié et collé dans le presse-papiers et à partir du presse-papiers.

Le presse-papiers

Mozilla fournit un certain nombre d'interfaces pour accéder au presse-papiers. Le composant '@mozilla.org/widget/clipboardhelper;1' peut être utilisé pour copier du texte dans le presse-papiers. Ce composant implémente l'interface nsIClipboardHelper, dont la fonction copyString peut être utilisée pour copier une chaîne de caractères.

  const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
    .getService(Components.interfaces.nsIClipboardHelper);
  gClipboardHelper.copyString("Put me on the clipboard, please.");

Cet exemple va tout d'abord créer un outil d'aide pour le presse-papiers puis y copiera une courte chaîne de caractère. Cette méthode fonctionne uniquement pour insérer des chaînes de caractères dans le presse-papiers. Pour d'autres types de données, comme les URLs ou les images, vous aurez besoin d'utiliser une méthode plus complexe.

Un composant '@mozilla.org/widget/clipboard;1' et une interface nsIClipboard fournissent un accès général au presse-papiers du système. Vous pouvez l'utiliser pour copier et coller n'importe quel type de données de votre application vers le presse-papiers. Trois objets XPCOM sont nécessaires pour manipuler les opérations concernant le presse-papiers. Le premier est un objet qui prend les données pour les insérer dans le presse-papiers. Le deuxième est l'objet presse-papiers. Le troisième est un objet qui est utilisé pour transférer les données du premier objet vers le presse-papiers. Le modèle de presse-papiers dans Mozilla nécessite que vous suiviez les étapes suivantes pour copier les données :

  1. Créez un container XPCOM pour les données que vous souhaitez insérer dans le presse-papiers. C'est nécessaire parce que vous pouvez y mettre n'importe quoi : du texte, des images...
  2. Créez un objet de transfert. Cet objet peut être le composant "@mozilla.org/widget/transferable;1" qui implémente l'interface nsITransferable.
  3. Spécifiez à l'objet de transfert le type de données à copier.
  4. Spécifiez à l'objet de transfert les données à copier.
  5. Créez un objet presse-papiers qui se réfère au presse-papiers du système.
  6. Spécifiez à l'objet presse-papiers de copier les données utilisant l'objet de transfert.

Vous pourriez vous demander pourquoi un objet de transfert est nécessaire au lieu de simplement insérer directement l'objet dans le presse-papiers. L'une des raisons est que certains systèmes ne copient pas les données tout de suite. Au lieu de cela, ils attendent jusqu'à ce que les données soient collées. Une autre raison est que l'objet de transfert peut contenir de multiples représentations d'une seule et même donnée. Par exemple, un morceau en HTML peut être représenté autant dans sa forme originale en HTML qu'en texte brut. Si une application souhaite obtenir la donnée à partir du presse-papiers et ne comprend pas le HTML, elle peut utiliser la version en texte brut. Si elle peut comprendre le HTML, elle peut récupérer cette version. L'objet de transfert contiendra le contenu du presse-papiers jusqu'à ce que l'application ait décidé de ce qu'elle a besoin. Cela permet au presse-papiers de pouvoir être utilisé par une autre application de suite.

Décomposons à présent les étapes nécessaires pour copier les données dans le presse-papiers. Tout d'abord, nous avons besoin de créer un objet XPCOM pour encapsuler ce que nous voulons copier. Nous supposerons que nous voulons copier un peu de texte. Nous utiliserons l'interface nsISupportsString qui peut être utilisée pour représenter des chaînes de caractères (spécifiquement, des chaînes en Unicode).

var copytext="Texte à copier";
var str = Components.classes["@mozilla.org/supports-string;1"]
   .createInstance(Components.interfaces.nsISupportsString);
str.data=copytext;

La première ligne contient le texte que l'on veut copier. Ensuite, la variable str est assignée à un composant qui peut être utilisé pour contenir une chaîne de caractères. La troisième ligne assigne la chaîne de caractères au composant en utilisant la propriété data. Ici, la chaîne de caractères Texte à copier va être copiée mais vous pouvez la remplacer par la chaîne de caractères que vous souhaitez copier. A présent que l'on a l'objet à copier, un objet de transfert doit être créé :

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

La première ligne reçoit le composant de transfert qui implémente nsITransferable. Ensuite, nous devons spécifier à l'objet de transfert quel type de données nous souhaitons utiliser. Le type de données est représenté par son type mime. La fonction addDataFlavor est utilisée pour indiquer à l'objet de transfert qu'il doit transférer les données d'un certain type. Dans le cas présent, nous transférons le type mime text/unicode qui indique une chaîne de caractère Unicode. Puis, la fonction setTransferData qui copie les données de la chaîne de caractère vers l'objet de transfert est appelée. Cette fonction prend en compte trois paramètres. Le premier est le type mime que nous déclarons, le deuxième est l'objet qui contient la chaîne de caractères et le troisième est la longueur de la donnée, en octets. Ici, la longueur est multipliée par deux car nous utilisons une chaîne de caractères Unicode qui requière deux octets par caractère.

Vous pouvez répéter les deux dernières lignes et appeler addDataFlavor et setTransferData pour de multiples types mime. De cette façon, vous pourriez avoir une version texte brut et une version HTML du contenu. L'objet de transfert va contenir sa propre copie des données. Lorsque vous avez ajouté tous les types que vous voulez, vous pouvez tous les mettre dans le presse-papiers immédiatement. L'objet de transfert va contenir toutes les données que vous voulez jusqu'à ce que vous soyez prêt à les insérer dans le presse-papiers.

Ensuite, nous devons créer un objet presse-papiers qui se réfère au presse-papiers du système.

var clipid = Components.interfaces.nsIClipboard;
var clip = Components.classes["@mozilla.org/widget/clipboard;1"].getService(clipid);
clip.setData(trans,null,clipid.kGlobalClipboard);

Nous obtenons l'objet presse-papiers du système et le stockons dans la variable clip. Nous pouvons copier la donnée dans le presse-papiers en appelant la fonction setData. Le premier paramètre de cette fonction est l'objet de transfert. Le second paramètre peut habituellement être déclaré à null mais vous pourriez le déclarer à un nsIClipboardOwner de sorte que vous puissiez spécifier quand la donnée que vous avez copié soit écrasée par une autre opération de copie. N'appelez setData que lorsque vous êtes prêt à copier dans le presse-papiers du système.

Le troisième paramètre de setData (ainsi que le paramètre de emptyClipboard) indique quel tampon de presse-papiers utiliser. Le code ci-dessus utilise la constante kGlobalConstant pour cela, qui se réfère au presse-papiers global. Ce serait la même qui coupe et colle les opérations dans le menu d'édition utilisé généralement. Si vous utilisez kSelectionClipboard à la place, vous allez copier dans le tampon de sélection, qui n'est en général disponible que dans les systèmes Unix.

Ce processus pluri-étapes a eu pour résultat la copie du texte dans le presse-papiers. Nous pouvons couper dans le presse-papiers au lieu de copier en faisant une copie et en effaçant la donnée originale. Normalement, le texte serait dans un document ou une zone de texte. Le code est rassemblé ci-dessous, avec en plus une vérification des erreurs :

var copytext="Texte à copier";

var str = Components.classes["@mozilla.org/supports-string;1"]
             .createInstance(Components.interfaces.nsISupportsString);
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 clipid=Components.interfaces.nsIClipboard;
var clip = Components.classes["@mozilla.org/widget/clipboard;1"].getService(clipid);
if (!clip) return false;

clip.setData(trans,null,clipid.kGlobalClipboard);

Coller les contenus du presse-papiers

Pour coller la donnée à partir du presse-papiers nous pouvons utiliser un processus similaire, sauf que nous employons getData au lieu de setData et getTransferData au lieu de setTransferData. Voici les étapes pour le collage :

  1. Créer un objet presse-papier qui se réfère au presse-papiers du système.
  2. Créer un objet de transfert qui implémente l'interface nsITransferable.
  3. Spécifier à l'objet de transfert quelle type de donnée vous souhaitez obtenir.
  4. Rechercher la donnée du presse-papiers et l'insérer dans l'objet de transfert.
  5. Obtenir la donnée à partir de l'objet de transfert.

La première étape est similaire à celle utilisée pour la copie :


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

Ce code reçoit l'objet presse-papiers du système et un objet de transfert. Le type mime est ajouté à ce dernier. Maintenant, nous avons besoin d'obtenir la donnée du presse-papiers :


clip.getData(trans,clip.kGlobalClipboard);

var str=new Object();
var strLength=new Object();

trans.getTransferData("text/unicode",str,strLength);

La première ligne exécute l'opposé de setData. La donnée actuellement dans le presse-papiers du système est placée dans l'objet de transfert. Ensuite, nous créons deux objets Javascript qui prendrons la donnée et sa longueur. Notez que nous n'avons aucune idée du type de donnée qui est actuellement dans le presse-papiers. Elle a pu avoir été placée là par une autre application. C'est pour cela que nous utilisons des objets génériques pour str et strLength.

Puis nous utilisons getTransferData pour récupérer la donnée à partir de l'objet de transfert. Nous spécifions le type mime que nous voudrions obtenir. La donnée sera convertie si elle n'est pas du type désiré et si une conversion entre le type mime actuel et celui voulu est possible. Si à l'origine vous avez copié la donnée sous plusieurs types dans le presse-papiers, vous pouvez récupérer la donnée dans le meilleur format nécessaire. Par exemple, une zone de texte accepterait du texte unicode (ou du texte brut) tandis qu'une fenêtre d'édition pourrait accepter du HTML et des images.

La variable str contient maintenant la donnée du presse-papiers. Nous devons à nouveau convertir la donnée dans une chaîne de caractères Javascript à partir d'un objet XPCOM. Pour ce faire, le code ci-dessous peut être utilisé :

if (str)
   str=str.value.QueryInterface(Components.interfaces.nsISupportsString);
if (str)
   pastetext = str.data.substring(0,strLength.value / 2);

Du fait que la donnée de l'objet de transfert est un nsISupportsString, nous devons la convertir en une chaîne de caractère Javascript. La propriété value de l'objet complété par getTransferData, qui est str dans ce cas, fournit la valeur actuelle de l'objet.

Nous assignons la chaîne de caractères à la variable pastetext. Nous pouvons ainsi la mettre dans une zone de texte ou à un autre endroit si nécessaire.


Dans la prochaine section, nous verrons comment créer des éléments qui supportent le copié-collé.