[XForms] Handle dynamically inserted instances. Bug 320081, patch by surkov, r=aaronr+me

This commit is contained in:
allan%beaufour.dk 2006-02-08 11:03:27 +00:00
Родитель 3adcfc3b07
Коммит 3acb880650
5 изменённых файлов: 129 добавлений и 71 удалений

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

@ -133,8 +133,19 @@ interface nsIModelElementPrivate : nsIXFormsModelElement
*/
void addInstanceElement(in nsIInstanceElementPrivate aInstanceElement);
/**
* Remove an instance element from the model's instance list
* @param aInstanceElement The instance element to remove from the list
*/
void removeInstanceElement(in nsIInstanceElementPrivate aInstanceElement);
/**
* This attribute is set when the model's instance was lazy authored
*/
readonly attribute boolean lazyAuthored;
/**
* This attribute is set when the model handled xforms-ready event
*/
readonly attribute boolean isReady;
};

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

@ -139,7 +139,9 @@ NS_IMETHODIMP
nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
{
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_ATTRIBUTE_SET |
nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED);
nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED |
nsIXTFElement::NOTIFY_WILL_CHANGE_PARENT |
nsIXTFElement::NOTIFY_PARENT_CHANGED);
nsCOMPtr<nsIDOMElement> node;
aWrapper->GetElementNode(getter_AddRefs(node));
@ -389,74 +391,81 @@ nsXFormsInstanceElement::GetElement(nsIDOMElement **aElement)
}
NS_IMETHODIMP
nsXFormsInstanceElement::Initialize()
nsXFormsInstanceElement::WillChangeParent(nsIDOMElement *aNewParent)
{
if (!aNewParent) {
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
if (model) {
model->RemoveInstanceElement(this);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::ParentChanged(nsIDOMElement *aNewParent)
{
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
if (!model) return NS_OK;
if (mInitialized || !mElement) {
return NS_OK;
}
mInitialized = PR_TRUE;
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
NS_ENSURE_TRUE(model, NS_ERROR_FAILURE);
model->AddInstanceElement(this);
// If model isn't loaded entirely (It means xforms-ready event hasn't been
// fired) then the instance will be initialized by model and will be backed up
// when xforms-ready event is fired.
PRBool isready;
model->GetIsReady(&isready);
if (!isready)
return NS_OK;
// If the model is loaded and ready then the instance is inserted dynamically.
// The instance should create instance document and back it up.
// Probably dynamic instances should be handled too when model isn't loaded
// entirely (for more information see a comment 29 of bug 320081
// https://bugzilla.mozilla.org/show_bug.cgi?id=320081#c29).
nsAutoString src;
mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
if (!src.IsEmpty()) {
// XXX: external dynamic instances isn't handled (see a bug 325684
// https://bugzilla.mozilla.org/show_bug.cgi?id=325684)
return NS_OK;
}
// If we don't have a linked external instance, use our inline data.
nsresult rv = CloneInlineInstance();
if (NS_FAILED(rv))
return rv;
return BackupOriginalDocument();
}
NS_IMETHODIMP
nsXFormsInstanceElement::Initialize()
{
mElement->HasAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_MOZ_XFORMS_LAZY),
NS_LITERAL_STRING("lazy"), &mLazy);
// Lazy instance
if (mLazy) {
nsCOMPtr<nsIDOMDocument> domDoc;
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
NS_ENSURE_STATE(domDoc);
nsCOMPtr<nsIDOMDOMImplementation> domImpl;
nsresult rv = domDoc->GetImplementation(getter_AddRefs(domImpl));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMDocument> newDoc;
rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(newDoc));
NS_ENSURE_SUCCESS(rv, rv);
rv = SetDocument(newDoc);
NS_ENSURE_SUCCESS(rv, rv);
// Lazy authored instance documents have a root named "instanceData"
nsCOMPtr<nsIDOMElement> instanceDataElement;
nsCOMPtr<nsIDOMNode> childReturn;
rv = mDocument->CreateElementNS(EmptyString(),
NS_LITERAL_STRING("instanceData"),
getter_AddRefs(instanceDataElement));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->AppendChild(instanceDataElement, getter_AddRefs(childReturn));
NS_ENSURE_SUCCESS(rv, rv);
// I don't know if not being able to create a backup document is worth
// failing this function. Since it probably won't be used often, we'll
// let it slide. But it probably does mean that things are going south
// with the browser.
domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(mOriginalDocument));
NS_WARN_IF_FALSE(mOriginalDocument, "Couldn't create mOriginalDocument!!");
} else {
// Normal instance
// By the time this is called, we should be inserted in the document and
// have all of our child elements, so this is our first opportunity to
// create the instance document.
nsAutoString src;
mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
if (src.IsEmpty()) {
// If we don't have a linked external instance, use our inline data.
CloneInlineInstance();
} else {
LoadExternalInstance(src);
}
if (mLazy) { // Lazy instance
return CreateInstanceDocument(NS_LITERAL_STRING("instanceData"));
}
// Normal instance
nsAutoString src;
mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
if (src.IsEmpty()) {
return CloneInlineInstance();
}
LoadExternalInstance(src);
return NS_OK;
}
@ -466,7 +475,7 @@ nsresult
nsXFormsInstanceElement::CloneInlineInstance()
{
// Clear out our existing instance data
nsresult rv = CreateInstanceDocument();
nsresult rv = CreateInstanceDocument(EmptyString());
if (NS_FAILED(rv))
return rv; // don't warn, we might just not be in the document yet
@ -528,7 +537,7 @@ nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc)
strings, 1, mElement, mElement);
} else {
// Clear out our existing instance data
if (NS_SUCCEEDED(CreateInstanceDocument())) {
if (NS_SUCCEEDED(CreateInstanceDocument(EmptyString()))) {
nsCOMPtr<nsIDocument> newDoc = do_QueryInterface(mDocument);
nsCOMPtr<nsIURI> uri;
@ -581,7 +590,7 @@ nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc)
}
nsresult
nsXFormsInstanceElement::CreateInstanceDocument()
nsXFormsInstanceElement::CreateInstanceDocument(const nsAString &aQualifiedName)
{
nsCOMPtr<nsIDOMDocument> doc;
nsresult rv = mElement->GetOwnerDocument(getter_AddRefs(doc));
@ -595,7 +604,7 @@ nsXFormsInstanceElement::CreateInstanceDocument()
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMDocument> newDoc;
rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
rv = domImpl->CreateDocument(EmptyString(), aQualifiedName, nsnull,
getter_AddRefs(newDoc));
NS_ENSURE_SUCCESS(rv, rv);
@ -606,7 +615,7 @@ nsXFormsInstanceElement::CreateInstanceDocument()
// failing this function. Since it probably won't be used often, we'll
// let it slide. But it probably does mean that things are going south
// with the browser.
domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
domImpl->CreateDocument(EmptyString(), aQualifiedName, nsnull,
getter_AddRefs(mOriginalDocument));
return rv;
}

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

@ -75,6 +75,8 @@ public:
NS_IMETHOD OnDestroyed();
NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aNewValue);
NS_IMETHOD AttributeRemoved(nsIAtom *aName);
NS_IMETHOD WillChangeParent(nsIDOMElement *aNewParent);
NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent);
NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *aWrapper);
nsXFormsInstanceElement() NS_HIDDEN;
@ -82,7 +84,7 @@ public:
private:
NS_HIDDEN_(nsresult) CloneInlineInstance();
NS_HIDDEN_(void) LoadExternalInstance(const nsAString &aSrc);
NS_HIDDEN_(nsresult) CreateInstanceDocument();
NS_HIDDEN_(nsresult) CreateInstanceDocument(const nsAString &aQualifiedName);
NS_HIDDEN_(already_AddRefed<nsIModelElementPrivate>) GetModel();
nsCOMPtr<nsIDOMDocument> mDocument;

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

@ -260,6 +260,7 @@ nsXFormsModelElement::nsXFormsModelElement()
mDocumentLoaded(PR_FALSE),
mNeedsRefresh(PR_FALSE),
mInstancesInitialized(PR_FALSE),
mReadyHandled(PR_FALSE),
mInstanceDocuments(nsnull),
mLazyModel(PR_FALSE)
{
@ -551,6 +552,7 @@ nsXFormsModelElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled)
rv = ConstructDone();
} else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_Ready].name)) {
Ready();
mReadyHandled = PR_TRUE;
} else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_Reset].name)) {
Reset();
} else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_BindingException].name)) {
@ -1169,6 +1171,20 @@ nsXFormsModelElement::HandleInstanceDataNode(nsIDOMNode *aInstanceDataNode, unsi
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::GetLazyAuthored(PRBool *aLazyInstance)
{
*aLazyInstance = mLazyModel;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::GetIsReady(PRBool *aIsReady)
{
*aIsReady = mReadyHandled;
return NS_OK;
}
// nsIXFormsContextControl
NS_IMETHODIMP
@ -1224,13 +1240,6 @@ nsXFormsModelElement::GetContext(nsAString &aModelID,
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::GetLazyAuthored(PRBool *aLazyInstance)
{
*aLazyInstance = mLazyModel;
return NS_OK;
}
// internal methods
already_AddRefed<nsIDOMDocument>
@ -1474,7 +1483,7 @@ nsXFormsModelElement::MaybeNotifyCompletion()
for (i = 0; i < models->Count(); ++i) {
nsXFormsModelElement *model =
NS_STATIC_CAST(nsXFormsModelElement *, models->ElementAt(i));
nsXFormsUtils::DispatchEvent(model->mElement, eEvent_Ready);
nsXFormsUtils::DispatchEvent(model->mElement, eEvent_Ready);
}
}
@ -1700,6 +1709,15 @@ nsXFormsModelElement::AddInstanceElement(nsIInstanceElementPrivate *aInstEle)
return NS_OK;
}
nsresult
nsXFormsModelElement::RemoveInstanceElement(nsIInstanceElementPrivate *aInstEle)
{
NS_ENSURE_STATE(mInstanceDocuments);
mInstanceDocuments->RemoveInstance(aInstEle);
return NS_OK;
}
/* static */ void
nsXFormsModelElement::Startup()
{
@ -1911,6 +1929,12 @@ nsXFormsModelInstanceDocuments::AddInstance(nsIInstanceElementPrivate *aInst)
mInstanceList.AppendObject(aInst);
}
void
nsXFormsModelInstanceDocuments::RemoveInstance(nsIInstanceElementPrivate *aInst)
{
mInstanceList.RemoveObject(aInst);
}
void
nsXFormsModelInstanceDocuments::DropReferences()
{

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

@ -89,6 +89,13 @@ public:
*/
void AddInstance(nsIInstanceElementPrivate *aInstance);
/**
* Remove an instance element
*
* @param aInstance The instance element
*/
void RemoveInstance(nsIInstanceElementPrivate *aInstance);
/**
* Get the instance document at a given index
*
@ -268,13 +275,18 @@ private:
// This flag indicates whether instance elements have been initialized
PRBool mInstancesInitialized;
/**
* Indicates whether the model's handled the xforms-ready event already
*/
PRBool mReadyHandled;
/**
* All instance documents contained by this model, including lazy-authored
* instance documents.
*/
nsRefPtr<nsXFormsModelInstanceDocuments> mInstanceDocuments;
/** Indicates whether the model's instance was built by lazy authoring */
// Indicates whether the model's instance was built by lazy authoring
PRBool mLazyModel;
};