Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <svx/dialmgr.hxx>
21 : #include <svx/fmshell.hxx>
22 : #include <svx/fmmodel.hxx>
23 : #include <svx/fmpage.hxx>
24 : #include <svx/fmglob.hxx>
25 : #include "svx/svditer.hxx"
26 : #include <svx/svdogrp.hxx>
27 : #include <svx/svdpagv.hxx>
28 :
29 : #include "fmprop.hrc"
30 :
31 : #include "fmundo.hxx"
32 : #include "fmhelp.hrc"
33 : #include "fmexpl.hxx"
34 : #include "svx/fmresids.hrc"
35 : #include "fmshimp.hxx"
36 : #include "fmobj.hxx"
37 : #include <sfx2/objsh.hxx>
38 : #include <tools/diagnose_ex.h>
39 : #include <com/sun/star/container/XContainer.hpp>
40 :
41 :
42 : namespace svxform
43 : {
44 :
45 :
46 : using namespace ::com::sun::star::uno;
47 : using namespace ::com::sun::star::lang;
48 : using namespace ::com::sun::star::beans;
49 : using namespace ::com::sun::star::form;
50 : using namespace ::com::sun::star::awt;
51 : using namespace ::com::sun::star::container;
52 : using namespace ::com::sun::star::script;
53 : using namespace ::com::sun::star::sdb;
54 :
55 0 : OFormComponentObserver::OFormComponentObserver(NavigatorTreeModel* _pModel)
56 : :m_pNavModel(_pModel)
57 : ,m_nLocks(0)
58 0 : ,m_bCanUndo(true)
59 : {
60 0 : }
61 :
62 : // XPropertyChangeListener
63 :
64 0 : void SAL_CALL OFormComponentObserver::disposing(const EventObject& Source) throw( RuntimeException, std::exception )
65 : {
66 0 : Remove( Source.Source );
67 0 : }
68 :
69 :
70 0 : void SAL_CALL OFormComponentObserver::propertyChange(const PropertyChangeEvent& evt) throw(RuntimeException, std::exception)
71 : {
72 0 : if( !m_pNavModel ) return;
73 0 : if( evt.PropertyName != FM_PROP_NAME ) return;
74 :
75 0 : Reference< XFormComponent > xFormComponent(evt.Source, UNO_QUERY);
76 0 : Reference< XForm > xForm(evt.Source, UNO_QUERY);
77 :
78 0 : FmEntryData* pEntryData( NULL );
79 0 : if( xForm.is() )
80 0 : pEntryData = m_pNavModel->FindData( xForm, m_pNavModel->GetRootList() );
81 0 : else if( xFormComponent.is() )
82 0 : pEntryData = m_pNavModel->FindData( xFormComponent, m_pNavModel->GetRootList() );
83 :
84 0 : if( pEntryData )
85 : {
86 0 : OUString aNewName = ::comphelper::getString(evt.NewValue);
87 0 : pEntryData->SetText( aNewName );
88 0 : FmNavNameChangedHint aNameChangedHint( pEntryData, aNewName );
89 0 : m_pNavModel->Broadcast( aNameChangedHint );
90 0 : }
91 : }
92 :
93 : // XContainerListener
94 :
95 0 : void SAL_CALL OFormComponentObserver::elementInserted(const ContainerEvent& evt) throw(RuntimeException, std::exception)
96 : {
97 0 : if (IsLocked() || !m_pNavModel)
98 0 : return;
99 :
100 : // insert no Undoaction
101 0 : m_bCanUndo = false;
102 :
103 0 : Reference< XInterface > xTemp;
104 0 : evt.Element >>= xTemp;
105 0 : Insert(xTemp, ::comphelper::getINT32(evt.Accessor));
106 :
107 0 : m_bCanUndo = true;
108 : }
109 :
110 :
111 0 : void OFormComponentObserver::Insert(const Reference< XInterface > & xIface, sal_Int32 nIndex)
112 : {
113 0 : Reference< XForm > xForm(xIface, UNO_QUERY);
114 0 : if (xForm.is())
115 : {
116 0 : m_pNavModel->InsertForm(xForm, sal_uInt32(nIndex));
117 0 : Reference< XIndexContainer > xContainer(xForm, UNO_QUERY);
118 0 : Reference< XInterface > xTemp;
119 0 : for (sal_Int32 i = 0; i < xContainer->getCount(); i++)
120 : {
121 0 : xContainer->getByIndex(i) >>= xTemp;
122 0 : Insert(xTemp, i);
123 0 : }
124 : }
125 : else
126 : {
127 0 : Reference< XFormComponent > xFormComp(xIface, UNO_QUERY);
128 0 : if (xFormComp.is())
129 0 : m_pNavModel->InsertFormComponent(xFormComp, sal_uInt32(nIndex));
130 0 : }
131 0 : }
132 :
133 :
134 0 : void SAL_CALL OFormComponentObserver::elementReplaced(const ContainerEvent& evt) throw(RuntimeException, std::exception)
135 : {
136 0 : if (IsLocked() || !m_pNavModel)
137 0 : return;
138 :
139 0 : m_bCanUndo = false;
140 :
141 : // delete EntryData
142 0 : Reference< XFormComponent > xReplaced;
143 0 : evt.ReplacedElement >>= xReplaced;
144 0 : FmEntryData* pEntryData = m_pNavModel->FindData(xReplaced, m_pNavModel->GetRootList(), true);
145 0 : if (pEntryData)
146 : {
147 0 : if (pEntryData->ISA(FmControlData))
148 : {
149 0 : Reference< XFormComponent > xComp;
150 0 : evt.Element >>= xComp;
151 : DBG_ASSERT(xComp.is(), "OFormComponentObserver::elementReplaced : invalid argument !");
152 : // FmControlData should be coupled with XFormComponent
153 0 : m_pNavModel->ReplaceFormComponent(xReplaced, xComp);
154 : }
155 0 : else if (pEntryData->ISA(FmFormData))
156 : {
157 : OSL_FAIL("replacing forms not implemented yet !");
158 : }
159 : }
160 :
161 0 : m_bCanUndo = true;
162 : }
163 :
164 :
165 0 : void OFormComponentObserver::Remove( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxElement )
166 : {
167 0 : if (IsLocked() || !m_pNavModel)
168 0 : return;
169 :
170 0 : m_bCanUndo = false;
171 :
172 :
173 : // delete EntryData
174 0 : FmEntryData* pEntryData = m_pNavModel->FindData( _rxElement, m_pNavModel->GetRootList(), true );
175 0 : if (pEntryData)
176 0 : m_pNavModel->Remove(pEntryData);
177 :
178 0 : m_bCanUndo = true;
179 : }
180 :
181 :
182 0 : void SAL_CALL OFormComponentObserver::elementRemoved(const ContainerEvent& evt) throw(RuntimeException, std::exception)
183 : {
184 0 : Reference< XInterface > xElement;
185 0 : evt.Element >>= xElement;
186 0 : Remove( xElement );
187 0 : }
188 :
189 0 : NavigatorTreeModel::NavigatorTreeModel( const ImageList& _rNormalImages )
190 : :m_pFormShell(NULL)
191 : ,m_pFormPage(NULL)
192 : ,m_pFormModel(NULL)
193 0 : ,m_aNormalImages( _rNormalImages )
194 : {
195 0 : m_pPropChangeList = new OFormComponentObserver(this);
196 0 : m_pPropChangeList->acquire();
197 0 : m_pRootList = new FmEntryDataList();
198 0 : }
199 :
200 :
201 0 : NavigatorTreeModel::~NavigatorTreeModel()
202 : {
203 :
204 : // unregister Listener
205 0 : if( m_pFormShell)
206 : {
207 0 : FmFormModel* pFormModel = m_pFormShell->GetFormModel();
208 0 : if( pFormModel && IsListening(*pFormModel))
209 0 : EndListening( *pFormModel );
210 :
211 0 : if (IsListening(*m_pFormShell))
212 0 : EndListening(*m_pFormShell);
213 : }
214 :
215 0 : Clear();
216 0 : delete m_pRootList;
217 0 : m_pPropChangeList->ReleaseModel();
218 0 : m_pPropChangeList->release();
219 0 : }
220 :
221 :
222 :
223 0 : void NavigatorTreeModel::SetModified( bool bMod )
224 : {
225 0 : if( !m_pFormShell ) return;
226 0 : SfxObjectShell* pObjShell = m_pFormShell->GetFormModel()->GetObjectShell();
227 0 : if( !pObjShell ) return;
228 0 : pObjShell->SetModified( bMod );
229 : }
230 :
231 :
232 0 : void NavigatorTreeModel::Clear()
233 : {
234 0 : Reference< css::form::XForms > xForms( GetForms());
235 0 : if(xForms.is())
236 0 : xForms->removeContainerListener(static_cast<XContainerListener*>(m_pPropChangeList));
237 :
238 :
239 : // delete RootList
240 0 : GetRootList()->clear();
241 :
242 :
243 : // notify UI
244 0 : FmNavClearedHint aClearedHint;
245 0 : Broadcast( aClearedHint );
246 0 : }
247 :
248 :
249 0 : Reference< css::form::XForms > NavigatorTreeModel::GetForms() const
250 : {
251 0 : if( !m_pFormShell || !m_pFormShell->GetCurPage())
252 0 : return NULL;
253 : else
254 0 : return m_pFormShell->GetCurPage()->GetForms();
255 : }
256 :
257 :
258 0 : void NavigatorTreeModel::Insert(FmEntryData* pEntry, sal_uLong nRelPos, bool bAlterModel)
259 : {
260 0 : if (IsListening(*m_pFormModel))
261 0 : EndListening(*m_pFormModel);
262 :
263 0 : m_pPropChangeList->Lock();
264 0 : FmFormData* pFolder = static_cast<FmFormData*>( pEntry->GetParent() );
265 0 : Reference< XChild > xElement( pEntry->GetChildIFace() );
266 0 : if (bAlterModel)
267 : {
268 0 : OUString aStr;
269 0 : if (pEntry->ISA(FmFormData))
270 0 : aStr = SVX_RESSTR(RID_STR_FORM);
271 : else
272 0 : aStr = SVX_RESSTR(RID_STR_CONTROL);
273 :
274 0 : Reference< XIndexContainer > xContainer;
275 0 : if (pFolder)
276 0 : xContainer = Reference< XIndexContainer > (pFolder->GetFormIface(), UNO_QUERY);
277 : else
278 0 : xContainer = Reference< XIndexContainer > (GetForms(), UNO_QUERY);
279 :
280 0 : bool bUndo = m_pFormModel->IsUndoEnabled();
281 :
282 0 : if( bUndo )
283 : {
284 0 : OUString aUndoStr(SVX_RESSTR(RID_STR_UNDO_CONTAINER_INSERT));
285 0 : aUndoStr = aUndoStr.replaceFirst("#", aStr);
286 0 : m_pFormModel->BegUndo(aUndoStr);
287 : }
288 :
289 0 : if (nRelPos >= (sal_uInt32)xContainer->getCount())
290 0 : nRelPos = (sal_uInt32)xContainer->getCount();
291 :
292 : // UndoAction
293 0 : if ( bUndo && m_pPropChangeList->CanUndo())
294 : {
295 : m_pFormModel->AddUndo(new FmUndoContainerAction(*m_pFormModel,
296 : FmUndoContainerAction::Inserted,
297 : xContainer,
298 : xElement,
299 0 : nRelPos));
300 : }
301 :
302 : // Element has to be of the expected type by the container
303 0 : if (xContainer->getElementType() ==
304 0 : cppu::UnoType<XForm>::get())
305 :
306 : {
307 0 : Reference< XForm > xElementAsForm(xElement, UNO_QUERY);
308 0 : xContainer->insertByIndex(nRelPos, makeAny(xElementAsForm));
309 : }
310 0 : else if (xContainer->getElementType() ==
311 0 : cppu::UnoType<XFormComponent>::get())
312 :
313 : {
314 0 : Reference< XFormComponent > xElementAsComponent(xElement, UNO_QUERY);
315 0 : xContainer->insertByIndex(nRelPos, makeAny(xElementAsComponent));
316 : }
317 : else
318 : {
319 : OSL_FAIL("NavigatorTreeModel::Insert : the parent container needs an elementtype I don't know !");
320 : }
321 :
322 0 : if( bUndo )
323 0 : m_pFormModel->EndUndo();
324 : }
325 :
326 : // register as PropertyChangeListener
327 0 : Reference< XPropertySet > xSet(xElement, UNO_QUERY);
328 0 : if( xSet.is() )
329 0 : xSet->addPropertyChangeListener( FM_PROP_NAME, m_pPropChangeList );
330 :
331 :
332 : // Remove data from model
333 0 : if (pEntry->ISA(FmFormData))
334 : {
335 0 : Reference< XContainer > xContainer(xElement, UNO_QUERY);
336 0 : if (xContainer.is())
337 0 : xContainer->addContainerListener(static_cast<XContainerListener*>(m_pPropChangeList));
338 : }
339 :
340 0 : if (pFolder)
341 0 : pFolder->GetChildList()->insert( pEntry, nRelPos );
342 : else
343 0 : GetRootList()->insert( pEntry, nRelPos );
344 :
345 :
346 : // notify UI
347 0 : FmNavInsertedHint aInsertedHint( pEntry, nRelPos );
348 0 : Broadcast( aInsertedHint );
349 :
350 0 : m_pPropChangeList->UnLock();
351 0 : if (IsListening(*m_pFormModel))
352 0 : StartListening(*m_pFormModel);
353 0 : }
354 :
355 :
356 0 : void NavigatorTreeModel::Remove(FmEntryData* pEntry, bool bAlterModel)
357 : {
358 :
359 : // get form and parent
360 0 : if (!pEntry || !m_pFormModel)
361 0 : return;
362 :
363 0 : if (IsListening(*m_pFormModel))
364 0 : EndListening(*m_pFormModel);
365 :
366 0 : const bool bUndo = m_pFormModel->IsUndoEnabled();
367 :
368 0 : m_pPropChangeList->Lock();
369 0 : FmFormData* pFolder = static_cast<FmFormData*>( pEntry->GetParent() );
370 0 : Reference< XChild > xElement ( pEntry->GetChildIFace() );
371 0 : if (bAlterModel)
372 : {
373 0 : OUString aStr;
374 0 : if (pEntry->ISA(FmFormData))
375 0 : aStr = SVX_RESSTR(RID_STR_FORM);
376 : else
377 0 : aStr = SVX_RESSTR(RID_STR_CONTROL);
378 :
379 0 : if( bUndo )
380 : {
381 0 : OUString aUndoStr(SVX_RESSTR(RID_STR_UNDO_CONTAINER_REMOVE));
382 0 : aUndoStr = aUndoStr.replaceFirst("#", aStr);
383 0 : m_pFormModel->BegUndo(aUndoStr);
384 0 : }
385 : }
386 :
387 : // now real deletion of data form model
388 0 : if (pEntry->ISA(FmFormData))
389 0 : RemoveForm(static_cast<FmFormData*>(pEntry));
390 : else
391 0 : RemoveFormComponent(static_cast<FmControlData*>(pEntry));
392 :
393 :
394 0 : if (bAlterModel)
395 : {
396 0 : Reference< XIndexContainer > xContainer(xElement->getParent(), UNO_QUERY);
397 : // remove from Container
398 0 : sal_Int32 nContainerIndex = getElementPos(xContainer.get(), xElement);
399 : // UndoAction
400 0 : if (nContainerIndex >= 0)
401 : {
402 0 : if ( bUndo && m_pPropChangeList->CanUndo())
403 : {
404 : m_pFormModel->AddUndo(new FmUndoContainerAction(*m_pFormModel,
405 : FmUndoContainerAction::Removed,
406 : xContainer,
407 0 : xElement, nContainerIndex ));
408 : }
409 0 : else if( !m_pPropChangeList->CanUndo() )
410 : {
411 0 : FmUndoContainerAction::DisposeElement( xElement );
412 : }
413 :
414 0 : xContainer->removeByIndex(nContainerIndex );
415 : }
416 :
417 0 : if( bUndo )
418 0 : m_pFormModel->EndUndo();
419 : }
420 :
421 : // remove from parent
422 0 : if (pFolder)
423 0 : pFolder->GetChildList()->remove( pEntry );
424 : else
425 : {
426 0 : GetRootList()->remove( pEntry );
427 :
428 : // If root has no more form, reset CurForm at shell
429 0 : if ( !GetRootList()->size() )
430 0 : m_pFormShell->GetImpl()->forgetCurrentForm();
431 : }
432 :
433 :
434 : // notify UI
435 0 : FmNavRemovedHint aRemovedHint( pEntry );
436 0 : Broadcast( aRemovedHint );
437 :
438 : // delete entry
439 0 : delete pEntry;
440 :
441 0 : m_pPropChangeList->UnLock();
442 0 : StartListening(*m_pFormModel);
443 : }
444 :
445 :
446 0 : void NavigatorTreeModel::RemoveForm(FmFormData* pFormData)
447 : {
448 :
449 : // get form and parent
450 0 : if (!pFormData || !m_pFormModel)
451 0 : return;
452 :
453 0 : FmEntryDataList* pChildList = pFormData->GetChildList();
454 0 : for ( size_t i = pChildList->size(); i > 0; )
455 : {
456 0 : FmEntryData* pEntryData = pChildList->at( --i );
457 :
458 :
459 : // Child is form -> recursive call
460 0 : if( pEntryData->ISA(FmFormData) )
461 0 : RemoveForm( static_cast<FmFormData*>(pEntryData));
462 0 : else if( pEntryData->ISA(FmControlData) )
463 0 : RemoveFormComponent(static_cast<FmControlData*>(pEntryData));
464 : }
465 :
466 :
467 : // unregister as PropertyChangeListener
468 0 : Reference< XPropertySet > xSet( pFormData->GetPropertySet() );
469 0 : if ( xSet.is() )
470 0 : xSet->removePropertyChangeListener( FM_PROP_NAME, m_pPropChangeList );
471 :
472 0 : Reference< XContainer > xContainer( pFormData->GetContainer() );
473 0 : if (xContainer.is())
474 0 : xContainer->removeContainerListener(static_cast<XContainerListener*>(m_pPropChangeList));
475 : }
476 :
477 :
478 0 : void NavigatorTreeModel::RemoveFormComponent(FmControlData* pControlData)
479 : {
480 :
481 : // get control and parent
482 0 : if (!pControlData)
483 0 : return;
484 :
485 :
486 : // unregister as PropertyChangeListener
487 0 : Reference< XPropertySet > xSet( pControlData->GetPropertySet() );
488 0 : if (xSet.is())
489 0 : xSet->removePropertyChangeListener( FM_PROP_NAME, m_pPropChangeList);
490 : }
491 :
492 :
493 0 : void NavigatorTreeModel::ClearBranch( FmFormData* pParentData )
494 : {
495 :
496 : // delete all entries of this branch
497 0 : FmEntryDataList* pChildList = pParentData->GetChildList();
498 :
499 0 : for( size_t i = pChildList->size(); i > 0; )
500 : {
501 0 : FmEntryData* pChildData = pChildList->at( --i );
502 0 : if( pChildData->ISA(FmFormData) )
503 0 : ClearBranch( static_cast<FmFormData*>(pChildData) );
504 :
505 0 : pChildList->remove( pChildData );
506 : }
507 0 : }
508 :
509 :
510 0 : void NavigatorTreeModel::FillBranch( FmFormData* pFormData )
511 : {
512 :
513 : // insert froms from root
514 0 : if( pFormData == NULL )
515 : {
516 0 : Reference< XIndexContainer > xForms(GetForms(), UNO_QUERY);
517 0 : if (!xForms.is())
518 0 : return;
519 :
520 0 : Reference< XForm > xSubForm;
521 0 : for (sal_Int32 i=0; i<xForms->getCount(); ++i)
522 : {
523 : DBG_ASSERT( xForms->getByIndex(i).getValueType() == cppu::UnoType<XForm>::get(),
524 : "NavigatorTreeModel::FillBranch : the root container should supply only elements of type XForm");
525 :
526 0 : xForms->getByIndex(i) >>= xSubForm;
527 0 : FmFormData* pSubFormData = new FmFormData( xSubForm, m_aNormalImages, pFormData );
528 0 : Insert( pSubFormData, CONTAINER_APPEND );
529 :
530 :
531 : // new branch, if SubForm contains Subforms itself
532 0 : FillBranch( pSubFormData );
533 0 : }
534 : }
535 :
536 :
537 : // insert components
538 : else
539 : {
540 0 : Reference< XIndexContainer > xComponents( GetFormComponents(pFormData));
541 0 : if( !xComponents.is() ) return;
542 :
543 0 : Reference< XInterface > xInterface;
544 0 : Reference< XPropertySet > xSet;
545 : FmControlData* pNewControlData;
546 : FmFormData* pSubFormData;
547 :
548 0 : Reference< XFormComponent > xCurrentComponent;
549 0 : for (sal_Int32 j=0; j<xComponents->getCount(); ++j)
550 : {
551 0 : xComponents->getByIndex(j) >>= xCurrentComponent;
552 0 : Reference< XForm > xSubForm(xCurrentComponent, UNO_QUERY);
553 :
554 0 : if (xSubForm.is())
555 : { // actuell component is a form
556 0 : pSubFormData = new FmFormData(xSubForm, m_aNormalImages, pFormData);
557 0 : Insert(pSubFormData, CONTAINER_APPEND);
558 :
559 :
560 : // new branch, if SubForm contains Subfroms itself
561 0 : FillBranch(pSubFormData);
562 : }
563 : else
564 : {
565 0 : pNewControlData = new FmControlData(xCurrentComponent, m_aNormalImages, pFormData);
566 0 : Insert(pNewControlData, CONTAINER_APPEND);
567 : }
568 0 : }
569 : }
570 : }
571 :
572 :
573 0 : void NavigatorTreeModel::InsertForm(const Reference< XForm > & xForm, sal_uInt32 nRelPos)
574 : {
575 0 : FmFormData* pFormData = static_cast<FmFormData*>(FindData( xForm, GetRootList() ));
576 0 : if (pFormData)
577 0 : return;
578 :
579 :
580 : // set ParentData
581 0 : Reference< XInterface > xIFace( xForm->getParent());
582 0 : Reference< XForm > xParentForm(xIFace, UNO_QUERY);
583 0 : FmFormData* pParentData = NULL;
584 0 : if (xParentForm.is())
585 0 : pParentData = static_cast<FmFormData*>(FindData( xParentForm, GetRootList() ));
586 :
587 0 : pFormData = new FmFormData( xForm, m_aNormalImages, pParentData );
588 0 : Insert( pFormData, nRelPos );
589 : }
590 :
591 :
592 0 : void NavigatorTreeModel::InsertFormComponent(const Reference< XFormComponent > & xComp, sal_uInt32 nRelPos)
593 : {
594 :
595 : // set ParentData
596 0 : Reference< XInterface > xIFace( xComp->getParent());
597 0 : Reference< XForm > xForm(xIFace, UNO_QUERY);
598 0 : if (!xForm.is())
599 0 : return;
600 :
601 0 : FmFormData* pParentData = static_cast<FmFormData*>(FindData( xForm, GetRootList() ));
602 0 : if( !pParentData )
603 : {
604 0 : pParentData = new FmFormData( xForm, m_aNormalImages, NULL );
605 0 : Insert( pParentData, CONTAINER_APPEND );
606 : }
607 :
608 0 : if (!FindData(xComp, pParentData->GetChildList(),false))
609 : {
610 :
611 : // set new EntryData
612 0 : FmEntryData* pNewEntryData = new FmControlData( xComp, m_aNormalImages, pParentData );
613 :
614 :
615 : // insert new EntryData
616 0 : Insert( pNewEntryData, nRelPos );
617 0 : }
618 : }
619 :
620 :
621 0 : void NavigatorTreeModel::ReplaceFormComponent(
622 : const Reference< XFormComponent > & xOld,
623 : const Reference< XFormComponent > & xNew
624 : )
625 : {
626 0 : FmEntryData* pData = FindData(xOld, GetRootList(), true);
627 : assert(pData && pData->ISA(FmControlData)); //NavigatorTreeModel::ReplaceFormComponent : invalid argument
628 0 : if (!pData || !pData->ISA(FmControlData))
629 0 : return;
630 0 : static_cast<FmControlData*>(pData)->ModelReplaced( xNew, m_aNormalImages );
631 :
632 0 : FmNavModelReplacedHint aReplacedHint( pData );
633 0 : Broadcast( aReplacedHint );
634 : }
635 :
636 :
637 0 : FmEntryData* NavigatorTreeModel::FindData(const Reference< XInterface > & xElement, FmEntryDataList* pDataList, bool bRecurs)
638 : {
639 : // normalize
640 0 : Reference< XInterface > xIFace( xElement, UNO_QUERY );
641 :
642 0 : for ( size_t i = 0; i < pDataList->size(); i++ )
643 : {
644 0 : FmEntryData* pEntryData = pDataList->at( i );
645 0 : if ( pEntryData->GetElement().get() == xIFace.get() )
646 0 : return pEntryData;
647 0 : else if (bRecurs)
648 : {
649 0 : pEntryData = FindData( xElement, pEntryData->GetChildList() );
650 0 : if (pEntryData)
651 0 : return pEntryData;
652 : }
653 : }
654 0 : return NULL;
655 : }
656 :
657 :
658 0 : FmEntryData* NavigatorTreeModel::FindData( const OUString& rText, FmFormData* pParentData, bool bRecurs )
659 : {
660 : FmEntryDataList* pDataList;
661 0 : if( !pParentData )
662 0 : pDataList = GetRootList();
663 : else
664 0 : pDataList = pParentData->GetChildList();
665 :
666 0 : OUString aEntryText;
667 : FmEntryData* pEntryData;
668 : FmEntryData* pChildData;
669 :
670 0 : for( size_t i = 0; i < pDataList->size(); i++ )
671 : {
672 0 : pEntryData = pDataList->at( i );
673 0 : aEntryText = pEntryData->GetText();
674 :
675 0 : if (rText == aEntryText)
676 0 : return pEntryData;
677 :
678 0 : if( bRecurs && pEntryData->ISA(FmFormData) )
679 : {
680 0 : pChildData = FindData( rText, static_cast<FmFormData*>(pEntryData) );
681 0 : if( pChildData )
682 0 : return pChildData;
683 : }
684 : }
685 :
686 0 : return NULL;
687 : }
688 :
689 :
690 0 : void NavigatorTreeModel::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
691 : {
692 0 : const SdrHint* pSdrHint = dynamic_cast<const SdrHint*>(&rHint);
693 0 : if( pSdrHint )
694 : {
695 0 : switch( pSdrHint->GetKind() )
696 : {
697 : case HINT_OBJINSERTED:
698 0 : InsertSdrObj(pSdrHint->GetObject());
699 0 : break;
700 : case HINT_OBJREMOVED:
701 0 : RemoveSdrObj(pSdrHint->GetObject());
702 0 : break;
703 : default:
704 0 : break;
705 : }
706 : }
707 : // is shell gone?
708 0 : else if ( dynamic_cast<const SfxSimpleHint*>(&rHint) && static_cast<const SfxSimpleHint*>(&rHint)->GetId() == SFX_HINT_DYING)
709 0 : UpdateContent(nullptr);
710 :
711 : // changed mark of controls?
712 0 : else if (dynamic_cast<const FmNavViewMarksChanged*>(&rHint))
713 : {
714 0 : const FmNavViewMarksChanged* pvmcHint = static_cast<const FmNavViewMarksChanged*>(&rHint);
715 0 : BroadcastMarkedObjects( pvmcHint->GetAffectedView()->GetMarkedObjectList() );
716 : }
717 0 : }
718 :
719 :
720 0 : void NavigatorTreeModel::InsertSdrObj( const SdrObject* pObj )
721 : {
722 0 : const FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
723 0 : if ( pFormObject )
724 : {
725 : try
726 : {
727 0 : Reference< XFormComponent > xFormComponent( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
728 0 : Reference< XIndexAccess > xContainer( xFormComponent->getParent(), UNO_QUERY_THROW );
729 :
730 0 : sal_Int32 nPos = getElementPos( xContainer, xFormComponent );
731 0 : InsertFormComponent( xFormComponent, nPos );
732 : }
733 0 : catch( const Exception& )
734 : {
735 : DBG_UNHANDLED_EXCEPTION();
736 : }
737 : }
738 0 : else if ( pObj->IsGroupObject() )
739 : {
740 0 : SdrObjListIter aIter( *pObj->GetSubList() );
741 0 : while ( aIter.IsMore() )
742 0 : InsertSdrObj( aIter.Next() );
743 : }
744 0 : }
745 :
746 :
747 0 : void NavigatorTreeModel::RemoveSdrObj( const SdrObject* pObj )
748 : {
749 0 : const FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
750 0 : if ( pFormObject )
751 : {
752 : try
753 : {
754 0 : Reference< XFormComponent > xFormComponent( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
755 0 : FmEntryData* pEntryData = FindData( xFormComponent, GetRootList(), true );
756 0 : if ( pEntryData )
757 0 : Remove( pEntryData );
758 : }
759 0 : catch( const Exception& )
760 : {
761 : DBG_UNHANDLED_EXCEPTION();
762 : }
763 : }
764 0 : else if ( pObj->IsGroupObject() )
765 : {
766 0 : SdrObjListIter aIter( *pObj->GetSubList() );
767 0 : while ( aIter.IsMore() )
768 0 : RemoveSdrObj( aIter.Next() );
769 : }
770 0 : }
771 :
772 0 : bool NavigatorTreeModel::InsertFormComponent(FmNavRequestSelectHint& rHint, SdrObject* pObject)
773 : {
774 0 : if ( pObject->ISA(SdrObjGroup) )
775 : { // descend recursively
776 0 : const SdrObjList *pChildren = static_cast<SdrObjGroup*>(pObject)->GetSubList();
777 0 : for ( size_t i=0; i<pChildren->GetObjCount(); ++i )
778 : {
779 0 : SdrObject* pCurrent = pChildren->GetObj(i);
780 0 : if (!InsertFormComponent(rHint, pCurrent))
781 0 : return false;
782 : }
783 : }
784 : else
785 : {
786 0 : FmFormObj* pFormObject = FmFormObj::GetFormObject( pObject );
787 0 : if ( !pFormObject )
788 0 : return false;
789 :
790 : try
791 : {
792 0 : Reference< XFormComponent > xFormViewControl( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
793 0 : FmEntryData* pControlData = FindData( xFormViewControl, GetRootList() );
794 0 : if ( !pControlData )
795 0 : return false;
796 :
797 0 : rHint.AddItem( pControlData );
798 0 : return true;
799 : }
800 0 : catch( const Exception& )
801 : {
802 : DBG_UNHANDLED_EXCEPTION();
803 0 : return false;
804 : }
805 : }
806 :
807 0 : return true;
808 : }
809 :
810 0 : void NavigatorTreeModel::BroadcastMarkedObjects(const SdrMarkList& mlMarked)
811 : {
812 : // search all objects, which can be handled, out of marked objects
813 0 : FmNavRequestSelectHint rshRequestSelection;
814 0 : bool bIsMixedSelection = false;
815 :
816 0 : for (size_t i=0; (i<mlMarked.GetMarkCount()) && !bIsMixedSelection; ++i)
817 : {
818 0 : SdrObject* pobjCurrent = mlMarked.GetMark(i)->GetMarkedSdrObj();
819 0 : bIsMixedSelection |= !InsertFormComponent(rshRequestSelection, pobjCurrent);
820 : // if Not-Form-Control, InsertFormComponent returns sal_False !
821 : }
822 :
823 0 : rshRequestSelection.SetMixedSelection(bIsMixedSelection);
824 0 : if (bIsMixedSelection)
825 0 : rshRequestSelection.ClearItems();
826 :
827 0 : Broadcast(rshRequestSelection);
828 : // an empty list causes NavigatorTree to remove his selection
829 0 : }
830 :
831 :
832 0 : void NavigatorTreeModel::UpdateContent( const Reference< css::form::XForms > & xForms )
833 : {
834 :
835 : // refill model form root upward
836 0 : Clear();
837 0 : if (xForms.is())
838 : {
839 0 : xForms->addContainerListener(static_cast<XContainerListener*>(m_pPropChangeList));
840 :
841 0 : FillBranch(NULL);
842 :
843 : // select same control in tree as in view
844 : // (or all of them), if there is one ...
845 0 : if(!m_pFormShell) return; // no shell
846 :
847 0 : FmFormView* pFormView = m_pFormShell->GetFormView();
848 : DBG_ASSERT(pFormView != NULL, "NavigatorTreeModel::UpdateContent : keine FormView");
849 0 : BroadcastMarkedObjects(pFormView->GetMarkedObjectList());
850 : }
851 : }
852 :
853 :
854 0 : void NavigatorTreeModel::UpdateContent( FmFormShell* pShell )
855 : {
856 :
857 : // If shell is unchanged, do nothing
858 0 : FmFormPage* pNewPage = pShell ? pShell->GetCurPage() : NULL;
859 0 : if ((pShell == m_pFormShell) && (m_pFormPage == pNewPage))
860 0 : return;
861 :
862 :
863 : // unregister as Listener
864 0 : if( m_pFormShell )
865 : {
866 0 : if (m_pFormModel)
867 0 : EndListening( *m_pFormModel );
868 0 : m_pFormModel = NULL;
869 0 : EndListening( *m_pFormShell );
870 0 : Clear();
871 : }
872 :
873 :
874 : // entire update
875 0 : m_pFormShell = pShell;
876 0 : if (m_pFormShell)
877 : {
878 0 : m_pFormPage = pNewPage;
879 0 : UpdateContent(m_pFormPage->GetForms());
880 : } else
881 0 : m_pFormPage = NULL;
882 :
883 :
884 : // register as Listener again
885 0 : if( m_pFormShell )
886 : {
887 0 : StartListening( *m_pFormShell );
888 0 : m_pFormModel = m_pFormShell->GetFormModel();
889 0 : if( m_pFormModel )
890 0 : StartListening( *m_pFormModel );
891 : }
892 : }
893 :
894 :
895 0 : Reference< XIndexContainer > NavigatorTreeModel::GetFormComponents( FmFormData* pFormData )
896 : {
897 :
898 : // get components from form
899 0 : if (pFormData)
900 0 : return Reference< XIndexContainer > (pFormData->GetFormIface(), UNO_QUERY);
901 :
902 0 : return Reference< XIndexContainer > ();
903 : }
904 :
905 :
906 0 : bool NavigatorTreeModel::Rename( FmEntryData* pEntryData, const OUString& rNewText )
907 : {
908 :
909 : // If name already exist, error message
910 0 : pEntryData->SetText( rNewText );
911 :
912 :
913 : // get PropertySet
914 0 : Reference< XFormComponent > xFormComponent;
915 :
916 0 : if( pEntryData->ISA(FmFormData) )
917 : {
918 0 : FmFormData* pFormData = static_cast<FmFormData*>(pEntryData);
919 0 : Reference< XForm > xForm( pFormData->GetFormIface());
920 0 : xFormComponent = xForm;
921 : }
922 :
923 0 : if( pEntryData->ISA(FmControlData) )
924 : {
925 0 : FmControlData* pControlData = static_cast<FmControlData*>(pEntryData);
926 0 : xFormComponent = pControlData->GetFormComponent();
927 : }
928 :
929 0 : if( !xFormComponent.is() ) return false;
930 0 : Reference< XPropertySet > xSet(xFormComponent, UNO_QUERY);
931 0 : if( !xSet.is() ) return false;
932 :
933 :
934 : // set name
935 0 : xSet->setPropertyValue( FM_PROP_NAME, makeAny(rNewText) );
936 :
937 0 : return true;
938 : }
939 :
940 :
941 0 : SdrObject* NavigatorTreeModel::Search(SdrObjListIter& rIter, const Reference< XFormComponent > & xComp)
942 : {
943 0 : while (rIter.IsMore())
944 : {
945 0 : SdrObject* pObj = rIter.Next();
946 0 : FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
947 0 : if ( pFormObject )
948 : {
949 0 : Reference< XFormComponent > xFormViewControl( pFormObject->GetUnoControlModel(), UNO_QUERY );
950 0 : if ( xFormViewControl == xComp )
951 0 : return pObj;
952 : }
953 0 : else if ( pObj->IsGroupObject() )
954 : {
955 0 : SdrObjListIter aIter( *pObj->GetSubList() );
956 0 : pObj = Search( aIter, xComp );
957 0 : if ( pObj )
958 0 : return pObj;
959 : }
960 : }
961 0 : return NULL;
962 : }
963 :
964 :
965 435 : }
966 :
967 :
968 :
969 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|