Back to index

lightning-sunbird  0.9+nobinonly
nsSVGStringProxyValue.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 the Mozilla SVG project.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Crocodile Clips Ltd..
00019  * Portions created by the Initial Developer are Copyright (C) 2004
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Alex Fritze <alex@croczilla.com> (original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsSVGValue.h"
00040 #include "nsWeakReference.h"
00041 
00043 // nsSVGStringProxyValue implementation
00044 //
00045 // This class is intended to sit between a client and an nsISVGValue object.
00046 // It is used to allow mapped SVG attributes (which store their value in parsed
00047 // form) to assume any string value. This is needed for SVG to work properly with
00048 // XUL templates, where we have XML like this: <svg:circle r="?r"/>.
00049 //
00050 // When nsSVGStringProxyValue::SetValueString() will attempt to call its
00051 // proxied object's SetValueString method. If that call fails, nsSVGStringProxyValue
00052 // will cache the string and return it for subsequent invocations of GetValueString().
00053 // If the call succeeds, however, invocations of GetValueString() will call the
00054 // proxied objects's GetValueString() method.
00055 // If the proxied object's data is changed internally, invocations of GetValueString()
00056 // will also return the proxied object's GetValueString().
00057 
00058 
00059 class nsSVGStringProxyValue : public nsSVGValue,
00060                               public nsISVGValueObserver,
00061                               public nsSupportsWeakReference
00062 {
00063 protected:
00064   friend nsresult
00065   NS_CreateSVGStringProxyValue(nsISVGValue* proxiedValue, nsISVGValue** aResult);
00066   
00067   nsSVGStringProxyValue();
00068   virtual ~nsSVGStringProxyValue();
00069   PRBool Init(nsISVGValue* proxiedValue);
00070   
00071 public:
00072   NS_DECL_ISUPPORTS
00073 
00074   // nsISVGValue interface: 
00075   NS_IMETHOD SetValueString(const nsAString& aValue);
00076   NS_IMETHOD GetValueString(nsAString& aValue);
00077 
00078   // nsISVGValueObserver
00079   NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable,
00080                                      modificationType aModType);
00081   NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
00082                                      modificationType aModType);
00083 
00084   // nsISupportsWeakReference
00085   // implementation inherited from nsSupportsWeakReference
00086 
00087 protected:
00088   nsString mCachedValue;
00089   nsCOMPtr<nsISVGValue> mProxiedValue;
00090   PRBool mUseCachedValue;
00091 };
00092 
00093 //----------------------------------------------------------------------
00094 
00095 nsresult
00096 NS_CreateSVGStringProxyValue(nsISVGValue* proxiedValue,
00097                              nsISVGValue** aResult)
00098 {
00099   *aResult = nsnull;
00100   
00101   nsSVGStringProxyValue *sp = new nsSVGStringProxyValue();
00102   if(!sp) return NS_ERROR_OUT_OF_MEMORY;
00103   NS_ADDREF(sp);
00104   if (!sp->Init(proxiedValue)) {
00105     NS_RELEASE(sp);
00106     return NS_ERROR_FAILURE;
00107   }
00108   
00109   *aResult = sp;
00110   return NS_OK;
00111 }
00112 
00113 nsSVGStringProxyValue::nsSVGStringProxyValue()
00114 {
00115 #ifdef DEBUG
00116   printf("nsSVGStringProxyValue CTOR\n");
00117 #endif
00118 }
00119 
00120 nsSVGStringProxyValue::~nsSVGStringProxyValue()
00121 {
00122   mProxiedValue->RemoveObserver(this);
00123 #ifdef DEBUG
00124   printf("nsSVGStringProxyValue DTOR\n");
00125 #endif
00126 }
00127 
00128 PRBool nsSVGStringProxyValue::Init(nsISVGValue* proxiedValue)
00129 {
00130   mProxiedValue = proxiedValue;
00131   mProxiedValue->AddObserver(this);
00132   return PR_TRUE;
00133 }  
00134 
00135 //----------------------------------------------------------------------
00136 // nsISupports methods:
00137 
00138 NS_IMPL_ADDREF(nsSVGStringProxyValue)
00139 NS_IMPL_RELEASE(nsSVGStringProxyValue)
00140 
00141 NS_INTERFACE_MAP_BEGIN(nsSVGStringProxyValue)
00142   NS_INTERFACE_MAP_ENTRY(nsISVGValue)
00143   NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
00144   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
00145   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue)
00146 NS_INTERFACE_MAP_END
00147 
00148 //----------------------------------------------------------------------
00149 // nsISVGValue methods:
00150 
00151 NS_IMETHODIMP
00152 nsSVGStringProxyValue::SetValueString(const nsAString& aValue)
00153 {
00154 #ifdef DEBUG
00155   printf("nsSVGStringProxyValue(%p)::SetValueString(%s)\n", this, NS_ConvertUCS2toUTF8(aValue).get());
00156 #endif
00157   if (NS_FAILED(mProxiedValue->SetValueString(aValue))) {
00158 #ifdef DEBUG
00159     printf("  -> call failed, now using cached value\n");
00160 #endif
00161     mUseCachedValue = PR_TRUE; // mUseCachedValue will be reset in DidModifySVGObservable, 
00162                                // should the inner object ever change state internally
00163     mCachedValue = aValue;
00164   }
00165   return NS_OK;
00166 }
00167 
00168 NS_IMETHODIMP
00169 nsSVGStringProxyValue::GetValueString(nsAString& aValue)
00170 {
00171   if (!mUseCachedValue)
00172     return mProxiedValue->GetValueString(aValue);
00173 
00174   aValue = mCachedValue;
00175   return NS_OK;
00176 }
00177 
00178 
00179 //----------------------------------------------------------------------
00180 // nsISVGValueObserver methods
00181 
00182 NS_IMETHODIMP
00183 nsSVGStringProxyValue::WillModifySVGObservable(nsISVGValue* observable,
00184                                                modificationType aModType)
00185 {
00186   WillModify(aModType);
00187   return NS_OK;
00188 }
00189 
00190 NS_IMETHODIMP
00191 nsSVGStringProxyValue::DidModifySVGObservable (nsISVGValue* observable,
00192                                                modificationType aModType)
00193 {
00194   // Our internal proxied object has set its state internally.
00195   // Make sure its new value takes priority over our cached string:
00196   mUseCachedValue = PR_FALSE;
00197   
00198   DidModify(aModType);
00199   return NS_OK;
00200 }