RetroZilla/browser/components/bookmarks/content/bookmarksTree.xml
2015-10-20 23:03:22 -04:00

1080 lines
45 KiB
XML

<?xml version="1.0"?>
# -*- Mode: HTML; indent-tabs-mode: nil; -*-
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Goodger <ben@netscape.com> (Original Author)
# Blake Ross <blaker@nemtscape.com>
# Pierre Chanial <chanial@noos.fr> (v 2.0)
# Joey Minta <jminta@gmail.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
<!DOCTYPE window [
<!ENTITY % bookmarksDTD SYSTEM "chrome://browser/locale/bookmarks/bookmarks.dtd" >
%bookmarksDTD;
]>
<bindings id="bookmarksBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="bookmarks-tree">
<implementation>
<constructor><![CDATA[
// This function only reads in the bookmarks from disk if they have not already been read.
initServices();
initBMService();
BMSVC.readBookmarks();
// We implement nsIController
this.tree.controllers.appendController(this.controller);
var olb = document.getAnonymousElementByAttribute(this, "anonid", "bookmarks-tree");
olb = olb.builder.QueryInterface(Components.interfaces.nsIXULTreeBuilder);
olb.addObserver(this.builderObserver);
// Load column settings from persisted attribute
var colinfostr = this.getAttribute("colinfo");
var colinfo = colinfostr.split(" ");
for (var i = 0; i < colinfo.length; ++i) {
if (colinfo[i] == "") continue;
var querymarker = colinfo[i].indexOf("?");
var anonid = colinfo[i].substring(4, querymarker);
var col = document.getAnonymousElementByAttribute(this, "id", anonid);
if (!anonid || !col) break;
var attrstring = colinfo[i].substr(querymarker + 1);
var attrpairs = attrstring.split("&");
for (var j = 0; j < attrpairs.length; ++j) {
var pair = attrpairs[j].split("=");
col.setAttribute(pair[0], pair[1]);
}
}
// Load sort data from preferences
this.refreshSort();
// Observe for changes in sort from other concurrent UI
const kPrefSvcContractID = "@mozilla.org/preferences-service;1";
const kPrefSvcIID = Components.interfaces.nsIPrefService;
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
var prefs = prefSvc.getBranch(null);
const kPrefBranchInternalIID = Components.interfaces.nsIPrefBranch2;
var bookmarksPrefsInternal = prefs.QueryInterface(kPrefBranchInternalIID);
bookmarksPrefsInternal.addObserver(this.sortChangedObserver.domain,
this.sortChangedObserver, false);
]]></constructor>
<destructor><![CDATA[
this.treeBuilder.removeObserver(this.builderObserver);
this.tree.controllers.removeController(this.controller);
// Save column settings and sort info to persisted attribute
var persistString = "";
var sortResource = gNC_NS + "Name";
var sortDirection = "none";
var treecols = document.getAnonymousElementByAttribute(this, "anonid", "treecols");
var child = treecols.firstChild;
while (child) {
if (child.localName != "splitter") {
var formatString = " col:%1%?width=%2%&hidden=%3%&ordinal=%6%";
formatString = formatString.replace(/%1%/, child.getAttribute("id"));
formatString = formatString.replace(/%2%/, child.getAttribute("width"));
formatString = formatString.replace(/%3%/, child.getAttribute("hidden"));
// While we're walking the columns, if we discover the column that represents the
// field sorted by, save the resource associated with that column so that we
// can save that in prefs (see below)
if (child.getAttribute("sortActive") == "true") {
sortResource = child.getAttribute("sort");
sortDirection = child.getAttribute("sortDirection");
}
formatString = formatString.replace(/%6%/, child.getAttribute("ordinal"));
persistString += formatString;
}
child = child.nextSibling;
}
this.setAttribute("colinfo", persistString);
document.persist(this.id, "colinfo");
// Unhook the sort change observer for this tree
const kPrefSvcContractID = "@mozilla.org/preferences-service;1";
const kPrefSvcIID = Components.interfaces.nsIPrefService;
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
var prefs = prefSvc.getBranch(null);
const kPrefBranchInternalIID = Components.interfaces.nsIPrefBranch2;
var bookmarksPrefsInternal = prefs.QueryInterface(kPrefBranchInternalIID);
bookmarksPrefsInternal.removeObserver(this.sortChangedObserver.domain,
this.sortChangedObserver);
]]></destructor>
<property name="db">
<getter><![CDATA[
return this.tree.database;
]]></getter>
</property>
<field name="sortChangedObserver">
<![CDATA[
({
outer: this,
domain: "browser.bookmarks.sort",
observe: function BMOL_sortChangedObserver(aSubject, aTopic, aPrefName)
{
if (aTopic != "nsPref:changed") return;
if (aPrefName.substr(0, this.domain.length) != this.domain) return;
this.outer.refreshSort();
}
})
]]>
</field>
<field name="sorted">false</field>
<method name="refreshSort">
<body>
<![CDATA[
const kPrefSvcContractID = "@mozilla.org/preferences-service;1";
const kPrefSvcIID = Components.interfaces.nsIPrefService;
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
var bookmarksSortPrefs = prefSvc.getBranch("browser.bookmarks.sort.");
// This ensures that we don't sort twice in the tree that is clicked on
// as a result of 1) the click and 2) the pref listener.
if (!this.sorted) {
try {
var sortResource = bookmarksSortPrefs.getCharPref("resource");
var sortDirection = bookmarksSortPrefs.getCharPref("direction");
// Walk the columns, when we find a column with a sort resource that matches the supplied
// data, stop and make sure it's sort active.
var treecols = document.getAnonymousElementByAttribute(this, "anonid", "treecols");
var child = treecols.firstChild;
while (child) {
if (child.localName != "splitter") {
if (child.getAttribute("sort") == sortResource) {
child.setAttribute("sortActive", "true");
child.setAttribute("sortDirection", sortDirection);
this.treeBuilder.sort(child, false);
break;
}
}
child = child.nextSibling;
}
}
catch (e) {
dump("error in refresh sort:"+e)
}
}
this.sorted = false;
]]>
</body>
</method>
<property name="columns">
<getter>
<![CDATA[
var cols = [];
var treecols = document.getAnonymousElementByAttribute(this, "anonid", "treecols");
var child = treecols.firstChild;
while (child) {
if (child.localName != "splitter") {
var obj = {
label: child.getAttribute("label"),
accesskey: child.getAttribute("accesskey"),
resource: child.getAttribute("sort"),
sortActive: child.getAttribute("sortActive") == "true",
hidden: child.getAttribute("hidden")
}
cols.push(obj);
}
child = child.nextSibling;
}
return cols;
]]>
</getter>
</property>
<method name="toggleColumnVisibility">
<parameter name="aColumnResource"/>
<body>
<![CDATA[
var elt = document.getAnonymousElementByAttribute(this, "sort", aColumnResource);
if (elt)
elt.setAttribute("hidden", elt.getAttribute("hidden") != "true");
]]>
</body>
</method>
<property name="tree">
<getter><![CDATA[
return document.getAnonymousElementByAttribute(this, "anonid", "bookmarks-tree");
]]></getter>
</property>
<property name="treeBoxObject">
<getter><![CDATA[
return this.tree.boxObject.QueryInterface(Components.interfaces.nsITreeBoxObject);
]]></getter>
</property>
<property name="treeBuilder">
<getter><![CDATA[
return this.tree.builder.QueryInterface(Components.interfaces.nsIXULTreeBuilder);
]]></getter>
</property>
<property name="type">
<getter><![CDATA[
if (!this._type) {
var type = this.getAttribute("type");
if (!type)
type = "multi-column";
this._type = type;
}
return this._type;
]]></getter>
</property>
<property name="currentIndex">
<getter><![CDATA[
return this.treeBoxObject.view.selection.currentIndex;
]]></getter>
</property>
<property name="currentResource">
<getter><![CDATA[
return this.treeBuilder.getResourceAtIndex(this.currentIndex);
]]></getter>
</property>
<method name="getRowResource">
<parameter name="aRow"/>
<body><![CDATA[
if (aRow != -1)
return this.treeBuilder.getResourceAtIndex(aRow);
else
return this.getRootResource();
]]></body>
</method>
<method name="getParentResource">
<parameter name="aRow"/>
<body><![CDATA[
if (aRow != -1) {
var parentIndex = this.treeBoxObject.view.getParentIndex(aRow);
return this.getRowResource(parentIndex);
}
return this.getRootResource(); // assume its parent is the root
]]></body>
</method>
<method name="getRootResource">
<body><![CDATA[
var tree = document.getAnonymousElementByAttribute(this, "anonid", "bookmarks-tree");
return RDF.GetResource(tree.ref);
]]></body>
</method>
<method name="selectResource">
<parameter name="aResource"/>
<body><![CDATA[
var index = this.treeBuilder.getIndexOfResource(aResource);
if (index != -1) {
if (!this.treeBoxObject.view.selection.isSelected(index))
this.treeBoxObject.view.selection.toggleSelect(index);
return;
}
var chain = BMSVC.getParentChain(aResource);
//dump("Chain:"+chain.length+"\n");
for (var i=0; i<chain.length; i++) {
var rParent = chain.queryElementAt(i, kRDFRSCIID);
index = this.treeBuilder.getIndexOfResource(rParent);
//dump(i+":"+BookmarksUtils.getProperty(rParent, gNC_NS+"Name")+", index:"+index+"\n");
if (index == -1)
# rParent is or is a parent of "ref", we go on searching for the
# first parent in the tree.
continue;
if (!this.treeBoxObject.view.isContainerOpen(index))
# we found one, let's open it.
this.treeBoxObject.view.toggleOpenState(index);
}
if (index == -1)
# none of the parents were in the tree, bailing
return;
index = this.treeBuilder.getIndexOfResource(aResource);
if (index != -1)
this.treeBoxObject.view.selection.toggleSelect(index);
]]></body>
</method>
<method name="focus">
<body>
this.tree.focus();
</body>
</method>
<field name="_selection">null</field>
<field name="_target"> null</field>
<method name="getTreeSelection">
<body><![CDATA[
var selection = {};
selection.item = [];
selection.parent = [];
selection.isExpanded = [];
var rangeCount = this.treeBoxObject.view.selection.getRangeCount();
// workaround for bug 171547: if rowCount==0, rangeCount==1
if (this.treeBuilder.rowCount > 0)
for (var k = 0; k < rangeCount; ++k) {
var rangeMin = {};
var rangeMax = {};
this.treeBoxObject.view.selection.getRangeAt(k, rangeMin, rangeMax);
for (var i = rangeMin.value; i <= rangeMax.value; ++i) {
var selectedItem = this.getRowResource(i);
var selectedParent = this.getParentResource(i);
var isExpanded = this.treeBoxObject.view.isContainerOpen(i);
selection.item .push(selectedItem);
selection.parent.push(selectedParent);
selection.isExpanded.push(isExpanded);
}
}
selection.length = selection.item.length;
BookmarksUtils.checkSelection(selection);
return selection;
]]></body>
</method>
<method name="getTreeTarget">
<parameter name="aItem"/>
<parameter name="aParent"/>
<parameter name="aOrientation"/>
<body><![CDATA[
if (!aParent || aParent.Value == "NC:BookmarksTopRoot")
return BookmarksUtils.getTargetFromFolder(RDF.GetResource("NC:BookmarksRoot"))
if (aOrientation == BookmarksUtils.DROP_ON)
return BookmarksUtils.getTargetFromFolder(aItem);
RDFC.Init(this.db, aParent);
var index = RDFC.IndexOf(aItem);
if (aOrientation == BookmarksUtils.DROP_AFTER)
++index;
return { parent: aParent, index: index };
]]></body>
</method>
# This function saves the current selection state before the tree is rebuilt
# following a command execution. This allows us to remember which item(s)
# was/were selected so that the user does not need to constantly refocus the
# tree to perform a sequence of commands.
<field name="_savedSelection">[]</field>
<method name="saveSelection">
<body><![CDATA[
var selection = this.treeBoxObject.view.selection;
var rangeCount = selection.getRangeCount();
var ranges = [];
var min = {}; var max = {};
for (var i = 0; i < rangeCount; ++i) {
selection.getRangeAt(i, min, max);
ranges.push({min: min.value, max: max.value});
}
this._savedSelection = ranges;
]]></body>
</method>
# This function restores the selection appropriately after a command executes.
# This is necessary because most commands trigger a rebuild of the tree which
# destroys the selection. The restoration of selection is handled in three
# different ways depending on the type of command that has been executed:
# 1) Commands that remove rows:
# The row immediately after the first range in the selection is selected,
# if there is no row immediately after the first range the item before it
# is selected
# 2) Commands that insert rows:
# The newly inserted rows are selected
# 3) Commands that do not change the row count
# The row(s) that was/were operated on remain selected.
#
# The calls to save/restore are placed in the doCommand method and thus all
# commands must pass through this gate. The result is that this method becomes
# the POLICY CENTER FOR POST-VIEW/EDIT SELECTION CHANGES.
<method name="restoreSelection">
<parameter name="aCommand"/>
<body><![CDATA[
var oldRanges = this._savedSelection;
var newRanges = [];
switch(aCommand) {
// [Category 1] - Commands that remove rows
case "cmd_cut":
case "cmd_delete":
// Since rows have been removed, the row immediately after the first range
// in the original selection now has the index of the first item in the first
// range.
var nextRow = oldRanges[0].min;
var maxCount = this.treeBoxObject.view.rowCount;
if (nextRow >= maxCount)
nextRow = maxCount-1;
if (nextRow >= 0)
newRanges.push({min: nextRow, max: nextRow});
break;
// [Category 2] - Commands that insert rows
case "cmd_paste":
case "cmd_bm_import":
case "cmd_bm_movebookmark":
case "cmd_bm_newbookmark":
case "cmd_bm_newfolder":
case "cmd_bm_newseparator":
case "cmd_undo": //XXXpch: doesn't work for insert
case "cmd_redo": //XXXpch: doesn't work for remove
// All items inserted will be selected. The implementation of this model
// is left to |preUpdateTreeSelection|, called when an insert transaction is
// executed, and |updateTreeSelection| called here.
this.updateTreeSelection();
break;
// [Category 3] - Commands that do not alter the row count
case "cmd_copy":
case "cmd_bm_properties":
case "cmd_bm_rename":
case "cmd_bm_setpersonaltoolbarfolder":
case "cmd_bm_export":
default:
// The selection is unchanged.
return;
}
var newSelection = this.treeBoxObject.view.selection;
for (i = 0; i < newRanges.length; ++i)
newSelection.rangedSelect(newRanges[i].min, newRanges[i].max, true);
]]></body>
</method>
<field name="_itemToBeToggled"> []</field>
// keep track of the items that we will select
// because we can not select rows during a batch.
<method name="preUpdateTreeSelection">
<parameter name="aTxn"/>
<parameter name="aDo"/>
<body><![CDATA[
if (aTxn) {
aTxn = aTxn.wrappedJSObject;
var type = aTxn.type;
// Skip transactions that aggregates nested "insert" or "remove" transactions.
if ((type == "insert") && aDo || (type == "remove") && !aDo)
this._itemToBeToggled = [aTxn.item];
} else {
var txnList;
var bkmkTxnSvc = Components.classes["@mozilla.org/bookmarks/transactionmanager;1"]
.getService(Components.interfaces.nsIBookmarkTransactionManager);
var txmgr = bkmkTxnSvc.transactionManager;
if (this.bookmarkTreeTransactionListener.mLastTxnWasDo) {
txnList = txmgr.getUndoList();
} else {
txnList = txmgr.getRedoList();
}
var items =[];
var childList = txnList.getChildListForItem(txnList.numItems-1);
for (var i=0; i<childList.numItems; i++) {
items.push(childList.getItem(i).wrappedJSObject.item);
}
this._itemToBeToggled = items;
}
},
]]></body>
</method>
<method name="updateTreeSelection">
<body><![CDATA[
this.treeBoxObject.view.selection.clearSelection();
for (var i=0; i<this._itemToBeToggled.length; ++i) {
index = this.treeBuilder.getIndexOfResource(this._itemToBeToggled[i]);
if (index != -1 && !this.treeBoxObject.view.selection.isSelected(index))
this.treeBoxObject.view.selection.toggleSelect(index);
}
]]></body>
</method>
<method name="createTreeContextMenu">
<parameter name="aEvent"/>
<body><![CDATA[
var selection = this._selection;
var target = this._target;
BookmarksCommand.createContextMenu(aEvent, selection);
this.onCommandUpdate();
]]></body>
</method>
<method name="openItemClick">
<parameter name="aEvent"/>
<parameter name="aClickCount"/>
<body><![CDATA[
if (aEvent.button == 2 || aEvent.originalTarget.localName != "treechildren")
return;
if (aClickCount != this.clickCount && aEvent.button != 1)
return;
var row = {};
var col = {};
var obj = {};
this.treeBoxObject.getCellAt(aEvent.clientX, aEvent.clientY, row, col, obj);
row = row.value;
if (row == -1 || obj.value == "twisty")
return;
var modifKey = aEvent.shiftKey || aEvent.ctrlKey || aEvent.altKey ||
aEvent.metaKey || aEvent.button == 1;
if (this.clickCount == 2 && !modifKey &&
this.treeBoxObject.view.isContainer(row))
return;
if (this.clickCount == 2 && modifKey) {
this.treeBoxObject.view.selection.select(row);
this._selection = this.getTreeSelection();
}
var selection = this._selection;
if (selection.isContainer[0]) {
if (this.clickCount == 1 && !modifKey) {
this.treeBoxObject.view.toggleOpenState(row);
//XXXpch: broken since we have single IDs
//if (selection.protocol[0] != "file")
return;
}
}
var browserTarget = whereToOpenLink(aEvent);
BookmarksCommand.openBookmark(selection, browserTarget, this.db);
]]></body>
</method>
<method name="openItemKey">
<body><![CDATA[
if (this._selection.length != 1) {
return;
}
if (!this._selection.isContainer[0])
BookmarksCommand.openBookmark(this._selection, "current", this.db)
]]></body>
</method>
<method name="searchBookmarks">
<parameter name="aInput"/>
<body><![CDATA[
if(!this.originalRef)
this.originalRef = this.tree.getAttribute("ref");
if (!aInput)
this.tree.setAttribute("ref", this.originalRef);
else
this.tree.setAttribute("ref",
"find:datasource=rdf:bookmarks&match=http://home.netscape.com/NC-rdf#Name&method=contains&text=" + encodeURIComponent(aInput));
]]></body>
</method>
<!-- observer -->
<field name="DNDObserver" readonly="true"><![CDATA[
({
mOuter: this,
onDragStart: function (aEvent, aXferData, aDragAction)
{
if (this.mOuter.tree.getAttribute("sortActive") == "true")
throw Components.results.NS_OK;
var selection = this.mOuter._selection;
aXferData.data = BookmarksUtils.getXferDataFromSelection(selection);
if (aEvent.ctrlKey)
aDragAction.action = kDSIID.DRAGDROP_ACTION_COPY;
},
onDragOver: function (aEvent, aFlavour, aDragSession)
{
// allow dropping of bookmarks below the tree
if (aDragSession.sourceNode == this.mOuter)
aDragSession.canDrop = true;
},
// the actual dropping happens in the nsIXULTreeBuilderObserver below
onDrop: function (aEvent, aXferData, aDragSession) { },
getSupportedFlavours: function ()
{
var flavourSet = new FlavourSet();
flavourSet.appendFlavour("moz/rdfitem");
flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
flavourSet.appendFlavour("text/x-moz-url");
flavourSet.appendFlavour("text/unicode");
return flavourSet;
}
})
]]></field>
<!-- nsIController -->
<field name="controller" readonly="true"><![CDATA[
({
mOuter: this,
supportsCommand: BookmarksController.supportsCommand,
isCommandEnabled: function (aCommand)
{
// warning: this is not the called function in BookmarksController.onCommandUpdate
var selection = this.mOuter._selection;
var target = this.mOuter._target;
return BookmarksController.isCommandEnabled(aCommand, selection, target)
},
doCommand: function (aCommand)
{
var selection = this.mOuter._selection;
var target = this.mOuter._target;
this.mOuter.treeBoxObject.view.selection.selectEventsSuppressed = true;
this.mOuter._itemToBeToggled = [];
switch (aCommand) {
case "cmd_selectAll":
this.mOuter.treeBoxObject.view.selection.selectAll();
break;
default:
this.mOuter.saveSelection();
BookmarksController.doCommand(aCommand, selection, target);
this.mOuter.restoreSelection(aCommand);
}
this.mOuter.treeBoxObject.view.selection.selectEventsSuppressed = false;
}
})
]]></field>
<method name="onCommandUpdate">
<body><![CDATA[
var selection = this._selection;
var target = this._target;
BookmarksController.onCommandUpdate(selection, target);
]]></body>
</method>
<method name="selectionChanged">
<parameter name="aEvent"/>
<body><![CDATA[
]]></body>
</method>
<!-- nsIXULTreeBuilderObserver -->
<field name="builderObserver"><![CDATA[
({
mOuter: this,
canDrop: function(index, orientation)
{
var dragSession = DS.getCurrentSession();
if (!dragSession)
return false;
var selection = BookmarksUtils.getSelectionFromXferData(dragSession);
var isBookmark = dragSession.isDataFlavorSupported("moz/rdfitem");
if (isBookmark && selection.containsImmutable)
return false;
if (orientation == BookmarksUtils.DROP_ON)
return true;
var rsrc = this.mOuter.getRowResource(index);
var rsrcParent = this.mOuter.getParentResource(index);
var rtype = BookmarksUtils.resolveType(rsrc);
var rptype = BookmarksUtils.resolveType(rsrcParent);
if (!BookmarksUtils.isValidTargetContainer (rsrcParent, selection))
return false;
if (index != 0)
return true;
if (rsrc.Value != "NC:BookmarksRoot")
return true;
return orientation == BookmarksUtils.DROP_BEFORE ? false : this.mOuter.treeBoxObject.view.isContainerOpen(0)
},
onDrop: function(row, orientation)
{
var dragSession = DS.getCurrentSession();
if (!dragSession)
return;
//var date = Date.now();
var selection = BookmarksUtils.getSelectionFromXferData(dragSession);
var rItem = this.mOuter.getRowResource(row);
var rParent = this.mOuter.getParentResource(row);
var target;
if (orientation == BookmarksUtils.DROP_AFTER &&
this.mOuter.treeBoxObject.view.isContainer(row) &&
this.mOuter.treeBoxObject.view.isContainerOpen(row) &&
!this.mOuter.treeBoxObject.view.isContainerEmpty(row))
target = { parent: rItem, index: 1 };
else {
target = this.mOuter.getTreeTarget(rItem, rParent, orientation);
}
this.mOuter.treeBoxObject.view.selection.selectEventsSuppressed = true;
this.mOuter._itemToBeToggled = [];
// we can only test for kCopyAction if the source is a bookmark
var checkCopy = dragSession.isDataFlavorSupported("moz/rdfitem");
const kCopyAction = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK;
// doCopy defaults to true; check if we should make it false.
// we make it false only if all the selection items have valid parent
// bookmark DS containers (i.e. aren't generated via aggregation)
var doCopy = true;
if (checkCopy && !(dragSession.dragAction & kCopyAction))
doCopy = BookmarksUtils.shouldCopySelection("drag", selection);
if (doCopy)
BookmarksUtils.insertAndCheckSelection("drag", selection, target);
else
BookmarksUtils.moveAndCheckSelection ("drag", selection, target);
if (this.mOuter._itemToBeToggled.length > 0)
this.mOuter.updateTreeSelection();
// use of a timer to speedup
var This = this.mOuter;
setTimeout( function (){This.treeBoxObject.view.selection.selectEventsSuppressed = false}, 100)
//dump("DND time:"+(Date.now()-date)+"\n")
},
onToggleOpenState: function (aRow)
{
// update the open attribute of the selection
var selection = this.mOuter._selection;
if (!selection)
return;
var resource = this.mOuter.getRowResource(aRow);
for (var i=0; i<selection.length; ++i) {
if (selection.item[i] == resource) {
selection.isExpanded[i] = !selection.isExpanded[i];
break;
}
}
},
onCycleHeader: function (aColumnID, aHeaderElement)
{
const kPrefSvcContractID = "@mozilla.org/preferences-service;1";
const kPrefSvcIID = Components.interfaces.nsIPrefService;
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
var bookmarksSortPrefs = prefSvc.getBranch("browser.bookmarks.sort.");
// Sorted! http://www.sorted.org.nz/
this.mOuter.sorted = true;
bookmarksSortPrefs.setCharPref("resource", aHeaderElement.getAttribute("sort"));
bookmarksSortPrefs.setCharPref("direction", aHeaderElement.getAttribute("sortDirection"));
},
onSelectionChanged: function ()
{
//dump("ONSELECTION CHANGED\n");
var selection = this.mOuter.getTreeSelection();
this.mOuter._selection = selection;
this.mOuter._target = this.mOuter.getTreeTarget(selection.item[0], selection.parent[0], BookmarksUtils.DROP_BEFORE);
this.mOuter.onCommandUpdate();
},
onCycleCell : function (aItemIndex, aColumnID) {},
onPerformAction : function (aAction) {},
onPerformActionOnRow : function (aAction, aItemIndex) {},
onPerformActionOnCell: function (aAction, aItemIndex, aColumnID) {}
})
]]></field>
<!-- nsITransactionManager listener -->
<field name="bookmarkTreeTransactionListener"><![CDATA[
({
mOuter: this,
mLastTxnWasDo: null,
willDo: function (aTxmgr, aTxn) {},
didDo : function (aTxmgr, aTxn) {
this.mLastTxnWasDo = true;
this.mOuter.preUpdateTreeSelection(aTxn, true);
},
willUndo: function (aTxmgr, aTxn) {},
didUndo : function (aTxmgr, aTxn) {
this.mLastTxnWasDo = false;
this.mOuter.preUpdateTreeSelection(aTxn, false);
},
willRedo: function (aTxmgr, aTxn) {},
didRedo : function (aTxmgr, aTxn) {
this.mLastTxnWasDo = true;
this.mOuter.preUpdateTreeSelection(aTxn, true);
},
didMerge : function (aTxmgr, aTxn) {},
didBeginBatch : function (aTxmgr, aTxn) {},
didEndBatch : function (aTxmgr, aTxn) {
this.mOuter.preUpdateTreeSelection(aTxn, this.mLastTxnWasDo);
},
willMerge : function (aTxmgr, aTxn) {},
willBeginBatch : function (aTxmgr, aTxn) {},
willEndBatch : function (aTxmgr, aTxn) {}
})
]]></field>
</implementation>
</binding>
<!-- Full Bookmarks Tree, multi-columned -->
<!-- Localize column labels! -->
<binding id="bookmarks-tree-full" extends="chrome://browser/content/bookmarks/bookmarksTree.xml#bookmarks-tree">
<xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:xbl="http://www.mozilla.org/xbl"
contextmenu="_child">
<!-- XXXben need focus event handler for cmd update -->
<!-- context menu -->
<menupopup onpopupshowing="this.parentNode.createTreeContextMenu(event);"
onpopuphidden="if (content) content.focus()"
onclick="event.stopPropagation();"
onkeypress="event.stopPropagation();"/>
<vbox flex="1">
<tree anonid="bookmarks-tree" flex="1" class="plain" enableColumnDrag="true"
datasources="rdf:bookmarks rdf:files rdf:localsearch" ref="NC:BookmarksTopRoot" flags="dont-build-content"
onkeypress="if (event.keyCode == 13) this.parentNode.parentNode.openItemKey();"
onclick="this.parentNode.parentNode.openItemClick(event, 1);"
ondblclick="this.parentNode.parentNode.openItemClick(event, 2);"
ondraggesture="if (event.originalTarget.localName == 'treechildren') nsDragAndDrop.startDrag(event, this.parentNode.parentNode.DNDObserver);"
onselect="this.treeBoxObject.view.selectionChanged();">
<template xmlns:nc="http://home.netscape.com/NC-rdf#">
<rule rdf:type="http://home.netscape.com/NC-rdf#BookmarkSeparator">
<treechildren>
<treeitem uri="rdf:*">
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type separator">
<treecell properties="separator" label="rdf:http://home.netscape.com/NC-rdf#Name"/>
</treerow>
</treeitem>
</treechildren>
</rule>
<rule rdf:type="http://home.netscape.com/NC-rdf#MicsumBookmark">
<treechildren>
<treeitem uri="rdf:*">
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type rdf:http://home.netscape.com/NC-rdf#loading rdf:http://home.netscape.com/WEB-rdf#status">
<treecell src="rdf:http://home.netscape.com/NC-rdf#Icon"
label="rdf:http://home.netscape.com/NC-rdf#GeneratedTitle"/>
<treecell label="rdf:http://home.netscape.com/NC-rdf#URL" />
<treecell label="rdf:http://home.netscape.com/NC-rdf#ShortcutURL" />
<treecell label="rdf:http://home.netscape.com/NC-rdf#Description" />
<treecell label="rdf:http://home.netscape.com/NC-rdf#BookmarkAddDate" />
<treecell label="rdf:http://home.netscape.com/WEB-rdf#LastModifiedDate" />
<treecell label="rdf:http://home.netscape.com/WEB-rdf#LastVisitDate"/>
</treerow>
</treeitem>
</treechildren>
</rule>
<rule>
<treechildren>
<treeitem uri="rdf:*">
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type rdf:http://home.netscape.com/NC-rdf#loading rdf:http://home.netscape.com/WEB-rdf#status">
<treecell src="rdf:http://home.netscape.com/NC-rdf#Icon"
label="rdf:http://home.netscape.com/NC-rdf#Name"/>
<treecell label="rdf:http://home.netscape.com/NC-rdf#URL" />
<treecell label="rdf:http://home.netscape.com/NC-rdf#ShortcutURL" />
<treecell label="rdf:http://home.netscape.com/NC-rdf#Description" />
<treecell label="rdf:http://home.netscape.com/NC-rdf#BookmarkAddDate" />
<treecell label="rdf:http://home.netscape.com/WEB-rdf#LastModifiedDate" />
<treecell label="rdf:http://home.netscape.com/WEB-rdf#LastVisitDate"/>
</treerow>
</treeitem>
</treechildren>
</rule>
</template>
<treecols anonid="treecols">
<treecol id="Name" label="&treecol.name.label;" flex="1" primary="true"
class="sortDirectionIndicator"
persist="width hidden ordinal"
sort="rdf:http://home.netscape.com/NC-rdf#Name"
sortActive="true" sortDirection="none"/>
<splitter class="tree-splitter" />
<treecol id="URL" label="&treecol.url.label;"
flex="1" class="sortDirectionIndicator"
sort="rdf:http://home.netscape.com/NC-rdf#URL"
persist="width hidden ordinal" />
<splitter class="tree-splitter" />
<treecol id="ShortcutURL" label="&treecol.shortcut.label;"
hidden="true" flex="1" class="sortDirectionIndicator"
persist="hidden width ordinal"
sort="rdf:http://home.netscape.com/NC-rdf#ShortcutURL"/>
<splitter class="tree-splitter"/>
<treecol id="Description" label="&treecol.description.label;"
flex="1" class="sortDirectionIndicator"
persist="hidden width ordinal"
sort="rdf:http://home.netscape.com/NC-rdf#Description"/>
<splitter class="tree-splitter"/>
<treecol id="AddDate" label="&treecol.addedon.label;"
hidden="true" flex="1" class="sortDirectionIndicator"
sort="rdf:http://home.netscape.com/NC-rdf#BookmarkAddDate"
persist="width hidden ordinal" />
<splitter class="tree-splitter" />
<treecol id="LastModDate" label="&treecol.lastmod.label;"
hidden="true" flex="1" class="sortDirectionIndicator"
sort="rdf:http://home.netscape.com/WEB-rdf#LastModifiedDate"
persist="width hidden ordinal" />
<splitter class="tree-splitter" />
<treecol id="LastVisitDate" label="&treecol.lastvisit.label;"
hidden="true" flex="1" class="sortDirectionIndicator"
sort="rdf:http://home.netscape.com/WEB-rdf#LastVisitDate"
persist="width hidden ordinal" />
</treecols>
</tree>
</vbox>
</xbl:content>
<implementation>
<constructor>
// Adding the transaction listener
var bkmkTxnSvc = Components.classes["@mozilla.org/bookmarks/transactionmanager;1"]
.getService(Components.interfaces.nsIBookmarkTransactionManager);
bkmkTxnSvc.transactionManager.AddListener(this.bookmarkTreeTransactionListener);
</constructor>
<destructor>
var bkmkTxnSvc = Components.classes["@mozilla.org/bookmarks/transactionmanager;1"]
.getService(Components.interfaces.nsIBookmarkTransactionManager);
bkmkTxnSvc.transactionManager.RemoveListener(this.bookmarkTreeTransactionListener);
</destructor>
<field name="clickCount">2</field>
</implementation>
</binding>
<!-- Single column tree -->
<binding id="bookmarks-tree-name" extends="chrome://browser/content/bookmarks/bookmarksTree.xml#bookmarks-tree">
<xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl" contextmenu="_child">
<!-- context menu -->
<menupopup xbl:inherits="onpopupshowing"
onpopupshowing="this.parentNode.createTreeContextMenu(event);"
onpopuphidden="if (content) content.focus()"
onclick="event.stopPropagation();"
onkeypress="event.stopPropagation();"/>
<tree anonid="bookmarks-tree" flex="1" class="plain" hidecolumnpicker="true"
datasources="rdf:bookmarks rdf:files rdf:localsearch" ref="NC:BookmarksRoot" flags="dont-build-content"
onselect="this.parentNode.treeBoxObject.view.selectionChanged();" seltype="single">
<template xmlns:nc="http://home.netscape.com/NC-rdf#">
<rule rdf:type="http://home.netscape.com/NC-rdf#BookmarkSeparator">
<treechildren>
<treeitem uri="rdf:*">
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type separator">
<treecell properties="separator" label="rdf:http://home.netscape.com/NC-rdf#Name"/>
</treerow>
</treeitem>
</treechildren>
</rule>
<rule rdf:type="http://home.netscape.com/NC-rdf#MicsumBookmark">
<treechildren>
<treeitem uri="rdf:*">
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type rdf:http://home.netscape.com/NC-rdf#loading rdf:http://home.netscape.com/WEB-rdf#status">
<treecell src="rdf:http://home.netscape.com/NC-rdf#Icon"
label="rdf:http://home.netscape.com/NC-rdf#GeneratedTitle"/>
</treerow>
</treeitem>
</treechildren>
</rule>
<rule>
<treechildren>
<treeitem uri="rdf:*">
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type rdf:http://home.netscape.com/NC-rdf#loading rdf:http://home.netscape.com/WEB-rdf#status">
<treecell src="rdf:http://home.netscape.com/NC-rdf#Icon"
label="rdf:http://home.netscape.com/NC-rdf#Name"/>
</treerow>
</treeitem>
</treechildren>
</rule>
</template>
<treecols anonid="treecols">
<treecol id="Name" flex="1" primary="true" hideheader="true"
sort="rdf:http://home.netscape.com/NC-rdf#Name"
sortActive="true" sortDirection="none"/>
</treecols>
</tree>
</xbl:content>
<implementation>
<field name="clickCount">1</field>
</implementation>
</binding>
<!-- Tree with folders only -->
<binding id="bookmarks-tree-folders" extends="chrome://browser/content/bookmarks/bookmarksTree.xml#bookmarks-tree">
<xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:xbl="http://www.mozilla.org/xbl">
<tree anonid="bookmarks-tree" class="bookmarksTree" flex="1" hidecolumnpicker="true"
xbl:inherits="rows,seltype"
datasources="rdf:bookmarks rdf:files rdf:localsearch" ref="NC:BookmarksTopRoot" flags="dont-build-content"
onselect="this.parentNode.treeBoxObject.view.selectionChanged();">
<template>
<!-- I don't want these things to appear at all, but that's not an option -->
<rule rdf:type="http://home.netscape.com/NC-rdf#Livemark">
<treechildren>
<treeitem uri="rdf:*">
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type rdf:http://home.netscape.com/NC-rdf#loading rdf:http://home.netscape.com/WEB-rdf#status">
<treecell label="rdf:http://home.netscape.com/NC-rdf#Name" />
</treerow>
</treeitem>
</treechildren>
</rule>
<rule iscontainer="true">
<treechildren>
<treeitem uri="rdf:*">
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type rdf:http://home.netscape.com/NC-rdf#loading rdf:http://home.netscape.com/WEB-rdf#status">
<treecell label="rdf:http://home.netscape.com/NC-rdf#Name" />
</treerow>
</treeitem>
</treechildren>
</rule>
</template>
<treecols anonid="treecols">
<treecol id="Name" flex="1" primary="true" hideheader="true"
sort="rdf:http://home.netscape.com/NC-rdf#Name"
sortActive="true" sortDirection="none"/>
</treecols>
</tree>
</xbl:content>
<implementation>
<field name="clickCount">2</field>
</implementation>
</binding>
</bindings>