Bug 1252211 - Convert XUL template builders to WebIDL. r=bz.

--HG--
rename : layout/xul/tree/nsITreeView.idl => dom/webidl/TreeView.webidl
rename : dom/xul/templates/nsIXULTemplateBuilder.idl => dom/webidl/XULTemplateBuilder.webidl
extra : rebase_source : 6788542d65fe446e851eebd4804d7dba428c8c84
extra : source : 599f27e86cb7ba543b4014c91be89c67225064ec
This commit is contained in:
Peter Van der Beken 2017-05-24 11:51:10 +02:00
parent 1b3cc60e04
commit 7c1c7552a6
24 changed files with 1723 additions and 642 deletions

View File

@ -76,7 +76,6 @@
#ifdef MOZ_XUL
#include "nsITreeContentView.h"
#include "nsITreeView.h"
#include "nsIXULTemplateBuilder.h"
#endif
#include "nsIEventListenerService.h"
@ -179,11 +178,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
#ifdef MOZ_XUL
NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(TreeContentView, nsDOMGenericSH,
DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULTemplateBuilder, nsDOMGenericSH,
DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULTreeBuilder, nsDOMGenericSH,
DEFAULT_SCRIPTABLE_FLAGS)
#endif
NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentFrameMessageManager,
@ -459,16 +453,6 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsITreeContentView)
DOM_CLASSINFO_MAP_ENTRY(nsITreeView)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(XULTemplateBuilder, nsIXULTemplateBuilder)
DOM_CLASSINFO_MAP_ENTRY(nsIXULTemplateBuilder)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(XULTreeBuilder, nsIXULTreeBuilder)
DOM_CLASSINFO_MAP_ENTRY(nsIXULTreeBuilder)
DOM_CLASSINFO_MAP_ENTRY(nsIXULTemplateBuilder)
DOM_CLASSINFO_MAP_ENTRY(nsITreeView)
DOM_CLASSINFO_MAP_END
#endif
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentFrameMessageManager, nsISupports)

View File

@ -24,11 +24,6 @@ enum nsDOMClassInfoID
eDOMClassInfo_TreeContentView_id,
#endif
#ifdef MOZ_XUL
eDOMClassInfo_XULTemplateBuilder_id,
eDOMClassInfo_XULTreeBuilder_id,
#endif
eDOMClassInfo_ContentFrameMessageManager_id,
eDOMClassInfo_ContentProcessMessageManager_id,
eDOMClassInfo_ChromeMessageBroadcaster_id,

View File

@ -1433,6 +1433,14 @@ DOMInterfaces = {
'nativeType': 'nsXULElement',
},
'XULTemplateBuilder': {
'nativeType': 'nsXULTemplateBuilder',
},
'XULTreeBuilder': {
'nativeType': 'nsXULTreeBuilder',
},
####################################
# Test Interfaces of various sorts #
####################################
@ -1739,7 +1747,6 @@ addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=Tru
addExternalIface('MozTreeView', nativeType='nsITreeView',
headerFile='nsITreeView.h', notflattened=True)
addExternalIface('MozWakeLockListener', headerFile='nsIDOMWakeLockListener.h')
addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder')
addExternalIface('nsIBrowserDOMWindow', nativeType='nsIBrowserDOMWindow',
notflattened=True)
addExternalIface('nsIDOMCrypto', nativeType='nsIDOMCrypto',
@ -1752,6 +1759,8 @@ addExternalIface('nsIMessageBroadcaster', nativeType='nsIMessageBroadcaster',
addExternalIface('nsISelectionListener', nativeType='nsISelectionListener')
addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
addExternalIface('nsITransportProvider', nativeType='nsITransportProvider')
addExternalIface('nsITreeSelection', nativeType='nsITreeSelection',
notflattened=True)
addExternalIface('nsISupports', nativeType='nsISupports')
addExternalIface('nsIDocShell', nativeType='nsIDocShell', notflattened=True)
addExternalIface('nsIEditor', nativeType='nsIEditor', notflattened=True)
@ -1766,3 +1775,7 @@ addExternalIface('StackFrame', nativeType='nsIStackFrame',
addExternalIface('URI', nativeType='nsIURI', headerFile='nsIURI.h',
notflattened=True)
addExternalIface('XULCommandDispatcher', notflattened=True)
addExternalIface('XULTemplateResult', nativeType='nsIXULTemplateResult',
notflattened=True)
addExternalIface('XULTemplateRuleFilter', nativeType='nsIXULTemplateRuleFilter',
notflattened=True)

View File

@ -1284,6 +1284,8 @@ var interfaceNamesInGlobalScope =
{name: "XULTemplateBuilder", xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XULTreeBuilder", xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XULTreeBuilderObserver", xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
];
// IMPORTANT: Do not change the list above without review from a DOM peer!

View File

@ -90,3 +90,4 @@ XMLHttpRequest implements LegacyQueryInterface;
XMLHttpRequestUpload implements LegacyQueryInterface;
XMLSerializer implements LegacyQueryInterface;
XPathEvaluator implements LegacyQueryInterface;
XULTemplateBuilder implements LegacyQueryInterface;

222
dom/webidl/TreeView.webidl Normal file
View File

@ -0,0 +1,222 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
interface nsITreeSelection;
[NoInterfaceObject]
interface TreeView
{
/**
* The total number of rows in the tree (including the offscreen rows).
*/
readonly attribute long rowCount;
/**
* The selection for this view.
*/
[SetterThrows]
attribute nsITreeSelection? selection;
/**
* A whitespace delimited list of properties. For each property X the view
* gives back will cause the pseudoclasses ::-moz-tree-cell(x),
* ::-moz-tree-row(x), ::-moz-tree-twisty(x), ::-moz-tree-image(x),
* ::-moz-tree-cell-text(x). to be matched on the pseudoelement
* ::moz-tree-row.
*/
[Throws]
DOMString getRowProperties(long row);
/**
* A whitespace delimited list of properties for a given cell. Each
* property, x, that the view gives back will cause the pseudoclasses
* ::-moz-tree-cell(x), ::-moz-tree-row(x), ::-moz-tree-twisty(x),
* ::-moz-tree-image(x), ::-moz-tree-cell-text(x). to be matched on the
* cell.
*/
[Throws]
DOMString getCellProperties(long row, TreeColumn column);
/**
* Called to get properties to paint a column background. For shading the sort
* column, etc.
*/
DOMString getColumnProperties(TreeColumn column);
/**
* Methods that can be used to test whether or not a twisty should be drawn,
* and if so, whether an open or closed twisty should be used.
*/
[Throws]
boolean isContainer(long row);
[Throws]
boolean isContainerOpen(long row);
[Throws]
boolean isContainerEmpty(long row);
/**
* isSeparator is used to determine if the row is a separator.
* A value of true will result in the tree drawing a horizontal separator.
* The tree uses the ::moz-tree-separator pseudoclass to draw the separator.
*/
[Throws]
boolean isSeparator(long row);
/**
* Specifies if there is currently a sort on any column. Used mostly by dragdrop
* to affect drop feedback.
*/
boolean isSorted();
const short DROP_BEFORE = -1;
const short DROP_ON = 0;
const short DROP_AFTER = 1;
/**
* Methods used by the drag feedback code to determine if a drag is allowable at
* the current location. To get the behavior where drops are only allowed on
* items, such as the mailNews folder pane, always return false when
* the orientation is not DROP_ON.
*/
[Throws]
boolean canDrop(long row, long orientation, DataTransfer? dataTransfer);
/**
* Called when the user drops something on this view. The |orientation| param
* specifies before/on/after the given |row|.
*/
[Throws]
void drop(long row, long orientation, DataTransfer? dataTransfer);
/**
* Methods used by the tree to draw thread lines in the tree.
* getParentIndex is used to obtain the index of a parent row.
* If there is no parent row, getParentIndex returns -1.
*/
[Throws]
long getParentIndex(long row);
/**
* hasNextSibling is used to determine if the row at rowIndex has a nextSibling
* that occurs *after* the index specified by afterIndex. Code that is forced
* to march down the view looking at levels can optimize the march by starting
* at afterIndex+1.
*/
[Throws]
boolean hasNextSibling(long row, long afterIndex);
/**
* The level is an integer value that represents
* the level of indentation. It is multiplied by the width specified in the
* :moz-tree-indentation pseudoelement to compute the exact indendation.
*/
[Throws]
long getLevel(long row);
/**
* The image path for a given cell. For defining an icon for a cell.
* If the empty string is returned, the :moz-tree-image pseudoelement
* will be used.
*/
[Throws]
DOMString getImageSrc(long row, TreeColumn column);
/**
* The progress mode for a given cell. This method is only called for
* columns of type |progressmeter|.
*/
const short PROGRESS_NORMAL = 1;
const short PROGRESS_UNDETERMINED = 2;
const short PROGRESS_NONE = 3;
[Throws]
long getProgressMode(long row, TreeColumn column);
/**
* The value for a given cell. This method is only called for columns
* of type other than |text|.
*/
[Throws]
DOMString getCellValue(long row, TreeColumn column);
/**
* The text for a given cell. If a column consists only of an image, then
* the empty string is returned.
*/
[Throws]
DOMString getCellText(long row, TreeColumn column);
/**
* Called during initialization to link the view to the front end box object.
*/
[Throws]
void setTree(TreeBoxObject? tree);
/**
* Called on the view when an item is opened or closed.
*/
[Throws]
void toggleOpenState(long row);
/**
* Called on the view when a header is clicked.
*/
[Throws]
void cycleHeader(TreeColumn column);
/**
* Should be called from a XUL onselect handler whenever the selection changes.
*/
void selectionChanged();
/**
* Called on the view when a cell in a non-selectable cycling column (e.g., unread/flag/etc.) is clicked.
*/
void cycleCell(long row, TreeColumn column);
/**
* isEditable is called to ask the view if the cell contents are editable.
* A value of true will result in the tree popping up a text field when
* the user tries to inline edit the cell.
*/
[Throws]
boolean isEditable(long row, TreeColumn column);
/**
* isSelectable is called to ask the view if the cell is selectable.
* This method is only called if the selection style is |cell| or |text|.
* XXXvarga shouldn't this be called isCellSelectable?
*/
[Throws]
boolean isSelectable(long row, TreeColumn column);
/**
* setCellValue is called when the value of the cell has been set by the user.
* This method is only called for columns of type other than |text|.
*/
[Throws]
void setCellValue(long row, TreeColumn column, DOMString value);
/**
* setCellText is called when the contents of the cell have been edited by the user.
*/
[Throws]
void setCellText(long row, TreeColumn column, DOMString value);
/**
* A command API that can be used to invoke commands on the selection. The tree
* will automatically invoke this method when certain keys are pressed. For example,
* when the DEL key is pressed, performAction will be called with the "delete" string.
*/
void performAction(DOMString action);
/**
* A command API that can be used to invoke commands on a specific row.
*/
void performActionOnRow(DOMString action, long row);
/**
* A command API that can be used to invoke commands on a specific cell.
*/
void performActionOnCell(DOMString action, long row, TreeColumn column);
};

View File

@ -8,7 +8,6 @@ interface XULControllers;
interface MozFrameLoader;
interface MozRDFCompositeDataSource;
interface MozRDFResource;
interface MozXULTemplateBuilder;
[Func="IsChromeOrXBL"]
interface XULElement : Element {
@ -85,7 +84,7 @@ interface XULElement : Element {
attribute boolean allowEvents;
readonly attribute MozRDFCompositeDataSource? database;
readonly attribute MozXULTemplateBuilder? builder;
readonly attribute XULTemplateBuilder? builder;
[Throws]
readonly attribute MozRDFResource? resource;
[Throws, ChromeOnly]

View File

@ -0,0 +1,398 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
interface MozRDFCompositeDataSource;
interface MozRDFResource;
interface nsISupports;
interface XULTemplateResult;
interface XULTemplateRuleFilter;
callback interface XULBuilderListener
{
void willRebuild(XULTemplateBuilder aBuilder);
void didRebuild(XULTemplateBuilder aBuilder);
};
/**
* A template builder, given an input source of data, a template, and a
* reference point, generates a list of results from the input, and copies
* part of the template for each result. Templates may generate content
* recursively, using the same template, but with the previous iteration's
* results as the reference point. As an example, for an XML datasource the
* initial reference point would be a specific node in the DOM tree and a
* template might generate a list of all child nodes. For the next iteration,
* those children would be used to generate output for their child nodes and
* so forth.
*
* A template builder is attached to a single DOM node; this node is called
* the root node and is expected to contain a XUL template element as a direct
* child. Different template builders may be specialized in the manner in
* which they generate and display the resulting content from the template.
*
* The structure of a template is as follows:
*
* <rootnode datasources="" ref="">
* <template>
* <queryset>
* <query>
* </query>
* <rule>
* <conditions>...</conditions>
* <bindings>...</bindings>
* <action>...</action>
* </rule>
* </queryset>
* </template>
* </rootnode>
*
* The datasources attribute on the root node is used to identify the source
* of data to be used. The ref attribute is used to specify the reference
* point for the query. Currently, the datasource will either be an
* nsIRDFDataSource or a DOM node. In the future, other datasource types may
* be used.
*
* The <queryset> element contains a single query and one or more <rule>
* elements. There may be more than one <queryset> if multiple queries are
* desired, and this element is optional if only one query is needed -- in
* that case the <query> and <rule>s are allowed to be children of the
* <template> node
*
* The contents of the query are processed by a separate component called a
* query processor. This query processor is expected to use this query to
* generate results when asked by the template builder. The template builder
* then generates output for each result based on the <rule> elements.
*
* This allows the query processor to be specific to a particular kind of
* input data or query syntax, while the template builder remains independent
* of the kind of data being used. Due to this, the query processor will be
* supplied with the datasource and query which the template builder handles
* in an opaque way, while the query processor handles these more
* specifically.
*
* Results implement the nsIXULTemplateResult interface and may be identified
* by an id which must be unique within a given set of query results.
*
* Each query may be accompanied by one or more <rule> elements. These rules
* are evaluated by the template builder for each result produced by the
* query. A rule consists of conditions that cause a rule to be either
* accepted or rejected. The condition syntax allows for common conditional
* handling; additional filtering may be applied by adding a custom filter
* to a rule with the builder's addRuleFilter method.
*
* If a result passes a rule's conditions, this is considered a match, and the
* content within the rule's <action> body is inserted as a sibling of the
* <template>, assuming the template builder creates real DOM content. Only
* one rule will match a result. For a tree builder, for example, the content
* within the action body is used to create the tree rows instead. A matching
* result must have its ruleMatched method called. When a result no longer
* matches, the result's hasBeenRemoved method must be called.
*
* Optionally, the rule may have a <bindings> section which may be used to
* define additional variables to be used within an action body. Each of these
* declared bindings must be supplied to the query processor via its
* addBinding method. The bindings are evaluated after a rule has matched.
*
* Templates may generate content recursively, using the previous iteration's
* results as reference point to invoke the same queries. Since the reference
* point is different, different output will typically be generated.
*
* The reference point nsIXULTemplateResult object for the first iteration is
* determined by calling the query processor's translateRef method using the
* value of the root node's ref attribute. This object may be retrieved later
* via the builder's rootResult property.
*
* For convenience, each reference point as well as all results implement the
* nsIXULTemplateResult interface, allowing the result objects from each
* iteration to be used directly as the reference points for the next
* iteration.
*
* When using multiple queries, each may generate results with the same id.
* More than one of these results may match one of the rules in their
* respective queries, however only the result for the earliest matching query
* in the template becomes the active match and generates output. The
* addResult, removeResult, replaceResult and resultBindingChanged methods may
* be called by the query processor to indicate that the set of valid results
* has changed, such that a different query may match. If a different match
* would become active, the content for the existing match is removed and the
* content for the new match is generated. A query processor is not required
* to provide any support for updating results after they have been generated.
*
* See http://wiki.mozilla.org/XUL:Templates_Plan for details about templates.
*/
[Func="IsChromeOrXBL"]
interface XULTemplateBuilder
{
/**
* The root node in the DOM to which this builder is attached.
*/
readonly attribute Element? root;
/**
* The opaque datasource object that is used for the template. This object
* is created by the getDataSource method of the query processor. May be
* null if the datasource has not been loaded yet. Set this attribute to
* use a different datasource and rebuild the template.
*
* For an RDF datasource, this will be the same as the database. For XML
* this will be the nsIDOMNode for the datasource document or node for
* an inline reference (such as #name). Other query processors may use
* other types for the datasource.
*/
[SetterThrows]
attribute nsISupports? datasource;
/**
* The composite datasource that the template builder observes
* and uses to create content. This is used only for RDF queries and is
* maintained for backwards compatibility. It will be the same object as
* the datasource property. For non-RDF queries, it will always be null.
*/
readonly attribute MozRDFCompositeDataSource? database;
/**
* The virtual result representing the starting reference point,
* determined by calling the query processor's translateRef method
* with the root node's ref attribute as an argument.
*/
readonly attribute XULTemplateResult? rootResult;
/**
* Force the template builder to rebuild its content. All existing content
* will be removed first. The query processor's done() method will be
* invoked during cleanup, followed by its initializeForBuilding method
* when the content is to be regenerated.
*
*/
[Throws]
void rebuild();
/**
* Reload any of our RDF datasources that support nsIRDFRemoteDatasource.
*
* @note This is a temporary hack so that remote-XUL authors can
* reload remote datasources. When RDF becomes remote-scriptable,
* this will no longer be necessary.
*/
[Throws]
void refresh();
/**
* Inform the template builder that a new result is available. The builder
* will add this result to the set of results. The query node that the
* new result applies to must be specified using the aQueryNode parameter.
*
* The builder will apply the rules associated with the query to the new
* result, unless a result with the same id from an earlier query
* supersedes it, and the result's RuleMatched method will be called if it
* matches.
*
* @param aResult the result to add
* @param aQueryNode the query that the result applies to
*/
[Throws]
void addResult(XULTemplateResult aResult, Node aQueryNode);
/**
* Inform the template builder that a result no longer applies. The builder
* will call the remove content generated for the result, if any. If a
* different query would then match instead, it will become the active
* match. This method will have no effect if the result isn't known to the
* builder.
*
* @param aResult the result to remove
*
* @throws NS_ERROR_NULL_POINTER if aResult is null
*/
[Throws]
void removeResult(XULTemplateResult aResult);
/**
* Inform the template builder that one result should be replaced with
* another. Both the old result (aOldResult) and the new result
* (aNewResult) must have the same id. The query node that the new result
* applies to must be specified using the aQueryNode parameter.
*
* This method is expected to have the same effect as calling both
* removeResult for the old result and addResult for the new result.
*
* @param aOldResult the old result
* @param aNewResult the new result
* @param aQueryNode the query that the new result applies to
*
* @throws NS_ERROR_NULL_POINTER if either argument is null, or
* NS_ERROR_INVALID_ARG if the ids don't match
*/
[Throws]
void replaceResult(XULTemplateResult aOldResult,
XULTemplateResult aNewResult,
Node aQueryNode);
/**
* Inform the template builder that one or more of the optional bindings
* for a result has changed. In this case, the rules are not reapplied as
* it is expected that the same rule will still apply. The builder will
* resynchronize any variables that are referenced in the action body.
*
* @param aResult the result to change
*
* @throws NS_ERROR_NULL_POINTER if aResult is null
*/
[Throws]
void resultBindingChanged(XULTemplateResult aResult);
/**
* Return the result for a given id. Only one such result is returned and
* is always the result with that id associated with the active match.
* This method will return null is there is no result for the id.
*
* @param aId the id to return the result for
*/
[Throws]
XULTemplateResult? getResultForId(DOMString aId);
/**
* Retrieve the result corresponding to a generated element, or null is
* there isn't one.
*
* @param aContent element to result the result of
*/
XULTemplateResult? getResultForContent(Element aElement);
/**
* Returns true if the node has content generated for it. This method is
* intended to be called only by the RDF query processor. If aTag is set,
* the content must have a tag name that matches aTag. aTag may be ignored
* for builders that don't generate real DOM content.
*
* @param aNode node to check
* @param aTag tag that must match
*/
[Throws]
boolean hasGeneratedContent(MozRDFResource aNode, DOMString? aTag);
/**
* Adds a rule filter for a given rule, which may be used for specialized
* rule filtering. Any existing filter on the rule is removed. The default
* conditions specified inside the <rule> tag are applied before the
* rule filter is applied, meaning that the filter may be used to further
* filter out results but not reaccept results that have already been
* rejected.
*
* @param aRule the rule to apply the filter to
* @param aFilter the filter to add
*/
[Throws]
void addRuleFilter(Node aRule, XULTemplateRuleFilter aFilter);
/**
* Add a listener to this template builder. The template builder
* holds a strong reference to the listener.
*/
void addListener(XULBuilderListener aListener);
/**
* Remove a listener from this template builder.
*/
void removeListener(XULBuilderListener aListener);
};
/**
* XULTreeBuilderObserver
* This interface allows clients of the XULTreeBuilder to define domain
* specific handling of specific nsITreeView methods that
* XULTreeBuilder does not implement.
*/
[Func="IsChromeOrXBL"]
callback interface XULTreeBuilderObserver
{
const long DROP_BEFORE = -1;
const long DROP_ON = 0;
const long DROP_AFTER = 1;
/**
* Methods used by the drag feedback code to determine if a drag is
* allowable at the current location. To get the behavior where drops are
* only allowed on items, such as the mailNews folder pane, always return
* false when the orientation is not DROP_ON.
*/
boolean canDrop(long index, long orientation, DataTransfer? dataTransfer);
/**
* Called when the user drops something on this view. The |orientation|
* param specifies before/on/after the given |row|.
*/
void onDrop(long row, long orientation, DataTransfer? dataTransfer);
/**
* Called when an item is opened or closed.
*/
void onToggleOpenState(long index);
/**
* Called when a header is clicked.
*/
void onCycleHeader(DOMString colID, Element? elt);
/**
* Called when a cell in a non-selectable cycling column (e.g.
* unread/flag/etc.) is clicked.
*/
void onCycleCell(long row, DOMString colID);
/**
* Called when selection in the tree changes
*/
void onSelectionChanged();
/**
* A command API that can be used to invoke commands on the selection.
* The tree will automatically invoke this method when certain keys
* are pressed. For example, when the DEL key is pressed, performAction
* will be called with the "delete" string.
*/
void onPerformAction(DOMString action);
/**
* A command API that can be used to invoke commands on a specific row.
*/
void onPerformActionOnRow(DOMString action, long row);
/**
* A command API that can be used to invoke commands on a specific cell.
*/
void onPerformActionOnCell(DOMString action, long row, DOMString colID);
};
[Func="IsChromeOrXBL"]
interface XULTreeBuilder : XULTemplateBuilder
{
/**
* Retrieve the RDF resource associated with the specified row.
*/
[Throws]
MozRDFResource? getResourceAtIndex(long aRowIndex);
/**
* Retrieve the index associated with specified RDF resource.
*/
[Throws]
long getIndexOfResource(MozRDFResource resource);
/**
* Add a Tree Builder Observer to handle Tree View
* methods that the base builder does not implement.
*/
void addObserver(XULTreeBuilderObserver aObserver);
/**
* Remove an Tree Builder Observer.
*/
void removeObserver(XULTreeBuilderObserver aObserver);
/**
* Sort the contents of the tree using the specified column.
*/
void sort(Element aColumnElement);
};
XULTreeBuilder implements TreeView;

View File

@ -926,6 +926,7 @@ WEBIDL_FILES = [
'TreeBoxObject.webidl',
'TreeColumn.webidl',
'TreeColumns.webidl',
'TreeView.webidl',
'TreeWalker.webidl',
'U2F.webidl',
'UDPMessageEvent.webidl',
@ -977,6 +978,7 @@ WEBIDL_FILES = [
'XULCommandEvent.webidl',
'XULDocument.webidl',
'XULElement.webidl',
'XULTemplateBuilder.webidl',
]
if CONFIG['MOZ_WEBRTC']:

View File

@ -96,6 +96,8 @@
#include "xpcpublic.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"
#include "nsXULTemplateBuilder.h"
#include "nsXULTreeBuilder.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -3658,7 +3660,7 @@ XULDocument::CheckTemplateBuilderHookup(nsIContent* aElement,
}
/* static */ nsresult
XULDocument::CreateTemplateBuilder(nsIContent* aElement)
XULDocument::CreateTemplateBuilder(Element* aElement)
{
// Check if need to construct a tree builder or content builder.
bool isTreeBuilder = false;
@ -3687,13 +3689,9 @@ XULDocument::CreateTemplateBuilder(nsIContent* aElement)
if (isTreeBuilder) {
// Create and initialize a tree builder.
nsCOMPtr<nsIXULTemplateBuilder> builder =
do_CreateInstance("@mozilla.org/xul/xul-tree-builder;1");
if (! builder)
return NS_ERROR_FAILURE;
builder->Init(aElement);
RefPtr<nsXULTreeBuilder> builder = new nsXULTreeBuilder(aElement);
nsresult rv = builder->Init();
NS_ENSURE_SUCCESS(rv, rv);
// Create a <treechildren> if one isn't there already.
// XXXvarga what about attributes?
@ -3712,13 +3710,10 @@ XULDocument::CreateTemplateBuilder(nsIContent* aElement)
}
else {
// Create and initialize a content builder.
nsCOMPtr<nsIXULTemplateBuilder> builder
= do_CreateInstance("@mozilla.org/xul/xul-template-builder;1");
nsCOMPtr<nsIXULTemplateBuilder> builder;
nsresult rv = NS_NewXULContentBuilder(aElement, getter_AddRefs(builder));
NS_ENSURE_SUCCESS(rv, rv);
if (! builder)
return NS_ERROR_FAILURE;
builder->Init(aElement);
builder->CreateContents(aElement, false);
}

View File

@ -474,7 +474,7 @@ protected:
* Create a XUL template builder on the specified node.
*/
static nsresult
CreateTemplateBuilder(nsIContent* aElement);
CreateTemplateBuilder(Element* aElement);
/**
* Add the current prototype's style sheets (currently it's just
@ -566,10 +566,10 @@ protected:
class TemplateBuilderHookup : public nsForwardReference
{
protected:
nsCOMPtr<nsIContent> mElement; // [OWNER]
nsCOMPtr<Element> mElement; // [OWNER]
public:
explicit TemplateBuilderHookup(nsIContent* aElement)
explicit TemplateBuilderHookup(Element* aElement)
: mElement(aElement) {}
virtual Phase GetPhase() override { return eHookup; }

View File

@ -17,6 +17,12 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'xultmpl'
EXPORTS += [
'nsTreeRows.h',
'nsXULTemplateBuilder.h',
'nsXULTreeBuilder.h',
]
UNIFIED_SOURCES += [
'nsContentSupportMap.cpp',
'nsContentTestNode.cpp',

View File

@ -282,14 +282,6 @@ interface nsIXULTemplateBuilder : nsISupports
*/
void addRuleFilter(in nsIDOMNode aRule, in nsIXULTemplateRuleFilter aFilter);
/**
* Called to initialize a XUL content builder on a particular root
* element. This element presumably has a ``datasources''
* attribute, which the builder will parse to set up the template
* builder's datasources.
*/
[noscript] void init(in nsIContent aElement);
/**
* Invoked lazily by a XUL element that needs its child content built.
* If aForceCreation is true, then the contents of an element will be

View File

@ -27,7 +27,7 @@ public:
Put(nsIContent* aContent, nsIContent* aTemplate) {
NS_ASSERTION(!mTable.Search(aContent), "aContent already in map");
auto entry = static_cast<Entry*>(mTable.Add(aContent, fallible));
auto entry = static_cast<Entry*>(mTable.Add(aContent, mozilla::fallible));
if (entry) {
entry->mContent = aContent;

View File

@ -10,9 +10,9 @@
#include "nsTArray.h"
#include "PLDHashTable.h"
#include "nsIXULTemplateResult.h"
#include "nsTemplateMatch.h"
#include "nsIRDFResource.h"
class nsTemplateMatch;
/**
* This class maintains the state of the XUL tree builder's

View File

@ -74,12 +74,13 @@ public:
// nsIXULTemplateBuilder interface
NS_IMETHOD CreateContents(nsIContent* aElement, bool aForceCreation) override;
NS_IMETHOD HasGeneratedContent(nsIRDFResource* aResource,
nsIAtom* aTag,
bool* aGenerated) override;
using nsIXULTemplateBuilder::HasGeneratedContent;
bool HasGeneratedContent(nsIRDFResource* aResource,
const nsAString& aTag,
ErrorResult& aError) override;
NS_IMETHOD GetResultForContent(nsIDOMElement* aContent,
nsIXULTemplateResult** aResult) override;
using nsIXULTemplateBuilder::GetResultForContent;
nsIXULTemplateResult* GetResultForContent(Element& aElement) override;
// nsIMutationObserver interface
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
@ -87,9 +88,9 @@ public:
protected:
friend nsresult
NS_NewXULContentBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult);
NS_NewXULContentBuilder(Element* aElement, nsIXULTemplateBuilder** aBuilder);
nsXULContentBuilder();
explicit nsXULContentBuilder(Element* aElement);
void Traverse(nsCycleCollectionTraversalCallback& aCb) const override
{
@ -340,26 +341,18 @@ protected:
};
nsresult
NS_NewXULContentBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult)
NS_NewXULContentBuilder(Element* aElement, nsIXULTemplateBuilder** aBuilder)
{
NS_PRECONDITION(aOuter == nullptr, "no aggregation");
if (aOuter)
return NS_ERROR_NO_AGGREGATION;
RefPtr<nsXULContentBuilder> builder = new nsXULContentBuilder(aElement);
nsresult rv = builder->Init();
NS_ENSURE_SUCCESS(rv, rv);
nsresult rv;
nsXULContentBuilder* result = new nsXULContentBuilder();
NS_ADDREF(result); // stabilize
rv = result->InitGlobals();
if (NS_SUCCEEDED(rv))
rv = result->QueryInterface(aIID, aResult);
NS_RELEASE(result);
return rv;
builder.forget(aBuilder);
return NS_OK;
}
nsXULContentBuilder::nsXULContentBuilder()
nsXULContentBuilder::nsXULContentBuilder(Element* aElement)
: nsXULTemplateBuilder(aElement)
{
mSortState.initialized = false;
}
@ -1418,83 +1411,71 @@ nsXULContentBuilder::CreateContents(nsIContent* aElement, bool aForceCreation)
return CreateTemplateAndContainerContents(aElement, aForceCreation);
}
NS_IMETHODIMP
bool
nsXULContentBuilder::HasGeneratedContent(nsIRDFResource* aResource,
nsIAtom* aTag,
bool* aGenerated)
const nsAString& aTag,
ErrorResult& aError)
{
*aGenerated = false;
NS_ENSURE_TRUE(mRoot, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_STATE(mRootResult);
if (!mRoot || !mRootResult) {
aError.Throw(NS_ERROR_NOT_INITIALIZED);
return false;
}
nsCOMPtr<nsIRDFResource> rootresource;
nsresult rv = mRootResult->GetResource(getter_AddRefs(rootresource));
if (NS_FAILED(rv))
return rv;
aError = mRootResult->GetResource(getter_AddRefs(rootresource));
if (aError.Failed()) {
return false;
}
// the root resource is always acceptable
if (aResource == rootresource) {
if (!aTag || mRoot->NodeInfo()->NameAtom() == aTag)
*aGenerated = true;
return DOMStringIsNull(aTag) || mRoot->NodeInfo()->LocalName().Equals(aTag);
}
else {
const char* uri;
aResource->GetValueConst(&uri);
NS_ConvertUTF8toUTF16 refID(uri);
const char* uri;
aResource->GetValueConst(&uri);
// just return if the node is no longer in a document
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mRoot->GetComposedDoc());
if (! xuldoc)
return NS_OK;
NS_ConvertUTF8toUTF16 refID(uri);
nsCOMArray<nsIContent> elements;
xuldoc->GetElementsForID(refID, elements);
// just return if the node is no longer in a document
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mRoot->GetComposedDoc());
if (!xuldoc) {
return false;
}
uint32_t cnt = elements.Count();
nsCOMArray<nsIContent> elements;
xuldoc->GetElementsForID(refID, elements);
for (int32_t i = int32_t(cnt) - 1; i >= 0; --i) {
nsCOMPtr<nsIContent> content = elements.SafeObjectAt(i);
uint32_t cnt = elements.Count();
do {
nsTemplateMatch* match;
if (content == mRoot || mContentSupportMap.Get(content, &match)) {
// If we've got a tag, check it to ensure we're consistent.
if (!aTag || content->NodeInfo()->NameAtom() == aTag) {
*aGenerated = true;
return NS_OK;
}
for (int32_t i = int32_t(cnt) - 1; i >= 0; --i) {
nsCOMPtr<nsIContent> content = elements.SafeObjectAt(i);
do {
nsTemplateMatch* match;
if (content == mRoot || mContentSupportMap.Get(content, &match)) {
// If we've got a tag, check it to ensure we're consistent.
if (DOMStringIsNull(aTag) || content->NodeInfo()->LocalName().Equals(aTag)) {
return true;
}
}
content = content->GetParent();
} while (content);
}
content = content->GetParent();
} while (content);
}
return NS_OK;
return false;
}
NS_IMETHODIMP
nsXULContentBuilder::GetResultForContent(nsIDOMElement* aElement,
nsIXULTemplateResult** aResult)
nsIXULTemplateResult*
nsXULContentBuilder::GetResultForContent(Element& aElement)
{
NS_ENSURE_ARG_POINTER(aElement);
NS_ENSURE_ARG_POINTER(aResult);
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
if (content == mRoot) {
*aResult = mRootResult;
}
else {
nsTemplateMatch *match = nullptr;
if (mContentSupportMap.Get(content, &match))
*aResult = match->mResult;
else
*aResult = nullptr;
if (&aElement == mRoot) {
return mRootResult;
}
NS_IF_ADDREF(*aResult);
return NS_OK;
nsTemplateMatch* match;
return mContentSupportMap.Get(&aElement, &match) ? match->mResult.get() : nullptr;
}
//----------------------------------------------------------------------

View File

@ -35,10 +35,12 @@
#include "nsIXULDocument.h"
#include "nsIXULTemplateBuilder.h"
#include "nsIXULBuilderListener.h"
#include "nsIRDFCompositeDataSource.h"
#include "nsIRDFRemoteDataSource.h"
#include "nsIRDFService.h"
#include "nsIScriptContext.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptSecurityManager.h"
#include "nsIServiceManager.h"
#include "nsISimpleEnumerator.h"
#include "nsIMutableArray.h"
@ -50,6 +52,8 @@
#include "nsXULContentUtils.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsTemplateMatch.h"
#include "nsTemplateRule.h"
#include "nsXPIDLString.h"
#include "nsWhitespaceTokenizer.h"
#include "nsGkAtoms.h"
@ -59,7 +63,6 @@
#include "rdf.h"
#include "PLDHashTable.h"
#include "plhash.h"
#include "nsDOMClassInfoID.h"
#include "nsPIDOMWindow.h"
#include "nsIConsoleService.h"
#include "nsNetUtil.h"
@ -70,6 +73,7 @@
#include "nsContentUtils.h"
#include "ChildIterator.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/XULTemplateBuilderBinding.h"
#include "nsGlobalWindow.h"
using namespace mozilla::dom;
@ -96,8 +100,9 @@ LazyLogModule gXULTemplateLog("nsXULTemplateBuilder");
// nsXULTemplateBuilder methods
//
nsXULTemplateBuilder::nsXULTemplateBuilder(void)
: mQueriesCompiled(false),
nsXULTemplateBuilder::nsXULTemplateBuilder(Element* aElement)
: mRoot(aElement),
mQueriesCompiled(false),
mFlags(0),
mTop(nullptr),
mObservedDocument(nullptr)
@ -226,6 +231,7 @@ nsXULTemplateBuilder::Uninit(bool aIsFinal)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateBuilder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateBuilder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDataSource)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDB)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCompDB)
@ -278,19 +284,27 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateBuilder)
}
tmp->Traverse(cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsXULTemplateBuilder)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULTemplateBuilder)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULTemplateBuilder)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULTemplateBuilder)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIXULTemplateBuilder)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULTemplateBuilder)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULTemplateBuilder)
NS_INTERFACE_MAP_END
JSObject*
nsXULTemplateBuilder::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return XULTemplateBuilderBinding::Wrap(aCx, this, aGivenProto);
}
//----------------------------------------------------------------------
//
// nsIXULTemplateBuilder methods
@ -299,36 +313,46 @@ NS_INTERFACE_MAP_END
NS_IMETHODIMP
nsXULTemplateBuilder::GetRoot(nsIDOMElement** aResult)
{
if (mRoot) {
return CallQueryInterface(mRoot, aResult);
}
*aResult = nullptr;
nsCOMPtr<nsIDOMElement> result = do_QueryInterface(GetRoot());
result.forget(aResult);
return NS_OK;
}
nsISupports*
nsXULTemplateBuilder::GetDatasource()
{
return mCompDB ? mCompDB : mDataSource;
}
NS_IMETHODIMP
nsXULTemplateBuilder::GetDatasource(nsISupports** aResult)
{
if (mCompDB)
NS_ADDREF(*aResult = mCompDB);
else
NS_IF_ADDREF(*aResult = mDataSource);
NS_IF_ADDREF(*aResult = GetDatasource());
return NS_OK;
}
void
nsXULTemplateBuilder::SetDatasource(nsISupports* aDatasource,
ErrorResult& aError)
{
mDataSource = aDatasource;
mCompDB = do_QueryInterface(mDataSource);
aError = Rebuild();
}
NS_IMETHODIMP
nsXULTemplateBuilder::SetDatasource(nsISupports* aResult)
{
mDataSource = aResult;
mCompDB = do_QueryInterface(mDataSource);
return Rebuild();
ErrorResult rv;
SetDatasource(aResult, rv);
return rv.StealNSResult();
}
NS_IMETHODIMP
nsXULTemplateBuilder::GetDatabase(nsIRDFCompositeDataSource** aResult)
{
NS_IF_ADDREF(*aResult = mCompDB);
NS_IF_ADDREF(*aResult = GetDatabase());
return NS_OK;
}
@ -339,16 +363,16 @@ nsXULTemplateBuilder::GetQueryProcessor(nsIXULTemplateQueryProcessor** aResult)
return NS_OK;
}
NS_IMETHODIMP
nsXULTemplateBuilder::AddRuleFilter(nsIDOMNode* aRule, nsIXULTemplateRuleFilter* aFilter)
void
nsXULTemplateBuilder::AddRuleFilter(nsINode& aRule,
nsIXULTemplateRuleFilter* aFilter,
ErrorResult& aError)
{
if (!aRule || !aFilter)
return NS_ERROR_NULL_POINTER;
// a custom rule filter may be added, one for each rule. If a new one is
// added, it replaces the old one. Look for the right rule and set its
// filter
nsIDOMNode* ruleAsDOMNode = aRule.AsDOMNode();
int32_t count = mQuerySets.Length();
for (int32_t q = 0; q < count; q++) {
nsTemplateQuerySet* queryset = mQuerySets[q];
@ -359,45 +383,66 @@ nsXULTemplateBuilder::AddRuleFilter(nsIDOMNode* aRule, nsIXULTemplateRuleFilter*
nsCOMPtr<nsIDOMNode> rulenode;
rule->GetRuleNode(getter_AddRefs(rulenode));
if (aRule == rulenode) {
if (ruleAsDOMNode == rulenode) {
rule->SetRuleFilter(aFilter);
return NS_OK;
return;
}
}
}
}
return NS_OK;
NS_IMETHODIMP
nsXULTemplateBuilder::AddRuleFilter(nsIDOMNode* aRule, nsIXULTemplateRuleFilter* aFilter)
{
nsCOMPtr<nsINode> rule = do_QueryInterface(aRule);
if (!rule) {
return NS_ERROR_NULL_POINTER;
}
NS_ENSURE_ARG_POINTER(aFilter);
ErrorResult rv;
AddRuleFilter(*rule, aFilter, rv);
return rv.StealNSResult();
}
void
nsXULTemplateBuilder::Rebuild(ErrorResult& aError)
{
int32_t i;
for (i = mListeners.Length() - 1; i >= 0; --i) {
mListeners[i]->WillRebuild(this);
}
aError = RebuildAll();
for (i = mListeners.Length() - 1; i >= 0; --i) {
mListeners[i]->DidRebuild(this);
}
}
NS_IMETHODIMP
nsXULTemplateBuilder::Rebuild()
{
int32_t i;
for (i = mListeners.Count() - 1; i >= 0; --i) {
mListeners[i]->WillRebuild(this);
}
nsresult rv = RebuildAll();
for (i = mListeners.Count() - 1; i >= 0; --i) {
mListeners[i]->DidRebuild(this);
}
return rv;
ErrorResult rv;
Rebuild(rv);
return rv.StealNSResult();
}
NS_IMETHODIMP
nsXULTemplateBuilder::Refresh()
void
nsXULTemplateBuilder::Refresh(ErrorResult& aError)
{
nsresult rv;
if (!mCompDB)
return NS_ERROR_FAILURE;
if (!mCompDB) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
nsCOMPtr<nsISimpleEnumerator> dslist;
rv = mCompDB->GetDataSources(getter_AddRefs(dslist));
NS_ENSURE_SUCCESS(rv, rv);
aError = mCompDB->GetDataSources(getter_AddRefs(dslist));
if (aError.Failed()) {
return;
}
bool hasMore;
nsCOMPtr<nsISupports> next;
@ -412,15 +457,21 @@ nsXULTemplateBuilder::Refresh()
// XXXbsmedberg: it would be kinda nice to install an async nsIRDFXMLSink
// observer and call rebuild() once the load is complete. See bug 254600.
return NS_OK;
}
NS_IMETHODIMP
nsXULTemplateBuilder::Init(nsIContent* aElement)
nsXULTemplateBuilder::Refresh()
{
NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
mRoot = aElement;
ErrorResult rv;
Refresh(rv);
return rv.StealNSResult();
}
nsresult
nsXULTemplateBuilder::Init()
{
nsresult rv = InitGlobals();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> doc = mRoot->GetComposedDoc();
NS_ASSERTION(doc, "element has no document");
@ -428,7 +479,7 @@ nsXULTemplateBuilder::Init(nsIContent* aElement)
return NS_ERROR_UNEXPECTED;
bool shouldDelay;
nsresult rv = LoadDataSources(doc, &shouldDelay);
rv = LoadDataSources(doc, &shouldDelay);
if (NS_SUCCEEDED(rv)) {
StartObserving(doc);
@ -448,8 +499,18 @@ nsXULTemplateBuilder::HasGeneratedContent(nsIRDFResource* aResource,
nsIAtom* aTag,
bool* aGenerated)
{
*aGenerated = false;
return NS_OK;
ErrorResult rv;
const nsAString& tag = aTag ? nsDependentAtomString(aTag) : NullString();
*aGenerated = HasGeneratedContent(aResource, tag, rv);
return rv.StealNSResult();
}
void
nsXULTemplateBuilder::AddResult(nsIXULTemplateResult* aResult,
nsINode& aQueryNode,
ErrorResult& aError)
{
aError = UpdateResult(nullptr, aResult, &aQueryNode);
}
NS_IMETHODIMP
@ -459,7 +520,17 @@ nsXULTemplateBuilder::AddResult(nsIXULTemplateResult* aResult,
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_ARG_POINTER(aQueryNode);
return UpdateResult(nullptr, aResult, aQueryNode);
ErrorResult rv;
nsCOMPtr<nsINode> queryNode = do_QueryInterface(aQueryNode);
AddResult(aResult, *queryNode, rv);
return rv.StealNSResult();
}
void
nsXULTemplateBuilder::RemoveResult(nsIXULTemplateResult* aResult,
ErrorResult& aError)
{
aError = UpdateResult(aResult, nullptr, nullptr);
}
NS_IMETHODIMP
@ -467,7 +538,21 @@ nsXULTemplateBuilder::RemoveResult(nsIXULTemplateResult* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
return UpdateResult(aResult, nullptr, nullptr);
ErrorResult rv;
RemoveResult(aResult, rv);
return rv.StealNSResult();
}
void
nsXULTemplateBuilder::ReplaceResult(nsIXULTemplateResult* aOldResult,
nsIXULTemplateResult* aNewResult,
nsINode& aQueryNode,
ErrorResult& aError)
{
aError = UpdateResult(aOldResult, nullptr, nullptr);
if (!aError.Failed()) {
aError = UpdateResult(nullptr, aNewResult, &aQueryNode);
}
}
NS_IMETHODIMP
@ -479,19 +564,16 @@ nsXULTemplateBuilder::ReplaceResult(nsIXULTemplateResult* aOldResult,
NS_ENSURE_ARG_POINTER(aNewResult);
NS_ENSURE_ARG_POINTER(aQueryNode);
// just remove the old result and then add a new result separately
nsresult rv = UpdateResult(aOldResult, nullptr, nullptr);
if (NS_FAILED(rv))
return rv;
return UpdateResult(nullptr, aNewResult, aQueryNode);
nsCOMPtr<nsINode> queryNode = do_QueryInterface(aQueryNode);
ErrorResult rv;
ReplaceResult(aOldResult, aNewResult, *queryNode, rv);
return rv.StealNSResult();
}
nsresult
nsXULTemplateBuilder::UpdateResult(nsIXULTemplateResult* aOldResult,
nsIXULTemplateResult* aNewResult,
nsIDOMNode* aQueryNode)
nsINode* aQueryNode)
{
MOZ_LOG(gXULTemplateLog, LogLevel::Info,
("nsXULTemplateBuilder::UpdateResult %p %p %p",
@ -978,81 +1060,113 @@ nsXULTemplateBuilder::UpdateResultInContainer(nsIXULTemplateResult* aOldResult,
return rv;
}
NS_IMETHODIMP
nsXULTemplateBuilder::ResultBindingChanged(nsIXULTemplateResult* aResult)
void
nsXULTemplateBuilder::ResultBindingChanged(nsIXULTemplateResult* aResult,
ErrorResult& aError)
{
// A binding update is used when only the values of the bindings have
// changed, so the same rule still applies. Just synchronize the content.
// The new result will have the new values.
if (mRoot && mQueriesCompiled) {
aError = SynchronizeResult(aResult);
}
}
NS_IMETHODIMP
nsXULTemplateBuilder::ResultBindingChanged(nsIXULTemplateResult* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
if (!mRoot || !mQueriesCompiled)
return NS_OK;
return SynchronizeResult(aResult);
ErrorResult rv;
ResultBindingChanged(aResult, rv);
return rv.StealNSResult();
}
NS_IMETHODIMP
nsXULTemplateBuilder::GetRootResult(nsIXULTemplateResult** aResult)
{
*aResult = mRootResult;
NS_IF_ADDREF(*aResult);
NS_IF_ADDREF(*aResult = GetRootResult());
return NS_OK;
}
NS_IMETHODIMP
nsXULTemplateBuilder::GetResultForId(const nsAString& aId,
nsIXULTemplateResult** aResult)
nsIXULTemplateResult*
nsXULTemplateBuilder::GetResultForId(const nsAString& aId, ErrorResult& aError)
{
if (aId.IsEmpty())
return NS_ERROR_INVALID_ARG;
if (aId.IsEmpty()) {
aError.Throw(NS_ERROR_INVALID_ARG);
return nullptr;
}
nsCOMPtr<nsIRDFResource> resource;
gRDFService->GetUnicodeResource(aId, getter_AddRefs(resource));
*aResult = nullptr;
nsTemplateMatch* match;
if (mMatchMap.Get(resource, &match)) {
// find the active match
while (match) {
if (match->IsActive()) {
*aResult = match->mResult;
NS_IF_ADDREF(*aResult);
break;
return match->mResult;
}
match = match->mNext;
}
}
return NS_OK;
return nullptr;
}
NS_IMETHODIMP
nsXULTemplateBuilder::GetResultForId(const nsAString& aId,
nsIXULTemplateResult** aResult)
{
ErrorResult rv;
NS_IF_ADDREF(*aResult = GetResultForId(aId, rv));
return rv.StealNSResult();
}
NS_IMETHODIMP
nsXULTemplateBuilder::GetResultForContent(nsIDOMElement* aContent,
nsIXULTemplateResult** aResult)
{
*aResult = nullptr;
nsCOMPtr<Element> element = do_QueryInterface(aContent);
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
NS_IF_ADDREF(*aResult = GetResultForContent(*element));
return NS_OK;
}
void
nsXULTemplateBuilder::AddListener(XULBuilderListener& aListener)
{
CallbackObjectHolder<XULBuilderListener, nsIXULBuilderListener>
holder(&aListener);
mListeners.AppendElement(holder.ToXPCOMCallback());
}
NS_IMETHODIMP
nsXULTemplateBuilder::AddListener(nsIXULBuilderListener* aListener)
{
NS_ENSURE_ARG(aListener);
if (!mListeners.AppendObject(aListener))
if (!mListeners.AppendElement(aListener))
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
void
nsXULTemplateBuilder::RemoveListener(XULBuilderListener& aListener)
{
CallbackObjectHolder<XULBuilderListener, nsIXULBuilderListener>
holder(&aListener);
nsCOMPtr<nsIXULBuilderListener> listener(holder.ToXPCOMCallback());
mListeners.RemoveElement(listener);
}
NS_IMETHODIMP
nsXULTemplateBuilder::RemoveListener(nsIXULBuilderListener* aListener)
{
NS_ENSURE_ARG(aListener);
mListeners.RemoveObject(aListener);
mListeners.RemoveElement(aListener);
return NS_OK;
}

View File

@ -6,31 +6,38 @@
#ifndef nsXULTemplateBuilder_h__
#define nsXULTemplateBuilder_h__
#include "mozilla/dom/Element.h"
#include "nsStubDocumentObserver.h"
#include "nsIScriptSecurityManager.h"
#include "nsIObserver.h"
#include "nsIRDFCompositeDataSource.h"
#include "nsIRDFContainer.h"
#include "nsIRDFContainerUtils.h"
#include "nsIRDFDataSource.h"
#include "nsIRDFObserver.h"
#include "nsIRDFService.h"
#include "nsIXULTemplateBuilder.h"
#include "nsCOMArray.h"
#include "nsTArray.h"
#include "nsDataHashtable.h"
#include "nsTemplateRule.h"
#include "nsTemplateMatch.h"
#include "nsIXULTemplateQueryProcessor.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/Logging.h"
extern mozilla::LazyLogModule gXULTemplateLog;
class nsIContent;
class nsIObserverService;
class nsIRDFCompositeDataSource;
class nsIRDFContainerUtils;
class nsIRDFDataSource;
class nsIRDFService;
class nsIScriptSecurityManager;
class nsIXULTemplateQueryProcessor;
class nsTemplateCondition;
class nsTemplateRule;
class nsTemplateMatch;
class nsTemplateQuerySet;
namespace mozilla {
namespace dom {
class XULBuilderListener;
} // namespace dom
} // namespace mozilla
/**
* An object that translates an RDF graph into a presentation using a
@ -38,13 +45,14 @@ class nsIRDFCompositeDataSource;
*/
class nsXULTemplateBuilder : public nsIXULTemplateBuilder,
public nsIObserver,
public nsStubDocumentObserver
public nsStubDocumentObserver,
public nsWrapperCache
{
void CleanUp(bool aIsFinal);
void DestroyMatchMap();
public:
nsXULTemplateBuilder();
nsresult Init();
nsresult InitGlobals();
@ -56,8 +64,58 @@ public:
// nsISupports interface
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULTemplateBuilder,
nsIXULTemplateBuilder)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsXULTemplateBuilder,
nsIXULTemplateBuilder)
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
Element* GetParentObject()
{
return mRoot;
}
Element* GetRoot()
{
return mRoot;
}
nsISupports* GetDatasource();
void SetDatasource(nsISupports* aDatasource, mozilla::ErrorResult& aError);
nsIRDFCompositeDataSource* GetDatabase()
{
return mCompDB;
}
nsIXULTemplateResult* GetRootResult()
{
return mRootResult;
}
void Rebuild(mozilla::ErrorResult& aError);
void Refresh(mozilla::ErrorResult& aError);
void AddResult(nsIXULTemplateResult* aResult, nsINode& aQueryNode,
mozilla::ErrorResult& aError);
void RemoveResult(nsIXULTemplateResult* aResult,
mozilla::ErrorResult& aError);
void ReplaceResult(nsIXULTemplateResult* aOldResult,
nsIXULTemplateResult* aNewResult,
nsINode& aQueryNode,
mozilla::ErrorResult& aError);
void ResultBindingChanged(nsIXULTemplateResult* aResult,
mozilla::ErrorResult& aError);
nsIXULTemplateResult* GetResultForId(const nsAString& aId,
mozilla::ErrorResult& aError);
virtual nsIXULTemplateResult* GetResultForContent(Element& aElement)
{
return nullptr;
}
virtual bool HasGeneratedContent(nsIRDFResource* aResource,
const nsAString& aTag,
mozilla::ErrorResult& aError)
{
return false;
}
void AddRuleFilter(nsINode& aRule, nsIXULTemplateRuleFilter* aFilter,
mozilla::ErrorResult& aError);
void AddListener(mozilla::dom::XULBuilderListener& aListener);
void RemoveListener(mozilla::dom::XULBuilderListener& aListener);
// nsIXULTemplateBuilder interface
NS_DECL_NSIXULTEMPLATEBUILDER
@ -83,7 +141,7 @@ public:
nsresult
UpdateResult(nsIXULTemplateResult* aOldResult,
nsIXULTemplateResult* aNewResult,
nsIDOMNode* aQueryNode);
nsINode* aQueryNode);
/**
* Remove an old result and/or add a new result from a specific container.
@ -331,6 +389,7 @@ public:
nsIRDFResource** aResource);
protected:
explicit nsXULTemplateBuilder(Element* aElement);
virtual ~nsXULTemplateBuilder();
nsCOMPtr<nsISupports> mDataSource;
@ -340,14 +399,14 @@ protected:
/**
* Circular reference, broken when the document is destroyed.
*/
nsCOMPtr<nsIContent> mRoot;
nsCOMPtr<Element> mRoot;
/**
* The root result, translated from the root element's ref
*/
nsCOMPtr<nsIXULTemplateResult> mRootResult;
nsCOMArray<nsIXULBuilderListener> mListeners;
nsTArray<nsCOMPtr<nsIXULBuilderListener>> mListeners;
/**
* The query processor which generates results
@ -499,4 +558,7 @@ protected:
nsIDocument* mObservedDocument;
};
nsresult NS_NewXULContentBuilder(Element* aElement,
nsIXULTemplateBuilder** aBuilder);
#endif // nsXULTemplateBuilder_h__

View File

@ -34,6 +34,7 @@
#include "nsXULTemplateQueryProcessorRDF.h"
#include "nsXULSortService.h"
#include "nsIDocument.h"
#include "nsIRDFCompositeDataSource.h"
//----------------------------------------------------------------------

View File

@ -27,6 +27,7 @@
#include "nsIChannel.h"
#include "nsIDocument.h"
#include "nsNetUtil.h"
#include "nsTemplateMatch.h"
//----------------------------------------------------------------------
//

File diff suppressed because it is too large Load Diff

View File

@ -37,9 +37,94 @@ class nsXULTreeBuilder : public nsXULTemplateBuilder,
public nsINativeTreeView
{
public:
explicit nsXULTreeBuilder(Element* aElement);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder)
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeBuilder,
nsXULTemplateBuilder)
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
already_AddRefed<nsIRDFResource>
GetResourceAtIndex(int32_t aIndex, mozilla::ErrorResult& aError);
int32_t GetIndexOfResource(nsIRDFResource* aResource,
mozilla::ErrorResult& aError);
void AddObserver(mozilla::dom::XULTreeBuilderObserver& aObserver);
void RemoveObserver(mozilla::dom::XULTreeBuilderObserver& aObserver);
void Sort(Element&);
int32_t RowCount()
{
return mRows.Count();
}
nsITreeSelection* GetSelection()
{
return mSelection;
}
void SetSelection(nsITreeSelection* aSelection,
mozilla::ErrorResult& aError);
void GetRowProperties(int32_t aRow, nsAString& aProperties,
mozilla::ErrorResult& aError);
void GetCellProperties(int32_t aRow, nsTreeColumn& aColumn,
nsAString& aProperties, mozilla::ErrorResult& aError);
void GetColumnProperties(nsTreeColumn& aColumn, nsAString& aProperties)
{
}
bool IsContainer(int32_t aRow, mozilla::ErrorResult& aError);
bool IsContainerOpen(int32_t aRow, mozilla::ErrorResult& aError);
bool IsContainerEmpty(int32_t aRow, mozilla::ErrorResult& aError);
bool IsSeparator(int32_t aRow, mozilla::ErrorResult& aError);
bool IsSorted()
{
return mSortVariable != nullptr;
}
bool CanDrop(int32_t aRow, int32_t aOrientation,
mozilla::dom::DataTransfer* aDataTransfer,
mozilla::ErrorResult& aError);
void Drop(int32_t aRow, int32_t aOrientation,
mozilla::dom::DataTransfer* aDataTransfer,
mozilla::ErrorResult& aError);
int32_t GetParentIndex(int32_t aRow, mozilla::ErrorResult& aError);
bool HasNextSibling(int32_t aRow, int32_t aAfterIndex,
mozilla::ErrorResult& aError);
int32_t GetLevel(int32_t aRow, mozilla::ErrorResult& aError);
void GetImageSrc(int32_t aRow, nsTreeColumn& aColumn, nsAString& aSrc,
mozilla::ErrorResult& aError);
int32_t GetProgressMode(int32_t aRow, nsTreeColumn& aColumn,
mozilla::ErrorResult& aError);
void GetCellValue(int32_t aRow, nsTreeColumn& aColumn, nsAString& aValue,
mozilla::ErrorResult& aError);
void GetCellText(int32_t aRow, nsTreeColumn& aColumn, nsAString& aText,
mozilla::ErrorResult& aError);
void SetTree(mozilla::dom::TreeBoxObject* aTree,
mozilla::ErrorResult& aError);
void ToggleOpenState(int32_t aRow, mozilla::ErrorResult& aError);
void CycleHeader(nsTreeColumn& aColumn, mozilla::ErrorResult& aError);
// XPCOM SelectionChanged() is OK
void CycleCell(int32_t aRow, nsTreeColumn& aColumn);
bool IsEditable(int32_t aRow, nsTreeColumn& aColumn,
mozilla::ErrorResult& aError);
bool IsSelectable(int32_t aRow, nsTreeColumn& aColumn,
mozilla::ErrorResult& aError);
void SetCellValue(int32_t aRow, nsTreeColumn& aColumn,
const nsAString& aValue, mozilla::ErrorResult& aError)
{
}
void SetCellText(int32_t aRow, nsTreeColumn& aColumn,
const nsAString& aText, mozilla::ErrorResult& aError)
{
}
void PerformAction(const nsAString& aAction);
void PerformActionOnRow(const nsAString& aAction, int32_t aRow);
void PerformActionOnCell(const nsAString& aAction, int32_t aRow,
nsTreeColumn& aColumn);
using nsIXULTemplateBuilder::HasGeneratedContent;
virtual bool HasGeneratedContent(nsIRDFResource* aResource,
const nsAString& aTag,
mozilla::ErrorResult& aError) override;
// nsIXULTreeBuilder
NS_DECL_NSIXULTREEBUILDER
@ -53,12 +138,8 @@ public:
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
protected:
friend nsresult
NS_NewXULTreeBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult);
friend struct ResultComparator;
nsXULTreeBuilder();
~nsXULTreeBuilder();
/**
@ -86,8 +167,8 @@ protected:
* Given a row and a column ID, use the row's match to figure out
* the appropriate <treecell> in the rule's <action>.
*/
nsresult
GetTemplateActionCellFor(int32_t aRow, nsITreeColumn* aCol, nsIContent** aResult);
nsIContent*
GetTemplateActionCellFor(int32_t aRow, nsTreeColumn& aCol);
/**
* Return the resource corresponding to a row in the tree.
@ -158,11 +239,6 @@ protected:
nsresult
SortSubtree(nsTreeRows::Subtree* aSubtree);
NS_IMETHOD
HasGeneratedContent(nsIRDFResource* aResource,
nsIAtom* aTag,
bool* aGenerated) override;
// GetInsertionLocations, ReplaceMatch and SynchronizeResult are inherited
// from nsXULTemplateBuilder
@ -189,6 +265,8 @@ protected:
virtual nsresult
SynchronizeResult(nsIXULTemplateResult* aResult) override;
bool IsValidRowIndex(int32_t aRowIndex);
/**
* The tree's box object, used to communicate with the front-end.
*/
@ -233,7 +311,7 @@ protected:
/**
* The builder observers.
*/
nsCOMArray<nsIXULTreeBuilderObserver> mObservers;
nsTArray<nsCOMPtr<nsIXULTreeBuilderObserver>> mObservers;
/*
* XUL store for holding open container state

View File

@ -156,12 +156,6 @@ class nsIDocumentLoaderFactory;
#ifdef MOZ_XUL
#include "nsIXULDocument.h"
#include "nsIXULSortService.h"
nsresult
NS_NewXULContentBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult);
nsresult
NS_NewXULTreeBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult);
#endif
static void Shutdown();
@ -466,8 +460,6 @@ MAKE_CTOR(CreatePlainTextSerializer, nsIContentSerializer, NS_NewPla
MAKE_CTOR(CreateContentPolicy, nsIContentPolicy, NS_NewContentPolicy)
#ifdef MOZ_XUL
MAKE_CTOR(CreateXULSortService, nsIXULSortService, NS_NewXULSortService)
// NS_NewXULContentBuilder
// NS_NewXULTreeBuilder
MAKE_CTOR(CreateXULDocument, nsIXULDocument, NS_NewXULDocument)
// NS_NewXULControllers
#endif
@ -630,8 +622,6 @@ NS_DEFINE_NAMED_CID(NS_NODATAPROTOCOLCONTENTPOLICY_CID);
NS_DEFINE_NAMED_CID(NS_XULCONTROLLERS_CID);
#ifdef MOZ_XUL
NS_DEFINE_NAMED_CID(NS_XULSORTSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_XULTEMPLATEBUILDER_CID);
NS_DEFINE_NAMED_CID(NS_XULTREEBUILDER_CID);
NS_DEFINE_NAMED_CID(NS_XULDOCUMENT_CID);
#endif
NS_DEFINE_NAMED_CID(NS_CONTENT_DOCUMENT_LOADER_FACTORY_CID);
@ -895,8 +885,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kNS_XULCONTROLLERS_CID, false, nullptr, NS_NewXULControllers },
#ifdef MOZ_XUL
{ &kNS_XULSORTSERVICE_CID, false, nullptr, CreateXULSortService },
{ &kNS_XULTEMPLATEBUILDER_CID, false, nullptr, NS_NewXULContentBuilder },
{ &kNS_XULTREEBUILDER_CID, false, nullptr, NS_NewXULTreeBuilder },
{ &kNS_XULDOCUMENT_CID, false, nullptr, CreateXULDocument },
#endif
{ &kNS_CONTENT_DOCUMENT_LOADER_FACTORY_CID, false, nullptr, CreateContentDLF },
@ -1031,8 +1019,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ "@mozilla.org/xul/xul-controllers;1", &kNS_XULCONTROLLERS_CID },
#ifdef MOZ_XUL
{ "@mozilla.org/xul/xul-sort-service;1", &kNS_XULSORTSERVICE_CID },
{ "@mozilla.org/xul/xul-template-builder;1", &kNS_XULTEMPLATEBUILDER_CID },
{ "@mozilla.org/xul/xul-tree-builder;1", &kNS_XULTREEBUILDER_CID },
{ "@mozilla.org/xul/xul-document;1", &kNS_XULDOCUMENT_CID },
#endif
{ CONTENT_DLF_CONTRACTID, &kNS_CONTENT_DOCUMENT_LOADER_FACTORY_CID },

View File

@ -11,6 +11,7 @@
#include "mozilla/Attributes.h"
#include "nsCoord.h"
#include "nsCycleCollectionParticipant.h"
#include "nsQueryObject.h"
#include "nsWrapperCache.h"
#include "nsString.h"
@ -46,6 +47,12 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_TREECOLUMN_IMPL_CID)
static already_AddRefed<nsTreeColumn> From(nsITreeColumn* aColumn)
{
RefPtr<nsTreeColumn> col = do_QueryObject(aColumn);
return col.forget();
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsTreeColumn)
NS_DECL_NSITREECOLUMN
@ -98,10 +105,12 @@ protected:
void SetColumns(nsTreeColumns* aColumns) { mColumns = aColumns; }
const nsAString& GetId() { return mId; }
nsIAtom* GetAtom() { return mAtom; }
public:
nsIAtom* GetAtom() { return mAtom; }
int32_t GetIndex() { return mIndex; }
protected:
bool IsPrimary() { return mIsPrimary; }
bool IsCycler() { return mIsCycler; }
bool IsEditable() { return mIsEditable; }