home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 November / november_2001.iso / Browsers / Netscape 6.1 / browser.xpi / bin / chrome / toolkit.jar / content / global / nsTransferable.js < prev    next >
Encoding:
JavaScript  |  2001-02-05  |  9.8 KB  |  287 lines

  1. /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  *
  13.  * The Original Code is mozilla.org code.
  14.  *
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation.  Portions created by Netscape are
  17.  * Copyright (C) 1998 Netscape Communications Corporation. All
  18.  * Rights Reserved.
  19.  *
  20.  * Contributor(s): 
  21.  *   Ben Goodger <ben@netscape.com> (Original Author)
  22.  */
  23.  
  24. ////////////////////////////////////////////////////////////////////////////
  25. // XXX - WARNING - DRAG AND DROP API CHANGE ALERT - XXX
  26. // This file has been extensively modified in a checkin planned for Mozilla
  27. // 0.8, and the API has been modified. DO NOT MODIFY THIS FILE without 
  28. // approval from ben@netscape.com, otherwise your changes will be lost. 
  29.  
  30. /** 
  31.  *  nsTransferable - a wrapper for nsITransferable that simplifies
  32.  *                   javascript clipboard and drag&drop. for use in
  33.  *                   these situations you should use the nsClipboard
  34.  *                   and nsDragAndDrop wrappers for more convenience
  35.  **/ 
  36.  
  37. var nsTransferable = {
  38.   /**
  39.    * nsITransferable set (TransferData aTransferData) ;
  40.    *
  41.    * Creates a transferable with data for a list of supported types ("flavours")
  42.    * 
  43.    * @param TransferData aTransferData
  44.    *        a javascript object in the format described above 
  45.    **/ 
  46.   set: function (aTransferDataSet)
  47.     {
  48.       var trans = this.createTransferable();
  49.       for (var i = 0; i < aTransferDataSet.dataList.length; ++i) 
  50.         {
  51.           var currData = aTransferDataSet.dataList[i];
  52.           var currFlavour = currData.flavour.contentType;
  53.           trans.addDataFlavor(currFlavour);
  54.           var supports = null; // nsISupports data
  55.           var length = 0;
  56.           if (currData.flavour.dataIIDKey == "nsISupportsWString")
  57.             {
  58.               supports = nsJSSupportsUtils.createSupportsWString();
  59.               supports.data = currData.supports;
  60.               length = supports.data.length;
  61.             }
  62.           else 
  63.             {
  64.               // non-string data. TBD!
  65.             }
  66.           trans.setTransferData(currFlavour, supports, length * 2);
  67.         }
  68.       return trans;
  69.     },
  70.   
  71.   /**
  72.    * TransferData/TransferDataSet get (FlavourSet aFlavourSet, 
  73.    *                                   Function aRetrievalFunc, Boolean aAnyFlag) ;
  74.    *
  75.    * Retrieves data from the transferable provided in aRetrievalFunc, formatted
  76.    * for more convenient access.
  77.    *
  78.    * @param FlavourSet aFlavourSet
  79.    *        a FlavourSet object that contains a list of supported flavours.
  80.    * @param Function aRetrievalFunc
  81.    *        a reference to a function that returns a nsISupportsArray of nsITransferables
  82.    *        for each item from the specified source (clipboard/drag&drop etc)
  83.    * @param Boolean aAnyFlag
  84.    *        a flag specifying whether or not a specific flavour is requested. If false,
  85.    *        data of the type of the first flavour in the flavourlist parameter is returned,
  86.    *        otherwise the best flavour supported will be returned.
  87.    **/
  88.   get: function (aFlavourSet, aRetrievalFunc, aAnyFlag)
  89.     {
  90.       if (!aRetrievalFunc) 
  91.         throw "No data retrieval handler provided!";
  92.       
  93.       var supportsArray = aRetrievalFunc(aFlavourSet);
  94.       var dataArray = [];
  95.       var count = supportsArray.Count();
  96.       
  97.       // Iterate over the number of items returned from aRetrievalFunc. For
  98.       // clipboard operations, this is 1, for drag and drop (where multiple
  99.       // items may have been dragged) this could be >1.
  100.       for (var i = 0; i < count; i++)
  101.         {
  102.           var trans = supportsArray.GetElementAt(i);
  103.           if (!trans) continue;
  104.           trans = trans.QueryInterface(Components.interfaces.nsITransferable);
  105.             
  106.           var data = { };
  107.           var length = { };
  108.           
  109.           var currData = null;
  110.           if (aAnyFlag)
  111.             { 
  112.               var flavour = { };
  113.               trans.getAnyTransferData(flavour, data, length);
  114.               if (data && flavour)
  115.                 {
  116.                   var selectedFlavour = aFlavourSet.flavourTable[flavour.value];
  117.                   if (selectedFlavour) 
  118.                     dataArray[i] = FlavourToXfer(data.value, length.value, selectedFlavour);
  119.                 }
  120.             }
  121.           else
  122.             {
  123.               var firstFlavour = aFlavourSet.flavours[0];
  124.               trans.getTransferData(firstFlavour, data, length);
  125.               if (data && firstFlavour)
  126.                 dataArray[i] = FlavourToXfer(data.value, length.value, firstFlavour);
  127.             }
  128.         }
  129.       return new TransferDataSet(dataArray);
  130.     },
  131.  
  132.   /** 
  133.    * nsITransferable createTransferable (void) ;
  134.    *
  135.    * Creates and returns a transferable object.
  136.    **/    
  137.   createTransferable: function ()
  138.     {
  139.       const kXferableContractID = "@mozilla.org/widget/transferable;1";
  140.       const kXferableIID = Components.interfaces.nsITransferable;
  141.       return Components.classes[kXferableContractID].createInstance(kXferableIID);
  142.     }
  143. };  
  144.  
  145. /** 
  146.  * A FlavourSet is a simple type that represents a collection of Flavour objects.
  147.  * FlavourSet is constructed from an array of Flavours, and stores this list as
  148.  * an array and a hashtable. The rationale for the dual storage is as follows:
  149.  * 
  150.  * Array: Ordering is important when adding data flavours to a transferable. 
  151.  *        Flavours added first are deemed to be 'preferred' by the client. 
  152.  * Hash:  Convenient lookup of flavour data using the content type (MIME type)
  153.  *        of data as a key. 
  154.  */
  155. function FlavourSet(aFlavourList)
  156. {
  157.   this.flavours = aFlavourList || [];
  158.   this.flavourTable = { };
  159.  
  160.   this._XferID = "FlavourSet";
  161.   
  162.   for (var i = 0; i < this.flavours.length; ++i)
  163.     this.flavourTable[this.flavours[i].contentType] = this.flavours[i];
  164. }
  165.  
  166. FlavourSet.prototype = {
  167.   appendFlavour: function (aFlavour, aFlavourIIDKey)
  168.   {
  169.     var flavour = new Flavour (aFlavour, aFlavourIIDKey);
  170.     this.flavours.push(flavour);
  171.     this.flavourTable[flavour.contentType] = flavour;
  172.   }
  173. };
  174.  
  175. /** 
  176.  * A Flavour is a simple type that represents a data type that can be handled. 
  177.  * It takes a content type (MIME type) which is used when storing data on the
  178.  * system clipboard/drag and drop, and an IIDKey (string interface name
  179.  * which is used to QI data to an appropriate form. The default interface is
  180.  * assumed to be wide-string.
  181.  */ 
  182. function Flavour(aContentType, aDataIIDKey)
  183. {
  184.   this.contentType = aContentType;
  185.   this.dataIIDKey = aDataIIDKey || "nsISupportsWString";
  186.  
  187.   this._XferID = "Flavour";
  188. }
  189.  
  190. function TransferDataBase() {}
  191. TransferDataBase.prototype = {
  192.   push: function (aItems)
  193.   {
  194.     this.dataList.push(aItems);
  195.   },
  196.  
  197.   get first ()
  198.   {
  199.     return "dataList" in this && this.dataList.length ? this.dataList[0] : null;
  200.   }
  201. };
  202.  
  203. /** 
  204.  * TransferDataSet is a list (array) of TransferData objects, which represents
  205.  * data dragged from one or more elements. 
  206.  */
  207. function TransferDataSet(aTransferDataList)
  208. {
  209.   this.dataList = aTransferDataList || [];
  210.  
  211.   this._XferID = "TransferDataSet";
  212. }
  213. TransferDataSet.prototype = TransferDataBase.prototype;
  214.  
  215. /** 
  216.  * TransferData is a list (array) of FlavourData for all the applicable content
  217.  * types associated with a drag from a single item. 
  218.  */
  219. function TransferData(aFlavourDataList)
  220. {
  221.   this.dataList = aFlavourDataList || [];
  222.  
  223.   this._XferID = "TransferData";
  224. }
  225. TransferData.prototype = {
  226.   __proto__: TransferDataBase.prototype,
  227.   
  228.   addDataForFlavour: function (aFlavourString, aData, aLength, aDataIIDKey)
  229.   {
  230.     this.dataList.push(new FlavourData(aData, aLength, 
  231.                        new Flavour(aFlavourString, aDataIIDKey)));
  232.   }
  233. };
  234.  
  235. /** 
  236.  * FlavourData is a type that represents data retrieved from the system 
  237.  * clipboard or drag and drop. It is constructed internally by the Transferable
  238.  * using the raw (nsISupports) data from the clipboard, the length of the data,
  239.  * and an object of type Flavour representing the type. Clients implementing
  240.  * IDragDropObserver receive an object of this type in their implementation of
  241.  * onDrop. They access the 'data' property to retrieve data, which is either data 
  242.  * QI'ed to a usable form, or unicode string. 
  243.  */
  244. function FlavourData(aData, aLength, aFlavour) 
  245. {
  246.   this.supports = aData;
  247.   this.contentLength = aLength;
  248.   this.flavour = aFlavour || null;
  249.   
  250.   this._XferID = "FlavourData";
  251. }
  252.  
  253. FlavourData.prototype = {
  254.   get data ()
  255.   {
  256.     if (this.flavour && 
  257.         this.flavour.dataIIDKey != "nsISupportsWString" )
  258.       return this.supports.QueryInterface(Components.interfaces[this.flavour.dataIIDKey]); 
  259.     else {
  260.       var unicode = this.supports.QueryInterface(Components.interfaces.nsISupportsWString);
  261.       if (unicode) 
  262.         return unicode.data.substring(0, this.contentLength/2);
  263.      
  264.       return this.supports;
  265.     }
  266.     return "";
  267.   }
  268. }
  269.  
  270. /** 
  271.  * Create a TransferData object with a single FlavourData entry. Used when 
  272.  * unwrapping data of a specific flavour from the drag service. 
  273.  */
  274. function FlavourToXfer(aData, aLength, aFlavour) 
  275. {
  276.   return new TransferData([new FlavourData(aData, aLength, aFlavour)]);
  277. }
  278.  
  279. /*
  280. function DUMP_obj (aObj) 
  281. {
  282.   for (var i in aObj)
  283.     dump("*** aObj[" + i + "] = " + aObj[i] + "\n");
  284. }
  285. */
  286.  
  287.