home *** CD-ROM | disk | FTP | other *** search
/ Clickx 63 / Clickx 63.iso / software / multimedia / mirov204 / Miro_Installer.exe / xulrunner / chrome / toolkit.jar / content / global / nsTreeController.js < prev    next >
Encoding:
Text File  |  2007-02-17  |  9.3 KB  |  325 lines

  1. /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Mozilla Public License Version
  6.  * 1.1 (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/MPL/
  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.  *   Blake Ross <blaker@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 MPL, 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 MPL, the GPL or the LGPL.
  36.  *
  37.  * ***** END LICENSE BLOCK ***** */
  38.  
  39. // helper routines, for doing rdf-based cut/copy/paste/etc
  40. // this needs to be more generic!
  41.  
  42. const nsTransferable_contractid = "@mozilla.org/widget/transferable;1";
  43. const clipboard_contractid = "@mozilla.org/widget/clipboard;1";
  44. const rdf_contractid = "@mozilla.org/rdf/rdf-service;1";
  45. const supportswstring_contractid = "@mozilla.org/supports-string;1";
  46. const rdfc_contractid = "@mozilla.org/rdf/container;1";
  47.  
  48. const nsISupportsString = Components.interfaces.nsISupportsString;
  49. const nsIClipboard = Components.interfaces.nsIClipboard;
  50. const nsITransferable = Components.interfaces.nsITransferable;
  51. const nsIRDFLiteral = Components.interfaces.nsIRDFLiteral;
  52. const nsIRDFContainer = Components.interfaces.nsIRDFContainer;
  53.  
  54. var gRDF;
  55. var gClipboard;
  56.  
  57. function isContainer(tree, index)
  58. {
  59.   return tree.treeBoxObject.view.isContainer(index);
  60. }
  61.  
  62. function isContainerOpen(tree, index)
  63. {
  64.   return tree.treeBoxObject.view.isContainerOpen(index);
  65. }
  66.  
  67. function nsTreeController_SetTransferData(transferable, flavor, text)
  68. {
  69.   if (!text)
  70.     return;
  71.   var textData = Components.classes[supportswstring_contractid].createInstance(nsISupportsString);
  72.   textData.data = text;
  73.  
  74.   transferable.addDataFlavor(flavor);
  75.   transferable.setTransferData(flavor, textData, text.length*2);
  76. }
  77.  
  78. function nsTreeController_copy()
  79. {
  80.   var rangeCount = this.treeSelection.getRangeCount();
  81.   if (rangeCount < 1)
  82.     return false;
  83.    
  84.   // Build a url that encodes all the select nodes 
  85.   // as well as their parent nodes
  86.   var url = "";
  87.   var text = "";
  88.   var html = "";
  89.   var min = new Object();
  90.   var max = new Object();
  91.  
  92.   for (var i = rangeCount - 1; i >= 0; --i) {
  93.     this.treeSelection.getRangeAt(i, min, max);
  94.     for (var k = max.value; k >= min.value; --k) {
  95.       // If one of the selected items is
  96.       // a container, ignore it.
  97.       if (isContainer(this.tree, k))
  98.         continue;
  99.       var col = this.tree.columns["URL"];
  100.       var pageUrl  = this.treeView.getCellText(k, col);
  101.       col = this.tree.columns["Name"];
  102.       var pageName = this.treeView.getCellText(k, col);
  103.  
  104.       url += "ID:{" + pageUrl + "};";
  105.       url += "NAME:{" + pageName + "};";
  106.  
  107.       text += pageUrl + "\r";
  108.       html += "<a href='" + pageUrl + "'>";
  109.       if (pageName) html += pageName;
  110.         html += "</a><p>";
  111.     } 
  112.   }
  113.  
  114.   if (!url)
  115.     return false;
  116.  
  117.   // get some useful components
  118.   var trans = Components.classes[nsTransferable_contractid].createInstance(nsITransferable);
  119.   
  120.   if (!gClipboard)
  121.     gClipboard = Components.classes[clipboard_contractid].getService(Components.interfaces.nsIClipboard);
  122.  
  123.   gClipboard.emptyClipboard(nsIClipboard.kGlobalClipboard);
  124.  
  125.   this.SetTransferData(trans, "text/unicode", text);
  126.   this.SetTransferData(trans, "moz/bookmarkclipboarditem", url);
  127.   this.SetTransferData(trans, "text/html", html);
  128.  
  129.   gClipboard.setData(trans, null, nsIClipboard.kGlobalClipboard);
  130.   return true;
  131. }
  132.  
  133. function nsTreeController_cut()
  134. {
  135.   if (this.copy()) {
  136.     this.doDelete();
  137.     return true;            // copy succeeded, don't care if delete failed
  138.   }
  139.   return false;             // copy failed, so did cut
  140. }
  141.  
  142. function nsTreeController_selectAll()
  143. {
  144.   this.treeSelection.selectAll();
  145. }
  146.  
  147. function nsTreeController_delete()
  148. {  
  149.   var rangeCount = this.treeSelection.getRangeCount();
  150.   if (rangeCount < 1)
  151.     return false;      
  152.   
  153.   var datasource = this.tree.database;
  154.   var dsEnum = datasource.GetDataSources();
  155.   dsEnum.getNext();
  156.   var ds = dsEnum.getNext()
  157.                  .QueryInterface(Components.interfaces.nsIRDFDataSource);
  158.  
  159.   var count = this.treeSelection.count;
  160.   
  161.   // XXX 9 is a random number, just looking for a sweetspot
  162.   // don't want to rebuild tree content for just a few items
  163.   if (count > 9) {
  164.     ds.beginUpdateBatch();
  165.   }
  166.  
  167.   var min = new Object(); 
  168.   var max = new Object();
  169.   var dirty = false;
  170.   for (var i = rangeCount - 1; i >= 0; --i) {
  171.     this.treeSelection.getRangeAt(i, min, max);
  172.     for (var k = max.value; k >= min.value; --k) {
  173.       if (!gRDF)
  174.         gRDF = Components.classes[rdf_contractid].getService(Components.interfaces.nsIRDFService);
  175.  
  176.       var IDRes = this.treeBuilder.getResourceAtIndex(k);
  177.       if (!IDRes)
  178.         continue;
  179.  
  180.       var root = this.tree.getAttribute('ref');
  181.       var parentIDRes;
  182.       try {
  183.         parentIDRes = this.treeBuilder.getResourceAtIndex(this.treeView.getParentIndex(k));
  184.       }
  185.       catch(ex) {
  186.         parentIDRes = gRDF.GetResource(root);
  187.       }
  188.       if (!parentIDRes)
  189.         continue;
  190.       
  191.       // otherwise remove the parent/child assertion then
  192.       var containment = gRDF.GetResource("http://home.netscape.com/NC-rdf#child");
  193.       ds.Unassert(parentIDRes, containment, IDRes);
  194.       dirty = true;
  195.     }
  196.   }
  197.  
  198.   if (count > 9) {
  199.     ds.endUpdateBatch();
  200.   }
  201.  
  202.   if (dirty) {    
  203.     try {
  204.       var remote = datasource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
  205.       remote.Flush();
  206.     } catch (ex) {
  207.     }
  208.   }
  209.   if (max.value != -1) {
  210.     var newIndex = min.value;
  211.     if (newIndex >= this.treeView.rowCount)
  212.       --newIndex;
  213.     if (newIndex >= 0)
  214.       this.treeSelection.select(newIndex);
  215.   }
  216.   return true;
  217. }
  218.  
  219. function nsTreeController(tree)
  220. {
  221.   this._tree = tree;
  222.   tree.controllers.appendController(this);
  223. }
  224.  
  225. nsTreeController.prototype = 
  226. {
  227.   _treeSelection: null,
  228.   _treeView: null,
  229.   _treeBuilder: null,
  230.   _treeBoxObject: null,
  231.   _tree: null,
  232.   get tree()
  233.   {
  234.     return this._tree;
  235.   },
  236.   get treeBoxObject()
  237.   {
  238.     if (this._treeBoxObject)
  239.       return this._treeBoxObject;
  240.     return this._treeBoxObject = this.tree.treeBoxObject;
  241.   },
  242.   get treeView()
  243.   {
  244.     if (this._treeView)
  245.       return this._treeView;
  246.     return this._treeView = this.tree.treeBoxObject.view;
  247.   },
  248.   get treeSelection()
  249.   {
  250.     if (this._treeSelection)
  251.       return this._treeSelection;
  252.     return this._treeSelection = this.tree.treeBoxObject.view.selection;
  253.   },
  254.   get treeBuilder()
  255.   {
  256.     if (this._treeBuilder)
  257.       return this._treeBuilder;
  258.     return this._treeBuilder = this.tree.builder.
  259.                                    QueryInterface(Components.interfaces.nsIXULTreeBuilder);
  260.   },
  261.   SetTransferData : nsTreeController_SetTransferData,
  262.  
  263.   supportsCommand: function(command)
  264.   {
  265.     switch(command)
  266.     {
  267.       case "cmd_cut":
  268.       case "cmd_copy":
  269.       case "cmd_delete":
  270.       case "cmd_selectAll":
  271.         return true;
  272.       default:
  273.         return false;
  274.     }
  275.   },
  276.  
  277.   isCommandEnabled: function(command)
  278.   {
  279.     var haveCommand;
  280.     switch (command)
  281.     {
  282.       // commands which do not require selection              
  283.       case "cmd_selectAll":
  284.         var treeView = this.treeView;
  285.         return (treeView.rowCount !=  treeView.selection.count);
  286.                 
  287.       // these commands require selection
  288.       case "cmd_cut":
  289.         haveCommand = (this.cut != undefined);
  290.         break;
  291.       case "cmd_copy":
  292.         haveCommand = (this.copy != undefined);
  293.         break;
  294.       case "cmd_delete":
  295.         haveCommand = (this.doDelete != undefined);
  296.         break;
  297.     }
  298.         
  299.     // if we get here, then we have a command that requires selection
  300.     var haveSelection = (this.treeSelection.count);
  301.     return (haveCommand && haveSelection);
  302.   },
  303.  
  304.   doCommand: function(command)
  305.   {
  306.     switch(command)
  307.     {
  308.       case "cmd_cut":
  309.         return this.cut();
  310.       case "cmd_copy":
  311.         return this.copy();
  312.       case "cmd_delete":
  313.         return this.doDelete();        
  314.       case "cmd_selectAll":
  315.         return this.selectAll();
  316.     }
  317.     return false;
  318.   },
  319.   copy: nsTreeController_copy,
  320.   cut: nsTreeController_cut,
  321.   doDelete: nsTreeController_delete,
  322.   selectAll: nsTreeController_selectAll
  323. }
  324.  
  325.