home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 May / PCWorld_2003-05_cd.bin / Komunik / phoenix / chrome / toolkit.jar / content / global / nsTransferable.js < prev    next >
Text File  |  2002-09-23  |  11KB  |  325 lines

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