1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/windowing/windowserver/nonnga/graphicdrawer/graphicdrawerarray.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,457 @@
1.4 +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "WSGRAPHICDRAWERARRAY.H"
1.20 +#include "Graphics/WSGRAPHICDRAWER.H"
1.21 +#include <Graphics/WSGRAPHICDRAWERINTERFACE.H>
1.22 +#include "panics.h"
1.23 +
1.24 +// CWsGraphicDrawerArray::XRollBackBase \\\\\\\\\\\\\\\\\\\\\\\\
1.25 +
1.26 +/** Base class for cleanup operations - used as a handle for the CommitP() method
1.27 + This cleanup object is created on the heap with new(ELeave).
1.28 + It must be immediately pushed onto the cleanup stack, BEFORE the operation it protects,
1.29 + and must be written so that it does nothing until "activated" by the operation completing successfully.
1.30 + iArray==NULL indicates this state.
1.31 + This is because the client does not know whether the new(ELeave), the PushL, or the operational meat
1.32 + generated the exception, and therefore the operation must be the last exception thrown in the method.
1.33 + @internalComponent
1.34 + @released
1.35 +*/
1.36 +NONSHARABLE_STRUCT(CWsGraphicDrawerArray::XRollBackBase)
1.37 + {
1.38 +public:
1.39 + XRollBackBase(): iArray(NULL) {}
1.40 + virtual ~XRollBackBase() {}
1.41 +public:
1.42 + CWsGraphicDrawerArray* iArray;
1.43 + };
1.44 +// CWsGraphicDrawerArray::XAddRollBack \\\\\\\\\\\\\\\\\\\\\\\\
1.45 +
1.46 +/** Cleanup record for Add operation. Removes the array entry at the recorded array index.
1.47 + @internalComponent
1.48 + @released
1.49 +*/
1.50 +NONSHARABLE_STRUCT(CWsGraphicDrawerArray::XAddRollBack) :public CWsGraphicDrawerArray::XRollBackBase
1.51 + {
1.52 + TGraphicDrawerId iId;
1.53 + static void RollBackD(TAny* aAddRollBack);
1.54 + };
1.55 +
1.56 +/** Rolls back an adding of a drawer to an array, but does not delete the drawer.
1.57 + Removes the array entry at the given array index.
1.58 +*/
1.59 +void CWsGraphicDrawerArray::XAddRollBack::RollBackD(TAny* aAddRollBack)
1.60 + {
1.61 + __ASSERT_DEBUG(aAddRollBack,Panic(EWsGraphicDrawerPanicBadAddLCCleanup));
1.62 + if(aAddRollBack)
1.63 + {
1.64 + XAddRollBack* rollBack = static_cast<XAddRollBack*>(aAddRollBack);
1.65 + // iArray would be NULL if you pushed a NULL drawer in release builds
1.66 + //It can also be null if the Add operation Leaves
1.67 + if(rollBack->iArray)
1.68 + {
1.69 + rollBack->iArray->Remove(rollBack->iId);
1.70 + }
1.71 + delete rollBack;
1.72 + }
1.73 + }
1.74 +
1.75 +// CWsGraphicDrawerArray::XRemoveRollBack \\\\\\\\\\\\\\\\\\\\\\\\
1.76 +
1.77 +/** Cleanup record for Swap operation. Re-inserts the recorded drawer by finding its index.
1.78 + @internalComponent
1.79 + @released
1.80 +*/
1.81 +NONSHARABLE_STRUCT(CWsGraphicDrawerArray::XSwapRollBack) :public CWsGraphicDrawerArray::XRollBackBase
1.82 + {
1.83 + CWsGraphicDrawer* iDrawer;
1.84 + static void RollBackD(TAny* aSwapRollBack);
1.85 + };
1.86 +
1.87 +/** Rolls back the swapping (replacing) of a drawer to an array, but does not delete the replacing drawer.
1.88 + Re-inserts the recorded drawer by finding its index.
1.89 + */
1.90 +void CWsGraphicDrawerArray::XSwapRollBack::RollBackD(TAny* aSwapRollBack)
1.91 + {
1.92 + __ASSERT_DEBUG(aSwapRollBack,Panic(EWsGraphicDrawerPanicBadSwapLCCleanup));
1.93 + if(aSwapRollBack)
1.94 + {
1.95 + XSwapRollBack* rollBack = static_cast<XSwapRollBack*>(aSwapRollBack);
1.96 + // would be NULL if you removed an id that wasn't in the array in release builds
1.97 + // or if the swap itself Leaves
1.98 + if(rollBack->iArray)
1.99 + {
1.100 + const TInt idx = rollBack->iArray->IndexOf(rollBack->iDrawer->Id());
1.101 + __ASSERT_DEBUG(0 <= idx,Panic(EWsGraphicDrawerPanicBadSwapLCCleanup));
1.102 + if(0 <= idx) // hmm, don't see how this could ever happen. If it does, better to leak memory etc
1.103 + {
1.104 + rollBack->iArray->iArray[idx].iDrawer = rollBack->iDrawer;
1.105 + }
1.106 + }
1.107 + delete rollBack;
1.108 + }
1.109 + }
1.110 +
1.111 +// CWsGraphicDrawerArray::XRemoveRollBack \\\\\\\\\\\\\\\\\\\\\\\\
1.112 +
1.113 +/** Cleanup record for Remove operation. Re-inserts the recorded drawer by finding its index.
1.114 + @internalComponent
1.115 + @released
1.116 +*/
1.117 +NONSHARABLE_STRUCT(CWsGraphicDrawerArray::XRemoveRollBack) :public CWsGraphicDrawerArray::XRollBackBase
1.118 + {
1.119 + CWsGraphicDrawer* iDrawer;
1.120 + static void RollBackD(TAny* aSwapRollBack);
1.121 + };
1.122 +
1.123 +/** Rolls back the deleting of a drawer from an array, but does not delete the replacing drawer.
1.124 + Re-inserts the recorded drawer by finding its index.
1.125 + */
1.126 +void CWsGraphicDrawerArray::XRemoveRollBack::RollBackD(TAny* aRemoveRollBack)
1.127 + {
1.128 + __ASSERT_DEBUG(aRemoveRollBack,Panic(EWsGraphicDrawerPanicBadSwapLCCleanup));
1.129 + if(aRemoveRollBack)
1.130 + {
1.131 + XRemoveRollBack* rollBack = static_cast<XRemoveRollBack*>(aRemoveRollBack);
1.132 + // would be NULL if you removed an id that wasn't in the array in release builds
1.133 + // or if the swap itself Leaves
1.134 + if(rollBack->iArray)
1.135 + {
1.136 + TGraphic graphic;
1.137 + graphic.iId = rollBack->iDrawer->Id();
1.138 + graphic.iDrawer = rollBack->iDrawer;
1.139 + TInt errCode= rollBack->iArray->iArray.InsertInOrder(graphic,GraphicDrawerCompare); // dups not allowed
1.140 + //This should not happen unless some non-transactional method has modified the array
1.141 + //between the call and the leave.
1.142 + __ASSERT_DEBUG(KErrAlreadyExists != errCode,Panic(EWsGraphicDrawerPanicBadSwapLCCleanup));
1.143 + //Other memory failure errors should not occur unless the array has been Compress()ed
1.144 + //between the call and the leave, and then memory fails.
1.145 + __ASSERT_DEBUG(KErrNone <= errCode,Panic(EWsGraphicDrawerPanicBadSwapLCCleanup));
1.146 + }
1.147 + delete rollBack;
1.148 + }
1.149 + }
1.150 +
1.151 +// CWsGraphicDrawerArray \\\\\\\\\\\\\\\\\\\\\\\\
1.152 +
1.153 +/** Compares two graphic array slots for id equality; the iDrawer pointer is ignored.
1.154 + Used to order the array.
1.155 +@internalComponent
1.156 +@released
1.157 +*/
1.158 +TInt CWsGraphicDrawerArray::GraphicDrawerCompare(const TGraphic& aFirst,const TGraphic& aSecond)
1.159 + {
1.160 + return aFirst.iId.Compare(aSecond.iId);
1.161 + }
1.162 +
1.163 +/** Adds a drawer to the array, with a transactional cleanup item that automatically removes
1.164 + it until popped (not destroying the drawer, however). This operation leaks memory and should not be used.
1.165 + @deprecated - Use AddL or AddRLC
1.166 +*/
1.167 +EXPORT_C void CWsGraphicDrawerArray::AddLC(CWsGraphicDrawer* aDrawer)
1.168 + {
1.169 + __ASSERT_DEBUG(aDrawer,Panic(EWsGraphicDrawerPanicBadArgument));
1.170 + XAddRollBack* rollBack = new(ELeave) XAddRollBack;
1.171 + CleanupStack::PushL(TCleanupItem(XAddRollBack::RollBackD,rollBack));
1.172 + if(aDrawer)
1.173 + {
1.174 + User::LeaveIfError(Add(aDrawer));
1.175 + rollBack->iArray = this;
1.176 + rollBack->iId = aDrawer->Id();
1.177 + }
1.178 + }
1.179 +
1.180 +/** Adds a drawer to the array, with a transactional cleanup item that automatically removes
1.181 + it (not destroying the drawer, however).
1.182 + CommitP() must be called on the returned pointer to release resources owned by the cleanup item,
1.183 + unless a Leave occurs.
1.184 + @param aDrawer the drawer to add
1.185 + @return cleanup record
1.186 +*/
1.187 +EXPORT_C CWsGraphicDrawerArray::XRollBackBase* CWsGraphicDrawerArray::AddTLC(CWsGraphicDrawer* aDrawer)
1.188 + {
1.189 + if(!aDrawer)
1.190 + {
1.191 + User::Leave(KErrArgument);
1.192 + }
1.193 + //need to create the rollback before the add because the client can't tell the difference between
1.194 + //the add failing and the new(ELeave) failing!
1.195 + XAddRollBack* rollBack = new(ELeave) XAddRollBack;
1.196 + CleanupStack::PushL(TCleanupItem(XAddRollBack::RollBackD,rollBack));
1.197 + User::LeaveIfError(Add(aDrawer));
1.198 + rollBack->iId = aDrawer->Id();
1.199 + rollBack->iArray = this;
1.200 +
1.201 + return rollBack;
1.202 + }
1.203 +
1.204 +/** Adds a drawer to the array. No cleanup - no leak
1.205 + @param aDrawer the drawer to add
1.206 + @return error code if the Add did not take place
1.207 +*/
1.208 +EXPORT_C TInt CWsGraphicDrawerArray::Add(CWsGraphicDrawer* aDrawer)
1.209 + {
1.210 + if(aDrawer)
1.211 + {
1.212 + TGraphic graphic;
1.213 + graphic.iId = aDrawer->Id();
1.214 + graphic.iDrawer = aDrawer;
1.215 + return iArray.InsertInOrder(graphic,GraphicDrawerCompare); // dups not allowed
1.216 + }
1.217 + else
1.218 + return KErrArgument;
1.219 + }
1.220 +
1.221 +/*Internal method to swap the given drawer into the array, removing the existing one and returning a pointer to it.
1.222 + Note that in an error just a NULL pointer is returned.
1.223 + Internal caller must infer KErrNotFound error code.
1.224 + @param aDrawer the drawer to add
1.225 + @return the drawer displaced, or NULL if the operation did not take place
1.226 +*/
1.227 +CWsGraphicDrawer* CWsGraphicDrawerArray::SwapIn(CWsGraphicDrawer* aDrawer)
1.228 + {
1.229 + if (aDrawer==NULL)
1.230 + return NULL;
1.231 + const TInt idx = IndexOf(aDrawer->Id());
1.232 + if (idx<KErrNone)
1.233 + return NULL;
1.234 + CWsGraphicDrawer* rv= iArray[idx].iDrawer;
1.235 + iArray[idx].iDrawer=aDrawer;
1.236 + return rv;
1.237 + }
1.238 +
1.239 +/** Replaces the drawer with the existing Id with this newer one.
1.240 + Pushes a transactional cleanup item to restore the previous drawer.
1.241 + This operation leaks memory when it does not get Leave clean-up and should not be used.
1.242 + @deprecated - Use SwapL or SwapRLC
1.243 +*/
1.244 +EXPORT_C TInt CWsGraphicDrawerArray::SwapLC(CWsGraphicDrawer* aDrawer)
1.245 + {
1.246 + __ASSERT_DEBUG(aDrawer,Panic(EWsGraphicDrawerPanicBadArgument));
1.247 + XSwapRollBack* rollBack = new(ELeave) XSwapRollBack;
1.248 + CleanupStack::PushL(TCleanupItem(XSwapRollBack::RollBackD,rollBack));
1.249 + CWsGraphicDrawer* rollBackDrawer=SwapIn(aDrawer);
1.250 + if (rollBackDrawer)
1.251 + {
1.252 + rollBack->iArray = this;
1.253 + rollBack->iDrawer = rollBackDrawer;
1.254 + return KErrNone;
1.255 + }
1.256 + else
1.257 + {
1.258 + __ASSERT_DEBUG(0,Panic(EWsGraphicDrawerPanicBadArgument));
1.259 + return KErrNotFound;
1.260 + }
1.261 + }
1.262 +
1.263 +/** Replaces the drawer with the existing Id with this newer one.
1.264 + Pushes a transactional cleanup item to restore the previous drawer.
1.265 + CommitP() must be called on the returned pointer to release resources owned by the cleanup item,
1.266 + unless a Leave occurs.
1.267 + @param aDrawer the drawer to add
1.268 + @return cleanup record
1.269 +*/
1.270 +EXPORT_C CWsGraphicDrawerArray::XRollBackBase* CWsGraphicDrawerArray::SwapTLC(CWsGraphicDrawer* aDrawer)
1.271 + {
1.272 + if (!aDrawer)
1.273 + User::Leave(KErrArgument);
1.274 + XSwapRollBack* rollBack = new(ELeave) XSwapRollBack;
1.275 + CleanupStack::PushL(TCleanupItem(XSwapRollBack::RollBackD,rollBack));
1.276 + CWsGraphicDrawer* rollBackDrawer=SwapIn(aDrawer);
1.277 + if (!rollBackDrawer)
1.278 + User::Leave(KErrNotFound);
1.279 + rollBack->iDrawer = rollBackDrawer;
1.280 + rollBack->iArray = this;
1.281 + return rollBack;
1.282 + }
1.283 +
1.284 +/** Replaces the drawer with the existing Id with this newer one. No cleanup - no leak
1.285 + @param aDrawer the drawer to add
1.286 + @return error code if the Swap did not take place
1.287 +*/
1.288 +EXPORT_C TInt CWsGraphicDrawerArray::Swap(CWsGraphicDrawer* aDrawer)
1.289 + {
1.290 + if (!aDrawer)
1.291 + return KErrArgument;
1.292 + CWsGraphicDrawer* oldDrawer=SwapIn(aDrawer);
1.293 + if (!oldDrawer)
1.294 + return KErrNotFound;
1.295 + else
1.296 + return KErrNone;
1.297 + }
1.298 +
1.299 +/** Removes the cleanup record after a SwapTLC or AddTLC operation,
1.300 + removing the opportunity to back out of the operation.
1.301 + Note that SwapTLC, AddTLC, and RemoveTLC cleanup operations can be stacked and should be committed
1.302 + in the opposite order. They cannot be safely intermingled with non-transactional operations.
1.303 + This method can be safely called with a NULL parameter indicating a failed operation.
1.304 + @param aRollBack handle to rollback information that will be discarded.
1.305 +**/
1.306 +EXPORT_C void CWsGraphicDrawerArray::CommitP(CWsGraphicDrawerArray::XRollBackBase* aRollBack)
1.307 + {
1.308 + if (aRollBack)
1.309 + {
1.310 + CleanupStack::Pop(aRollBack);
1.311 + delete aRollBack;
1.312 + }
1.313 + }
1.314 +
1.315 +/** Removes the specified drawer from the array.
1.316 + Pushes a transactional cleanup item to restore the previous drawer.
1.317 + @note The array should not be Compressed() during the transaction period
1.318 + to ensure that the RollBack operation will always succeed.
1.319 + @param aId the ID of the drawer to remove
1.320 + @return cleanup record
1.321 +*/
1.322 +EXPORT_C CWsGraphicDrawerArray::XRollBackBase* CWsGraphicDrawerArray::RemoveTLC(const TGraphicDrawerId& aId)
1.323 + {
1.324 + XRemoveRollBack* rollBack = new(ELeave) XRemoveRollBack;
1.325 + CleanupStack::PushL(TCleanupItem(XRemoveRollBack::RollBackD,rollBack));
1.326 + const TInt idx = IndexOf(aId);
1.327 + if(0 > idx)
1.328 + {
1.329 + User::Leave(idx);
1.330 + }
1.331 + rollBack->iDrawer=iArray[idx].iDrawer;
1.332 + iArray.Remove(idx);
1.333 + rollBack->iArray=this;
1.334 + return rollBack;
1.335 + }
1.336 +
1.337 +/** Removes the specified drawer from the array
1.338 + @param aId the ID of the drawer to remove
1.339 + @return KErrNone if the drawer was removed, KErrNotFound if the drawer was not in the array
1.340 +*/
1.341 +EXPORT_C TInt CWsGraphicDrawerArray::Remove(const TGraphicDrawerId& aId)
1.342 + {
1.343 + const TInt idx = IndexOf(aId);
1.344 + if(0 <= idx)
1.345 + {
1.346 + iArray.Remove(idx);
1.347 + return KErrNone;
1.348 + }
1.349 + return idx;
1.350 + }
1.351 +
1.352 +EXPORT_C TInt CWsGraphicDrawerArray::RemoveAndDestroy(const TGraphicDrawerId& aId)
1.353 +/** Removes and deletes the specified drawer from the array
1.354 + @param aId the ID of the drawer to remove and delete
1.355 + @return KErrNone if the drawer was removed and deleted, KErrNotFound if the drawer was not in the array
1.356 +*/ {
1.357 + const TInt idx = IndexOf(aId);
1.358 + if(0 <= idx)
1.359 + {
1.360 + delete iArray[idx].iDrawer;
1.361 + iArray.Remove(idx);
1.362 + return KErrNone;
1.363 + }
1.364 + return idx;
1.365 + }
1.366 +
1.367 +/** Removes all drawers from the array which are owned by the specified client session
1.368 + @param aOwner the client session that owns the drawers to be removed
1.369 + @return the number of drawers that were removed
1.370 +*/
1.371 +EXPORT_C TInt CWsGraphicDrawerArray::RemoveAll(const MWsClient& aOwner)
1.372 + {
1.373 + TInt removed = 0;
1.374 + TInt count = iArray.Count();
1.375 + TInt i = 0;
1.376 + while(i < count)
1.377 + {
1.378 + if(iArray[i].iDrawer && (&(iArray[i].iDrawer->Owner()) == &aOwner))
1.379 + {
1.380 + iArray.Remove(i);
1.381 + count--;
1.382 + removed++;
1.383 + }
1.384 + else
1.385 + {
1.386 + i++;
1.387 + }
1.388 + }
1.389 + return removed;
1.390 + }
1.391 +
1.392 +/** Removes and deletes all drawers from the array which are owned by the specified client session
1.393 + @param aOwner the client session that owns the drawers to be removed and deleted
1.394 + @return the number of drawers that were removed and deleted
1.395 +*/
1.396 +EXPORT_C TInt CWsGraphicDrawerArray::RemoveAndDestroyAll(const MWsClient& aOwner)
1.397 + {
1.398 + TInt removed = 0;
1.399 + TInt count = iArray.Count();
1.400 + TInt i = 0;
1.401 + while(i < count)
1.402 + {
1.403 + if(iArray[i].iDrawer && (&(iArray[i].iDrawer->Owner()) == &aOwner))
1.404 + {
1.405 + delete iArray[i].iDrawer;
1.406 + iArray.Remove(i);
1.407 + count--;
1.408 + removed++;
1.409 + }
1.410 + else
1.411 + {
1.412 + i++;
1.413 + }
1.414 + }
1.415 + return removed;
1.416 + }
1.417 +
1.418 +EXPORT_C const CWsGraphicDrawer* CWsGraphicDrawerArray::ResolveGraphic(const TGraphicDrawerId& aId) const
1.419 +/** Find a graphic by it's ID
1.420 + @param aId the ID of the graphic to find
1.421 + @return the drawer if it is in the array, else NULL
1.422 +*/ {
1.423 + const TInt idx = IndexOf(aId);
1.424 + if(KErrNotFound != idx)
1.425 + {
1.426 + return iArray[idx].iDrawer;
1.427 + }
1.428 + return NULL;
1.429 + }
1.430 +
1.431 +EXPORT_C void CWsGraphicDrawerArray::Close()
1.432 +/** Close the array, not destroying the drawers that it indexes
1.433 +*/ {
1.434 + iArray.Close();
1.435 + }
1.436 +
1.437 +EXPORT_C void CWsGraphicDrawerArray::ResetAndDestroy()
1.438 +/** Reset the array, destroying the drawers that it indexes.
1.439 +Only the 'owner' array should call this
1.440 +*/ {
1.441 + const TInt count = iArray.Count();
1.442 + for(TInt i=0; i<count; i++)
1.443 + {
1.444 + delete iArray[i].iDrawer;
1.445 + }
1.446 + iArray.Reset();
1.447 + }
1.448 +
1.449 +EXPORT_C TBool CWsGraphicDrawerArray::IsEmpty() const
1.450 +/** @return ETrue if the array contains no drawers
1.451 +*/ {
1.452 + return !iArray.Count();
1.453 + }
1.454 +
1.455 +TInt CWsGraphicDrawerArray::IndexOf(const TGraphicDrawerId& aId) const
1.456 +/** @internalComponent
1.457 +*/ {
1.458 + return iArray.FindInOrder(reinterpret_cast<const TGraphic&>(aId),GraphicDrawerCompare);
1.459 + }
1.460 +