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