Made nsXULAttribute implement nsIDOMAttr, and made nsXULAttributes implement nsIDOMNamedNodeMap. Updated the nsRDFElement accordingly, and implemented GetAttributes() and Set/GetAttributeNode().

This commit is contained in:
waterson%netscape.com 1999-04-06 06:40:31 +00:00
Родитель c45bb6f9cd
Коммит e463eee79f
7 изменённых файлов: 1363 добавлений и 191 удалений

Просмотреть файл

@ -24,42 +24,505 @@
*/
#include "nsXULAttributes.h"
/*
* Notes
*
* A lot of these methods delegate back to the original content node
* that created them. This is so that we can lazily produce attribute
* values from the RDF graph as they're asked for.
*
*/
#include "nsCOMPtr.h"
#include "nsDOMCID.h"
#include "nsIContent.h"
#include "nsICSSParser.h"
#include "nsIDOMElement.h"
#include "nsIDOMScriptObjectFactory.h"
#include "nsINameSpaceManager.h"
#include "nsIServiceManager.h"
#include "nsIURL.h"
#include "nsXULAttributes.h"
const PRUnichar kNullCh = PRUnichar('\0');
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
static void ParseClasses(const nsString& aClassString, nsClassList** aClassList)
////////////////////////////////////////////////////////////////////////
// nsXULAttribute
nsXULAttribute::nsXULAttribute(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue)
: mNameSpaceID(aNameSpaceID),
mName(aName),
mValue(aValue),
mContent(aContent),
mScriptObject(nsnull)
{
NS_ASSERTION(nsnull == *aClassList, "non null start list");
nsAutoString classStr(aClassString); // copy to work buffer
classStr.Append(kNullCh); // put an extra null at the end
PRUnichar* start = (PRUnichar*)(const PRUnichar*)classStr;
PRUnichar* end = start;
while (kNullCh != *start) {
while ((kNullCh != *start) && nsString::IsSpace(*start)) { // skip leading space
start++;
}
end = start;
while ((kNullCh != *end) && (PR_FALSE == nsString::IsSpace(*end))) { // look for space or end
end++;
}
*end = kNullCh; // end string here
if (start < end) {
*aClassList = new nsClassList(NS_NewAtom(start));
aClassList = &((*aClassList)->mNext);
}
start = ++end;
}
NS_INIT_REFCNT();
NS_IF_ADDREF(aName);
}
nsXULAttribute::~nsXULAttribute()
{
NS_IF_RELEASE(mName);
}
nsresult
NS_NewXULAttribute(nsXULAttribute** aResult,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (! (*aResult = new nsXULAttribute(aContent, aNameSpaceID, aName, aValue)))
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
// nsISupports interface
NS_IMPL_ADDREF(nsXULAttribute);
NS_IMPL_RELEASE(nsXULAttribute);
NS_IMETHODIMP
nsXULAttribute::QueryInterface(REFNSIID aIID, void** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsIDOMAttr::GetIID()) ||
aIID.Equals(nsIDOMNode::GetIID()) ||
aIID.Equals(kISupportsIID)) {
*aResult = NS_STATIC_CAST(nsIDOMAttr*, this);
NS_ADDREF(this);
return NS_OK;
}
else if (aIID.Equals(nsIScriptObjectOwner::GetIID())) {
*aResult = NS_STATIC_CAST(nsIScriptObjectOwner*, this);
NS_ADDREF(this);
return NS_OK;
}
else {
*aResult = nsnull;
return NS_NOINTERFACE;
}
}
// nsIDOMNode interface
NS_IMETHODIMP
nsXULAttribute::GetNodeName(nsString& aNodeName)
{
aNodeName.SetString(mName->GetUnicode());
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetNodeValue(nsString& aNodeValue)
{
aNodeValue.SetString(mValue);
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::SetNodeValue(const nsString& aNodeValue)
{
return SetValue(aNodeValue);
}
NS_IMETHODIMP
nsXULAttribute::GetNodeType(PRUint16* aNodeType)
{
*aNodeType = (PRUint16)nsIDOMNode::ATTRIBUTE_NODE;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetParentNode(nsIDOMNode** aParentNode)
{
*aParentNode = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetChildNodes(nsIDOMNodeList** aChildNodes)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::GetFirstChild(nsIDOMNode** aFirstChild)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::GetLastChild(nsIDOMNode** aLastChild)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::GetPreviousSibling(nsIDOMNode** aPreviousSibling)
{
*aPreviousSibling = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetNextSibling(nsIDOMNode** aNextSibling)
{
*aNextSibling = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
{
*aAttributes = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aReturn)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttribute::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttribute::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttribute::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttribute::HasChildNodes(PRBool* aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
// nsIDOMAttr interface
NS_IMETHODIMP
nsXULAttribute::GetName(nsString& aName)
{
aName.SetString(mName->GetUnicode());
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetSpecified(PRBool* aSpecified)
{
// XXX this'll break when we make Clone() work
*aSpecified = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetValue(nsString& aValue)
{
aValue.SetString(mValue);
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::SetValue(const nsString& aValue)
{
nsCOMPtr<nsIDOMElement> element( do_QueryInterface(mContent) );
if (element) {
return element->SetAttribute(GetQualifiedName(), aValue);
}
else {
return NS_ERROR_FAILURE;
}
}
// nsIScriptObjectOwner interface
NS_IMETHODIMP
nsXULAttribute::GetScriptObject(nsIScriptContext* aContext, void** aScriptObject)
{
nsresult rv = NS_OK;
if (! mScriptObject) {
nsIDOMScriptObjectFactory *factory;
rv = nsServiceManager::GetService(kDOMScriptObjectFactoryCID,
nsIDOMScriptObjectFactory::GetIID(),
(nsISupports **)&factory);
if (NS_FAILED(rv))
return rv;
rv = factory->NewScriptAttr(aContext,
(nsISupports*)(nsIDOMAttr*) this,
(nsISupports*) mContent,
(void**) &mScriptObject);
nsServiceManager::ReleaseService(kDOMScriptObjectFactoryCID, factory);
}
*aScriptObject = mScriptObject;
return rv;
}
NS_IMETHODIMP
nsXULAttribute::SetScriptObject(void *aScriptObject)
{
mScriptObject = aScriptObject;
return NS_OK;
}
// Implementation methods
const nsString&
nsXULAttribute::GetQualifiedName()
{
nsAutoString result;
if ((mNameSpaceID != kNameSpaceID_None) &&
(mNameSpaceID != kNameSpaceID_Unknown)) {
nsIAtom* prefix;
if (NS_SUCCEEDED(mContent->GetNameSpacePrefixFromId(mNameSpaceID, prefix))) {
result.Append(prefix->GetUnicode());
result.Append(':');
NS_RELEASE(prefix);
}
}
result.Append(mName->GetUnicode());
return result;
}
////////////////////////////////////////////////////////////////////////
// nsXULAttributes
nsXULAttributes::nsXULAttributes(nsIContent* aContent)
: mContent(aContent),
mClassList(nsnull),
mStyleRule(nsnull),
mScriptObject(nsnull)
{
NS_INIT_REFCNT();
}
nsXULAttributes::~nsXULAttributes()
{
PRInt32 count = mAttributes.Count();
PRInt32 index;
for (index = 0; index < count; index++) {
nsXULAttribute* attr = (nsXULAttribute*)mAttributes.ElementAt(index);
NS_RELEASE(attr);
}
}
nsresult
NS_NewXULAttributes(nsXULAttributes** aResult, nsIContent* aContent)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (! (*aResult = new nsXULAttributes(aContent)))
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
// nsISupports interface
NS_IMPL_ADDREF(nsXULAttributes);
NS_IMPL_RELEASE(nsXULAttributes);
NS_IMETHODIMP
nsXULAttributes::QueryInterface(REFNSIID aIID, void** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsIDOMNamedNodeMap::GetIID()) ||
aIID.Equals(kISupportsIID)) {
*aResult = NS_STATIC_CAST(nsIDOMNamedNodeMap*, this);
NS_ADDREF(this);
return NS_OK;
}
else if (aIID.Equals(nsIScriptObjectOwner::GetIID())) {
*aResult = NS_STATIC_CAST(nsIScriptObjectOwner*, this);
NS_ADDREF(this);
return NS_OK;
}
else {
*aResult = nsnull;
return NS_NOINTERFACE;
}
}
// nsIDOMNamedNodeMap interface
NS_IMETHODIMP
nsXULAttributes::GetLength(PRUint32* aLength)
{
NS_PRECONDITION(aLength != nsnull, "null ptr");
if (! aLength)
return NS_ERROR_NULL_POINTER;
*aLength = mAttributes.Count();
return NS_OK;
}
NS_IMETHODIMP
nsXULAttributes::GetNamedItem(const nsString& aName, nsIDOMNode** aReturn)
{
NS_PRECONDITION(aReturn != nsnull, "null ptr");
if (! aReturn)
return NS_ERROR_NULL_POINTER;
nsresult rv;
*aReturn = nsnull;
PRInt32 nameSpaceID;
nsIAtom* name;
if (NS_FAILED(rv = mContent->ParseAttributeString(aName, name, nameSpaceID)))
return rv;
// XXX doing this instead of calling mContent->GetAttribute() will
// make it a lot harder to lazily instantiate properties from the
// graph. The problem is, how else do we get the named item?
for (PRInt32 i = mAttributes.Count() - 1; i >= 0; --i) {
nsXULAttribute* attr = (nsXULAttribute*) mAttributes[i];
if (((nameSpaceID == attr->mNameSpaceID) ||
(nameSpaceID == kNameSpaceID_Unknown) ||
(nameSpaceID == kNameSpaceID_None)) &&
(name == attr->mName)) {
NS_ADDREF(attr);
*aReturn = attr;
break;
}
}
NS_RELEASE(name);
return NS_OK;
}
NS_IMETHODIMP
nsXULAttributes::SetNamedItem(nsIDOMNode* aArg, nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttributes::RemoveNamedItem(const nsString& aName, nsIDOMNode** aReturn)
{
nsCOMPtr<nsIDOMElement> element( do_QueryInterface(mContent) );
if (element) {
return element->RemoveAttribute(aName);
*aReturn = nsnull; // XXX should be the element we just removed
return NS_OK;
}
else {
return NS_ERROR_FAILURE;
}
}
NS_IMETHODIMP
nsXULAttributes::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
{
*aReturn = (nsXULAttribute*) mAttributes[aIndex];
NS_IF_ADDREF(*aReturn);
return NS_OK;
}
// nsIScriptObjectOwner interface
NS_IMETHODIMP
nsXULAttributes::GetScriptObject(nsIScriptContext* aContext, void** aScriptObject)
{
nsresult rv = NS_OK;
if (! mScriptObject) {
nsIDOMScriptObjectFactory *factory;
rv = nsServiceManager::GetService(kDOMScriptObjectFactoryCID,
nsIDOMScriptObjectFactory::GetIID(),
(nsISupports **)&factory);
if (NS_FAILED(rv))
return rv;
rv = factory->NewScriptNamedNodeMap(aContext,
(nsISupports*)(nsIDOMNamedNodeMap*) this,
(nsISupports*) mContent,
(void**) &mScriptObject);
nsServiceManager::ReleaseService(kDOMScriptObjectFactoryCID, factory);
}
*aScriptObject = mScriptObject;
return rv;
}
NS_IMETHODIMP
nsXULAttributes::SetScriptObject(void *aScriptObject)
{
mScriptObject = aScriptObject;
return NS_OK;
}
// Implementation methods
nsresult
nsXULAttributes::GetClasses(nsVoidArray& aArray) const
{
@ -142,3 +605,38 @@ nsresult nsXULAttributes::GetInlineStyleRule(nsIStyleRule*& aRule)
return result;
}
void
nsXULAttributes::ParseClasses(const nsString& aClassString, nsClassList** aClassList)
{
static const PRUnichar kNullCh = PRUnichar('\0');
NS_ASSERTION(nsnull == *aClassList, "non null start list");
nsAutoString classStr(aClassString); // copy to work buffer
classStr.Append(kNullCh); // put an extra null at the end
PRUnichar* start = (PRUnichar*)(const PRUnichar*)classStr;
PRUnichar* end = start;
while (kNullCh != *start) {
while ((kNullCh != *start) && nsString::IsSpace(*start)) { // skip leading space
start++;
}
end = start;
while ((kNullCh != *end) && (PR_FALSE == nsString::IsSpace(*end))) { // look for space or end
end++;
}
*end = kNullCh; // end string here
if (start < end) {
*aClassList = new nsClassList(NS_NewAtom(start));
aClassList = &((*aClassList)->mNext);
}
start = ++end;
}
}

Просмотреть файл

@ -20,13 +20,16 @@
/*
A helper class used to implement attributes.
A set of helper classes used to implement attributes.
*/
#ifndef nsXULAttributes_h__
#define nsXULAttributes_h__
#include "nsIDOMAttr.h"
#include "nsIDOMNamedNodeMap.h"
#include "nsIScriptObjectOwner.h"
#include "nsIStyleRule.h"
#include "nsString.h"
#include "nsIAtom.h"
@ -61,53 +64,88 @@ struct nsClassList {
nsClassList* mNext;
};
struct nsXULAttribute
////////////////////////////////////////////////////////////////////////
class nsXULAttribute : public nsIDOMAttr,
public nsIScriptObjectOwner
{
nsXULAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, const nsString& aValue)
{
mNameSpaceID = aNameSpaceID;
NS_IF_ADDREF(aName);
mName = aName;
mValue = aValue;
}
private:
nsXULAttribute(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue);
~nsXULAttribute()
{
NS_IF_RELEASE(mName);
}
~nsXULAttribute();
PRInt32 mNameSpaceID;
nsIAtom* mName;
nsString mValue;
friend nsresult
NS_NewXULAttribute(nsXULAttribute** aResult,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue);
public:
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIDOMNode interface
NS_DECL_IDOMNODE
// nsIDOMAttr interface
NS_DECL_IDOMATTR
// nsIScriptObjectOwner interface
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext, void** aScriptObject);
NS_IMETHOD SetScriptObject(void *aScriptObject);
// Implementation methods
const nsString& GetQualifiedName();
PRInt32 GetNameSpaceID();
nsIAtom* GetName();
const nsString& GetValue();
// Publicly exposed to make life easier. This is a private class
// anyway.
PRInt32 mNameSpaceID;
nsIAtom* mName;
nsString mValue;
private:
nsIContent* mContent;
void* mScriptObject;
};
class nsXULAttributes
nsresult
NS_NewXULAttribute(nsXULAttribute** aResult,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue);
////////////////////////////////////////////////////////////////////////
class nsXULAttributes : public nsIDOMNamedNodeMap,
public nsIScriptObjectOwner
{
public:
nsXULAttributes()
: mClassList(nsnull), mStyleRule(nsnull)
{
mAttributes = new nsVoidArray();
}
// nsISupports interface
NS_DECL_ISUPPORTS
~nsXULAttributes(void)
{
if (nsnull != mAttributes) {
PRInt32 count = mAttributes->Count();
PRInt32 index;
for (index = 0; index < count; index++) {
nsXULAttribute* attr = (nsXULAttribute*)mAttributes->ElementAt(index);
delete attr;
}
}
delete mAttributes;
}
// nsIDOMNamedNodeMap interface
NS_DECL_IDOMNAMEDNODEMAP
// nsIScriptObjectOwner interface
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext, void** aScriptObject);
NS_IMETHOD SetScriptObject(void *aScriptObject);
// Implementation methods
// VoidArray Helpers
PRInt32 Count() { return mAttributes->Count(); };
nsXULAttribute* ElementAt(PRInt32 i) { return (nsXULAttribute*)mAttributes->ElementAt(i); };
void AppendElement(nsXULAttribute* aElement) { mAttributes->AppendElement((void*)aElement); };
void RemoveElementAt(PRInt32 index) { mAttributes->RemoveElementAt(index); };
PRInt32 Count() { return mAttributes.Count(); };
nsXULAttribute* ElementAt(PRInt32 i) { return (nsXULAttribute*)mAttributes.ElementAt(i); };
void AppendElement(nsXULAttribute* aElement) { mAttributes.AppendElement((void*)aElement); };
void RemoveElementAt(PRInt32 index) { mAttributes.RemoveElementAt(index); };
// Style Helpers
nsresult GetClasses(nsVoidArray& aArray) const;
@ -117,12 +155,26 @@ public:
nsresult UpdateStyleRule(nsIURL* aDocURL, const nsString& aValue);
nsresult GetInlineStyleRule(nsIStyleRule*& aRule);
public:
nsClassList* mClassList;
private:
friend nsresult
NS_NewXULAttributes(nsXULAttributes** aResult, nsIContent* aContent);
nsXULAttributes(nsIContent* aContent);
virtual ~nsXULAttributes();
static void
ParseClasses(const nsString& aClassString, nsClassList** aClassList);
nsIContent* mContent;
nsClassList* mClassList;
nsIStyleRule* mStyleRule;
nsVoidArray* mAttributes;
nsVoidArray mAttributes;
void* mScriptObject;
};
nsresult
NS_NewXULAttributes(nsXULAttributes** aResult, nsIContent* aContent);
#endif // nsXULAttributes_h__

Просмотреть файл

@ -24,9 +24,8 @@
TO DO
1) Convert mBroadcastListeners to a _pointer_ to an nsVoidArray,
instead of an automatic nsVoidArray. This should reduce the
footprint per element by 40-50 bytes.
1) Instead of creating all the properties up front, instantiate them
lazily as they are asked for (see Bug 3367).
*/
@ -374,7 +373,7 @@ RDFElementImpl::RDFElementImpl(PRInt32 aNameSpaceID, nsIAtom* aTag)
RDFElementImpl::~RDFElementImpl()
{
delete mAttributes; // nsXULAttributes destructor takes care of the rest.
NS_IF_RELEASE(mAttributes);
//NS_IF_RELEASE(mDocument); // not refcounted
//NS_IF_RELEASE(mParent) // not refcounted
@ -687,8 +686,16 @@ RDFElementImpl::GetNextSibling(nsIDOMNode** aNextSibling)
NS_IMETHODIMP
RDFElementImpl::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv;
if (! mAttributes) {
rv = NS_NewXULAttributes(&mAttributes, this);
if (NS_FAILED(rv))
return rv;
}
NS_ADDREF(mAttributes);
*aAttributes = mAttributes;
return NS_OK;
}
@ -879,8 +886,24 @@ RDFElementImpl::RemoveAttribute(const nsString& aName)
NS_IMETHODIMP
RDFElementImpl::GetAttributeNode(const nsString& aName, nsIDOMAttr** aReturn)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_NOT_IMPLEMENTED;
NS_PRECONDITION(aReturn != nsnull, "null ptr");
if (! aReturn)
return NS_ERROR_NULL_POINTER;
nsIDOMNamedNodeMap* map;
nsresult rv = GetAttributes(&map);
if (NS_SUCCEEDED(rv)) {
nsIDOMNode* node;
rv = map->GetNamedItem(aName, &node);
if (NS_SUCCEEDED(rv) && node) {
rv = node->QueryInterface(nsIDOMAttr::GetIID(), (void**) aReturn);
NS_RELEASE(node);
}
NS_RELEASE(map);
}
return rv;
}
@ -1639,13 +1662,14 @@ RDFElementImpl::SetAttribute(PRInt32 aNameSpaceID,
if (nsnull == aName)
return NS_ERROR_NULL_POINTER;
if (nsnull == mAttributes) {
if ((mAttributes = new nsXULAttributes()) == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = NS_OK;
if (! mAttributes) {
rv = NS_NewXULAttributes(&mAttributes, this);
if (NS_FAILED(rv))
return rv;
}
// Check to see if the CLASS attribute is being set. If so, we need to rebuild our
// class list.
if (mDocument && (aNameSpaceID == kNameSpaceID_None) && aName == kClassAtom) {
@ -1684,9 +1708,9 @@ RDFElementImpl::SetAttribute(PRInt32 aNameSpaceID,
attr->mValue = aValue;
}
else { // didn't find it
attr = new nsXULAttribute(aNameSpaceID, aName, aValue);
if (! attr)
return NS_ERROR_OUT_OF_MEMORY;
rv = NS_NewXULAttribute(&attr, this, aNameSpaceID, aName, aValue);
if (NS_FAILED(rv))
return rv;
mAttributes->AppendElement(attr);
}
@ -1906,7 +1930,7 @@ RDFElementImpl::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNot
nsXULAttribute* attr = (nsXULAttribute*)mAttributes->ElementAt(index);
if ((attr->mNameSpaceID == aNameSpaceID) && (attr->mName == aName)) {
mAttributes->RemoveElementAt(index);
delete attr;
NS_RELEASE(attr);
successful = PR_TRUE;
break;
}

Просмотреть файл

@ -24,9 +24,8 @@
TO DO
1) Convert mBroadcastListeners to a _pointer_ to an nsVoidArray,
instead of an automatic nsVoidArray. This should reduce the
footprint per element by 40-50 bytes.
1) Instead of creating all the properties up front, instantiate them
lazily as they are asked for (see Bug 3367).
*/
@ -374,7 +373,7 @@ RDFElementImpl::RDFElementImpl(PRInt32 aNameSpaceID, nsIAtom* aTag)
RDFElementImpl::~RDFElementImpl()
{
delete mAttributes; // nsXULAttributes destructor takes care of the rest.
NS_IF_RELEASE(mAttributes);
//NS_IF_RELEASE(mDocument); // not refcounted
//NS_IF_RELEASE(mParent) // not refcounted
@ -687,8 +686,16 @@ RDFElementImpl::GetNextSibling(nsIDOMNode** aNextSibling)
NS_IMETHODIMP
RDFElementImpl::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv;
if (! mAttributes) {
rv = NS_NewXULAttributes(&mAttributes, this);
if (NS_FAILED(rv))
return rv;
}
NS_ADDREF(mAttributes);
*aAttributes = mAttributes;
return NS_OK;
}
@ -879,8 +886,24 @@ RDFElementImpl::RemoveAttribute(const nsString& aName)
NS_IMETHODIMP
RDFElementImpl::GetAttributeNode(const nsString& aName, nsIDOMAttr** aReturn)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_NOT_IMPLEMENTED;
NS_PRECONDITION(aReturn != nsnull, "null ptr");
if (! aReturn)
return NS_ERROR_NULL_POINTER;
nsIDOMNamedNodeMap* map;
nsresult rv = GetAttributes(&map);
if (NS_SUCCEEDED(rv)) {
nsIDOMNode* node;
rv = map->GetNamedItem(aName, &node);
if (NS_SUCCEEDED(rv) && node) {
rv = node->QueryInterface(nsIDOMAttr::GetIID(), (void**) aReturn);
NS_RELEASE(node);
}
NS_RELEASE(map);
}
return rv;
}
@ -1639,13 +1662,14 @@ RDFElementImpl::SetAttribute(PRInt32 aNameSpaceID,
if (nsnull == aName)
return NS_ERROR_NULL_POINTER;
if (nsnull == mAttributes) {
if ((mAttributes = new nsXULAttributes()) == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = NS_OK;
if (! mAttributes) {
rv = NS_NewXULAttributes(&mAttributes, this);
if (NS_FAILED(rv))
return rv;
}
// Check to see if the CLASS attribute is being set. If so, we need to rebuild our
// class list.
if (mDocument && (aNameSpaceID == kNameSpaceID_None) && aName == kClassAtom) {
@ -1684,9 +1708,9 @@ RDFElementImpl::SetAttribute(PRInt32 aNameSpaceID,
attr->mValue = aValue;
}
else { // didn't find it
attr = new nsXULAttribute(aNameSpaceID, aName, aValue);
if (! attr)
return NS_ERROR_OUT_OF_MEMORY;
rv = NS_NewXULAttribute(&attr, this, aNameSpaceID, aName, aValue);
if (NS_FAILED(rv))
return rv;
mAttributes->AppendElement(attr);
}
@ -1906,7 +1930,7 @@ RDFElementImpl::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNot
nsXULAttribute* attr = (nsXULAttribute*)mAttributes->ElementAt(index);
if ((attr->mNameSpaceID == aNameSpaceID) && (attr->mName == aName)) {
mAttributes->RemoveElementAt(index);
delete attr;
NS_RELEASE(attr);
successful = PR_TRUE;
break;
}

Просмотреть файл

@ -24,42 +24,505 @@
*/
#include "nsXULAttributes.h"
/*
* Notes
*
* A lot of these methods delegate back to the original content node
* that created them. This is so that we can lazily produce attribute
* values from the RDF graph as they're asked for.
*
*/
#include "nsCOMPtr.h"
#include "nsDOMCID.h"
#include "nsIContent.h"
#include "nsICSSParser.h"
#include "nsIDOMElement.h"
#include "nsIDOMScriptObjectFactory.h"
#include "nsINameSpaceManager.h"
#include "nsIServiceManager.h"
#include "nsIURL.h"
#include "nsXULAttributes.h"
const PRUnichar kNullCh = PRUnichar('\0');
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
static void ParseClasses(const nsString& aClassString, nsClassList** aClassList)
////////////////////////////////////////////////////////////////////////
// nsXULAttribute
nsXULAttribute::nsXULAttribute(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue)
: mNameSpaceID(aNameSpaceID),
mName(aName),
mValue(aValue),
mContent(aContent),
mScriptObject(nsnull)
{
NS_ASSERTION(nsnull == *aClassList, "non null start list");
nsAutoString classStr(aClassString); // copy to work buffer
classStr.Append(kNullCh); // put an extra null at the end
PRUnichar* start = (PRUnichar*)(const PRUnichar*)classStr;
PRUnichar* end = start;
while (kNullCh != *start) {
while ((kNullCh != *start) && nsString::IsSpace(*start)) { // skip leading space
start++;
}
end = start;
while ((kNullCh != *end) && (PR_FALSE == nsString::IsSpace(*end))) { // look for space or end
end++;
}
*end = kNullCh; // end string here
if (start < end) {
*aClassList = new nsClassList(NS_NewAtom(start));
aClassList = &((*aClassList)->mNext);
}
start = ++end;
}
NS_INIT_REFCNT();
NS_IF_ADDREF(aName);
}
nsXULAttribute::~nsXULAttribute()
{
NS_IF_RELEASE(mName);
}
nsresult
NS_NewXULAttribute(nsXULAttribute** aResult,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (! (*aResult = new nsXULAttribute(aContent, aNameSpaceID, aName, aValue)))
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
// nsISupports interface
NS_IMPL_ADDREF(nsXULAttribute);
NS_IMPL_RELEASE(nsXULAttribute);
NS_IMETHODIMP
nsXULAttribute::QueryInterface(REFNSIID aIID, void** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsIDOMAttr::GetIID()) ||
aIID.Equals(nsIDOMNode::GetIID()) ||
aIID.Equals(kISupportsIID)) {
*aResult = NS_STATIC_CAST(nsIDOMAttr*, this);
NS_ADDREF(this);
return NS_OK;
}
else if (aIID.Equals(nsIScriptObjectOwner::GetIID())) {
*aResult = NS_STATIC_CAST(nsIScriptObjectOwner*, this);
NS_ADDREF(this);
return NS_OK;
}
else {
*aResult = nsnull;
return NS_NOINTERFACE;
}
}
// nsIDOMNode interface
NS_IMETHODIMP
nsXULAttribute::GetNodeName(nsString& aNodeName)
{
aNodeName.SetString(mName->GetUnicode());
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetNodeValue(nsString& aNodeValue)
{
aNodeValue.SetString(mValue);
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::SetNodeValue(const nsString& aNodeValue)
{
return SetValue(aNodeValue);
}
NS_IMETHODIMP
nsXULAttribute::GetNodeType(PRUint16* aNodeType)
{
*aNodeType = (PRUint16)nsIDOMNode::ATTRIBUTE_NODE;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetParentNode(nsIDOMNode** aParentNode)
{
*aParentNode = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetChildNodes(nsIDOMNodeList** aChildNodes)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::GetFirstChild(nsIDOMNode** aFirstChild)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::GetLastChild(nsIDOMNode** aLastChild)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::GetPreviousSibling(nsIDOMNode** aPreviousSibling)
{
*aPreviousSibling = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetNextSibling(nsIDOMNode** aNextSibling)
{
*aNextSibling = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
{
*aAttributes = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aReturn)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttribute::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttribute::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttribute::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXULAttribute::HasChildNodes(PRBool* aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttribute::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
// nsIDOMAttr interface
NS_IMETHODIMP
nsXULAttribute::GetName(nsString& aName)
{
aName.SetString(mName->GetUnicode());
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetSpecified(PRBool* aSpecified)
{
// XXX this'll break when we make Clone() work
*aSpecified = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::GetValue(nsString& aValue)
{
aValue.SetString(mValue);
return NS_OK;
}
NS_IMETHODIMP
nsXULAttribute::SetValue(const nsString& aValue)
{
nsCOMPtr<nsIDOMElement> element( do_QueryInterface(mContent) );
if (element) {
return element->SetAttribute(GetQualifiedName(), aValue);
}
else {
return NS_ERROR_FAILURE;
}
}
// nsIScriptObjectOwner interface
NS_IMETHODIMP
nsXULAttribute::GetScriptObject(nsIScriptContext* aContext, void** aScriptObject)
{
nsresult rv = NS_OK;
if (! mScriptObject) {
nsIDOMScriptObjectFactory *factory;
rv = nsServiceManager::GetService(kDOMScriptObjectFactoryCID,
nsIDOMScriptObjectFactory::GetIID(),
(nsISupports **)&factory);
if (NS_FAILED(rv))
return rv;
rv = factory->NewScriptAttr(aContext,
(nsISupports*)(nsIDOMAttr*) this,
(nsISupports*) mContent,
(void**) &mScriptObject);
nsServiceManager::ReleaseService(kDOMScriptObjectFactoryCID, factory);
}
*aScriptObject = mScriptObject;
return rv;
}
NS_IMETHODIMP
nsXULAttribute::SetScriptObject(void *aScriptObject)
{
mScriptObject = aScriptObject;
return NS_OK;
}
// Implementation methods
const nsString&
nsXULAttribute::GetQualifiedName()
{
nsAutoString result;
if ((mNameSpaceID != kNameSpaceID_None) &&
(mNameSpaceID != kNameSpaceID_Unknown)) {
nsIAtom* prefix;
if (NS_SUCCEEDED(mContent->GetNameSpacePrefixFromId(mNameSpaceID, prefix))) {
result.Append(prefix->GetUnicode());
result.Append(':');
NS_RELEASE(prefix);
}
}
result.Append(mName->GetUnicode());
return result;
}
////////////////////////////////////////////////////////////////////////
// nsXULAttributes
nsXULAttributes::nsXULAttributes(nsIContent* aContent)
: mContent(aContent),
mClassList(nsnull),
mStyleRule(nsnull),
mScriptObject(nsnull)
{
NS_INIT_REFCNT();
}
nsXULAttributes::~nsXULAttributes()
{
PRInt32 count = mAttributes.Count();
PRInt32 index;
for (index = 0; index < count; index++) {
nsXULAttribute* attr = (nsXULAttribute*)mAttributes.ElementAt(index);
NS_RELEASE(attr);
}
}
nsresult
NS_NewXULAttributes(nsXULAttributes** aResult, nsIContent* aContent)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (! (*aResult = new nsXULAttributes(aContent)))
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
// nsISupports interface
NS_IMPL_ADDREF(nsXULAttributes);
NS_IMPL_RELEASE(nsXULAttributes);
NS_IMETHODIMP
nsXULAttributes::QueryInterface(REFNSIID aIID, void** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsIDOMNamedNodeMap::GetIID()) ||
aIID.Equals(kISupportsIID)) {
*aResult = NS_STATIC_CAST(nsIDOMNamedNodeMap*, this);
NS_ADDREF(this);
return NS_OK;
}
else if (aIID.Equals(nsIScriptObjectOwner::GetIID())) {
*aResult = NS_STATIC_CAST(nsIScriptObjectOwner*, this);
NS_ADDREF(this);
return NS_OK;
}
else {
*aResult = nsnull;
return NS_NOINTERFACE;
}
}
// nsIDOMNamedNodeMap interface
NS_IMETHODIMP
nsXULAttributes::GetLength(PRUint32* aLength)
{
NS_PRECONDITION(aLength != nsnull, "null ptr");
if (! aLength)
return NS_ERROR_NULL_POINTER;
*aLength = mAttributes.Count();
return NS_OK;
}
NS_IMETHODIMP
nsXULAttributes::GetNamedItem(const nsString& aName, nsIDOMNode** aReturn)
{
NS_PRECONDITION(aReturn != nsnull, "null ptr");
if (! aReturn)
return NS_ERROR_NULL_POINTER;
nsresult rv;
*aReturn = nsnull;
PRInt32 nameSpaceID;
nsIAtom* name;
if (NS_FAILED(rv = mContent->ParseAttributeString(aName, name, nameSpaceID)))
return rv;
// XXX doing this instead of calling mContent->GetAttribute() will
// make it a lot harder to lazily instantiate properties from the
// graph. The problem is, how else do we get the named item?
for (PRInt32 i = mAttributes.Count() - 1; i >= 0; --i) {
nsXULAttribute* attr = (nsXULAttribute*) mAttributes[i];
if (((nameSpaceID == attr->mNameSpaceID) ||
(nameSpaceID == kNameSpaceID_Unknown) ||
(nameSpaceID == kNameSpaceID_None)) &&
(name == attr->mName)) {
NS_ADDREF(attr);
*aReturn = attr;
break;
}
}
NS_RELEASE(name);
return NS_OK;
}
NS_IMETHODIMP
nsXULAttributes::SetNamedItem(nsIDOMNode* aArg, nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULAttributes::RemoveNamedItem(const nsString& aName, nsIDOMNode** aReturn)
{
nsCOMPtr<nsIDOMElement> element( do_QueryInterface(mContent) );
if (element) {
return element->RemoveAttribute(aName);
*aReturn = nsnull; // XXX should be the element we just removed
return NS_OK;
}
else {
return NS_ERROR_FAILURE;
}
}
NS_IMETHODIMP
nsXULAttributes::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
{
*aReturn = (nsXULAttribute*) mAttributes[aIndex];
NS_IF_ADDREF(*aReturn);
return NS_OK;
}
// nsIScriptObjectOwner interface
NS_IMETHODIMP
nsXULAttributes::GetScriptObject(nsIScriptContext* aContext, void** aScriptObject)
{
nsresult rv = NS_OK;
if (! mScriptObject) {
nsIDOMScriptObjectFactory *factory;
rv = nsServiceManager::GetService(kDOMScriptObjectFactoryCID,
nsIDOMScriptObjectFactory::GetIID(),
(nsISupports **)&factory);
if (NS_FAILED(rv))
return rv;
rv = factory->NewScriptNamedNodeMap(aContext,
(nsISupports*)(nsIDOMNamedNodeMap*) this,
(nsISupports*) mContent,
(void**) &mScriptObject);
nsServiceManager::ReleaseService(kDOMScriptObjectFactoryCID, factory);
}
*aScriptObject = mScriptObject;
return rv;
}
NS_IMETHODIMP
nsXULAttributes::SetScriptObject(void *aScriptObject)
{
mScriptObject = aScriptObject;
return NS_OK;
}
// Implementation methods
nsresult
nsXULAttributes::GetClasses(nsVoidArray& aArray) const
{
@ -142,3 +605,38 @@ nsresult nsXULAttributes::GetInlineStyleRule(nsIStyleRule*& aRule)
return result;
}
void
nsXULAttributes::ParseClasses(const nsString& aClassString, nsClassList** aClassList)
{
static const PRUnichar kNullCh = PRUnichar('\0');
NS_ASSERTION(nsnull == *aClassList, "non null start list");
nsAutoString classStr(aClassString); // copy to work buffer
classStr.Append(kNullCh); // put an extra null at the end
PRUnichar* start = (PRUnichar*)(const PRUnichar*)classStr;
PRUnichar* end = start;
while (kNullCh != *start) {
while ((kNullCh != *start) && nsString::IsSpace(*start)) { // skip leading space
start++;
}
end = start;
while ((kNullCh != *end) && (PR_FALSE == nsString::IsSpace(*end))) { // look for space or end
end++;
}
*end = kNullCh; // end string here
if (start < end) {
*aClassList = new nsClassList(NS_NewAtom(start));
aClassList = &((*aClassList)->mNext);
}
start = ++end;
}
}

Просмотреть файл

@ -20,13 +20,16 @@
/*
A helper class used to implement attributes.
A set of helper classes used to implement attributes.
*/
#ifndef nsXULAttributes_h__
#define nsXULAttributes_h__
#include "nsIDOMAttr.h"
#include "nsIDOMNamedNodeMap.h"
#include "nsIScriptObjectOwner.h"
#include "nsIStyleRule.h"
#include "nsString.h"
#include "nsIAtom.h"
@ -61,53 +64,88 @@ struct nsClassList {
nsClassList* mNext;
};
struct nsXULAttribute
////////////////////////////////////////////////////////////////////////
class nsXULAttribute : public nsIDOMAttr,
public nsIScriptObjectOwner
{
nsXULAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, const nsString& aValue)
{
mNameSpaceID = aNameSpaceID;
NS_IF_ADDREF(aName);
mName = aName;
mValue = aValue;
}
private:
nsXULAttribute(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue);
~nsXULAttribute()
{
NS_IF_RELEASE(mName);
}
~nsXULAttribute();
PRInt32 mNameSpaceID;
nsIAtom* mName;
nsString mValue;
friend nsresult
NS_NewXULAttribute(nsXULAttribute** aResult,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue);
public:
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIDOMNode interface
NS_DECL_IDOMNODE
// nsIDOMAttr interface
NS_DECL_IDOMATTR
// nsIScriptObjectOwner interface
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext, void** aScriptObject);
NS_IMETHOD SetScriptObject(void *aScriptObject);
// Implementation methods
const nsString& GetQualifiedName();
PRInt32 GetNameSpaceID();
nsIAtom* GetName();
const nsString& GetValue();
// Publicly exposed to make life easier. This is a private class
// anyway.
PRInt32 mNameSpaceID;
nsIAtom* mName;
nsString mValue;
private:
nsIContent* mContent;
void* mScriptObject;
};
class nsXULAttributes
nsresult
NS_NewXULAttribute(nsXULAttribute** aResult,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
const nsString& aValue);
////////////////////////////////////////////////////////////////////////
class nsXULAttributes : public nsIDOMNamedNodeMap,
public nsIScriptObjectOwner
{
public:
nsXULAttributes()
: mClassList(nsnull), mStyleRule(nsnull)
{
mAttributes = new nsVoidArray();
}
// nsISupports interface
NS_DECL_ISUPPORTS
~nsXULAttributes(void)
{
if (nsnull != mAttributes) {
PRInt32 count = mAttributes->Count();
PRInt32 index;
for (index = 0; index < count; index++) {
nsXULAttribute* attr = (nsXULAttribute*)mAttributes->ElementAt(index);
delete attr;
}
}
delete mAttributes;
}
// nsIDOMNamedNodeMap interface
NS_DECL_IDOMNAMEDNODEMAP
// nsIScriptObjectOwner interface
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext, void** aScriptObject);
NS_IMETHOD SetScriptObject(void *aScriptObject);
// Implementation methods
// VoidArray Helpers
PRInt32 Count() { return mAttributes->Count(); };
nsXULAttribute* ElementAt(PRInt32 i) { return (nsXULAttribute*)mAttributes->ElementAt(i); };
void AppendElement(nsXULAttribute* aElement) { mAttributes->AppendElement((void*)aElement); };
void RemoveElementAt(PRInt32 index) { mAttributes->RemoveElementAt(index); };
PRInt32 Count() { return mAttributes.Count(); };
nsXULAttribute* ElementAt(PRInt32 i) { return (nsXULAttribute*)mAttributes.ElementAt(i); };
void AppendElement(nsXULAttribute* aElement) { mAttributes.AppendElement((void*)aElement); };
void RemoveElementAt(PRInt32 index) { mAttributes.RemoveElementAt(index); };
// Style Helpers
nsresult GetClasses(nsVoidArray& aArray) const;
@ -117,12 +155,26 @@ public:
nsresult UpdateStyleRule(nsIURL* aDocURL, const nsString& aValue);
nsresult GetInlineStyleRule(nsIStyleRule*& aRule);
public:
nsClassList* mClassList;
private:
friend nsresult
NS_NewXULAttributes(nsXULAttributes** aResult, nsIContent* aContent);
nsXULAttributes(nsIContent* aContent);
virtual ~nsXULAttributes();
static void
ParseClasses(const nsString& aClassString, nsClassList** aClassList);
nsIContent* mContent;
nsClassList* mClassList;
nsIStyleRule* mStyleRule;
nsVoidArray* mAttributes;
nsVoidArray mAttributes;
void* mScriptObject;
};
nsresult
NS_NewXULAttributes(nsXULAttributes** aResult, nsIContent* aContent);
#endif // nsXULAttributes_h__

Просмотреть файл

@ -24,9 +24,8 @@
TO DO
1) Convert mBroadcastListeners to a _pointer_ to an nsVoidArray,
instead of an automatic nsVoidArray. This should reduce the
footprint per element by 40-50 bytes.
1) Instead of creating all the properties up front, instantiate them
lazily as they are asked for (see Bug 3367).
*/
@ -374,7 +373,7 @@ RDFElementImpl::RDFElementImpl(PRInt32 aNameSpaceID, nsIAtom* aTag)
RDFElementImpl::~RDFElementImpl()
{
delete mAttributes; // nsXULAttributes destructor takes care of the rest.
NS_IF_RELEASE(mAttributes);
//NS_IF_RELEASE(mDocument); // not refcounted
//NS_IF_RELEASE(mParent) // not refcounted
@ -687,8 +686,16 @@ RDFElementImpl::GetNextSibling(nsIDOMNode** aNextSibling)
NS_IMETHODIMP
RDFElementImpl::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv;
if (! mAttributes) {
rv = NS_NewXULAttributes(&mAttributes, this);
if (NS_FAILED(rv))
return rv;
}
NS_ADDREF(mAttributes);
*aAttributes = mAttributes;
return NS_OK;
}
@ -879,8 +886,24 @@ RDFElementImpl::RemoveAttribute(const nsString& aName)
NS_IMETHODIMP
RDFElementImpl::GetAttributeNode(const nsString& aName, nsIDOMAttr** aReturn)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_NOT_IMPLEMENTED;
NS_PRECONDITION(aReturn != nsnull, "null ptr");
if (! aReturn)
return NS_ERROR_NULL_POINTER;
nsIDOMNamedNodeMap* map;
nsresult rv = GetAttributes(&map);
if (NS_SUCCEEDED(rv)) {
nsIDOMNode* node;
rv = map->GetNamedItem(aName, &node);
if (NS_SUCCEEDED(rv) && node) {
rv = node->QueryInterface(nsIDOMAttr::GetIID(), (void**) aReturn);
NS_RELEASE(node);
}
NS_RELEASE(map);
}
return rv;
}
@ -1639,13 +1662,14 @@ RDFElementImpl::SetAttribute(PRInt32 aNameSpaceID,
if (nsnull == aName)
return NS_ERROR_NULL_POINTER;
if (nsnull == mAttributes) {
if ((mAttributes = new nsXULAttributes()) == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = NS_OK;
if (! mAttributes) {
rv = NS_NewXULAttributes(&mAttributes, this);
if (NS_FAILED(rv))
return rv;
}
// Check to see if the CLASS attribute is being set. If so, we need to rebuild our
// class list.
if (mDocument && (aNameSpaceID == kNameSpaceID_None) && aName == kClassAtom) {
@ -1684,9 +1708,9 @@ RDFElementImpl::SetAttribute(PRInt32 aNameSpaceID,
attr->mValue = aValue;
}
else { // didn't find it
attr = new nsXULAttribute(aNameSpaceID, aName, aValue);
if (! attr)
return NS_ERROR_OUT_OF_MEMORY;
rv = NS_NewXULAttribute(&attr, this, aNameSpaceID, aName, aValue);
if (NS_FAILED(rv))
return rv;
mAttributes->AppendElement(attr);
}
@ -1906,7 +1930,7 @@ RDFElementImpl::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNot
nsXULAttribute* attr = (nsXULAttribute*)mAttributes->ElementAt(index);
if ((attr->mNameSpaceID == aNameSpaceID) && (attr->mName == aName)) {
mAttributes->RemoveElementAt(index);
delete attr;
NS_RELEASE(attr);
successful = PR_TRUE;
break;
}