1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26 
27 //_________________________________________________________________________________________________________________
28 //	my own includes
29 //_________________________________________________________________________________________________________________
30 #include <helper/oframes.hxx>
31 
32 #ifndef _FRAMEWORK_THREADHELP_RESETABLEGUARD_HXX_
33 #include <threadhelp/resetableguard.hxx>
34 #endif
35 
36 //_________________________________________________________________________________________________________________
37 //	interface includes
38 //_________________________________________________________________________________________________________________
39 #include <com/sun/star/frame/XDesktop.hpp>
40 #include <com/sun/star/frame/FrameSearchFlag.hpp>
41 
42 //_________________________________________________________________________________________________________________
43 //	includes of other projects
44 //_________________________________________________________________________________________________________________
45 #include <vcl/svapp.hxx>
46 
47 //_________________________________________________________________________________________________________________
48 //	namespace
49 //_________________________________________________________________________________________________________________
50 
51 namespace framework{
52 
53 using namespace ::com::sun::star::container		;
54 using namespace ::com::sun::star::frame			;
55 using namespace ::com::sun::star::lang			;
56 using namespace ::com::sun::star::uno			;
57 using namespace ::cppu							;
58 using namespace ::osl							;
59 using namespace ::rtl							;
60 using namespace ::std							;
61 using namespace ::vos							;
62 
63 //_________________________________________________________________________________________________________________
64 //	non exported const
65 //_________________________________________________________________________________________________________________
66 
67 //_________________________________________________________________________________________________________________
68 //	non exported definitions
69 //_________________________________________________________________________________________________________________
70 
71 //_________________________________________________________________________________________________________________
72 //	declarations
73 //_________________________________________________________________________________________________________________
74 
75 //*****************************************************************************************************************
76 //	constructor
77 //*****************************************************************************************************************
78 OFrames::OFrames(	const	css::uno::Reference< XMultiServiceFactory >&	xFactory		,
79 					const	css::uno::Reference< XFrame >&				xOwner			,
80 							FrameContainer*						pFrameContainer	)
81 		//	Init baseclasses first
82         :   ThreadHelpBase              ( &Application::GetSolarMutex() )
83 		// Init member
84         ,   m_xFactory                  ( xFactory                      )
85         ,   m_xOwner                    ( xOwner                        )
86         ,   m_pFrameContainer           ( pFrameContainer               )
87         ,   m_bRecursiveSearchProtection( sal_False                     )
88 {
89 	// Safe impossible cases
90 	// Method is not defined for ALL incoming parameters!
91     LOG_ASSERT( impldbg_checkParameter_OFramesCtor( xFactory, xOwner, pFrameContainer ), "OFrames::OFrames()\nInvalid parameter detected!\n" )
92 }
93 
94 //*****************************************************************************************************************
95 //	(proteced!) destructor
96 //*****************************************************************************************************************
97 OFrames::~OFrames()
98 {
99 	// Reset instance, free memory ....
100 	impl_resetObject();
101 }
102 
103 //*****************************************************************************************************************
104 //	XFrames
105 //*****************************************************************************************************************
106 void SAL_CALL OFrames::append( const css::uno::Reference< XFrame >& xFrame ) throw( RuntimeException )
107 {
108 	// Ready for multithreading
109 	ResetableGuard aGuard( m_aLock );
110 
111 	// Safe impossible cases
112 	// Method is not defined for ALL incoming parameters!
113 	LOG_ASSERT( impldbg_checkParameter_append( xFrame ), "OFrames::append()\nInvalid parameter detected!\n" )
114 
115 	// Do the follow only, if owner instance valid!
116 	// Lock owner for follow operations - make a "hard reference"!
117 	css::uno::Reference< XFramesSupplier > xOwner( m_xOwner.get(), UNO_QUERY );
118 	if ( xOwner.is() == sal_True )
119 	{
120 		// Append frame to the end of the container ...
121 		m_pFrameContainer->append( xFrame );
122 		// Set owner of this instance as parent of the new frame in container!
123 		xFrame->setCreator( xOwner );
124 	}
125 	// Else; Do nothing! Ouer owner is dead.
126 	LOG_ASSERT( !(xOwner.is()==sal_False), "OFrames::append()\nOuer owner is dead - you can't append any frames ...!\n" )
127 }
128 
129 //*****************************************************************************************************************
130 //	XFrames
131 //*****************************************************************************************************************
132 void SAL_CALL OFrames::remove( const css::uno::Reference< XFrame >& xFrame ) throw( RuntimeException )
133 {
134 	// Ready for multithreading
135 	ResetableGuard aGuard( m_aLock );
136 
137 	// Safe impossible cases
138 	// Method is not defined for ALL incoming parameters!
139 	LOG_ASSERT( impldbg_checkParameter_remove( xFrame ), "OFrames::remove()\nInvalid parameter detected!\n" )
140 
141 	// Do the follow only, if owner instance valid!
142 	// Lock owner for follow operations - make a "hard reference"!
143 	css::uno::Reference< XFramesSupplier > xOwner( m_xOwner.get(), UNO_QUERY );
144 	if ( xOwner.is() == sal_True )
145 	{
146 		// Search frame and remove it from container ...
147 		m_pFrameContainer->remove( xFrame );
148 		// Don't reset owner-property of removed frame!
149 		// This must do the caller of this method himself.
150 		// See documentation of interface XFrames for further informations.
151 	}
152 	// Else; Do nothing! Ouer owner is dead.
153 	LOG_ASSERT( !(xOwner.is()==sal_False), "OFrames::remove()\nOuer owner is dead - you can't remove any frames ...!\n" )
154 }
155 
156 //*****************************************************************************************************************
157 //	XFrames
158 //*****************************************************************************************************************
159 Sequence< css::uno::Reference< XFrame > > SAL_CALL OFrames::queryFrames( sal_Int32 nSearchFlags ) throw( RuntimeException )
160 {
161 	// Ready for multithreading
162 	ResetableGuard aGuard( m_aLock );
163 
164 	// Safe impossible cases
165 	// Method is not defined for ALL incoming parameters!
166 	LOG_ASSERT( impldbg_checkParameter_queryFrames( nSearchFlags ), "OFrames::queryFrames()\nInvalid parameter detected!\n" )
167 
168 	// Set default return value. (empty sequence)
169 	Sequence< css::uno::Reference< XFrame > > seqFrames;
170 
171 	// Do the follow only, if owner instance valid.
172 	// Lock owner for follow operations - make a "hard reference"!
173 	css::uno::Reference< XFrame > xOwner( m_xOwner.get(), UNO_QUERY );
174 	if ( xOwner.is() == sal_True )
175 	{
176 		// Work only, if search was not started here ...!
177 		if( m_bRecursiveSearchProtection == sal_False )
178 		{
179 			// This class is a helper for services, which must implement XFrames.
180 			// His parent and childs are MY parent and childs to.
181 			// All searchflags are supported by this implementation!
182 			// If some flags should not be supported - don't call me with this flags!!!
183 
184 			//_____________________________________________________________________________________________________________
185 			// Search with AUTO-flag is not supported yet!
186 			// We think about right implementation.
187 			LOG_ASSERT( !(nSearchFlags & FrameSearchFlag::AUTO), "OFrames::queryFrames()\nSearch with AUTO-flag is not supported yet!\nWe think about right implementation.\n" )
188 			// If searched for tasks ...
189 			// Its not supported yet.
190 			LOG_ASSERT( !(nSearchFlags & FrameSearchFlag::AUTO), "OFrames::queryFrames()\nSearch for tasks not supported yet!\n" )
191 
192 			//_____________________________________________________________________________________________________________
193 			// Search for ALL and GLOBAL is superflous!
194 			// We support all necessary flags, from which these two flags are derived.
195 			//		ALL		= PARENT + SELF  + CHILDREN + SIBLINGS
196 			//		GLOBAL	= ALL    + TASKS
197 
198 			//_____________________________________________________________________________________________________________
199 			// Add parent to list ... if any exist!
200 			if( nSearchFlags & FrameSearchFlag::PARENT )
201 			{
202 				css::uno::Reference< XFrame > xParent( xOwner->getCreator(), UNO_QUERY );
203 				if( xParent.is() == sal_True )
204 				{
205 					Sequence< css::uno::Reference< XFrame > > seqParent( 1 );
206 					seqParent[0] = xParent;
207 					impl_appendSequence( seqFrames, seqParent );
208 				}
209 			}
210 
211 			//_____________________________________________________________________________________________________________
212 			// Add owner to list if SELF is searched.
213 			if( nSearchFlags & FrameSearchFlag::SELF )
214 			{
215 				Sequence< css::uno::Reference< XFrame > > seqSelf( 1 );
216 				seqSelf[0] = xOwner;
217 				impl_appendSequence( seqFrames, seqSelf );
218 			}
219 
220 			//_____________________________________________________________________________________________________________
221 			// Add SIBLINGS to list.
222 			if( nSearchFlags & FrameSearchFlag::SIBLINGS )
223 			{
224 				// Else; start a new search.
225 				// Protect this instance against recursive calls from parents.
226 				m_bRecursiveSearchProtection = sal_True;
227 				// Ask parent of my owner for frames and append results to return list.
228 				css::uno::Reference< XFramesSupplier > xParent( xOwner->getCreator(), UNO_QUERY );
229 				// If a parent exist ...
230 				if ( xParent.is() == sal_True )
231 				{
232 					// ... ask him for right frames.
233 					impl_appendSequence( seqFrames, xParent->getFrames()->queryFrames( nSearchFlags ) );
234 				}
235 				// We have all searched informations.
236 				// Reset protection-mode.
237 				m_bRecursiveSearchProtection = sal_False;
238 			}
239 
240 			//_____________________________________________________________________________________________________________
241 			// If searched for children, step over all elements in container and collect the informations.
242 			if ( nSearchFlags & FrameSearchFlag::CHILDREN )
243 			{
244 				// Don't search for parents, siblings and self at childrens!
245 				// These things are supported by this instance himself.
246 				sal_Int32 nChildSearchFlags = FrameSearchFlag::SELF | FrameSearchFlag::CHILDREN;
247 				// Step over all items of container and ask childrens for frames.
248 				sal_uInt32 nCount = m_pFrameContainer->getCount();
249 				for ( sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex )
250 				{
251 					// We don't must control this conversion.
252 					// We have done this at append()!
253 					css::uno::Reference< XFramesSupplier > xItem( (*m_pFrameContainer)[nIndex], UNO_QUERY );
254 					impl_appendSequence( seqFrames, xItem->getFrames()->queryFrames( nChildSearchFlags ) );
255 				}
256 			}
257 		}
258 	}
259 	// Else; Do nothing! Ouer owner is dead.
260 	LOG_ASSERT( !(xOwner.is()==sal_False), "OFrames::queryFrames()\nOuer owner is dead - you can't query for frames ...!\n" )
261 
262 	// Resturn result of this operation.
263 	return seqFrames;
264 }
265 
266 //*****************************************************************************************************************
267 //	XIndexAccess
268 //*****************************************************************************************************************
269 sal_Int32 SAL_CALL OFrames::getCount() throw( RuntimeException )
270 {
271 	// Ready for multithreading
272 	ResetableGuard aGuard( m_aLock );
273 
274 	// Set default return value.
275 	sal_Int32 nCount = 0;
276 
277 	// Do the follow only, if owner instance valid.
278 	// Lock owner for follow operations - make a "hard reference"!
279 	css::uno::Reference< XFrame > xOwner( m_xOwner.get(), UNO_QUERY );
280 	if ( xOwner.is() == sal_True )
281 	{
282 		// Set CURRENT size of container for return.
283 		nCount = m_pFrameContainer->getCount();
284 	}
285 
286 	// Return result.
287 	return nCount;
288 }
289 
290 //*****************************************************************************************************************
291 //	XIndexAccess
292 //*****************************************************************************************************************
293 Any SAL_CALL OFrames::getByIndex( sal_Int32 nIndex ) throw(	IndexOutOfBoundsException	,
294 															WrappedTargetException		,
295 															RuntimeException			)
296 {
297 	// Ready for multithreading
298 	ResetableGuard aGuard( m_aLock );
299 
300       sal_uInt32 nCount = m_pFrameContainer->getCount();
301       if ( nIndex < 0 || ( sal::static_int_cast< sal_uInt32 >( nIndex ) >= nCount ))
302           throw IndexOutOfBoundsException( OUString::createFromAscii( "OFrames::getByIndex - Index out of bounds" ),
303                                            (OWeakObject *)this );
304 
305 	// Set default return value.
306 	Any aReturnValue;
307 
308 	// Do the follow only, if owner instance valid.
309 	// Lock owner for follow operations - make a "hard reference"!
310 	css::uno::Reference< XFrame > xOwner( m_xOwner.get(), UNO_QUERY );
311 	if ( xOwner.is() == sal_True )
312 	{
313 		// Get element form container.
314 		// (If index not valid, FrameContainer return NULL!)
315             aReturnValue <<= (*m_pFrameContainer)[nIndex];
316 	}
317 
318 	// Return result of this operation.
319 	return aReturnValue;
320 }
321 
322 //*****************************************************************************************************************
323 //	XElementAccess
324 //*****************************************************************************************************************
325 Type SAL_CALL OFrames::getElementType() throw( RuntimeException )
326 {
327 	// This "container" support XFrame-interfaces only!
328 	return ::getCppuType( (const css::uno::Reference< XFrame >*)NULL );
329 }
330 
331 //*****************************************************************************************************************
332 //	XElementAccess
333 //*****************************************************************************************************************
334 sal_Bool SAL_CALL OFrames::hasElements() throw( RuntimeException )
335 {
336 	// Ready for multithreading
337 	ResetableGuard aGuard( m_aLock );
338 
339 	// Set default return value.
340 	sal_Bool bHasElements = sal_False;
341 	// Do the follow only, if owner instance valid.
342 	// Lock owner for follow operations - make a "hard reference"!
343 	css::uno::Reference< XFrame > xOwner( m_xOwner.get(), UNO_QUERY );
344 	if ( xOwner.is() == sal_True )
345 	{
346 		// If some elements exist ...
347 		if ( m_pFrameContainer->getCount() > 0 )
348 		{
349 			// ... change this state value!
350 			bHasElements = sal_True;
351 		}
352 	}
353 	// Return result of this operation.
354 	return bHasElements;
355 }
356 
357 //*****************************************************************************************************************
358 //	proteced method
359 //*****************************************************************************************************************
360 void OFrames::impl_resetObject()
361 {
362 	// Attention:
363 	// Write this for multiple calls - NOT AT THE SAME TIME - but for more then one call again)!
364 	// It exist two ways to call this method. From destructor and from disposing().
365 	// I can't say, which one is the first. Normaly the disposing-call - but other way ....
366 
367 	// This instance can't work if the weakreference to owner is invalid!
368 	// Destroy this to reset this object.
369 	m_xOwner = WeakReference< XFrame >();
370 	// Reset pointer to shared container to!
371 	m_pFrameContainer = NULL;
372 }
373 
374 //*****************************************************************************************************************
375 //	private method
376 //*****************************************************************************************************************
377 void OFrames::impl_appendSequence(			Sequence< css::uno::Reference< XFrame > >&	seqDestination	,
378 			 						const	Sequence< css::uno::Reference< XFrame > >&	seqSource		)
379 {
380 	// Get some informations about the sequences.
381 	sal_Int32						nSourceCount		= seqSource.getLength();
382 	sal_Int32						nDestinationCount	= seqDestination.getLength();
383 	const css::uno::Reference< XFrame >* 		pSourceAccess		= seqSource.getConstArray();
384 	css::uno::Reference< XFrame >*			pDestinationAccess	= seqDestination.getArray();
385 
386 	// Get memory for result list.
387 	Sequence< css::uno::Reference< XFrame > >	seqResult			( nSourceCount + nDestinationCount );
388 	css::uno::Reference< XFrame >*			pResultAccess		= seqResult.getArray();
389 	sal_Int32						nResultPosition		= 0;
390 
391 	// Copy all items from first sequence.
392 	for ( sal_Int32 nSourcePosition=0; nSourcePosition<nSourceCount; ++nSourcePosition )
393 	{
394 		pResultAccess[nResultPosition] = pSourceAccess[nSourcePosition];
395 		++nResultPosition;
396 	}
397 
398 	// Don't manipulate nResultPosition between these two loops!
399 	// Its the current position in the result list.
400 
401 	// Copy all items from second sequence.
402 	for ( sal_Int32 nDestinationPosition=0; nDestinationPosition<nDestinationCount; ++nDestinationPosition )
403 	{
404 		pResultAccess[nResultPosition] = pDestinationAccess[nDestinationPosition];
405 		++nResultPosition;
406 	}
407 
408 	// Return result of this operation.
409 	seqDestination.realloc( 0 );
410 	seqDestination = seqResult;
411 }
412 
413 //_________________________________________________________________________________________________________________
414 //	debug methods
415 //_________________________________________________________________________________________________________________
416 
417 /*-----------------------------------------------------------------------------------------------------------------
418 	The follow methods checks the parameter for other functions. If a parameter or his value is non valid,
419 	we return "sal_False". (else sal_True) This mechanism is used to throw an ASSERT!
420 
421 	ATTENTION
422 
423 		If you miss a test for one of this parameters, contact the author or add it himself !(?)
424 		But ... look for right testing! See using of this methods!
425 -----------------------------------------------------------------------------------------------------------------*/
426 
427 #ifdef ENABLE_ASSERTIONS
428 
429 //*****************************************************************************************************************
430 // An instance of this class can only work with valid initialization.
431 // We share the mutex with ouer owner class, need a valid factory to instanciate new services and
432 // use the access to ouer owner for some operations.
433 sal_Bool OFrames::impldbg_checkParameter_OFramesCtor(	const	css::uno::Reference< XMultiServiceFactory >&	xFactory		,
434 														const	css::uno::Reference< XFrame >&				xOwner			,
435 																FrameContainer*						pFrameContainer	)
436 {
437 	// Set default return value.
438 	sal_Bool bOK = sal_True;
439 	// Check parameter.
440 	if	(
441 			( &xFactory			==	NULL		)	||
442 			( &xOwner			==	NULL		)	||
443 			( xFactory.is()		==	sal_False	)	||
444 			( xOwner.is()		==	sal_False	)	||
445 			( pFrameContainer	==	NULL		)
446 		)
447 	{
448 		bOK = sal_False ;
449 	}
450 	// Return result of check.
451 	return bOK ;
452 }
453 
454 //*****************************************************************************************************************
455 // Its only allowed to add valid references to container.
456 // AND - alle frames must support XFrames-interface!
457 sal_Bool OFrames::impldbg_checkParameter_append( const css::uno::Reference< XFrame >& xFrame )
458 {
459 	// Set default return value.
460 	sal_Bool bOK = sal_True;
461 	// Check parameter.
462 	if	(
463 			( &xFrame		==	NULL		)	||
464 			( xFrame.is()	==	sal_False	)
465 		)
466 	{
467 		bOK = sal_False ;
468 	}
469 	// Return result of check.
470 	return bOK ;
471 }
472 
473 //*****************************************************************************************************************
474 // Its only allowed to add valid references to container...
475 // ... => You can only delete valid references!
476 sal_Bool OFrames::impldbg_checkParameter_remove( const css::uno::Reference< XFrame >& xFrame )
477 {
478 	// Set default return value.
479 	sal_Bool bOK = sal_True;
480 	// Check parameter.
481 	if	(
482 			( &xFrame		==	NULL		)	||
483 			( xFrame.is()	==	sal_False	)
484 		)
485 	{
486 		bOK = sal_False ;
487 	}
488 	// Return result of check.
489 	return bOK ;
490 }
491 
492 //*****************************************************************************************************************
493 // A search for frames must initiate with right flags.
494 // Some one are superflous and not supported yet. But here we control only the range of incoming parameter!
495 sal_Bool OFrames::impldbg_checkParameter_queryFrames( sal_Int32 nSearchFlags )
496 {
497 	// Set default return value.
498 	sal_Bool bOK = sal_True;
499 	// Check parameter.
500 	if	(
501 			( 	 nSearchFlags != FrameSearchFlag::AUTO		  )	&&
502 			( !( nSearchFlags &  FrameSearchFlag::PARENT	) )	&&
503 			( !( nSearchFlags &  FrameSearchFlag::SELF		) )	&&
504 			( !( nSearchFlags &  FrameSearchFlag::CHILDREN	) )	&&
505 			( !( nSearchFlags &  FrameSearchFlag::CREATE	) )	&&
506 			( !( nSearchFlags &  FrameSearchFlag::SIBLINGS	) )	&&
507 			( !( nSearchFlags &  FrameSearchFlag::TASKS		) )	&&
508 			( !( nSearchFlags &  FrameSearchFlag::ALL		) )	&&
509 			( !( nSearchFlags &  FrameSearchFlag::GLOBAL	) )
510 		)
511 	{
512 		bOK = sal_False ;
513 	}
514 	// Return result of check.
515 	return bOK ;
516 }
517 
518 #endif	//	#ifdef ENABLE_ASSERTIONS
519 
520 }		//	namespace framework
521