windowing/windowserver/nga/graphicdrawer/graphicdrawerarray.cpp
changeset 0 5d03bc08d59c
child 121 d72fc2aace31
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "WSGRAPHICDRAWERARRAY.H"
       
    17 #include "Graphics/WSGRAPHICDRAWER.H"
       
    18 #include <Graphics/WSGRAPHICDRAWERINTERFACE.H>
       
    19 #include "panics.h"
       
    20 
       
    21 // CWsGraphicDrawerArray::XRollBackBase \\\\\\\\\\\\\\\\\\\\\\\\
       
    22 
       
    23 /** Base class for cleanup operations - used as a handle for the CommitP() method
       
    24 	This cleanup object is created on the heap with new(ELeave).
       
    25 	It must be immediately pushed onto the cleanup stack, BEFORE the operation it protects,
       
    26 	and must be written so that it does nothing until "activated" by the operation completing successfully.
       
    27 	iArray==NULL indicates this state.
       
    28 	This is because the client does not know whether the new(ELeave), the PushL, or the operational meat 
       
    29 	generated the exception, and therefore the operation must be the last exception thrown in the method.
       
    30 	@internalComponent
       
    31 	@released
       
    32 */
       
    33 NONSHARABLE_STRUCT(CWsGraphicDrawerArray::XRollBackBase)
       
    34 	{
       
    35 public:
       
    36 	XRollBackBase():	iArray(NULL)	{}
       
    37 	virtual ~XRollBackBase()			{}
       
    38 public:
       
    39 	CWsGraphicDrawerArray*				iArray;
       
    40 	};
       
    41 // CWsGraphicDrawerArray::XAddRollBack \\\\\\\\\\\\\\\\\\\\\\\\
       
    42 
       
    43 /** Cleanup record for Add operation. Removes the array entry at the recorded array index.
       
    44 	@internalComponent
       
    45 	@released
       
    46 */
       
    47 NONSHARABLE_STRUCT(CWsGraphicDrawerArray::XAddRollBack) :public  CWsGraphicDrawerArray::XRollBackBase
       
    48 	{
       
    49 	TGraphicDrawerId iId;
       
    50 	static void RollBackD(TAny* aAddRollBack);
       
    51 	};
       
    52 
       
    53 /** Rolls back an adding of a drawer to an array, but does not delete the drawer.
       
    54 	Removes the array entry at the given array index.	
       
    55 */
       
    56 void CWsGraphicDrawerArray::XAddRollBack::RollBackD(TAny* aAddRollBack)
       
    57 	{
       
    58 	__ASSERT_DEBUG(aAddRollBack,Panic(EWsGraphicDrawerPanicBadAddLCCleanup));
       
    59 	if(aAddRollBack)
       
    60 		{
       
    61 		XAddRollBack* rollBack = static_cast<XAddRollBack*>(aAddRollBack);
       
    62 		// iArray would be NULL if you pushed a NULL drawer in release builds
       
    63 		//It can also be null if the Add operation Leaves
       
    64 		if(rollBack->iArray) 
       
    65 			{
       
    66 			rollBack->iArray->Remove(rollBack->iId);
       
    67 			}
       
    68 		delete  rollBack;
       
    69 		}
       
    70 	}
       
    71 
       
    72 // CWsGraphicDrawerArray::XRemoveRollBack \\\\\\\\\\\\\\\\\\\\\\\\
       
    73 
       
    74 /** Cleanup record for Swap operation. Re-inserts the recorded drawer by finding its index.
       
    75 	@internalComponent
       
    76 	@released
       
    77 */
       
    78 NONSHARABLE_STRUCT(CWsGraphicDrawerArray::XSwapRollBack) :public  CWsGraphicDrawerArray::XRollBackBase
       
    79 	{
       
    80 	CWsGraphicDrawer* iDrawer;
       
    81 	static void RollBackD(TAny* aSwapRollBack);
       
    82 	};
       
    83 
       
    84 /** Rolls back the swapping (replacing) of a drawer to an array, but does not delete the replacing drawer.
       
    85 	Re-inserts the recorded drawer by finding its index.
       
    86  */
       
    87 void CWsGraphicDrawerArray::XSwapRollBack::RollBackD(TAny* aSwapRollBack)
       
    88 	{
       
    89 	__ASSERT_DEBUG(aSwapRollBack,Panic(EWsGraphicDrawerPanicBadSwapLCCleanup));
       
    90 	if(aSwapRollBack)
       
    91 		{
       
    92 		XSwapRollBack* rollBack = static_cast<XSwapRollBack*>(aSwapRollBack);
       
    93 		// would be NULL if you removed an id that wasn't in the array in release builds
       
    94 		// or if the swap itself Leaves
       
    95 		if(rollBack->iArray) 
       
    96 			{
       
    97 			const TInt idx = rollBack->iArray->IndexOf(rollBack->iDrawer->Id());
       
    98 			__ASSERT_DEBUG(0 <= idx,Panic(EWsGraphicDrawerPanicBadSwapLCCleanup));
       
    99 			if(0 <= idx) // hmm, don't see how this could ever happen.  If it does, better to leak memory etc 
       
   100 				{
       
   101 				rollBack->iArray->iArray[idx].iDrawer = rollBack->iDrawer;
       
   102 				}
       
   103 			}
       
   104 		delete rollBack;
       
   105 		}
       
   106 	}
       
   107 
       
   108 // CWsGraphicDrawerArray::XRemoveRollBack \\\\\\\\\\\\\\\\\\\\\\\\
       
   109 
       
   110 /** Cleanup record for Remove operation. Re-inserts the recorded drawer by finding its index.
       
   111 	@internalComponent
       
   112 	@released
       
   113 */
       
   114 NONSHARABLE_STRUCT(CWsGraphicDrawerArray::XRemoveRollBack) :public  CWsGraphicDrawerArray::XRollBackBase
       
   115 	{
       
   116 	CWsGraphicDrawer* iDrawer;
       
   117 	static void RollBackD(TAny* aSwapRollBack);
       
   118 	};
       
   119 
       
   120 /** Rolls back the deleting of a drawer from an array, but does not delete the replacing drawer.
       
   121 	Re-inserts the recorded drawer by finding its index.
       
   122  */
       
   123 void CWsGraphicDrawerArray::XRemoveRollBack::RollBackD(TAny* aRemoveRollBack)
       
   124 	{
       
   125 	__ASSERT_DEBUG(aRemoveRollBack,Panic(EWsGraphicDrawerPanicBadSwapLCCleanup));
       
   126 	if(aRemoveRollBack)
       
   127 		{
       
   128 		XRemoveRollBack* rollBack = static_cast<XRemoveRollBack*>(aRemoveRollBack);
       
   129 		// would be NULL if you removed an id that wasn't in the array in release builds
       
   130 		// or if the swap itself Leaves
       
   131 		if(rollBack->iArray) 
       
   132 			{
       
   133 			TGraphic graphic;
       
   134 			graphic.iId = rollBack->iDrawer->Id();
       
   135 			graphic.iDrawer = rollBack->iDrawer;
       
   136 			TInt errCode= rollBack->iArray->iArray.InsertInOrder(graphic,GraphicDrawerCompare); // dups not allowed
       
   137 			//This should not happen unless some non-transactional method has modified the array
       
   138 			//between the call and the leave.
       
   139 			__ASSERT_DEBUG(KErrAlreadyExists != errCode,Panic(EWsGraphicDrawerPanicBadSwapLCCleanup));
       
   140 			//Other memory failure errors should not occur unless the array has been Compress()ed
       
   141 			//between the call and the leave, and then memory fails.
       
   142 			__ASSERT_DEBUG(KErrNone <= errCode,Panic(EWsGraphicDrawerPanicBadSwapLCCleanup));
       
   143 			}
       
   144 		delete rollBack;
       
   145 		}
       
   146 	}
       
   147 
       
   148 // CWsGraphicDrawerArray \\\\\\\\\\\\\\\\\\\\\\\\
       
   149 
       
   150 /** Compares two graphic array slots for id equality; the iDrawer pointer is ignored.
       
   151 	Used to order the array.
       
   152 @internalComponent
       
   153 @released
       
   154 */
       
   155 TInt CWsGraphicDrawerArray::GraphicDrawerCompare(const TGraphic& aFirst,const TGraphic& aSecond)
       
   156 	{
       
   157 	return aFirst.iId.Compare(aSecond.iId);
       
   158 	}
       
   159 
       
   160 /** Adds a drawer to the array, with a transactional cleanup item that automatically removes
       
   161 	it until popped (not destroying the drawer, however). This operation leaks memory and should not be used.
       
   162 	@deprecated	 - Use AddL or AddRLC
       
   163 */
       
   164 EXPORT_C void CWsGraphicDrawerArray::AddLC(CWsGraphicDrawer* aDrawer)
       
   165 	{
       
   166 	__ASSERT_DEBUG(aDrawer,Panic(EWsGraphicDrawerPanicBadArgument));
       
   167 	XAddRollBack* rollBack = new(ELeave) XAddRollBack;
       
   168 	CleanupStack::PushL(TCleanupItem(XAddRollBack::RollBackD,rollBack));
       
   169 	if(aDrawer)
       
   170 		{
       
   171 		User::LeaveIfError(Add(aDrawer));
       
   172 		rollBack->iArray = this;
       
   173 		rollBack->iId = aDrawer->Id();		
       
   174 		}
       
   175 	}
       
   176 
       
   177 /** Adds a drawer to the array, with a transactional cleanup item that automatically removes
       
   178 	it (not destroying the drawer, however).
       
   179 	CommitP() must be called on the returned pointer to release resources owned by the cleanup item,
       
   180 	unless a Leave occurs.
       
   181 	@param 	 aDrawer	the drawer to add
       
   182 	@return		cleanup record
       
   183 */
       
   184 EXPORT_C CWsGraphicDrawerArray::XRollBackBase* CWsGraphicDrawerArray::AddTLC(CWsGraphicDrawer* aDrawer)
       
   185 	{
       
   186 	if(!aDrawer)
       
   187 		{
       
   188 		User::Leave(KErrArgument);
       
   189 		}
       
   190 	//need to create the rollback before the add because the client can't tell the difference between 
       
   191 	//the add failing and the new(ELeave) failing!
       
   192 	XAddRollBack* rollBack = new(ELeave) XAddRollBack;
       
   193 	CleanupStack::PushL(TCleanupItem(XAddRollBack::RollBackD,rollBack));
       
   194 	User::LeaveIfError(Add(aDrawer));
       
   195 	rollBack->iId = aDrawer->Id();		
       
   196 	rollBack->iArray = this;
       
   197 	
       
   198 	return rollBack;
       
   199 	}
       
   200 
       
   201 /** Adds a drawer to the array. No cleanup - no leak 
       
   202 	@param 	 aDrawer	the drawer to add
       
   203 	@return		error code if the Add did not take place
       
   204 */
       
   205 EXPORT_C TInt CWsGraphicDrawerArray::Add(CWsGraphicDrawer* aDrawer)
       
   206 	{
       
   207 	if(aDrawer)
       
   208 		{
       
   209 		TGraphic graphic;
       
   210 		graphic.iId = aDrawer->Id();
       
   211 		graphic.iDrawer = aDrawer;
       
   212 		return iArray.InsertInOrder(graphic,GraphicDrawerCompare); // dups not allowed
       
   213 		}
       
   214 	else
       
   215 		return KErrArgument;
       
   216 	}
       
   217 
       
   218 /*Internal method to swap the given drawer into the array, removing the existing one and returning a pointer to it.
       
   219 	Note that in an error just a NULL pointer is returned.
       
   220 	Internal caller must infer KErrNotFound error code.
       
   221 	@param 	 aDrawer	the drawer to add
       
   222 	@return				the drawer displaced, or NULL if the operation did not take place
       
   223 */
       
   224 CWsGraphicDrawer* CWsGraphicDrawerArray::SwapIn(CWsGraphicDrawer* aDrawer)
       
   225 	{
       
   226 	if (aDrawer==NULL)
       
   227 		return NULL;
       
   228 	const TInt idx = IndexOf(aDrawer->Id());
       
   229 	if (idx<KErrNone)
       
   230 		return NULL;
       
   231 	CWsGraphicDrawer* rv= iArray[idx].iDrawer;
       
   232 	iArray[idx].iDrawer=aDrawer;
       
   233 	return rv;
       
   234 	}
       
   235 
       
   236 /** Replaces the drawer with the existing Id with this newer one.  
       
   237 	Pushes a transactional cleanup item to restore the previous drawer. 
       
   238 	This operation leaks memory when it does not get Leave clean-up and should not be used.
       
   239 	@deprecated	 - Use SwapL or SwapRLC
       
   240 */
       
   241 EXPORT_C TInt CWsGraphicDrawerArray::SwapLC(CWsGraphicDrawer* aDrawer)
       
   242 	{
       
   243 	__ASSERT_DEBUG(aDrawer,Panic(EWsGraphicDrawerPanicBadArgument));
       
   244 	XSwapRollBack* rollBack = new(ELeave) XSwapRollBack;
       
   245 	CleanupStack::PushL(TCleanupItem(XSwapRollBack::RollBackD,rollBack));
       
   246 	CWsGraphicDrawer* rollBackDrawer=SwapIn(aDrawer);
       
   247 	if (rollBackDrawer)
       
   248 		{
       
   249 		rollBack->iArray = this;
       
   250 		rollBack->iDrawer = rollBackDrawer;
       
   251 		return KErrNone;
       
   252 		}
       
   253 	else
       
   254 		{
       
   255 		__ASSERT_DEBUG(0,Panic(EWsGraphicDrawerPanicBadArgument));
       
   256 		return KErrNotFound;
       
   257 		}
       
   258 	}
       
   259 
       
   260 /** Replaces the drawer with the existing Id with this newer one.  
       
   261 	Pushes a transactional cleanup item to restore the previous drawer. 
       
   262 	CommitP() must be called on the returned pointer to release resources owned by the cleanup item,
       
   263 	unless a Leave occurs.
       
   264 	@param 	 aDrawer	the drawer to add
       
   265 	@return		cleanup record
       
   266 */
       
   267 EXPORT_C CWsGraphicDrawerArray::XRollBackBase* CWsGraphicDrawerArray::SwapTLC(CWsGraphicDrawer* aDrawer)
       
   268 	{
       
   269 	if (!aDrawer)
       
   270 		User::Leave(KErrArgument);
       
   271 	XSwapRollBack* rollBack = new(ELeave) XSwapRollBack;
       
   272 	CleanupStack::PushL(TCleanupItem(XSwapRollBack::RollBackD,rollBack));
       
   273 	CWsGraphicDrawer* rollBackDrawer=SwapIn(aDrawer);
       
   274 	if (!rollBackDrawer)
       
   275 		User::Leave(KErrNotFound);
       
   276 	rollBack->iDrawer = rollBackDrawer;
       
   277 	rollBack->iArray = this;
       
   278 	return rollBack;
       
   279 	}
       
   280 
       
   281 /** Replaces the drawer with the existing Id with this newer one. No cleanup - no leak 
       
   282 	@param 	 aDrawer	the drawer to add
       
   283 	@return		error code if the Swap did not take place
       
   284 */
       
   285 EXPORT_C TInt CWsGraphicDrawerArray::Swap(CWsGraphicDrawer* aDrawer)
       
   286 	{
       
   287 	if (!aDrawer)
       
   288 		return KErrArgument;
       
   289 	CWsGraphicDrawer* oldDrawer=SwapIn(aDrawer);
       
   290 	if (!oldDrawer)
       
   291 		return KErrNotFound;
       
   292 	else
       
   293 		return KErrNone;
       
   294 	}
       
   295 	
       
   296 /**	Removes the cleanup record after a SwapTLC or AddTLC operation,
       
   297 	removing the opportunity to back out of the operation.
       
   298 	Note that SwapTLC, AddTLC, and RemoveTLC cleanup operations can be stacked and should be committed 
       
   299 	in the opposite order. They cannot be safely intermingled with non-transactional operations.
       
   300 	This method can be safely called with a NULL parameter indicating a failed operation.
       
   301 	@param aRollBack	handle to rollback information that will be discarded.
       
   302 **/
       
   303 EXPORT_C void  CWsGraphicDrawerArray::CommitP(CWsGraphicDrawerArray::XRollBackBase* aRollBack)
       
   304 	{
       
   305 	if (aRollBack)
       
   306 		{
       
   307 		CleanupStack::Pop(aRollBack);
       
   308 		delete aRollBack;
       
   309 		}
       
   310 	}
       
   311 
       
   312 /** Removes the specified drawer from the array.
       
   313 	Pushes a transactional cleanup item to restore the previous drawer.
       
   314 	@note 	The array should not be Compressed() during the transaction period 
       
   315 			to ensure that the RollBack operation will always succeed.
       
   316 	@param aId the ID of the drawer to remove
       
   317 	@return	cleanup record
       
   318 */
       
   319 EXPORT_C CWsGraphicDrawerArray::XRollBackBase*  CWsGraphicDrawerArray::RemoveTLC(const TGraphicDrawerId& aId)
       
   320 	{
       
   321 	XRemoveRollBack* rollBack = new(ELeave) XRemoveRollBack;
       
   322 	CleanupStack::PushL(TCleanupItem(XRemoveRollBack::RollBackD,rollBack));
       
   323 	const TInt idx = IndexOf(aId);
       
   324 	if(0 > idx)
       
   325 		{
       
   326 		User::Leave(idx);
       
   327 		}
       
   328 	rollBack->iDrawer=iArray[idx].iDrawer;
       
   329 	iArray.Remove(idx);
       
   330 	rollBack->iArray=this;
       
   331 	return rollBack;
       
   332 	}
       
   333 	
       
   334 /** Removes the specified drawer from the array
       
   335 	@param aId the ID of the drawer to remove
       
   336 	@return KErrNone if the drawer was removed, KErrNotFound if the drawer was not in the array
       
   337 */
       
   338 EXPORT_C TInt CWsGraphicDrawerArray::Remove(const TGraphicDrawerId& aId)
       
   339 	{
       
   340 	const TInt idx = IndexOf(aId);
       
   341 	if(0 <= idx)
       
   342 		{
       
   343 		iArray.Remove(idx);
       
   344 		return KErrNone;
       
   345 		}
       
   346 	return idx;
       
   347 	}
       
   348 	
       
   349 EXPORT_C TInt CWsGraphicDrawerArray::RemoveAndDestroy(const TGraphicDrawerId& aId)
       
   350 /** Removes and deletes the specified drawer from the array
       
   351 	@param aId the ID of the drawer to remove and delete
       
   352 	@return KErrNone if the drawer was removed and deleted, KErrNotFound if the drawer was not in the array
       
   353 */	{
       
   354 	const TInt idx = IndexOf(aId);
       
   355 	if(0 <= idx)
       
   356 		{
       
   357 		delete iArray[idx].iDrawer;
       
   358 		iArray.Remove(idx);
       
   359 		// coverity[extend_simple_error]
       
   360 		return KErrNone;
       
   361 		}
       
   362 	return idx;
       
   363 	}
       
   364 
       
   365 /** Removes all drawers from the array which are owned by the specified client session
       
   366 	@param aOwner the client session that owns the drawers to be removed
       
   367 	@return the number of drawers that were removed
       
   368 */
       
   369 EXPORT_C TInt CWsGraphicDrawerArray::RemoveAll(const MWsClient& aOwner)
       
   370 	{
       
   371 	TInt removed = 0;
       
   372 	TInt count = iArray.Count();
       
   373 	TInt i = 0;
       
   374 	while(i < count)
       
   375 		{
       
   376 		if(iArray[i].iDrawer && (&(iArray[i].iDrawer->Owner()) == &aOwner))
       
   377 			{
       
   378 			iArray.Remove(i);
       
   379 			count--;
       
   380 			removed++;
       
   381 			}
       
   382 		else
       
   383 			{
       
   384 			i++;
       
   385 			}
       
   386 		}
       
   387 	return removed;
       
   388 	}
       
   389 
       
   390 /** Removes and deletes all drawers from the array which are owned by the specified client session
       
   391 	@param aOwner the client session that owns the drawers to be removed and deleted
       
   392 	@return the number of drawers that were removed and deleted
       
   393 */
       
   394 EXPORT_C TInt CWsGraphicDrawerArray::RemoveAndDestroyAll(const MWsClient& aOwner)
       
   395 	{
       
   396 	TInt removed = 0;
       
   397 	TInt count = iArray.Count();
       
   398 	TInt i = 0;
       
   399 	while(i < count)
       
   400 		{
       
   401 		if(iArray[i].iDrawer && (&(iArray[i].iDrawer->Owner()) == &aOwner))
       
   402 			{
       
   403 			delete iArray[i].iDrawer;
       
   404 			iArray.Remove(i);
       
   405 			count--;
       
   406 			removed++;
       
   407 			}
       
   408 		else
       
   409 			{
       
   410 			i++;
       
   411 			}
       
   412 		}
       
   413 	// coverity[extend_simple_error]
       
   414 	return removed;
       
   415 	}
       
   416 
       
   417 EXPORT_C const CWsGraphicDrawer* CWsGraphicDrawerArray::ResolveGraphic(const TGraphicDrawerId& aId) const
       
   418 /** Find a graphic by it's ID
       
   419 	@param aId the ID of the graphic to find
       
   420 	@return the drawer if it is in the array, else NULL
       
   421 */	{
       
   422 	const TInt idx = IndexOf(aId);
       
   423 	if(KErrNotFound != idx)
       
   424 		{
       
   425 		return iArray[idx].iDrawer;
       
   426 		}
       
   427 	return NULL;
       
   428 	}
       
   429 
       
   430 EXPORT_C void CWsGraphicDrawerArray::Close()
       
   431 /** Close the array, not destroying the drawers that it indexes
       
   432 */	{
       
   433 	iArray.Close();
       
   434 	}
       
   435 
       
   436 EXPORT_C void CWsGraphicDrawerArray::ResetAndDestroy()
       
   437 /** Reset the array, destroying the drawers that it indexes.
       
   438 Only the 'owner' array should call this
       
   439 */	{
       
   440 	const TInt count = iArray.Count();
       
   441 	for(TInt i=0; i<count; i++)
       
   442 		{
       
   443 		delete iArray[i].iDrawer;
       
   444 		}
       
   445 	iArray.Reset();
       
   446 	// coverity[extend_simple_error]
       
   447 	}
       
   448 	
       
   449 EXPORT_C TBool CWsGraphicDrawerArray::IsEmpty() const
       
   450 /** @return ETrue if the array contains no drawers
       
   451 */	{
       
   452 	return !iArray.Count();
       
   453 	}
       
   454 	
       
   455 TInt CWsGraphicDrawerArray::IndexOf(const TGraphicDrawerId& aId) const
       
   456 /** @internalComponent
       
   457 */	{
       
   458 	return iArray.FindInOrder(reinterpret_cast<const TGraphic&>(aId),GraphicDrawerCompare);
       
   459 	}
       
   460