Back to index

lightning-sunbird  0.9+nobinonly
nsXFormsOutputElement.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla XForms support.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Novell, Inc.
00019  * Portions created by the Initial Developer are Copyright (C) 2004
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *  Allan Beaufour <abeaufour@novell.com>
00024  *  Olli Pettay <Olli.Pettay@helsinki.fi>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #ifdef DEBUG
00041 //#define DEBUG_XF_OUTPUT
00042 #endif
00043 
00044 #include "nsAutoPtr.h"
00045 #include "nsCOMPtr.h"
00046 #include "nsMemory.h"
00047 #include "nsString.h"
00048 #include "nsDOMString.h"
00049 #include "nsIDOM3Node.h"
00050 #include "nsIDOMDocument.h"
00051 #include "nsIDOMElement.h"
00052 #include "nsIDOMEventTarget.h"
00053 #include "nsIDOMXPathExpression.h"
00054 #include "nsIDOMXPathResult.h"
00055 #include "nsISchema.h"
00056 
00057 #include "nsIModelElementPrivate.h"
00058 #include "nsXFormsDelegateStub.h"
00059 #include "nsXFormsAtoms.h"
00060 #include "nsXFormsUtils.h"
00061 #include "nsIXFormsUIWidget.h"
00062 #include "nsXFormsModelElement.h"
00063 
00064 
00074 class nsXFormsOutputElement : public nsXFormsDelegateStub
00075 {
00076 public:
00077   // nsIXFormsControl
00078   NS_IMETHOD Bind(PRBool* aContextChanged);
00079   NS_IMETHOD Refresh();
00080   NS_IMETHOD GetBoundNode(nsIDOMNode **aBoundNode);
00081 
00082   // nsIXFormsDelegate
00083   NS_IMETHOD GetValue(nsAString& aValue);
00084   NS_IMETHOD SetValue(const nsAString& aValue);
00085   NS_IMETHOD GetHasBoundNode(PRBool *aHasBoundNode);
00086 
00087   virtual PRBool IsContentAllowed();
00088 
00089   nsXFormsOutputElement();
00090 
00091 private:
00092   // The value of the "value" attribute (if any). Updated by Bind()
00093   nsString       mValue;
00094 
00095   // Use the "value" attribute
00096   PRBool         mUseValueAttribute;
00097 };
00098 
00099 nsXFormsOutputElement::nsXFormsOutputElement()
00100   : nsXFormsDelegateStub(NS_LITERAL_STRING("output")),
00101     mUseValueAttribute(PR_FALSE)
00102 {
00103 }
00104 
00105 // nsIXFormsControl
00106 
00107 nsresult
00108 nsXFormsOutputElement::Bind(PRBool *aContextChanged)
00109 {
00110   SetDOMStringToNull(mValue);
00111   mUseValueAttribute = PR_FALSE;
00112 
00113   nsresult rv = nsXFormsDelegateStub::Bind(aContextChanged);
00114   NS_ENSURE_SUCCESS(rv, rv);
00115 
00116   if (!mHasParent || !mElement || rv == NS_OK_XFORMS_DEFERRED)
00117     return NS_OK;
00118 
00119   // Besides the standard single node binding (SNB) attributes, <output>
00120   // also has a "value" attribute, which is used when there are not other SNB
00121   // attributes.
00122   if (!HasBindingAttribute()) {
00123     mUseValueAttribute = PR_TRUE;
00124   } else {
00125     PRBool hasAttr;
00126     rv = mElement->HasAttribute(NS_LITERAL_STRING("ref"), &hasAttr);
00127     NS_ENSURE_SUCCESS(rv, rv);
00128     if (!hasAttr) {
00129       rv = mElement->HasAttribute(NS_LITERAL_STRING("bind"), &hasAttr);
00130       NS_ENSURE_SUCCESS(rv, rv);
00131       mUseValueAttribute = !hasAttr;
00132     }
00133   }
00134 
00135   if (!mUseValueAttribute)
00136     return NS_OK;
00137 
00138   // Bind to model and set mBoundNode . The bound node is used for setting
00139   // context for our children (our parent's context in the case of @value),
00140   // and the call to ProcessNodeBinding() will not set it.
00141   rv = BindToModel(PR_TRUE);
00142   NS_ENSURE_SUCCESS(rv, rv);
00143 
00144   // Process node binding
00145   nsCOMPtr<nsIDOMXPathResult> result;
00146   rv = ProcessNodeBinding(NS_LITERAL_STRING("value"),
00147                           nsIDOMXPathResult::STRING_TYPE,
00148                           getter_AddRefs(result));
00149   NS_ENSURE_SUCCESS(rv, rv);
00150 
00151   if (rv == NS_OK_XFORMS_DEFERRED) {
00152     // Can't leave the output in the model list.  Since the xforms processor
00153     // is still deferring binds any contextcontrol helping to set the context
00154     // for the output's value expression probably isn't in the control list
00155     // yet.  And if that's the case, we can't have the output in the list
00156     // before the contextcontrol or the output won't bind right once the
00157     // deferred binds finallyhappen.  If we got mBoundNode in addition to
00158     // mModel during BindToModel, it isn't likely good, either, so junk it, too.
00159     mBoundNode = nsnull;
00160     if (mModel) {
00161       mModel->RemoveFormControl(this);
00162       mModel = nsnull;
00163     }
00164   
00165     return NS_OK;
00166   }
00167 
00168   if (result) {
00169     rv = result->GetStringValue(mValue);
00170     NS_ENSURE_SUCCESS(rv, rv);
00171   }
00172 
00173   return NS_OK;
00174 }
00175 
00176 NS_IMETHODIMP
00177 nsXFormsOutputElement::Refresh()
00178 {
00179   return nsXFormsDelegateStub::Refresh();
00180 }
00181 
00182 NS_IMETHODIMP
00183 nsXFormsOutputElement::GetBoundNode(nsIDOMNode **aBoundNode)
00184 {
00185   return !mUseValueAttribute ? nsXFormsDelegateStub::GetBoundNode(aBoundNode)
00186                              : NS_OK;
00187 }
00188 
00189 NS_IMETHODIMP
00190 nsXFormsOutputElement::GetHasBoundNode(PRBool *aHasBoundNode)
00191 {
00192   NS_ENSURE_ARG_POINTER(aHasBoundNode);
00193   *aHasBoundNode = (mBoundNode && !mUseValueAttribute) ? PR_TRUE : PR_FALSE;
00194   return NS_OK;
00195 }
00196 
00197 NS_IMETHODIMP
00198 nsXFormsOutputElement::GetValue(nsAString& aValue)
00199 {
00200   if (mUseValueAttribute) {
00201     aValue = mValue;
00202     return NS_OK;
00203   }
00204 
00205   return nsXFormsDelegateStub::GetValue(aValue);
00206 }
00207 
00208 NS_IMETHODIMP
00209 nsXFormsOutputElement::SetValue(const nsAString& aValue)
00210 {
00211   // Setting the value on an output controls seems wrong semantically.
00212   return NS_ERROR_NOT_AVAILABLE;
00213 }
00214 
00215 PRBool
00216 nsXFormsOutputElement::IsContentAllowed()
00217 {
00218   PRBool isAllowed = PR_TRUE;
00219 
00220   // Output may not be bound to complexContent.
00221   PRBool isComplex = IsContentComplex();
00222   if (isComplex) {
00223     isAllowed = PR_FALSE;
00224   }
00225   return isAllowed;
00226 }
00227 
00228 NS_HIDDEN_(nsresult)
00229 NS_NewXFormsOutputElement(nsIXTFElement **aResult)
00230 {
00231   *aResult = new nsXFormsOutputElement();
00232   if (!*aResult)
00233     return NS_ERROR_OUT_OF_MEMORY;
00234 
00235   NS_ADDREF(*aResult);
00236   return NS_OK;
00237 }