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 #ifndef INCLUDED_SVX_SOURCE_INC_FMEXPL_HXX 20 #define INCLUDED_SVX_SOURCE_INC_FMEXPL_HXX 21 22 #include <config_options.h> 23 #include <svl/lstner.hxx> 24 #include <svl/SfxBroadcaster.hxx> 25 #include <vcl/window.hxx> 26 #include <sfx2/childwin.hxx> 27 #include <svl/poolitem.hxx> 28 #include <sfx2/bindings.hxx> 29 #include <sfx2/dockwin.hxx> 30 #include <sfx2/ctrlitem.hxx> 31 32 #include <com/sun/star/form/XForm.hpp> 33 #include <com/sun/star/form/XFormComponent.hpp> 34 #include <com/sun/star/beans/PropertyChangeEvent.hpp> 35 #include <com/sun/star/container/XContainerListener.hpp> 36 #include <com/sun/star/beans/XPropertyChangeListener.hpp> 37 #include <com/sun/star/container/XIndexContainer.hpp> 38 39 #include <svx/fmview.hxx> 40 41 #include "fmexch.hxx" 42 #include <vector> 43 #include <set> 44 #include <cppuhelper/implbase.hxx> 45 46 class SdrObjListIter; 47 class FmFormShell; 48 class SdrObject; 49 class FmFormModel; 50 class FmFormView; 51 class SdrMarkList; 52 53 54 class FmEntryData; 55 class FmNavInsertedHint : public SfxHint 56 { 57 FmEntryData* pEntryData; 58 sal_uInt32 nPos; 59 60 public: 61 FmNavInsertedHint( FmEntryData* pInsertedEntryData, sal_uInt32 nRelPos ); 62 virtual ~FmNavInsertedHint() override; 63 GetEntryData() const64 FmEntryData* GetEntryData() const { return pEntryData; } GetRelPos() const65 sal_uInt32 GetRelPos() const { return nPos; } 66 }; 67 68 69 class FmNavModelReplacedHint : public SfxHint 70 { 71 FmEntryData* pEntryData; // the data of the entry that has got a new model 72 73 public: 74 FmNavModelReplacedHint( FmEntryData* pAffectedEntryData ); 75 virtual ~FmNavModelReplacedHint() override; 76 GetEntryData() const77 FmEntryData* GetEntryData() const { return pEntryData; } 78 }; 79 80 81 class FmNavRemovedHint : public SfxHint 82 { 83 FmEntryData* pEntryData; 84 85 public: 86 FmNavRemovedHint( FmEntryData* pInsertedEntryData ); 87 virtual ~FmNavRemovedHint() override; 88 GetEntryData() const89 FmEntryData* GetEntryData() const { return pEntryData; } 90 }; 91 92 93 class FmNavNameChangedHint : public SfxHint 94 { 95 FmEntryData* pEntryData; 96 OUString aNewName; 97 98 public: 99 FmNavNameChangedHint( FmEntryData* pData, const OUString& rNewName ); 100 virtual ~FmNavNameChangedHint() override; 101 GetEntryData() const102 FmEntryData* GetEntryData() const { return pEntryData; } GetNewName() const103 const OUString& GetNewName() const { return aNewName; } 104 }; 105 106 107 class FmNavClearedHint : public SfxHint 108 { 109 public: 110 FmNavClearedHint(); 111 virtual ~FmNavClearedHint() override; 112 }; 113 114 115 class FmNavViewMarksChanged : public SfxHint 116 { 117 FmFormView* pView; 118 public: FmNavViewMarksChanged(FmFormView * pWhichView)119 FmNavViewMarksChanged(FmFormView* pWhichView) { pView = pWhichView; } 120 GetAffectedView() const121 const FmFormView* GetAffectedView() const { return pView; } 122 }; 123 124 125 class FmEntryDataList; 126 class FmEntryData 127 { 128 private: 129 css::uno::Reference< css::uno::XInterface > m_xNormalizedIFace; 130 css::uno::Reference< css::beans::XPropertySet > m_xProperties; 131 css::uno::Reference< css::container::XChild > m_xChild; 132 133 protected: 134 OUString m_aNormalImage; 135 OUString aText; 136 137 std::unique_ptr<FmEntryDataList> 138 pChildList; 139 FmEntryData* pParent; 140 141 protected: 142 void newObject( const css::uno::Reference< css::uno::XInterface >& _rxIFace ); 143 144 public: 145 146 FmEntryData( FmEntryData* pParentData, const css::uno::Reference< css::uno::XInterface >& _rIFace ); 147 FmEntryData( const FmEntryData& rEntryData ); 148 virtual ~FmEntryData(); 149 SetText(const OUString & rText)150 void SetText( const OUString& rText ){ aText = rText; } SetParent(FmEntryData * pParentData)151 void SetParent( FmEntryData* pParentData ){ pParent = pParentData; } 152 GetNormalImage() const153 const OUString& GetNormalImage() const { return m_aNormalImage; } 154 GetText() const155 const OUString& GetText() const { return aText; } GetParent() const156 FmEntryData* GetParent() const { return pParent; } GetChildList() const157 FmEntryDataList* GetChildList() const { return pChildList.get(); } 158 159 virtual bool IsEqualWithoutChildren( FmEntryData* pEntryData ); 160 virtual std::unique_ptr<FmEntryData> Clone() = 0; 161 162 // note that the interface returned is normalized, i.e. querying the given XInterface of the object 163 // for XInterface must return the interface itself. GetElement() const164 const css::uno::Reference< css::uno::XInterface >& GetElement() const 165 { 166 return m_xNormalizedIFace; 167 } 168 GetPropertySet() const169 const css::uno::Reference< css::beans::XPropertySet >& GetPropertySet() const 170 { 171 return m_xProperties; 172 } 173 GetChildIFace() const174 const css::uno::Reference< css::container::XChild >& GetChildIFace() const 175 { 176 return m_xChild; 177 } 178 }; 179 180 181 class FmEntryDataList final 182 { 183 private: 184 std::vector< std::unique_ptr<FmEntryData> > maEntryDataList; 185 186 public: 187 FmEntryDataList(); 188 ~FmEntryDataList(); 189 at(size_t Index)190 FmEntryData* at( size_t Index ) 191 { return maEntryDataList.at(Index).get(); } 192 size() const193 size_t size() const { return maEntryDataList.size(); } 194 void removeNoDelete( FmEntryData* pItem ); 195 void insert( std::unique_ptr<FmEntryData> pItem, size_t Index ); 196 void clear(); 197 }; 198 199 200 // FmNavRequestSelectHint - someone tells the NavigatorTree to select certain entries 201 202 typedef std::set<FmEntryData*> FmEntryDataArray; 203 204 class FmNavRequestSelectHint : public SfxHint 205 { 206 FmEntryDataArray m_arredToSelect; 207 bool m_bMixedSelection; 208 public: FmNavRequestSelectHint()209 FmNavRequestSelectHint() 210 : m_bMixedSelection(false) 211 { 212 } 213 SetMixedSelection(bool bMixedSelection)214 void SetMixedSelection(bool bMixedSelection) { m_bMixedSelection = bMixedSelection; } IsMixedSelection() const215 bool IsMixedSelection() const { return m_bMixedSelection; } AddItem(FmEntryData * pEntry)216 void AddItem(FmEntryData* pEntry) { m_arredToSelect.insert(pEntry); } ClearItems()217 void ClearItems() { m_arredToSelect.clear(); } GetItems()218 FmEntryDataArray& GetItems() { return m_arredToSelect; } 219 }; 220 221 222 class FmFormData : public FmEntryData 223 { 224 css::uno::Reference< css::form::XForm > m_xForm; 225 226 public: 227 FmFormData(const css::uno::Reference< css::form::XForm >& _rxForm, FmFormData* _pParent); 228 FmFormData( const FmFormData& rFormData ); 229 virtual ~FmFormData() override; 230 GetFormIface() const231 const css::uno::Reference< css::form::XForm >& GetFormIface() const { return m_xForm; } 232 233 virtual bool IsEqualWithoutChildren( FmEntryData* pEntryData ) override; 234 virtual std::unique_ptr<FmEntryData> Clone() override; 235 }; 236 237 238 class FmControlData : public FmEntryData 239 { 240 css::uno::Reference< css::form::XFormComponent > m_xFormComponent; 241 242 OUString GetImage() const; 243 244 public: 245 246 FmControlData( 247 const css::uno::Reference< css::form::XFormComponent >& _rxComponent, 248 FmFormData* _pParent 249 ); 250 FmControlData( const FmControlData& rControlData ); 251 virtual ~FmControlData() override; 252 GetFormComponent() const253 const css::uno::Reference< css::form::XFormComponent >& GetFormComponent() const { return m_xFormComponent; } 254 virtual bool IsEqualWithoutChildren( FmEntryData* pEntryData ) override; 255 virtual std::unique_ptr<FmEntryData> Clone() override; 256 257 void ModelReplaced(const css::uno::Reference< css::form::XFormComponent >& _rxNew); 258 }; 259 260 261 namespace svxform 262 { 263 264 265 class NavigatorTreeModel; 266 267 class OFormComponentObserver final 268 :public ::cppu::WeakImplHelper < css::beans::XPropertyChangeListener 269 , css::container::XContainerListener 270 > 271 { 272 ::svxform::NavigatorTreeModel* m_pNavModel; 273 sal_uInt32 m_nLocks; 274 bool m_bCanUndo; 275 276 public: 277 OFormComponentObserver( ::svxform::NavigatorTreeModel* pModel ); 278 279 // XEventListenerListener 280 virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override; 281 282 // css::beans::XPropertyChangeListener 283 virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent& evt) override; 284 285 // css::container::XContainerListener 286 287 virtual void SAL_CALL elementInserted(const css::container::ContainerEvent& rEvent) override; 288 virtual void SAL_CALL elementReplaced(const css::container::ContainerEvent& rEvent) override; 289 virtual void SAL_CALL elementRemoved(const css::container::ContainerEvent& rEvent) override; 290 Lock()291 void Lock() { m_nLocks++; } UnLock()292 void UnLock() { m_nLocks--; } IsLocked() const293 bool IsLocked() const { return m_nLocks != 0; } CanUndo() const294 bool CanUndo() const { return m_bCanUndo; } ReleaseModel()295 void ReleaseModel() { m_pNavModel = nullptr; } 296 private: 297 void Insert(const css::uno::Reference< css::uno::XInterface >& xIface, sal_Int32 nIndex); 298 void Remove( const css::uno::Reference< css::uno::XInterface >& _rxElement ); 299 }; 300 301 class NavigatorTreeModel : public SfxBroadcaster 302 ,public SfxListener 303 { 304 friend class NavigatorTree; 305 friend class OFormComponentObserver; 306 307 std::unique_ptr<FmEntryDataList> 308 m_pRootList; 309 FmFormShell* m_pFormShell; 310 FmFormPage* m_pFormPage; 311 FmFormModel* m_pFormModel; 312 rtl::Reference<OFormComponentObserver> m_pPropChangeList; 313 314 void UpdateContent( const css::uno::Reference< css::form::XForms >& xForms ); 315 316 void InsertForm(const css::uno::Reference< css::form::XForm >& xForm, sal_uInt32 nRelPos); 317 void RemoveForm(FmFormData const * pFormData); 318 319 void InsertFormComponent(const css::uno::Reference< css::form::XFormComponent >& xComp, sal_uInt32 nRelPos); 320 void RemoveFormComponent(FmControlData const * pControlData); 321 void InsertSdrObj(const SdrObject* pSdrObj); 322 void RemoveSdrObj(const SdrObject* pSdrObj); 323 324 void ReplaceFormComponent(const css::uno::Reference< css::form::XFormComponent >& xOld, const css::uno::Reference< css::form::XFormComponent >& xNew); 325 326 void BroadcastMarkedObjects(const SdrMarkList& mlMarked); 327 // send a RequestSelectHint with the currently selected objects 328 bool InsertFormComponent(FmNavRequestSelectHint& rHint, SdrObject* pObject); 329 // is a helper for previous, manages the ... in SdrObjGroups; 330 // returns sal_True if the object is a FormComponent (or recursively consists only of such) 331 332 public: 333 NavigatorTreeModel(); 334 virtual ~NavigatorTreeModel() override; 335 336 void FillBranch( FmFormData* pParentData ); 337 void UpdateContent( FmFormShell* pNewShell ); 338 339 void Insert(FmEntryData* pEntryData, sal_uInt32 nRelPos = SAL_MAX_UINT32, 340 bool bAlterModel = false); 341 void Remove(FmEntryData* pEntryData, bool bAlterModel = false); 342 343 static bool Rename( FmEntryData* pEntryData, const OUString& rNewText ); 344 345 void Clear(); 346 void SetModified(); 347 348 css::uno::Reference< css::form::XForms > GetForms() const; GetFormShell() const349 FmFormShell* GetFormShell() const { return m_pFormShell; } GetFormPage() const350 FmFormPage* GetFormPage() const { return m_pFormPage; } 351 FmEntryData* FindData( const css::uno::Reference< css::uno::XInterface >& xElement, FmEntryDataList* pDataList, bool bRecurs=true ); 352 FmEntryData* FindData( const OUString& rText, FmFormData const * pParentData, bool bRecurs ); GetRootList() const353 FmEntryDataList* GetRootList() const { return m_pRootList.get(); } 354 static css::uno::Reference< css::container::XIndexContainer > GetFormComponents( FmFormData const * pParentFormData ); 355 356 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; 357 }; 358 359 class NavigatorTree; 360 361 class NavigatorTreeDropTarget : public DropTargetHelper 362 { 363 private: 364 NavigatorTree& m_rTreeView; 365 366 virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override; 367 virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override; 368 369 public: 370 NavigatorTreeDropTarget(NavigatorTree& rTreeView); 371 }; 372 373 typedef std::set<std::unique_ptr<weld::TreeIter>> SvLBoxEntrySortedArray; 374 375 class NavigatorTree final : public SfxListener 376 { 377 std::unique_ptr<weld::TreeView> m_xTreeView; 378 NavigatorTreeDropTarget m_aDropTargetHelper; 379 380 enum SELDATA_ITEMS { SDI_DIRTY, SDI_ALL, SDI_NORMALIZED, SDI_NORMALIZED_FORMARK }; 381 382 Timer m_aSynchronizeTimer; 383 // the meta-data about my current selection 384 SvLBoxEntrySortedArray m_arrCurrentSelection; 385 // the entries which, in the view, are currently marked as "cut" (painted semi-transparent) 386 ListBoxEntrySet m_aCutEntries; 387 388 ::svxform::OControlExchangeHelper m_aControlExchange; 389 390 std::unique_ptr<NavigatorTreeModel> m_pNavModel; 391 std::unique_ptr<weld::TreeIter> m_xRootEntry; 392 std::unique_ptr<weld::TreeIter> m_xEditEntry; 393 394 ImplSVEvent * nEditEvent; 395 396 SELDATA_ITEMS m_sdiState; 397 398 sal_uInt16 m_nSelectLock; 399 sal_uInt16 m_nFormsSelected; 400 sal_uInt16 m_nControlsSelected; 401 sal_uInt16 m_nHiddenControls; // (the number is included in m_nControlsSelected) 402 403 bool m_bDragDataDirty : 1; // ditto 404 bool m_bPrevSelectionMixed : 1; 405 bool m_bRootSelected : 1; 406 bool m_bInitialUpdate : 1; // am I the first time in the UpdateContent? 407 bool m_bKeyboardCut : 1; 408 bool m_bEditing : 1; 409 410 FmControlData* NewControl(const OUString& rServiceName, const weld::TreeIter& rParentEntry, bool bEditName); 411 void NewForm(const weld::TreeIter& rParentEntry); 412 std::unique_ptr<weld::TreeIter> Insert(FmEntryData* pEntryData, int nRelPos); 413 void Remove( FmEntryData* pEntryData ); 414 415 416 void CollectSelectionData(SELDATA_ITEMS sdiHow); 417 // Collects the currently selected entries in m_arrCurrentSelection, normalizes the list if requested. 418 // - SDI_NORMALIZED simply means that all entries that already have a selected ancestor are not collected. 419 // - SDI_NORMALIZED_FORMARK means that the procedure is the same as for SDI_NORMALIZED, 420 // but entries whose direct parent is not selected are collected (independent of the 421 // status of further ancestors). The same applies for forms that are selected, 422 // regardless of the status of any ancestors. 423 // For both normalized modes, the m_nFormsSelected, ... contain the correct number, 424 // even if not all of these entries end up in m_arrCurrentSelection. 425 // SDI_DIRTY is of course not allowed as a parameter. 426 427 // a single interface for all selected entries 428 void ShowSelectionProperties(bool bForce = false); 429 // delete all selected elements 430 void DeleteSelection(); 431 432 void SynchronizeSelection(FmEntryDataArray& arredToSelect); 433 // after calling this method, exactly the entries marked in the array are selected 434 void SynchronizeSelection(); 435 // makes the same, takes the MarkList of the View 436 void SynchronizeMarkList(); 437 // reverse direction of SynchronizeMarkList: selects in the view all controls corresponding to the current selection 438 439 void CollectObjects(FmFormData const * pFormData, bool bDeep, ::std::set< css::uno::Reference< css::form::XFormComponent > >& _rObjects); 440 441 // in the Select I usually update the Marklist of the corresponding view, 442 // with the following functions I can control the locking of this behavior LockSelectionHandling()443 void LockSelectionHandling() { ++m_nSelectLock; } UnlockSelectionHandling()444 void UnlockSelectionHandling() { --m_nSelectLock; } IsSelectionHandlingLocked() const445 bool IsSelectionHandlingLocked() const { return m_nSelectLock>0; } 446 IsEditingActive() const447 bool IsEditingActive() const { return m_bEditing; } 448 449 static bool IsHiddenControl(FmEntryData const * pEntryData); 450 451 DECL_LINK( KeyInputHdl, const KeyEvent&, bool ); 452 DECL_LINK( PopupMenuHdl, const CommandEvent&, bool ); 453 454 DECL_LINK(EditingEntryHdl, const weld::TreeIter&, bool); 455 typedef std::pair<const weld::TreeIter&, OUString> IterString; 456 DECL_LINK(EditedEntryHdl, const IterString&, bool); 457 458 DECL_LINK( OnEdit, void*, void ); 459 460 DECL_LINK( OnEntrySelDesel, weld::TreeView&, void ); 461 DECL_LINK( OnSynchronizeTimer, Timer*, void ); 462 463 DECL_LINK( OnClipboardAction, OLocalExchange&, void ); 464 465 DECL_LINK( DragBeginHdl, bool&, bool ); 466 467 public: 468 NavigatorTree(std::unique_ptr<weld::TreeView> xTreeView); 469 virtual ~NavigatorTree() override; 470 471 void Clear(); 472 void UpdateContent( FmFormShell* pFormShell ); 473 void MarkViewObj( FmFormData const * pFormData, bool bDeep ); 474 void MarkViewObj( FmControlData const * pControlData ); 475 void UnmarkAllViewObj(); 476 GrabFocus()477 void GrabFocus() { m_xTreeView->grab_focus(); } 478 479 bool IsFormEntry(const weld::TreeIter& rEntry); 480 bool IsFormComponentEntry(const weld::TreeIter& rEntry); 481 482 OUString GenerateName( FmEntryData const * pEntryData ); 483 GetNavModel() const484 NavigatorTreeModel* GetNavModel() const { return m_pNavModel.get(); } 485 std::unique_ptr<weld::TreeIter> FindEntry(FmEntryData* pEntryData); 486 487 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; 488 get_widget()489 weld::TreeView& get_widget() { return *m_xTreeView; } 490 491 sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt); 492 sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt); 493 494 private: 495 sal_Int8 implAcceptDataTransfer( const DataFlavorExVector& _rFlavors, sal_Int8 _nAction, const weld::TreeIter* _pTargetEntry, bool _bDnD ); 496 497 sal_Int8 implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, const Point& _rDropPos, bool _bDnD ); 498 sal_Int8 implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, const weld::TreeIter* _pTargetEntry, bool _bDnD ); 499 500 // check if a cut, copy, or drag operation can be started in the current situation 501 bool implAllowExchange( sal_Int8 _nAction, bool* _pHasNonHidden = nullptr ); 502 // check if a paste with the current clipboard content can be accepted 503 bool implAcceptPaste( ); 504 505 // fills m_aControlExchange in preparation of a DnD or clipboard operation 506 bool implPrepareExchange( sal_Int8 _nAction ); 507 508 void ModelHasRemoved(const weld::TreeIter* _pEntry); 509 510 void doPaste(); 511 void doCopy(); 512 void doCut(); 513 doingKeyboardCut() const514 bool doingKeyboardCut( ) const { return m_bKeyboardCut; } 515 }; 516 517 class NavigatorFrame : public SfxDockingWindow, public SfxControllerItem 518 { 519 private: 520 std::unique_ptr<NavigatorTree> m_xNavigatorTree; 521 522 protected: 523 virtual bool Close() override; 524 virtual void GetFocus() override; 525 virtual Size CalcDockingSize( SfxChildAlignment ) override; 526 virtual SfxChildAlignment CheckAlignment( SfxChildAlignment, SfxChildAlignment ) override; 527 528 using SfxDockingWindow::StateChanged; 529 530 public: 531 NavigatorFrame( SfxBindings *pBindings, SfxChildWindow *pMgr, 532 vcl::Window* pParent ); 533 virtual ~NavigatorFrame() override; 534 virtual void dispose() override; 535 536 void UpdateContent( FmFormShell* pFormShell ); 537 void StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState ) override; 538 void FillInfo( SfxChildWinInfo& rInfo ) const override; 539 }; 540 541 class UNLESS_MERGELIBS(SVXCORE_DLLPUBLIC) NavigatorFrameManager : public SfxChildWindow 542 { 543 public: 544 SVX_DLLPRIVATE NavigatorFrameManager( vcl::Window *pParent, sal_uInt16 nId, SfxBindings *pBindings, 545 SfxChildWinInfo *pInfo ); 546 SFX_DECL_CHILDWINDOW( NavigatorFrameManager ); 547 }; 548 } 549 550 #endif // INCLUDED_SVX_SOURCE_INC_FMEXPL_HXX 551 552 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 553