home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 July & August / PCWorld_2005-07-08_cd.bin / komunikace / netscape / nsb-install-8-0.exe / chrome / toolkit.jar / content / global / nsTreeController.js < prev    next >
Text File  |  2004-11-25  |  10KB  |  322 lines

  1. /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  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.  *   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 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. // 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 pageUrl  = this.treeView.getCellText(k, "URL");        
  100.       var pageName = this.treeView.getCellText(k, "Name");
  101.  
  102.       url += "ID:{" + pageUrl + "};";
  103.       url += "NAME:{" + pageName + "};";
  104.  
  105.       text += pageUrl + "\r";
  106.       html += "<a href='" + pageUrl + "'>";
  107.       if (pageName) html += pageName;
  108.         html += "</a><p>";
  109.     } 
  110.   }
  111.  
  112.   if (!url)
  113.     return false;
  114.  
  115.   // get some useful components
  116.   var trans = Components.classes[nsTransferable_contractid].createInstance(nsITransferable);
  117.   
  118.   if (!gClipboard)
  119.     gClipboard = Components.classes[clipboard_contractid].getService(Components.interfaces.nsIClipboard);
  120.  
  121.   gClipboard.emptyClipboard(nsIClipboard.kGlobalClipboard);
  122.  
  123.   this.SetTransferData(trans, "text/unicode", text);
  124.   this.SetTransferData(trans, "moz/bookmarkclipboarditem", url);
  125.   this.SetTransferData(trans, "text/html", html);
  126.  
  127.   gClipboard.setData(trans, null, nsIClipboard.kGlobalClipboard);
  128.   return true;
  129. }
  130.  
  131. function nsTreeController_cut()
  132. {
  133.   if (this.copy()) {
  134.     this.doDelete();
  135.     return true;            // copy succeeded, don't care if delete failed
  136.   }
  137.   return false;             // copy failed, so did cut
  138. }
  139.  
  140. function nsTreeController_selectAll()
  141. {
  142.   this.treeSelection.selectAll();
  143. }
  144.  
  145. function nsTreeController_delete()
  146. {  
  147.   var rangeCount = this.treeSelection.getRangeCount();
  148.   if (rangeCount < 1)
  149.     return false;      
  150.   
  151.   var datasource = this.tree.database;
  152.   var dsEnum = datasource.GetDataSources();
  153.   dsEnum.getNext();
  154.   var ds = dsEnum.getNext()
  155.                  .QueryInterface(Components.interfaces.nsIRDFDataSource);
  156.  
  157.   var count = this.treeSelection.count;
  158.   
  159.   // XXX 9 is a random number, just looking for a sweetspot
  160.   // don't want to rebuild tree content for just a few items
  161.   if (count > 9) {
  162.     ds.beginUpdateBatch();
  163.   }
  164.  
  165.   var min = new Object(); 
  166.   var max = new Object();
  167.   var dirty = false;
  168.   for (var i = rangeCount - 1; i >= 0; --i) {
  169.     this.treeSelection.getRangeAt(i, min, max);
  170.     for (var k = max.value; k >= min.value; --k) {
  171.       if (!gRDF)
  172.         gRDF = Components.classes[rdf_contractid].getService(Components.interfaces.nsIRDFService);
  173.  
  174.       var IDRes = this.treeBuilder.getResourceAtIndex(k);
  175.       if (!IDRes)
  176.         continue;
  177.  
  178.       var root = this.tree.getAttribute('ref');
  179.       var parentIDRes;
  180.       try {
  181.         parentIDRes = this.treeBuilder.getResourceAtIndex(this.treeView.getParentIndex(k));
  182.       }
  183.       catch(ex) {
  184.         parentIDRes = gRDF.GetResource(root);
  185.       }
  186.       if (!parentIDRes)
  187.         continue;
  188.       
  189.       // otherwise remove the parent/child assertion then
  190.       var containment = gRDF.GetResource("http://home.netscape.com/NC-rdf#child");
  191.       ds.Unassert(parentIDRes, containment, IDRes);
  192.       dirty = true;
  193.     }
  194.   }
  195.  
  196.   if (count > 9) {
  197.     ds.endUpdateBatch();
  198.   }
  199.  
  200.   if (dirty) {    
  201.     try {
  202.       var remote = datasource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
  203.       remote.Flush();
  204.     } catch (ex) {
  205.     }
  206.   }
  207.   if (max.value) {
  208.     var newIndex = max.value - (max.value - min.value);
  209.     if (newIndex >= this.treeView.rowCount)
  210.       --newIndex;
  211.     this.treeSelection.select(newIndex);
  212.   }
  213.   return true;
  214. }
  215.  
  216. function nsTreeController(tree)
  217. {
  218.   this._tree = tree;
  219.   tree.controllers.appendController(this);
  220. }
  221.  
  222. nsTreeController.prototype = 
  223. {
  224.   _treeSelection: null,
  225.   _treeView: null,
  226.   _treeBuilder: null,
  227.   _treeBoxObject: null,
  228.   _tree: null,
  229.   get tree()
  230.   {
  231.     return this._tree;
  232.   },
  233.   get treeBoxObject()
  234.   {
  235.     if (this._treeBoxObject)
  236.       return this._treeBoxObject;
  237.     return this._treeBoxObject = this.tree.treeBoxObject;
  238.   },
  239.   get treeView()
  240.   {
  241.     if (this._treeView)
  242.       return this._treeView;
  243.     return this._treeView = this.tree.treeBoxObject.view;
  244.   },
  245.   get treeSelection()
  246.   {
  247.     if (this._treeSelection)
  248.       return this._treeSelection;
  249.     return this._treeSelection = this.tree.treeBoxObject.view.selection;
  250.   },
  251.   get treeBuilder()
  252.   {
  253.     if (this._treeBuilder)
  254.       return this._treeBuilder;
  255.     return this._treeBuilder = this.tree.builder.
  256.                                    QueryInterface(Components.interfaces.nsIXULTreeBuilder);
  257.   },
  258.   SetTransferData : nsTreeController_SetTransferData,
  259.  
  260.   supportsCommand: function(command)
  261.   {
  262.     switch(command)
  263.     {
  264.       case "cmd_cut":
  265.       case "cmd_copy":
  266.       case "cmd_delete":
  267.       case "cmd_selectAll":
  268.         return true;
  269.       default:
  270.         return false;
  271.     }
  272.   },
  273.  
  274.   isCommandEnabled: function(command)
  275.   {
  276.     var haveCommand;
  277.     switch (command)
  278.     {
  279.       // commands which do not require selection              
  280.       case "cmd_selectAll":
  281.         var treeView = this.treeView;
  282.         return (treeView.rowCount !=  treeView.selection.count);
  283.                 
  284.       // these commands require selection
  285.       case "cmd_cut":
  286.         haveCommand = (this.cut != undefined);
  287.         break;
  288.       case "cmd_copy":
  289.         haveCommand = (this.copy != undefined);
  290.         break;
  291.       case "cmd_delete":
  292.         haveCommand = (this.doDelete != undefined);
  293.         break;
  294.     }
  295.         
  296.     // if we get here, then we have a command that requires selection
  297.     var haveSelection = (this.treeSelection.count);
  298.     return (haveCommand && haveSelection);
  299.   },
  300.  
  301.   doCommand: function(command)
  302.   {
  303.     switch(command)
  304.     {
  305.       case "cmd_cut":
  306.         return this.cut();
  307.       case "cmd_copy":
  308.         return this.copy();
  309.       case "cmd_delete":
  310.         return this.doDelete();        
  311.       case "cmd_selectAll":
  312.         return this.selectAll();
  313.     }
  314.     return false;
  315.   },
  316.   copy: nsTreeController_copy,
  317.   cut: nsTreeController_cut,
  318.   doDelete: nsTreeController_delete,
  319.   selectAll: nsTreeController_selectAll
  320. }
  321.  
  322.