/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla XForms support. * * The Initial Developer of the Original Code is IBM Corporation. * Portions created by the Initial Developer are Copyright (C) 2004 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsIXTFXMLVisual.h" #include "nsIDOM3Node.h" #include "nsIDOMElement.h" #include "nsIDOMUIEvent.h" #include "nsIDOMEventTarget.h" #include "nsIDOMDocumentEvent.h" #include "nsIDOMDocument.h" #include "nsIDOMHTMLElement.h" #include "nsIDOMHTMLButtonElement.h" #include "nsIDOMDocumentView.h" #include "nsIDOMAbstractView.h" #include "nsCOMPtr.h" #include "nsString.h" #include "nsIXTFXMLVisualWrapper.h" #include "nsXFormsAtoms.h" #include "nsXFormsUtils.h" #include "nsXFormsControlStub.h" #include "nsIXFormsSubmitElement.h" #include "nsIXFormsSubmissionElement.h" class nsXFormsTriggerElement : public nsXFormsControlStub { public: // nsIXTFXMLVisual overrides NS_IMETHOD OnCreated(nsIXTFXMLVisualWrapper *aWrapper); // nsIXTFVisual overrides NS_IMETHOD GetVisualContent(nsIDOMElement **aElement); NS_IMETHOD GetInsertionPoint(nsIDOMElement **aElement); // nsIXTFElement overrides NS_IMETHOD BeginAddingChildren(); NS_IMETHOD DoneAddingChildren(); NS_IMETHOD AttributeRemoved(nsIAtom *aName); NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aValue); // nsIXFormsControl NS_IMETHOD HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled); NS_IMETHOD Refresh(); NS_IMETHOD TryFocus(PRBool* aOK); // nsXFormsTriggerElement nsXFormsTriggerElement() : mIsMinimal(PR_FALSE), mDoneAddingChildren(PR_TRUE) {} protected: nsCOMPtr mVisualContent; nsCOMPtr mHTMLElement; nsCOMPtr mInsertionPoint; PRPackedBool mIsMinimal; PRPackedBool mDoneAddingChildren; }; // nsIXTFXMLVisual NS_IMETHODIMP nsXFormsTriggerElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper) { nsresult rv = nsXFormsControlStub::OnCreated(aWrapper); NS_ENSURE_SUCCESS(rv, rv); aWrapper->SetNotificationMask(kStandardNotificationMask | nsIXTFElement::NOTIFY_HANDLE_DEFAULT | nsIXTFElement::NOTIFY_BEGIN_ADDING_CHILDREN | nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN | nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED); ResetHelpAndHint(PR_TRUE); nsCOMPtr domDoc; mElement->GetOwnerDocument(getter_AddRefs(domDoc)); NS_ENSURE_STATE(domDoc); // Create visual (span + button) domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML), NS_LITERAL_STRING("span"), getter_AddRefs(mVisualContent)); nsCOMPtr button; domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML), NS_LITERAL_STRING("button"), getter_AddRefs(button)); nsCOMPtr insertedButton; mVisualContent->AppendChild(button, getter_AddRefs(insertedButton)); mHTMLElement = do_QueryInterface(insertedButton); NS_ENSURE_STATE(mHTMLElement); // Create insertion point nsCOMPtr span; domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML), NS_LITERAL_STRING("span"), getter_AddRefs(span)); NS_ENSURE_STATE(span); nsCOMPtr insertedSpan; rv = mHTMLElement->AppendChild(span, getter_AddRefs(insertedSpan)); NS_ENSURE_SUCCESS(rv, rv); mInsertionPoint = do_QueryInterface(insertedSpan); NS_ENSURE_STATE(mInsertionPoint); return NS_OK; } // nsIXTFVisual NS_IMETHODIMP nsXFormsTriggerElement::GetVisualContent(nsIDOMElement **aElement) { NS_ADDREF(*aElement = mVisualContent); return NS_OK; } NS_IMETHODIMP nsXFormsTriggerElement::GetInsertionPoint(nsIDOMElement **aElement) { NS_ADDREF(*aElement = mInsertionPoint); return NS_OK; } NS_IMETHODIMP nsXFormsTriggerElement::BeginAddingChildren() { mDoneAddingChildren = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsXFormsTriggerElement::DoneAddingChildren() { mDoneAddingChildren = PR_TRUE; return NS_OK; } NS_IMETHODIMP nsXFormsTriggerElement::AttributeRemoved(nsIAtom *aName) { return aName == nsXFormsAtoms::appearance ? AttributeSet(aName, EmptyString()) : nsXFormsControlStub::AttributeRemoved(aName); } NS_IMETHODIMP nsXFormsTriggerElement::AttributeSet(nsIAtom *aName, const nsAString &aValue) { if (aName == nsXFormsAtoms::appearance) { if (mIsMinimal != aValue.EqualsLiteral("minimal")) { nsCOMPtr parent, next, tmp; if (mDoneAddingChildren) { mElement->GetParentNode(getter_AddRefs(parent)); if (parent) { mElement->GetNextSibling(getter_AddRefs(next)); // Removing this element temporarily from the document so that // the UI will be re-created properly later. parent->RemoveChild(mElement, getter_AddRefs(tmp)); } } // Switch state mIsMinimal = !mIsMinimal; // Create new element nsCOMPtr domDoc; mVisualContent->GetOwnerDocument(getter_AddRefs(domDoc)); NS_ENSURE_STATE(domDoc); nsCOMPtr htmlElement; if (mIsMinimal) { domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML), NS_LITERAL_STRING("span"), getter_AddRefs(htmlElement)); } else { domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML), NS_LITERAL_STRING("button"), getter_AddRefs(htmlElement)); } NS_ENSURE_STATE(htmlElement); // Append inner content (insertion point) nsCOMPtr newnode; nsresult rv = htmlElement->AppendChild(mInsertionPoint, getter_AddRefs(newnode)); NS_ENSURE_SUCCESS(rv, rv); // Replace current visual rv = mVisualContent->ReplaceChild(htmlElement, mHTMLElement, getter_AddRefs(tmp)); mHTMLElement = do_QueryInterface(htmlElement); if (mDoneAddingChildren && parent) parent->InsertBefore(mElement, next, getter_AddRefs(tmp)); } } else { nsXFormsControlStub::AttributeSet(aName, aValue); } return NS_OK; } NS_IMETHODIMP nsXFormsTriggerElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled) { nsresult rv; rv = nsXFormsControlStub::HandleDefault(aEvent, aHandled); NS_ENSURE_SUCCESS(rv, rv); if (*aHandled || !mIsMinimal) { return NS_OK; } nsAutoString type; aEvent->GetType(type); // Check for click on minimal trigger if (!(*aHandled = type.EqualsLiteral("click"))) return NS_OK; // We need to dend DOMActivate nsCOMPtr target = do_QueryInterface(mElement); NS_ENSURE_STATE(target); nsCOMPtr domDoc; mElement->GetOwnerDocument(getter_AddRefs(domDoc)); nsCOMPtr doc = do_QueryInterface(domDoc); NS_ENSURE_STATE(doc); nsCOMPtr dView = do_QueryInterface(domDoc); NS_ENSURE_STATE(dView); nsCOMPtr aView; dView->GetDefaultView(getter_AddRefs(aView)); NS_ENSURE_STATE(aView); nsCOMPtr event; doc->CreateEvent(NS_LITERAL_STRING("UIEvents"), getter_AddRefs(event)); nsCOMPtr uiEvent = do_QueryInterface(event); NS_ENSURE_TRUE(uiEvent, NS_ERROR_OUT_OF_MEMORY); uiEvent->InitUIEvent(NS_LITERAL_STRING("DOMActivate"), PR_TRUE, PR_TRUE, aView, 1); // Simple click PRBool cancelled; return target->DispatchEvent(uiEvent, &cancelled); } // nsIXFormsControl NS_IMETHODIMP nsXFormsTriggerElement::Refresh() { return NS_OK; } NS_IMETHODIMP nsXFormsTriggerElement::TryFocus(PRBool *aOK) { *aOK = GetRelevantState() && nsXFormsUtils::FocusControl(mHTMLElement); return NS_OK; } //----------------------------------------------------------------------------- class nsXFormsSubmitElement : public nsXFormsTriggerElement, public nsIXFormsSubmitElement { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIXFORMSSUBMITELEMENT // nsIXTFElement overrides NS_IMETHOD HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled); }; NS_IMPL_ISUPPORTS_INHERITED1(nsXFormsSubmitElement, nsXFormsTriggerElement, nsIXFormsSubmitElement) // nsIXTFElement NS_IMETHODIMP nsXFormsSubmitElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled) { nsresult rv; rv = nsXFormsTriggerElement::HandleDefault(aEvent, aHandled); NS_ENSURE_SUCCESS(rv, rv); if (*aHandled) { return NS_OK; } nsAutoString type; aEvent->GetType(type); if (!(*aHandled = type.EqualsLiteral("DOMActivate"))) return NS_OK; NS_NAMED_LITERAL_STRING(submission, "submission"); nsAutoString submissionID; mElement->GetAttribute(submission, submissionID); nsCOMPtr ownerDoc; mElement->GetOwnerDocument(getter_AddRefs(ownerDoc)); NS_ENSURE_STATE(ownerDoc); nsCOMPtr submissionElement; ownerDoc->GetElementById(submissionID, getter_AddRefs(submissionElement)); nsCOMPtr xfSubmission(do_QueryInterface(submissionElement)); if (!xfSubmission) { const PRUnichar *strings[] = { submissionID.get(), submission.get() }; nsXFormsUtils::ReportError(NS_LITERAL_STRING("idRefError"), strings, 2, mElement, mElement); return nsXFormsUtils::DispatchEvent(mElement, eEvent_BindingException); } xfSubmission->SetActivator(this); nsXFormsUtils::DispatchEvent(submissionElement, eEvent_Submit); *aHandled = PR_TRUE; return NS_OK; } NS_IMETHODIMP nsXFormsSubmitElement::SetDisabled(PRBool aDisable) { /// /// @todo Fix SetDisabled() behaviour when mIsMinimal == PR_TRUE (XXX) nsCOMPtr button = do_QueryInterface(mHTMLElement); if (button) button->SetDisabled(aDisable); return NS_OK; } //----------------------------------------------------------------------------- NS_HIDDEN_(nsresult) NS_NewXFormsTriggerElement(nsIXTFElement **aResult) { *aResult = new nsXFormsTriggerElement(); if (!*aResult) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(*aResult); return NS_OK; } NS_HIDDEN_(nsresult) NS_NewXFormsSubmitElement(nsIXTFElement **aResult) { *aResult = new nsXFormsSubmitElement(); if (!*aResult) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(*aResult); return NS_OK; }