gecko-dev/browser/components/places/content/tree.xml
2005-11-29 17:12:02 +00:00

497 lines
18 KiB
XML

<?xml version="1.0"?>
<bindings id="placesTreeBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="places-tree" extends="chrome://global/content/bindings/tree.xml#tree">
<implementation implements="nsINavHistoryResultViewObserver">
<constructor><![CDATA[
this._places =
Cc["@mozilla.org/browser/nav-history;1"].
getService(Ci.nsINavHistory);
// Let's all do the happy QI/IRQ dance.
// Go from window->docshell->window.
window.QueryInterface(Ci.nsIInterfaceRequestor);
var shell = window.getInterface(Ci.nsIWebNavigation);
shell.QueryInterface(Ci.nsIDocShell);
var item = shell.QueryInterface(Ci.nsIDocShellTreeItem);
while (item.parent)
item = item.parent;
item.QueryInterface(Ci.nsIInterfaceRequestor);
this._browserWindow = item.getInterface(Ci.nsIDOMWindowInternal);
this._bms =
Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
this._bms.addObserver(this._bookmarkObserver);
]]></constructor>
<destructor><![CDATA[
this._bms.removeObserver(this._bookmarkObserver);
]]></destructor>
<method name="_fireEvent">
<parameter name="name"/>
<body><![CDATA[
var event = document.createEvent("events");
event.initEvent("placestree-" + name, false, true);
var canceled = !this.dispatchEvent(event);
var handler = this.getAttribute("onplacestree" + name);
if (handler != "") {
var fn = new Function("event", handler);
if (!fn(event))
canceled = true;
}
return !canceled;
]]></body>
</method>
<!-- AVI Method -->
<method name="getResult">
<body><![CDATA[
try {
return this.view.QueryInterface(Ci.nsINavHistoryResult);
}
catch (e) {
}
]]></body>
</method>
<!-- overriding -->
<property name="view">
<getter><![CDATA[
return this.treeBoxObject.view;
]]></getter>
<setter><![CDATA[
// Make sure the last result doesn't hold a reference to us anymore
var result = this.getResult();
if (result)
result.removeObserver(this._viewObserver);
this.treeBoxObject.view = val;
this.getResult().addObserver(this._viewObserver);
]]></setter>
</property>
<method name="getBestOptions">
<body><![CDATA[
// Get the best set of grouping options to use, either reuse the
// existing ones or create new ones.
var options = this.getResult().queryOptions;
if (!options)
options = this._places.getNewQueryOptions();
return options;
]]></body>
</method>
<property name="filterString">
<getter><![CDATA[
var queries = this.getResult().getQueries({ });
if (queries[i].hasSearchTerms)
return queries[i].searchTerms;
return null;
]]></getter>
<setter><![CDATA[
var query = this._places.getNewQuery();
query.searchTerms = val;
this.load([query], this.getBestOptions());
return val;
]]></setter>
</property>
<method name="applyFilter">
<parameter name="filterString"/>
<parameter name="onlyBookmarks"/>
<parameter name="folderRestrict"/>
<body><![CDATA[
// preserve grouping
var options = this.getResult().queryOptions;
if (!options)
options = this._places.getNewQueryOptions();
var query = this._places.getNewQuery();
query.searchTerms = filterString;
query.onlyBookmarked = onlyBookmarks;
//if (onlyBookmarks)
// query.setFolders(folderRestrict, folderRestrict.length);
this.load([query], this.getBestOptions());
]]></body>
</method>
<property name="queryString">
<getter><![CDATA[
var result = this.getResult();
var queries = result.getQueries({ });
var options = result.queryOptions;
const NH = Ci.nsINavHistory;
return this._places.queriesToQueryString(queries, queries.length,
options);
]]></getter>
<setter><![CDATA[
var queries = { }, options = { };
this._places.queryStringToQueries(val, queries, { }, options);
if (!queries.value.length)
queries.value = [this._places.getNewQuery()];
this.load(queries.value, options.value);
return val;
]]></setter>
</property>
<method name="loadFolder">
<parameter name="folderId"/>
<parameter name="filterOptions"/>
<body><![CDATA[
var query = this._places.getNewQuery();
query.setFolders([folderId], 1);
if (filterOptions) {
query.itemTypes = filterOptions;
}
var options = this._places.getNewQueryOptions();
options.setGroupingMode([Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER], 1);
// options.setExpandPlaces(); ???
var result = this._places.executeQuery(query, options);
result.QueryInterface(Ci.nsITreeView);
this.view = result;
this._lastFilterOptions = filterOptions;
this._fireEvent("reloaded");
]]></body>
</method>
<method name="load">
<parameter name="queries"/>
<parameter name="options"/>
<body><![CDATA[
var result = this._places.executeQueries(queries, queries.length,
options);
result.QueryInterface(Ci.nsITreeView);
this.view = result;
this._fireEvent("reloaded");
]]></body>
</method>
<!-- AVI Method -->
<property name="hasSelection">
<getter><![CDATA[
return this.view.selection.count >= 1;
]]></getter>
</property>
<!-- AVI Method -->
<property name="hasSingleSelection">
<getter><![CDATA[
return this.view.selection.count == 1;
]]></getter>
</property>
<!-- AVI Method -->
<method name="getSelectionNodes">
<body><![CDATA[
var selection = this.view.selection;
var rc = selection.getRangeCount();
var nodes = [];
var result = this.getResult();
for (var i = 0; i < rc; ++i) {
var min = { }, max = { };
selection.getRangeAt(i, min, max);
for (var j = min.value; j <= max.value; ++j)
nodes.push(result.nodeForTreeIndex(j));
}
return nodes;
]]></body>
</method>
<!-- AVI Method -->
<method name="getCopyableSelection">
<body><![CDATA[
// XXXben implement me!
return this.getSelectionNodes();
]]></body>
</method>
<!-- AVI Method -->
<property name="selectedNode">
<getter><![CDATA[
var view = this.view;
var selection = view.selection;
var rc = selection.getRangeCount();
if (rc != 1)
return null;
var min = { }, max = { };
selection.getRangeAt(0, min, max);
return this.getResult().nodeForTreeIndex(min.value);
]]></getter>
</property>
<!-- AVI Method -->
<property name="selectedURLNode">
<getter><![CDATA[
var view = this.view;
var selection = view.selection;
var rc = selection.getRangeCount();
if (rc != 1)
return null;
var min = { }, max = { };
selection.getRangeAt(0, min, max);
// Cannot load containers
if (view.isContainer(min.value) || view.isSeparator(min.value))
return null;
return this.getResult().nodeForTreeIndex(min.value);
]]></getter>
</property>
<!-- AVI Method -->
<property name="insertionPoint">
<getter><![CDATA[
var selection = this.view.selection;
var rc = selection.getRangeCount();
var min = { }, max = { };
selection.getRangeAt(rc - 1, min, max);
return this._getInsertionPoint(max.value, 1);
]]></getter>
</property>
<method name="_getInsertionPoint">
<parameter name="index"/>
<parameter name="orientation"/>
<body><![CDATA[
const NHRVO = Ci.nsINavHistoryResultViewObserver;
var result = this.getResult();
var container = result;
// When there's no selection, assume the container is the container
// the view is populated from (i.e. the result's folderId).
if (index != -1) {
var lastSelected = result.nodeForTreeIndex(index);
if (this.view.isContainer(index) &&
(this.view.isContainerOpen(index) || orientation == NHRVO.DROP_ON)) {
// If the last selected item is an open container, append _into_
// it, rather than insert adjacent to it.
container = lastSelected;
index = -1;
}
else {
// Any visible selected item will always have a parent. The parent of
// an item at the root is the result itself, which can be QI'ed to
// nsINavHistoryResult
container = lastSelected.parent;
var lsi = PlacesController.getIndexOfNode(lastSelected);
if (lsi < container.childCount)
index = orientation == NHRVO.DROP_BEFORE ? lsi : lsi + 1;
else
index = orientation == NHRVO.DROP_BEFORE ? lsi - 1 : lsi;
}
}
return new InsertionPoint(container.folderId, index);
]]></body>
</method>
<!-- AVI Method -->
<property name="browserWindow" onget="return this._browserWindow"/>
<!-- AVI Method -->
<field name="firstDropIndex">null</field>
<!-- AVI Method -->
<field name="supportedDropTypes">null</field>
<!-- AVI Method -->
<field name="supportedDropOnTypes">null</field>
<!-- AVI Method -->
<method name="selectAll">
<body><![CDATA[
this.view.selection.selectAll();
]]></body>
</method>
<field name="_DNDObserver"><![CDATA[({
// XXXben ew.
_self: this,
onDragStart: function TV_DO_onDragStart(event, xferData, dragAction) {
if (this._self.getAttribute("sortActive") == "true")
throw Components.results.NS_OK;
xferData.data = PlacesController.getTransferData();
// XXXben - the drag wrapper should do this automatically.
if (event.ctrlKey)
dragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_COPY;
},
canDrop: function TV_DO_canDrop(event, session) {
return this._self._viewObserver.canDrop(-1, -1);
},
onDragOver: function TV_DO_onDragOver(event, flavor, session) {
},
getSupportedFlavours: function TV_DO_getSupportedFlavours() {
var flavorSet = new FlavourSet();
for (var i = 0; i < this._self.supportedDropTypes.length; ++i)
flavorSet.appendFlavour(this._self.supportedDropTypes[i]);
return flavorSet;
},
})]]></field>
<field name="_viewObserver"><![CDATA[({
_self: this,
canDrop: function VO_canDrop(index, orientation) {
var root = this._self.getResult();
var node = index != -1 ? root.nodeForTreeIndex(index) : root;
// Cannot drop before fixed items in the list.
if (node.parent == root &&
PlacesController.getIndexOfNode(node) < this._self.firstDropIndex &&
orientation != Ci.nsINavHistoryResultViewObserver.DROP_ON)
return false;
return PlacesControllerDragHelper.canDrop(this._self, orientation);
},
onDrop: function VO_onDrop(index, orientation) {
LOG("VO: onDrop: " + index + ", orientation: " + orientation);
if (!this.canDrop(index, orientation))
return;
// We are responsible for translating the |index| and |orientation|
// parameters into a container id and index within the container,
// since this information is specific to the tree view.
var ip = this._self._getInsertionPoint(index, orientation);
PlacesControllerDragHelper.onDrop(this._self, ip.folderId, ip.index,
orientation);
},
_states: { },
onToggleOpenState: function VO_onToggleOpenState(index) {
// XXXben we will probably have to implement this to refresh Live
// Bookmarks.
var view = this._self.view;
if (view.isContainer(index))
this._states[index] = view.isContainerOpen(index);
},
onSelectionChanged: function VO_onSelectionChanged() { },
onCycleHeader: function VO_onCycleHeader(column) { },
onCycleCell: function VO_onCycleCell(row, column) { },
onPerformAction: function VO_onPerformAction(action) { },
onPerformActionOnRow: function VO_onPerformActionOnRow(action, row) { },
onPerformActionOnCell: function VO_onPerformActionOnCell(action, row, column) { },
})]]></field>
<field name="_selection">null</field>
<method name="_saveSelection">
<body><![CDATA[
this._selection = [];
var selection = this.view.selection;
var rc = selection.getRangeCount();
for (var i = 0; i < rc; ++i) {
var min = { }, max = { };
selection.getRangeAt(i, min, max);
this._selection.push({ min: min.value, max: max.value });
}
]]></body>
</method>
<method name="_restoreSelection">
<body><![CDATA[
var selection = this.view.selection;
for (var i = 0; i < this._selection.length; ++i) {
var range = this._selection[i];
selection.rangedSelect(range.min, range.max, true);
}
]]></body>
</method>
<method name="_reloadView">
<body><![CDATA[
var result = this.getResult();
this._saveSelection();
if (PlacesController.nodeIsFolder(result))
this.loadFolder(result.folderId, this._lastFilterOptions);
else
this.load(result.getQueries({ }), result.queryOptions);
this._restoreSelection();
]]></body>
</method>
<!-- nsINavBookmarkObserver -->
<field name="_bookmarkObserver"><![CDATA[({
_numBatches: 0,
_self: this,
onBeginUpdateBatch: function PT_O_onBeginUpdateBatch() {
++this._numBatches;
},
onEndUpdateBatch: function PT_O_onEndUpdateBatch() {
if (!--this._numBatches)
this._self._reloadView();
},
get wantAllDetails() {
return false;
},
onItemAdded: function PT_O_onItemAdded(bookmark, folder, index) {
this._self._reloadView();
},
onItemRemoved: function PT_O_onItemRemoved(bookmark, folder, index) {
this._self._reloadView();
},
onItemMoved: function PT_O_onItemMoved(bookmark, folder, oldIndex, newIndex) {
this._self._reloadView();
},
onItemChanged: function PT_O_onItemChanged(bookmark, property) {
this._self._reloadView();
},
onFolderAdded: function PT_O_onFolderAdded(folder, parent, index) {
this._self._reloadView();
},
onFolderRemoved: function PT_O_onFolderRemoved(folder, parent, index) {
this._self._reloadView();
},
onFolderMoved: function PT_O_onFolderMoved(folder, oldParent, oldIndex, newParent, newIndex) {
this._self._reloadView();
},
onFolderChanged: function PT_O_onFolderChanged(folder, property) {
this._self._reloadView();
},
})]]></field>
</implementation>
<handlers>
<handler event="focus"><![CDATA[
PlacesController.activeView = this;
document.commandDispatcher.updateCommands("focus");
]]></handler>
<handler event="select"><![CDATA[
document.commandDispatcher.updateCommands("select");
]]></handler>
<handler event="click"><![CDATA[
if (this.getAttribute("singleclick") == "true") {
var view = this.view;
var selection = view.selection;
var rc = selection.getRangeCount();
if (rc != 1)
return null;
var min = { };
selection.getRangeAt(0, min, { });
if (!view.isContainerEmpty(min.value))
view.toggleOpenState(min.value);
}
]]></handler>
<handler event="draggesture"><![CDATA[
// XXXben ew.
if (event.target.localName == "treechildren")
nsDragAndDrop.startDrag(event, this._DNDObserver);
]]></handler>
<handler event="dragover"><![CDATA[
if (event.target.localName == "treechildren")
nsDragAndDrop.dragOver(event, this._DNDObserver);
]]></handler>
</handlers>
</binding>
</bindings>