os/graphics/windowing/windowserver/nonnga/graphicdrawer/graphicdrawerarray.cpp
changeset 0 bde4ae8d615e
     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 +