1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 #include <svx/dialmgr.hxx>
31 #include <svx/fmshell.hxx>
32 #include <svx/fmmodel.hxx>
33 #include <svx/fmpage.hxx>
34 #include <svx/fmglob.hxx>
35 #include "svx/svditer.hxx"
36 #include <svx/svdogrp.hxx>
37 #include <svx/svdpagv.hxx>
38 
39 #include "fmprop.hrc"
40 
41 #include "fmundo.hxx"
42 #include "fmhelp.hrc"
43 #include "fmexpl.hrc"
44 #include "fmexpl.hxx"
45 #include "svx/fmresids.hrc"
46 #include "fmshimp.hxx"
47 #include "fmobj.hxx"
48 #include <sfx2/objsh.hxx>
49 #include <tools/diagnose_ex.h>
50 #include <rtl/logfile.hxx>
51 #include <com/sun/star/container/XContainer.hpp>
52 
53 //............................................................................
54 namespace svxform
55 {
56 //............................................................................
57 
58 	using namespace ::com::sun::star::uno;
59 	using namespace ::com::sun::star::lang;
60 	using namespace ::com::sun::star::beans;
61 	using namespace ::com::sun::star::form;
62 	using namespace ::com::sun::star::awt;
63 	using namespace ::com::sun::star::container;
64 	using namespace ::com::sun::star::script;
65 	using namespace ::com::sun::star::sdb;
66 
67 	//========================================================================
68 	// class OFormComponentObserver
69 	//========================================================================
70 	//------------------------------------------------------------------------
71 	OFormComponentObserver::OFormComponentObserver(NavigatorTreeModel* _pModel)
72         :m_pNavModel(_pModel)
73         ,m_nLocks(0)
74         ,m_bCanUndo(sal_True)
75 	{
76         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::OFormComponentObserver" );
77 	}
78 
79 	// XPropertyChangeListener
80 	//------------------------------------------------------------------------
81 	void SAL_CALL OFormComponentObserver::disposing(const EventObject& Source) throw( RuntimeException )
82 	{
83         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::disposing" );
84 		Remove( Source.Source );
85 	}
86 
87 	//------------------------------------------------------------------------
88 	void SAL_CALL OFormComponentObserver::propertyChange(const PropertyChangeEvent& evt) throw(RuntimeException)
89 	{
90         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::propertyChange" );
91 		if( !m_pNavModel ) return;
92 		if( evt.PropertyName != FM_PROP_NAME ) return;
93 
94 		Reference< XFormComponent >  xFormComponent(evt.Source, UNO_QUERY);
95 		Reference< XForm >  xForm(evt.Source, UNO_QUERY);
96 
97 		FmEntryData* pEntryData( NULL );
98 		if( xForm.is() )
99 			pEntryData = m_pNavModel->FindData( xForm, m_pNavModel->GetRootList() );
100 		else if( xFormComponent.is() )
101 			pEntryData = m_pNavModel->FindData( xFormComponent, m_pNavModel->GetRootList() );
102 
103 		if( pEntryData )
104 		{
105 			::rtl::OUString aNewName =  ::comphelper::getString(evt.NewValue);
106 			pEntryData->SetText( aNewName );
107 			FmNavNameChangedHint aNameChangedHint( pEntryData, aNewName );
108 			m_pNavModel->Broadcast( aNameChangedHint );
109 		}
110 	}
111 
112 	// XContainerListener
113 	//------------------------------------------------------------------------------
114 	void SAL_CALL OFormComponentObserver::elementInserted(const ContainerEvent& evt) throw(RuntimeException)
115 	{
116         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::elementInserted" );
117 		if (IsLocked() || !m_pNavModel)
118 			return;
119 
120 		// keine Undoaction einfuegen
121 		m_bCanUndo = sal_False;
122 
123 		Reference< XInterface > xTemp;
124 		evt.Element >>= xTemp;
125 		Insert(xTemp, ::comphelper::getINT32(evt.Accessor));
126 
127 		m_bCanUndo = sal_True;
128 	}
129 
130 	//------------------------------------------------------------------------------
131 	void OFormComponentObserver::Insert(const Reference< XInterface > & xIface, sal_Int32 nIndex)
132 	{
133         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::Insert" );
134 		Reference< XForm >  xForm(xIface, UNO_QUERY);
135 		if (xForm.is())
136 		{
137 			m_pNavModel->InsertForm(xForm, sal_uInt32(nIndex));
138 			Reference< XIndexContainer >  xContainer(xForm, UNO_QUERY);
139 			Reference< XInterface > xTemp;
140 			for (sal_Int32 i = 0; i < xContainer->getCount(); i++)
141 			{
142 				xContainer->getByIndex(i) >>= xTemp;
143 				Insert(xTemp, i);
144 			}
145 		}
146 		else
147 		{
148 			Reference< XFormComponent >  xFormComp(xIface, UNO_QUERY);
149 			if (xFormComp.is())
150 				m_pNavModel->InsertFormComponent(xFormComp, sal_uInt32(nIndex));
151 		}
152 	}
153 
154 	//------------------------------------------------------------------------------
155 	void SAL_CALL OFormComponentObserver::elementReplaced(const ContainerEvent& evt) throw(RuntimeException)
156 	{
157         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::elementReplaced" );
158 		if (IsLocked() || !m_pNavModel)
159 			return;
160 
161 		m_bCanUndo = sal_False;
162 
163 		// EntryData loeschen
164 		Reference< XFormComponent >  xReplaced;
165 		evt.ReplacedElement >>= xReplaced;
166 		FmEntryData* pEntryData = m_pNavModel->FindData(xReplaced, m_pNavModel->GetRootList(), sal_True);
167 		if (pEntryData)
168 		{
169 			if (pEntryData->ISA(FmControlData))
170 			{
171 				Reference< XFormComponent >  xComp;
172 				evt.Element >>= xComp;
173 				DBG_ASSERT(xComp.is(), "OFormComponentObserver::elementReplaced : invalid argument !");
174 					// an einer FmControlData sollte eine XFormComponent haengen
175 				m_pNavModel->ReplaceFormComponent(xReplaced, xComp);
176 			}
177 			else if (pEntryData->ISA(FmFormData))
178 			{
179 				DBG_ERROR("replacing forms not implemented yet !");
180 			}
181 		}
182 
183 		m_bCanUndo = sal_True;
184 	}
185 
186 	//------------------------------------------------------------------------------
187 	void OFormComponentObserver::Remove( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxElement )
188 	{
189         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::Remove" );
190 		if (IsLocked() || !m_pNavModel)
191 			return;
192 
193 		m_bCanUndo = sal_False;
194 
195 		//////////////////////////////////////////////////////////
196 		// EntryData loeschen
197 		FmEntryData* pEntryData = m_pNavModel->FindData( _rxElement, m_pNavModel->GetRootList(), sal_True );
198 		if (pEntryData)
199 			m_pNavModel->Remove(pEntryData);
200 
201 		m_bCanUndo = sal_True;
202 	}
203 
204 	//------------------------------------------------------------------------------
205 	void SAL_CALL OFormComponentObserver::elementRemoved(const ContainerEvent& evt) throw(RuntimeException)
206 	{
207         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::elementRemoved" );
208 		Reference< XInterface > xElement;
209 		evt.Element >>= xElement;
210 		Remove( xElement );
211 	}
212 
213 	//========================================================================
214 	// class NavigatorTreeModel
215 	//========================================================================
216 
217 	//------------------------------------------------------------------------
218 	NavigatorTreeModel::NavigatorTreeModel( const ImageList& _rNormalImages, const ImageList& _rHCImages )
219 					:m_pFormShell(NULL)
220 					,m_pFormPage(NULL)
221 					,m_pFormModel(NULL)
222 					,m_aNormalImages( _rNormalImages )
223 					,m_aHCImages( _rHCImages )
224 	{
225         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::NavigatorTreeModel" );
226 		m_pPropChangeList = new OFormComponentObserver(this);
227 		m_pPropChangeList->acquire();
228 		m_pRootList = new FmEntryDataList();
229 	}
230 
231 	//------------------------------------------------------------------------
232 	NavigatorTreeModel::~NavigatorTreeModel()
233 	{
234 		//////////////////////////////////////////////////////////////////////
235 		// Als Listener abmelden
236 		if( m_pFormShell)
237 		{
238 			FmFormModel* pFormModel = m_pFormShell->GetFormModel();
239 			if( pFormModel && IsListening(*pFormModel))
240 				EndListening( *pFormModel );
241 
242 			if (IsListening(*m_pFormShell))
243 				EndListening(*m_pFormShell);
244 		}
245 
246 		Clear();
247 		delete m_pRootList;
248 		m_pPropChangeList->ReleaseModel();
249 		m_pPropChangeList->release();
250 	}
251 
252 
253 	//------------------------------------------------------------------------
254 	void NavigatorTreeModel::SetModified( sal_Bool bMod )
255 	{
256         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::SetModified" );
257 		if( !m_pFormShell ) return;
258 		SfxObjectShell* pObjShell = m_pFormShell->GetFormModel()->GetObjectShell();
259 		if( !pObjShell ) return;
260 		pObjShell->SetModified( bMod );
261 	}
262 
263 	//------------------------------------------------------------------------
264 	void NavigatorTreeModel::Clear()
265 	{
266         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::Clear" );
267 		Reference< XNameContainer >  xForms( GetForms());
268 		Reference< XContainer >  xContainer(xForms, UNO_QUERY);
269 		if (xContainer.is())
270 			xContainer->removeContainerListener((XContainerListener*)m_pPropChangeList);
271 
272 		//////////////////////////////////////////////////////////////////////
273 		// RootList loeschen
274 		FmEntryData* pChildData;
275 		FmEntryDataList* pRootList = GetRootList();
276 
277 		for( sal_uInt32 i=pRootList->Count(); i>0; i-- )
278 		{
279 			pChildData = pRootList->GetObject(i-1);
280 			pRootList->Remove( pChildData );
281 			delete pChildData;
282 		}
283 
284 		//////////////////////////////////////////////////////////////////////
285 		// UI benachrichtigen
286 		FmNavClearedHint aClearedHint;
287 		Broadcast( aClearedHint );
288 	}
289 
290 	//------------------------------------------------------------------------
291 	Reference< XNameContainer >  NavigatorTreeModel::GetForms() const
292 	{
293         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::GetForms" );
294 		if( !m_pFormShell || !m_pFormShell->GetCurPage())
295 			return NULL;
296 		else
297 			return m_pFormShell->GetCurPage()->GetForms();
298 	}
299 
300 	//------------------------------------------------------------------------
301 	void NavigatorTreeModel::Insert(FmEntryData* pEntry, sal_uLong nRelPos, sal_Bool bAlterModel)
302 	{
303         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::Insert" );
304 		if (IsListening(*m_pFormModel))
305 			EndListening(*m_pFormModel);
306 
307 		m_pPropChangeList->Lock();
308 		FmFormData* pFolder     = (FmFormData*) pEntry->GetParent();
309 		Reference< XChild > xElement( pEntry->GetChildIFace() );
310 		if (bAlterModel)
311 		{
312 			XubString aStr;
313 			if (pEntry->ISA(FmFormData))
314 				aStr = SVX_RES(RID_STR_FORM);
315 			else
316 				aStr = SVX_RES(RID_STR_CONTROL);
317 
318 			Reference< XIndexContainer >  xContainer;
319 			if (pFolder)
320 				xContainer = Reference< XIndexContainer > (pFolder->GetFormIface(), UNO_QUERY);
321 			else
322 				xContainer = Reference< XIndexContainer > (GetForms(), UNO_QUERY);
323 
324 			bool bUndo = m_pFormModel->IsUndoEnabled();
325 
326 			if( bUndo )
327 			{
328 				XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT));
329 				aUndoStr.SearchAndReplace('#', aStr);
330 				m_pFormModel->BegUndo(aUndoStr);
331 			}
332 
333 			if (nRelPos >= (sal_uInt32)xContainer->getCount())
334 				nRelPos = (sal_uInt32)xContainer->getCount();
335 
336 			// UndoAction
337 			if ( bUndo && m_pPropChangeList->CanUndo())
338 			{
339 				m_pFormModel->AddUndo(new FmUndoContainerAction(*m_pFormModel,
340 														 FmUndoContainerAction::Inserted,
341 														 xContainer,
342 														 xElement,
343 														 nRelPos));
344 			}
345 
346 			// das Element muss den Typ haben, den der Container erwartet
347 			if (xContainer->getElementType() ==
348 				::getCppuType((const Reference< XForm>*)0))
349 
350 			{
351 				Reference< XForm >  xElementAsForm(xElement, UNO_QUERY);
352 				xContainer->insertByIndex(nRelPos, makeAny(xElementAsForm));
353 			}
354 			else if (xContainer->getElementType() ==
355 				::getCppuType((const Reference< XFormComponent>*)0))
356 
357 			{
358 				Reference< XFormComponent >  xElementAsComponent(xElement, UNO_QUERY);
359 				xContainer->insertByIndex(nRelPos, makeAny(xElementAsComponent));
360 			}
361 			else
362 			{
363 				DBG_ERROR("NavigatorTreeModel::Insert : the parent container needs an elementtype I don't know !");
364 			}
365 
366 			if( bUndo )
367 				m_pFormModel->EndUndo();
368 		}
369 
370 		//////////////////////////////////////////////////////////////////////
371 		// Als PropertyChangeListener anmelden
372 		Reference< XPropertySet >  xSet(xElement, UNO_QUERY);
373 		if( xSet.is() )
374 			xSet->addPropertyChangeListener( FM_PROP_NAME, m_pPropChangeList );
375 
376 		//////////////////////////////////////////////////////////////////////
377 		// Daten aus Model entfernen
378 		if (pEntry->ISA(FmFormData))
379 		{
380 			Reference< XContainer >  xContainer(xElement, UNO_QUERY);
381 			if (xContainer.is())
382 				xContainer->addContainerListener((XContainerListener*)m_pPropChangeList);
383 		}
384 
385 		if (pFolder)
386 			pFolder->GetChildList()->Insert( pEntry, nRelPos );
387 		else
388 			GetRootList()->Insert( pEntry, nRelPos );
389 
390 		//////////////////////////////////////////////////////////////////////
391 		// UI benachrichtigen
392 		FmNavInsertedHint aInsertedHint( pEntry, nRelPos );
393 		Broadcast( aInsertedHint );
394 
395 		m_pPropChangeList->UnLock();
396 		if (IsListening(*m_pFormModel))
397 			StartListening(*m_pFormModel);
398 	}
399 
400 	//------------------------------------------------------------------------
401 	void NavigatorTreeModel::Remove(FmEntryData* pEntry, sal_Bool bAlterModel)
402 	{
403         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::Remove" );
404 		//////////////////////////////////////////////////////////////////////
405 		// Form und Parent holen
406 		if (!pEntry || !m_pFormModel)
407 			return;
408 
409 		if (IsListening(*m_pFormModel))
410 			EndListening(*m_pFormModel);
411 
412 		const bool bUndo = m_pFormModel->IsUndoEnabled();
413 
414 		m_pPropChangeList->Lock();
415 		FmFormData*     pFolder     = (FmFormData*) pEntry->GetParent();
416 		Reference< XChild > xElement ( pEntry->GetChildIFace() );
417 		if (bAlterModel)
418 		{
419 			XubString        aStr;
420 			if (pEntry->ISA(FmFormData))
421 				aStr = SVX_RES(RID_STR_FORM);
422 			else
423 				aStr = SVX_RES(RID_STR_CONTROL);
424 
425 			if( bUndo )
426 			{
427 				XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_REMOVE));
428 				aUndoStr.SearchAndReplace('#', aStr);
429 				m_pFormModel->BegUndo(aUndoStr);
430 			}
431 		}
432 
433 		// jetzt die eigentliche Entfernung der Daten aus dem Model
434 		if (pEntry->ISA(FmFormData))
435 			RemoveForm((FmFormData*)pEntry);
436 		else
437 			RemoveFormComponent((FmControlData*)pEntry);
438 
439 
440 		if (bAlterModel)
441 		{
442 			Reference< XIndexContainer >  xContainer(xElement->getParent(), UNO_QUERY);
443 			// aus dem Container entfernen
444 			sal_Int32 nContainerIndex = getElementPos(xContainer.get(), xElement);
445 			// UndoAction
446 			if (nContainerIndex >= 0)
447 			{
448 				if ( bUndo && m_pPropChangeList->CanUndo())
449 				{
450 					m_pFormModel->AddUndo(new FmUndoContainerAction(*m_pFormModel,
451 														  FmUndoContainerAction::Removed,
452 														  xContainer,
453 														  xElement, nContainerIndex ));
454 				}
455 				else if( !m_pPropChangeList->CanUndo() )
456 				{
457 					FmUndoContainerAction::DisposeElement( xElement );
458 				}
459 
460 				xContainer->removeByIndex(nContainerIndex );
461 			}
462 
463 			if( bUndo )
464 				m_pFormModel->EndUndo();
465 		}
466 
467 		// beim Vater austragen
468 		if (pFolder)
469 			pFolder->GetChildList()->Remove(pEntry);
470 		else
471 		{
472 			GetRootList()->Remove(pEntry);
473 			//////////////////////////////////////////////////////////////////////
474 			// Wenn keine Form mehr in der Root, an der Shell CurForm zuruecksetzen
475 			if (!GetRootList()->Count())
476 				m_pFormShell->GetImpl()->forgetCurrentForm();
477 		}
478 
479 		//////////////////////////////////////////////////////////////////////
480 		// UI benachrichtigen
481 		FmNavRemovedHint aRemovedHint( pEntry );
482 		Broadcast( aRemovedHint );
483 
484 		// Eintrag loeschen
485 		delete pEntry;
486 
487 		m_pPropChangeList->UnLock();
488 		StartListening(*m_pFormModel);
489 	}
490 
491 	//------------------------------------------------------------------------
492 	void NavigatorTreeModel::RemoveForm(FmFormData* pFormData)
493 	{
494         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::RemoveForm" );
495 		//////////////////////////////////////////////////////////////////////
496 		// Form und Parent holen
497 		if (!pFormData || !m_pFormModel)
498 			return;
499 
500 		FmEntryDataList*    pChildList = pFormData->GetChildList();
501 		sal_uInt32 nCount = pChildList->Count();
502 		for (sal_uInt32 i = nCount; i > 0; i--)
503 		{
504 			FmEntryData* pEntryData = pChildList->GetObject(i - 1);
505 
506 			//////////////////////////////////////////////////////////////////////
507 			// Child ist Form -> rekursiver Aufruf
508 			if( pEntryData->ISA(FmFormData) )
509 				RemoveForm( (FmFormData*)pEntryData);
510 			else if( pEntryData->ISA(FmControlData) )
511 				RemoveFormComponent((FmControlData*) pEntryData);
512 		}
513 
514 		//////////////////////////////////////////////////////////////////////
515 		// Als PropertyChangeListener abmelden
516 		Reference< XPropertySet > xSet( pFormData->GetPropertySet() );
517 		if ( xSet.is() )
518 			xSet->removePropertyChangeListener( FM_PROP_NAME, m_pPropChangeList );
519 
520 		Reference< XContainer >  xContainer( pFormData->GetContainer() );
521 		if (xContainer.is())
522 			xContainer->removeContainerListener((XContainerListener*)m_pPropChangeList);
523 	}
524 
525 	//------------------------------------------------------------------------
526 	void NavigatorTreeModel::RemoveFormComponent(FmControlData* pControlData)
527 	{
528         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::RemoveFormComponent" );
529 		//////////////////////////////////////////////////////////////////////
530 		// Control und Parent holen
531 		if (!pControlData)
532 			return;
533 
534 		//////////////////////////////////////////////////////////////////////
535 		// Als PropertyChangeListener abmelden
536 		Reference< XPropertySet >  xSet( pControlData->GetPropertySet() );
537 		if (xSet.is())
538 			xSet->removePropertyChangeListener( FM_PROP_NAME, m_pPropChangeList);
539 	}
540 
541 	//------------------------------------------------------------------------
542 	void NavigatorTreeModel::ClearBranch( FmFormData* pParentData )
543 	{
544         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::ClearBranch" );
545 		//////////////////////////////////////////////////////////////////////
546 		// Alle Eintraege dieses Zweiges loeschen
547 		FmEntryDataList* pChildList = pParentData->GetChildList();
548 		FmEntryData* pChildData;
549 
550 		for( sal_uInt32 i=pChildList->Count(); i>0; i-- )
551 		{
552 			pChildData = pChildList->GetObject(i-1);
553 			if( pChildData->ISA(FmFormData) )
554 				ClearBranch( (FmFormData*)pChildData );
555 
556 			pChildList->Remove( pChildData );
557 		}
558 	}
559 
560 	//------------------------------------------------------------------------
561 	void NavigatorTreeModel::FillBranch( FmFormData* pFormData )
562 	{
563         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::FillBranch" );
564 		//////////////////////////////////////////////////////////////
565 		// Forms aus der Root einfuegen
566 		if( pFormData == NULL )
567 		{
568 			Reference< XIndexContainer >   xForms(GetForms(), UNO_QUERY);
569 			if (!xForms.is())
570 				return;
571 
572 			Reference< XForm >     xSubForm;
573 			FmFormData* pSubFormData;
574 			for (sal_Int32 i=0; i<xForms->getCount(); ++i)
575 			{
576 				DBG_ASSERT( xForms->getByIndex(i).getValueType() == ::getCppuType((const Reference< XForm>*)NULL),
577 					"NavigatorTreeModel::FillBranch : the root container should supply only elements of type XForm");
578 
579 				xForms->getByIndex(i) >>= xSubForm;
580 				pSubFormData = new FmFormData( xSubForm, m_aNormalImages, m_aHCImages, pFormData );
581 				Insert( pSubFormData, LIST_APPEND );
582 
583 				//////////////////////////////////////////////////////////////
584 				// Neuer Branch, wenn SubForm wiederum Subforms enthaelt
585 				FillBranch( pSubFormData );
586 			}
587 		}
588 
589 		//////////////////////////////////////////////////////////////
590 		// Componenten einfuegen
591 		else
592 		{
593 			Reference< XIndexContainer >  xComponents( GetFormComponents(pFormData));
594 			if( !xComponents.is() ) return;
595 
596 			::rtl::OUString aControlName;
597 			Reference< XInterface >  xInterface;
598 			Reference< XPropertySet >  xSet;
599 			FmControlData* pNewControlData;
600 			FmFormData* pSubFormData;
601 
602 			Reference< XFormComponent >  xCurrentComponent;
603 			for (sal_Int32 j=0; j<xComponents->getCount(); ++j)
604 			{
605 				xComponents->getByIndex(j) >>= xCurrentComponent;
606 				Reference< XForm >  xSubForm(xCurrentComponent, UNO_QUERY);
607 
608 				if (xSubForm.is())
609 				{   // die aktuelle Component ist eine Form
610 					pSubFormData = new FmFormData(xSubForm, m_aNormalImages, m_aHCImages, pFormData);
611 					Insert(pSubFormData, LIST_APPEND);
612 
613 					//////////////////////////////////////////////////////////////
614 					// Neuer Branch, wenn SubForm wiederum Subforms enthaelt
615 					FillBranch(pSubFormData);
616 				}
617 				else
618 				{
619 					pNewControlData = new FmControlData(xCurrentComponent, m_aNormalImages, m_aHCImages, pFormData);
620 					Insert(pNewControlData, LIST_APPEND);
621 				}
622 			}
623 		}
624 	}
625 
626 	//------------------------------------------------------------------------
627 	void NavigatorTreeModel::InsertForm(const Reference< XForm > & xForm, sal_uInt32 nRelPos)
628 	{
629         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::InsertForm" );
630 		FmFormData* pFormData = (FmFormData*)FindData( xForm, GetRootList() );
631 		if (pFormData)
632 			return;
633 
634 		//////////////////////////////////////////////////////////
635 		// ParentData setzen
636 		Reference< XInterface >  xIFace( xForm->getParent());
637 		Reference< XForm >  xParentForm(xIFace, UNO_QUERY);
638 		FmFormData* pParentData = NULL;
639 		if (xParentForm.is())
640 			pParentData = (FmFormData*)FindData( xParentForm, GetRootList() );
641 
642 		pFormData = new FmFormData( xForm, m_aNormalImages, m_aHCImages, pParentData );
643 		Insert( pFormData, nRelPos );
644 	}
645 
646 	//------------------------------------------------------------------------
647 	void NavigatorTreeModel::InsertFormComponent(const Reference< XFormComponent > & xComp, sal_uInt32 nRelPos)
648 	{
649         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::InsertFormComponent" );
650 		//////////////////////////////////////////////////////////
651 		// ParentData setzen
652 		Reference< XInterface >  xIFace( xComp->getParent());
653 		Reference< XForm >  xForm(xIFace, UNO_QUERY);
654 		if (!xForm.is())
655 			return;
656 
657 		FmFormData* pParentData = (FmFormData*)FindData( xForm, GetRootList() );
658 		if( !pParentData )
659 		{
660 			pParentData = new FmFormData( xForm, m_aNormalImages, m_aHCImages, NULL );
661 			Insert( pParentData, LIST_APPEND );
662 		}
663 
664 		if (!FindData(xComp, pParentData->GetChildList(),sal_False))
665 		{
666 			//////////////////////////////////////////////////////////
667 			// Neue EntryData setzen
668 			FmEntryData* pNewEntryData = new FmControlData( xComp, m_aNormalImages, m_aHCImages, pParentData );
669 
670 			//////////////////////////////////////////////////////////
671 			// Neue EntryData einfuegen
672 			Insert( pNewEntryData, nRelPos );
673 		}
674 	}
675 
676 	//------------------------------------------------------------------------
677 	void NavigatorTreeModel::ReplaceFormComponent(const Reference< XFormComponent > & xOld, const Reference< XFormComponent > & xNew)
678 	{
679         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::ReplaceFormComponent" );
680 		FmEntryData* pData = FindData(xOld, GetRootList(), sal_True);
681 		DBG_ASSERT(pData && pData->ISA(FmControlData), "NavigatorTreeModel::ReplaceFormComponent : invalid argument !");
682 		((FmControlData*)pData)->ModelReplaced( xNew, m_aNormalImages, m_aHCImages );
683 
684 		FmNavModelReplacedHint aReplacedHint( pData );
685 		Broadcast( aReplacedHint );
686 	}
687 
688 	//------------------------------------------------------------------------
689 	FmEntryData* NavigatorTreeModel::FindData(const Reference< XInterface > & xElement, FmEntryDataList* pDataList, sal_Bool bRecurs)
690 	{
691         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::FindData" );
692 		// normalize
693 		Reference< XInterface > xIFace( xElement, UNO_QUERY );
694 
695 		for (sal_uInt16 i=0; i < pDataList->Count(); i++)
696 		{
697 			FmEntryData* pEntryData = pDataList->GetObject(i);
698 			if ( pEntryData->GetElement().get() == xIFace.get() )
699 				return pEntryData;
700 			else if (bRecurs)
701 			{
702 				pEntryData = FindData( xElement, pEntryData->GetChildList() );
703 				if (pEntryData)
704 					return pEntryData;
705 			}
706 		}
707 		return NULL;
708 	}
709 
710 	//------------------------------------------------------------------------
711 	FmEntryData* NavigatorTreeModel::FindData( const ::rtl::OUString& rText, FmFormData* pParentData, sal_Bool bRecurs )
712 	{
713         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::FindData" );
714 		FmEntryDataList* pDataList;
715 		if( !pParentData )
716 			pDataList = GetRootList();
717 		else
718 			pDataList = pParentData->GetChildList();
719 
720 		::rtl::OUString aEntryText;
721 		FmEntryData* pEntryData;
722 		FmEntryData* pChildData;
723 
724 		for( sal_uInt16 i=0; i<pDataList->Count(); i++ )
725 		{
726 			pEntryData = pDataList->GetObject(i);
727 			aEntryText = pEntryData->GetText();
728 
729 			if (rText == aEntryText)
730 				return pEntryData;
731 
732 			if( bRecurs && pEntryData->ISA(FmFormData) )
733 			{
734 				pChildData = FindData( rText, (FmFormData*)pEntryData );
735 				if( pChildData )
736 					return pChildData;
737 			}
738 		}
739 
740 		return NULL;
741 	}
742 
743 	//------------------------------------------------------------------------
744 	void NavigatorTreeModel::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
745 	{
746         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::Notify" );
747 		if( rHint.ISA(SdrHint) )
748 		{
749 			SdrHint* pSdrHint = (SdrHint*)&rHint;
750 			switch( pSdrHint->GetKind() )
751 			{
752 				case HINT_OBJINSERTED:
753 					InsertSdrObj(pSdrHint->GetObject());
754 					break;
755 				case HINT_OBJREMOVED:
756 					RemoveSdrObj(pSdrHint->GetObject());
757 					break;
758                 default:
759                     break;
760 			}
761 		}
762 		// hat sich die shell verabschiedet?
763 		else if ( rHint.ISA(SfxSimpleHint) && ((SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING)
764 			UpdateContent((FmFormShell*)NULL);
765 
766 		// hat sich die Markierung der Controls veraendert ?
767 		else if (rHint.ISA(FmNavViewMarksChanged))
768 		{
769 			FmNavViewMarksChanged* pvmcHint = (FmNavViewMarksChanged*)&rHint;
770 			BroadcastMarkedObjects( pvmcHint->GetAffectedView()->GetMarkedObjectList() );
771 		}
772 	}
773 
774 	//------------------------------------------------------------------------
775 	void NavigatorTreeModel::InsertSdrObj( const SdrObject* pObj )
776     {
777         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::InsertSdrObj" );
778         const FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
779         if ( pFormObject )
780         {
781             try
782             {
783                 Reference< XFormComponent > xFormComponent( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
784                 Reference< XIndexAccess > xContainer( xFormComponent->getParent(), UNO_QUERY_THROW );
785 
786                 sal_Int32 nPos = getElementPos( xContainer, xFormComponent );
787                 InsertFormComponent( xFormComponent, nPos );
788             }
789             catch( const Exception& )
790             {
791                 DBG_UNHANDLED_EXCEPTION();
792             }
793         }
794         else if ( pObj->IsGroupObject() )
795         {
796             SdrObjListIter aIter( *pObj->GetSubList() );
797             while ( aIter.IsMore() )
798                 InsertSdrObj( aIter.Next() );
799         }
800     }
801 
802     //------------------------------------------------------------------------
803     void NavigatorTreeModel::RemoveSdrObj( const SdrObject* pObj )
804     {
805         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::RemoveSdrObj" );
806         const FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
807         if ( pFormObject )
808         {
809             try
810             {
811                 Reference< XFormComponent > xFormComponent( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
812                 FmEntryData* pEntryData = FindData( xFormComponent, GetRootList(), sal_True );
813                 if ( pEntryData )
814                     Remove( pEntryData );
815             }
816             catch( const Exception& )
817             {
818                 DBG_UNHANDLED_EXCEPTION();
819             }
820         }
821         else if ( pObj->IsGroupObject() )
822         {
823             SdrObjListIter aIter( *pObj->GetSubList() );
824             while ( aIter.IsMore() )
825                 RemoveSdrObj( aIter.Next() );
826         }
827     }
828 
829 	sal_Bool NavigatorTreeModel::InsertFormComponent(FmNavRequestSelectHint& rHint, SdrObject* pObject)
830 	{
831         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::InsertFormComponent" );
832 		if ( pObject->ISA(SdrObjGroup) )
833 		{   // rekursiv absteigen
834 			const SdrObjList *pChilds = ((SdrObjGroup*)pObject)->GetSubList();
835 			for ( sal_uInt16 i=0; i<pChilds->GetObjCount(); ++i )
836 			{
837 				SdrObject* pCurrent = pChilds->GetObj(i);
838 				if (!InsertFormComponent(rHint, pCurrent))
839 					return sal_False;
840 			}
841 		}
842         else
843         {
844 			FmFormObj* pFormObject = FmFormObj::GetFormObject( pObject );
845             if ( !pFormObject )
846                 return sal_False;
847 
848             try
849             {
850                 Reference< XFormComponent > xFormViewControl( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
851                 FmEntryData* pControlData = FindData( xFormViewControl, GetRootList() );
852                 if ( !pControlData )
853                     return sal_False;
854 
855                 rHint.AddItem( pControlData );
856                 return sal_True;
857             }
858             catch( const Exception& )
859             {
860             	DBG_UNHANDLED_EXCEPTION();
861                 return sal_False;
862             }
863         }
864 
865         return sal_True;
866 	}
867 
868 	void NavigatorTreeModel::BroadcastMarkedObjects(const SdrMarkList& mlMarked)
869 	{
870         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::BroadcastMarkedObjects" );
871 		// gehen wir durch alle markierten Objekte und suchen wir die raus, mit denen ich was anfangen kann
872 		FmNavRequestSelectHint rshRequestSelection;
873 		sal_Bool bIsMixedSelection = sal_False;
874 
875 		for (sal_uLong i=0; (i<mlMarked.GetMarkCount()) && !bIsMixedSelection; i++)
876 		{
877 			SdrObject* pobjCurrent = mlMarked.GetMark(i)->GetMarkedSdrObj();
878 			bIsMixedSelection |= !InsertFormComponent(rshRequestSelection, pobjCurrent);
879 				// bei einem Nicht-Form-Control liefert InsertFormComponent sal_False !
880 		}
881 
882 		rshRequestSelection.SetMixedSelection(bIsMixedSelection);
883 		if (bIsMixedSelection)
884 			rshRequestSelection.ClearItems();
885 
886 		Broadcast(rshRequestSelection);
887 			// eine leere Liste interpretiert der NavigatorTree so, dass er seine Selektion komplett rausnimmt
888 	}
889 
890 	//------------------------------------------------------------------------
891 	void NavigatorTreeModel::UpdateContent( const Reference< XNameContainer > & xForms )
892 	{
893         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::UpdateContent" );
894 		//////////////////////////////////////////////////////////////////////
895 		// Model von der Root aufwaerts neu fuellen
896 		Clear();
897 		if (xForms.is())
898 		{
899 			Reference< XContainer >  xFormContainer(xForms, UNO_QUERY);
900 			if (xFormContainer.is())
901 				xFormContainer->addContainerListener((XContainerListener*)m_pPropChangeList);
902 
903 			FillBranch(NULL);
904 
905 			// jetzt in meinem Tree genau die das in meiner View markierte Control selektieren
906 			// (bzw alle solchen), falls es eines gibt ...
907 			if(!m_pFormShell) return;       // keine Shell -> wech
908 
909 			FmFormView* pFormView = m_pFormShell->GetFormView();
910 			DBG_ASSERT(pFormView != NULL, "NavigatorTreeModel::UpdateContent : keine FormView");
911 			BroadcastMarkedObjects(pFormView->GetMarkedObjectList());
912 		}
913 	}
914 
915 	//------------------------------------------------------------------------
916 	void NavigatorTreeModel::UpdateContent( FmFormShell* pShell )
917 	{
918         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::UpdateContent" );
919 		//////////////////////////////////////////////////////////////////////
920 		// Wenn Shell sich nicht veraendert hat, nichts machen
921 		FmFormPage* pNewPage = pShell ? pShell->GetCurPage() : NULL;
922 		if ((pShell == m_pFormShell) && (m_pFormPage == pNewPage))
923 			return;
924 
925 		//////////////////////////////////////////////////////////////////////
926 		// Als Listener abmelden
927 		if( m_pFormShell )
928 		{
929 			if (m_pFormModel)
930 				EndListening( *m_pFormModel );
931 			m_pFormModel = NULL;
932 			EndListening( *m_pFormShell );
933 			Clear();
934 		}
935 
936 		//////////////////////////////////////////////////////////////////////
937 		// Vollupdate
938 		m_pFormShell = pShell;
939 		if (m_pFormShell)
940 		{
941 			m_pFormPage = pNewPage;
942 			UpdateContent(m_pFormPage->GetForms());
943 		} else
944 			m_pFormPage = NULL;
945 
946 		//////////////////////////////////////////////////////////////////////
947 		// Als Listener neu anmelden
948 		if( m_pFormShell )
949 		{
950 			StartListening( *m_pFormShell );
951 			m_pFormModel = m_pFormShell->GetFormModel();
952 			if( m_pFormModel )
953 				StartListening( *m_pFormModel );
954 		}
955 	}
956 
957 	//------------------------------------------------------------------------
958 	Reference< XIndexContainer >  NavigatorTreeModel::GetFormComponents( FmFormData* pFormData )
959 	{
960         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::GetFormComponents" );
961 		//////////////////////////////////////////////////////////////////////
962 		// Von der Form Components holen
963 		if (pFormData)
964 			return Reference< XIndexContainer > (pFormData->GetFormIface(), UNO_QUERY);
965 
966 		return Reference< XIndexContainer > ();
967 	}
968 
969 	//------------------------------------------------------------------------
970 	sal_Bool NavigatorTreeModel::CheckEntry( FmEntryData* pEntryData )
971 	{
972         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::CheckEntry" );
973 		//////////////////////////////////////////////////////////////////////
974 		// Nur Forms duerfen auf Doppeldeutigkeit untersucht werden
975 		if( !pEntryData->ISA(FmFormData) ) return sal_True;
976 
977 		//////////////////////////////////////////////////////////////////////
978 		// ChildListe des Parents holen
979 		FmFormData* pParentData = (FmFormData*)pEntryData->GetParent();
980 		FmEntryDataList* pChildList;
981 		if( !pParentData )
982 			pChildList = GetRootList();
983 		else
984 			pChildList = pParentData->GetChildList();
985 
986 		//////////////////////////////////////////////////////////////////////
987 		// In ChildListe nach doppelten Namen suchen
988 		::rtl::OUString aChildText;
989 		FmEntryData* pChildData;
990 
991 		for( sal_uInt16 i=0; i<pChildList->Count(); i++ )
992 		{
993 			pChildData = pChildList->GetObject(i);
994 			aChildText = pChildData->GetText();
995 
996 			//////////////////////////////////////////////////////////////////////
997 			// Gleichen Eintrag gefunden
998 			if	(	(aChildText == pEntryData->GetText())
999 				&&	(pEntryData!=pChildData)
1000 				)
1001 			{
1002 
1003 
1004 				SQLContext aError;
1005 				aError.Message = String(SVX_RES(RID_ERR_CONTEXT_ADDFORM));
1006 				aError.Details = String(SVX_RES(RID_ERR_DUPLICATE_NAME));
1007 				displayException(aError);
1008 
1009 				return sal_False;
1010 			}
1011 		}
1012 
1013 		return sal_True;
1014 	}
1015 
1016 	//------------------------------------------------------------------------
1017 	sal_Bool NavigatorTreeModel::Rename( FmEntryData* pEntryData, const ::rtl::OUString& rNewText )
1018 	{
1019         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::Rename" );
1020 		//////////////////////////////////////////////////////////////////////
1021 		// Wenn Name schon vorhanden, Fehlermeldung
1022 		pEntryData->SetText( rNewText );
1023 
1024 		//////////////////////////////////////////////////////////////////////
1025 		// PropertySet besorgen
1026 		Reference< XFormComponent >  xFormComponent;
1027 
1028 		if( pEntryData->ISA(FmFormData) )
1029 		{
1030 			FmFormData* pFormData = (FmFormData*)pEntryData;
1031 			Reference< XForm >  xForm( pFormData->GetFormIface());
1032 			xFormComponent = Reference< XFormComponent > (xForm, UNO_QUERY);
1033 		}
1034 
1035 		if( pEntryData->ISA(FmControlData) )
1036 		{
1037 			FmControlData* pControlData = (FmControlData*)pEntryData;
1038 			xFormComponent = pControlData->GetFormComponent();
1039 		}
1040 
1041 		if( !xFormComponent.is() ) return sal_False;
1042 		Reference< XPropertySet >  xSet(xFormComponent, UNO_QUERY);
1043 		if( !xSet.is() ) return sal_False;
1044 
1045 		//////////////////////////////////////////////////////////////////////
1046 		// Namen setzen
1047 		xSet->setPropertyValue( FM_PROP_NAME, makeAny(rNewText) );
1048 
1049 		return sal_True;
1050 	}
1051 
1052 	//------------------------------------------------------------------------
1053 	sal_Bool NavigatorTreeModel::IsNameAlreadyDefined( const ::rtl::OUString& rName, FmFormData* pParentData )
1054 	{
1055         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::IsNameAlreadyDefined" );
1056 		//////////////////////////////////////////////////////////////////////
1057 		// Form in der Root
1058 		if( !pParentData )
1059 		{
1060 			if (GetForms()->hasByName(rName))
1061 				return sal_True;
1062 		}
1063 
1064 		//////////////////////////////////////////////////////////////////////
1065 		// Restliche Components
1066 		else
1067 		{
1068 			Reference< XNameContainer >  xFormComponents(GetFormComponents(pParentData), UNO_QUERY);
1069 			if (xFormComponents.is() && xFormComponents->hasByName(rName))
1070 				return sal_True;
1071 		}
1072 
1073 		return sal_False;
1074 	}
1075 
1076 	//------------------------------------------------------------------------
1077 	SdrObject* NavigatorTreeModel::GetSdrObj( FmControlData* pControlData )
1078 	{
1079         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::GetSdrObj" );
1080 		if (!pControlData || !m_pFormShell)
1081 			return NULL;
1082 
1083 		//////////////////////////////////////////////////////////////////////
1084 		// In der Page das entsprechende SdrObj finden und selektieren
1085 		Reference< XFormComponent >  xFormComponent( pControlData->GetFormComponent());
1086 		if (!xFormComponent.is())
1087 			return NULL;
1088 
1089 		FmFormView*     pFormView       = m_pFormShell->GetFormView();
1090 		SdrPageView*    pPageView       = pFormView->GetSdrPageView();
1091 		SdrPage*        pPage           = pPageView->GetPage();
1092 
1093 		SdrObjListIter  aIter( *pPage );
1094 		return Search(aIter, xFormComponent);
1095 	}
1096 
1097     //------------------------------------------------------------------
1098     SdrObject* NavigatorTreeModel::Search(SdrObjListIter& rIter, const Reference< XFormComponent > & xComp)
1099     {
1100         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::Search" );
1101         while (rIter.IsMore())
1102         {
1103             SdrObject* pObj = rIter.Next();
1104             FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
1105             if ( pFormObject )
1106             {
1107                 Reference< XFormComponent > xFormViewControl( pFormObject->GetUnoControlModel(), UNO_QUERY );
1108                 if ( xFormViewControl == xComp )
1109                     return pObj;
1110             }
1111             else if ( pObj->IsGroupObject() )
1112             {
1113                 SdrObjListIter aIter( *pObj->GetSubList() );
1114                 pObj = Search( aIter, xComp );
1115                 if ( pObj )
1116                     return pObj;
1117             }
1118         }
1119         return NULL;
1120     }
1121 
1122 //............................................................................
1123 }	// namespace svxform
1124 //............................................................................
1125 
1126 
1127