LibreOffice Module svx (master)  1
navigatortree.cxx
Go to the documentation of this file.
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 <memory>
21 #include <svx/dialmgr.hxx>
22 #include <svx/fmshell.hxx>
23 #include <svx/fmmodel.hxx>
24 #include <svx/fmpage.hxx>
25 #include <svx/svdpagv.hxx>
26 #include <svx/svditer.hxx>
27 
28 #include <helpids.h>
29 #include <fmexpl.hxx>
30 #include <fmshimp.hxx>
31 #include <fmservs.hxx>
32 #include <fmundo.hxx>
33 #include <fmpgeimp.hxx>
34 #include <fmobj.hxx>
35 #include <fmprop.hxx>
36 #include <sal/log.hxx>
37 #include <vcl/svapp.hxx>
38 #include <sfx2/viewsh.hxx>
39 #include <sfx2/dispatch.hxx>
40 #include <sfx2/viewfrm.hxx>
42 #include <comphelper/property.hxx>
43 #include <comphelper/types.hxx>
44 #include <com/sun/star/form/FormComponentType.hpp>
45 #include <com/sun/star/sdb/CommandType.hpp>
46 #include <com/sun/star/beans/PropertyAttribute.hpp>
47 #include <com/sun/star/script/XEventAttacherManager.hpp>
48 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
49 #include <com/sun/star/datatransfer/XTransferable.hpp>
50 #include <com/sun/star/uno/XComponentContext.hpp>
51 #include <svx/sdrpaintwindow.hxx>
52 
53 #include <svx/svxdlg.hxx>
54 #include <svx/strings.hrc>
55 #include <tools/diagnose_ex.h>
56 #include <svx/svxids.hrc>
57 #include <bitmaps.hlst>
58 #include <vcl/treelistentry.hxx>
59 #include <vcl/commandevent.hxx>
60 
61 namespace svxform
62 {
63 
64 
65  #define DROP_ACTION_TIMER_INITIAL_TICKS 10
66  // Time until scroll starts
67  #define DROP_ACTION_TIMER_SCROLL_TICKS 3
68  // Time to scroll one line
69  #define DROP_ACTION_TIMER_TICK_BASE 10
70  // factor for both declarations (in ms)
71 
72  #define EXPLORER_SYNC_DELAY 200
73  // Time (in ms) until explorer synchronizes the view after select or deselect
74 
75  using namespace ::com::sun::star::uno;
76  using namespace ::com::sun::star::lang;
77  using namespace ::com::sun::star::beans;
78  using namespace ::com::sun::star::form;
79  using namespace ::com::sun::star::awt;
80  using namespace ::com::sun::star::container;
81  using namespace ::com::sun::star::script;
82  using namespace ::com::sun::star::datatransfer;
84  using namespace ::com::sun::star::sdb;
85 
86 
87  // helper
88 
89 
90  typedef ::std::map< Reference< XInterface >, SdrObject* > MapModelToShape;
91 
92 
93  static void collectShapeModelMapping( SdrPage const * _pPage, MapModelToShape& _rMapping )
94  {
95  OSL_ENSURE( _pPage, "collectShapeModelMapping: invalid arg!" );
96 
97  _rMapping.clear();
98 
99  SdrObjListIter aIter( _pPage );
100  while ( aIter.IsMore() )
101  {
102  SdrObject* pSdrObject = aIter.Next();
103  FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject );
104  if ( !pFormObject )
105  continue;
106 
107  Reference< XInterface > xNormalizedModel( pFormObject->GetUnoControlModel(), UNO_QUERY );
108  // note that this is normalized (i.e. queried for XInterface explicitly)
109 
110  ::std::pair< MapModelToShape::iterator, bool > aPos =
111  _rMapping.emplace( xNormalizedModel, pSdrObject );
112  DBG_ASSERT( aPos.second, "collectShapeModelMapping: model was already existent!" );
113  // if this asserts, this would mean we have 2 shapes pointing to the same model
114  }
115  }
116 
118  :SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HSCROLL ) // #100258# OJ WB_HSCROLL added
119  ,m_aControlExchange(this)
120  ,m_pRootEntry(nullptr)
121  ,m_pEditEntry(nullptr)
122  ,nEditEvent(nullptr)
123  ,m_sdiState(SDI_DIRTY)
124  ,m_aTimerTriggered(-1,-1)
125  ,m_aDropActionType( DA_SCROLLUP )
126  ,m_nSelectLock(0)
127  ,m_nFormsSelected(0)
128  ,m_nControlsSelected(0)
129  ,m_nHiddenControls(0)
130  ,m_aTimerCounter( DROP_ACTION_TIMER_INITIAL_TICKS )
131  ,m_bDragDataDirty(false)
132  ,m_bPrevSelectionMixed(false)
133  ,m_bRootSelected(false)
134  ,m_bInitialUpdate(true)
135  ,m_bKeyboardCut( false )
136  {
138 
140  Image(StockImage::Yes, RID_SVXBMP_COLLAPSEDNODE),
141  Image(StockImage::Yes, RID_SVXBMP_EXPANDEDNODE)
142  );
143 
144  SetDragDropMode(DragDropMode::ALL);
145  EnableInplaceEditing( true );
146  SetSelectionMode(SelectionMode::Multiple);
147 
148  m_pNavModel.reset(new NavigatorTreeModel());
149  Clear();
150 
152 
153  m_aDropActionTimer.SetInvokeHandler(LINK(this, NavigatorTree, OnDropActionTimer));
154 
155  m_aSynchronizeTimer.SetInvokeHandler(LINK(this, NavigatorTree, OnSynchronizeTimer));
156  SetSelectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
157  SetDeselectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
158  }
159 
160 
162  {
163  disposeOnce();
164  }
165 
167  {
168  if( nEditEvent )
170 
173 
174  DBG_ASSERT(GetNavModel() != nullptr, "NavigatorTree::~NavigatorTree : unexpected : no ExplorerModel");
176  Clear();
177  m_pNavModel.reset();
179  }
180 
181 
183  {
184  m_pNavModel->Clear();
185  }
186 
187 
189  {
190  if (m_bInitialUpdate)
191  {
192  GrabFocus();
193  m_bInitialUpdate = false;
194  }
195 
196  FmFormShell* pOldShell = GetNavModel()->GetFormShell();
197  FmFormPage* pOldPage = GetNavModel()->GetFormPage();
198  FmFormPage* pNewPage = pFormShell ? pFormShell->GetCurPage() : nullptr;
199 
200  if ((pOldShell != pFormShell) || (pOldPage != pNewPage))
201  {
202  // new shell during editing
203  if (IsEditingActive())
205 
206  m_bDragDataDirty = true; // as a precaution, although I don't drag
207  }
208  GetNavModel()->UpdateContent( pFormShell );
209 
210  // if there is a form, expand root
213  // if there is EXACTLY ONE form, expand it too
214  if (m_pRootEntry)
215  {
217  if (pFirst && !pFirst->NextSibling())
218  Expand(pFirst);
219  }
220  }
221 
222 
223  bool NavigatorTree::implAllowExchange( sal_Int8 _nAction, bool* _pHasNonHidden )
224  {
225  SvTreeListEntry* pCurEntry = GetCurEntry();
226  if (!pCurEntry)
227  return false;
228 
229  // Information for AcceptDrop and Execute Drop
231  if (m_arrCurrentSelection.empty())
232  // nothing to do
233  return false;
234 
235  // check whether there are only hidden controls
236  // I may add a format to pCtrlExch
237  bool bHasNonHidden = std::any_of(m_arrCurrentSelection.begin(), m_arrCurrentSelection.end(),
238  [](const SvTreeListEntry* pEntry) {
239  FmEntryData* pCurrent = static_cast< FmEntryData* >( pEntry->GetUserData() );
240  return !IsHiddenControl( pCurrent );
241  });
242 
243  if ( bHasNonHidden && ( 0 == ( _nAction & DND_ACTION_MOVE ) ) )
244  // non-hidden controls need to be moved
245  return false;
246 
247  if ( _pHasNonHidden )
248  *_pHasNonHidden = bHasNonHidden;
249 
250  return true;
251  }
252 
253 
255  {
256  EndSelection();
257 
258  bool bHasNonHidden = false;
259  if ( !implAllowExchange( _nAction, &bHasNonHidden ) )
260  return false;
261 
264 
265  for (const auto& rpEntry : m_arrCurrentSelection)
267 
268  m_aControlExchange->setFormsRoot( GetNavModel()->GetFormPage()->GetForms() );
270 
271  if (!bHasNonHidden)
272  {
273  // create a sequence
274  Sequence< Reference< XInterface > > seqIFaces(m_arrCurrentSelection.size());
275  Reference< XInterface >* pArray = seqIFaces.getArray();
276  for (const auto& rpEntry : m_arrCurrentSelection)
277  {
278  *pArray = static_cast< FmEntryData* >( rpEntry->GetUserData() )->GetElement();
279  ++pArray;
280  }
281  // and the new format
283  }
284 
285  m_bDragDataDirty = false;
286  return true;
287  }
288 
289 
290  void NavigatorTree::StartDrag( sal_Int8 /*nAction*/, const ::Point& /*rPosPixel*/ )
291  {
292  EndSelection();
293 
295  // nothing to do or something went wrong
296  return;
297 
298  // collected all possible formats for current situation, we can start now
300  }
301 
302 
304  {
305  bool bHandled = false;
306  switch( rEvt.GetCommand() )
307  {
308  case CommandEventId::ContextMenu:
309  {
310  // Position of click
311  ::Point ptWhere;
312  if (rEvt.IsMouseEvent())
313  {
314  ptWhere = rEvt.GetMousePosPixel();
315  SvTreeListEntry* ptClickedOn = GetEntry(ptWhere);
316  if (ptClickedOn == nullptr)
317  break;
318  if ( !IsSelected(ptClickedOn) )
319  {
320  SelectAll(false);
321  Select(ptClickedOn);
322  SetCurEntry(ptClickedOn);
323  }
324  }
325  else
326  {
327  if (m_arrCurrentSelection.empty()) // only happens with context menu via keyboard
328  break;
329 
330  SvTreeListEntry* pCurrent = GetCurEntry();
331  if (!pCurrent)
332  break;
333  ptWhere = GetEntryPosition(pCurrent);
334  }
335 
336  // update my selection data
338 
339  // if there is at least one no-root-entry and the root selected, I deselect root
340  if ( (m_arrCurrentSelection.size() > 1) && m_bRootSelected )
341  {
342  Select( m_pRootEntry, false );
343  SetCursor( *m_arrCurrentSelection.begin(), true);
344  }
345  bool bSingleSelection = (m_arrCurrentSelection.size() == 1);
346 
347 
348  DBG_ASSERT( (!m_arrCurrentSelection.empty()) || m_bRootSelected, "no entries selected" );
349  // shouldn't happen, because I would have selected one during call to IsSelected,
350  // if there was none before
351 
352 
353  // create menu
354  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
355  FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : nullptr;
356  if( pFormShell && pFormModel )
357  {
358  VclBuilder aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/formnavimenu.ui", "");
359  VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu"));
360  const sal_uInt16 nNewId = aContextMenu->GetItemId("new");
361  PopupMenu* pSubMenuNew = aContextMenu->GetPopupMenu(nNewId);
362 
363  // menu 'New' only exists, if only the root or only one form is selected
364  aContextMenu->EnableItem(nNewId, bSingleSelection && (m_nFormsSelected || m_bRootSelected));
365 
366  // 'New'\'Form' under the same terms
367  const sal_uInt16 nFormId = pSubMenuNew->GetItemId("form");
368  pSubMenuNew->EnableItem(nFormId, bSingleSelection && (m_nFormsSelected || m_bRootSelected));
369  pSubMenuNew->SetItemImage(nFormId, Image(StockImage::Yes, RID_SVXBMP_FORM));
370 
371  // 'New'\'hidden...', if exactly one form is selected
372  const sal_uInt16 nHiddenId = pSubMenuNew->GetItemId("hidden");
373  pSubMenuNew->EnableItem(nHiddenId, bSingleSelection && m_nFormsSelected);
374  pSubMenuNew->SetItemImage(nHiddenId, Image(StockImage::Yes, RID_SVXBMP_HIDDEN));
375 
376  // 'Delete': everything which is not root can be removed
377  aContextMenu->EnableItem(aContextMenu->GetItemId("delete"), !m_bRootSelected);
378 
379  // 'Cut', 'Copy' and 'Paste'
380  aContextMenu->EnableItem(aContextMenu->GetItemId("cut"), !m_bRootSelected && implAllowExchange(DND_ACTION_MOVE));
381  aContextMenu->EnableItem(aContextMenu->GetItemId("copy"), !m_bRootSelected && implAllowExchange(DND_ACTION_COPY));
382  aContextMenu->EnableItem(aContextMenu->GetItemId("paste"), implAcceptPaste());
383 
384  // TabDialog, if exactly one form
385  aContextMenu->EnableItem(aContextMenu->GetItemId("taborder"), bSingleSelection && m_nFormsSelected);
386 
387  const sal_uInt16 nBrowserId = aContextMenu->GetItemId("props");
388  // in XML forms, we don't allow for the properties of a form
389  // #i36484#
390  if (pFormShell->GetImpl()->isEnhancedForm_Lock() && !m_nControlsSelected)
391  aContextMenu->RemoveItem(aContextMenu->GetItemPos(nBrowserId));
392 
393  // if the property browser is already open, we don't allow for the properties, too
394  if (pFormShell->GetImpl()->IsPropBrwOpen_Lock())
395  aContextMenu->RemoveItem(aContextMenu->GetItemPos(nBrowserId));
396  // and finally, if there's a mixed selection of forms and controls, disable the entry, too
397  else
398  aContextMenu->EnableItem(nBrowserId,
400 
401  // rename, if one element and no root
402  aContextMenu->EnableItem(aContextMenu->GetItemId("rename"), bSingleSelection && !m_bRootSelected);
403 
404  // Readonly-entry is only for root
405  aContextMenu->EnableItem(aContextMenu->GetItemId("designmode"), m_bRootSelected);
406  // the same for automatic control focus
407  aContextMenu->EnableItem(aContextMenu->GetItemId("controlfocus"), m_bRootSelected);
408 
409  std::unique_ptr<VclBuilder> xBuilder;
410  VclPtr<PopupMenu> xConversionMenu;
411  // ConvertTo-Slots are enabled, if one control is selected
412  // the corresponding slot is disabled
413  const sal_Int16 nChangeId = aContextMenu->GetItemId("change");
415  {
417  xConversionMenu = xBuilder->get_menu("menu");
418  aContextMenu->SetPopupMenu(nChangeId, xConversionMenu);
419 #if OSL_DEBUG_LEVEL > 0
420  FmControlData* pCurrent = static_cast<FmControlData*>((*m_arrCurrentSelection.begin())->GetUserData());
421  OSL_ENSURE( pFormShell->GetImpl()->isSolelySelected_Lock( pCurrent->GetFormComponent() ),
422  "NavigatorTree::Command: inconsistency between the navigator selection, and the selection as the shell knows it!" );
423 #endif
424 
425  pFormShell->GetImpl()->checkControlConversionSlotsForCurrentSelection_Lock(*aContextMenu->GetPopupMenu(nChangeId));
426  }
427  else
428  aContextMenu->EnableItem(nChangeId, false );
429 
430  // remove all disabled entries
431  aContextMenu->RemoveDisabledEntries(true, true);
432 
433  // set OpenReadOnly
434 
435  aContextMenu->CheckItem("designmode", pFormModel->GetOpenInDesignMode());
436  aContextMenu->CheckItem("controlfocus", pFormModel->GetAutoControlFocus());
437 
438  aContextMenu->Execute(this, ptWhere);
439  OString sIdent;
440  if (xConversionMenu)
441  sIdent = xConversionMenu->GetCurItemIdent();
442  if (sIdent.isEmpty())
443  sIdent = pSubMenuNew->GetCurItemIdent();
444  if (sIdent.isEmpty())
445  sIdent = aContextMenu->GetCurItemIdent();
446  if (sIdent == "form")
447  {
448  OUString aStr(SvxResId(RID_STR_FORM));
449  OUString aUndoStr = SvxResId(RID_STR_UNDO_CONTAINER_INSERT).replaceAll("#", aStr);
450 
451  pFormModel->BegUndo(aUndoStr);
452  // slot was only available, if there is only one selected entry,
453  // which is a root or a form
454  NewForm( *m_arrCurrentSelection.begin() );
455  pFormModel->EndUndo();
456  }
457  else if (sIdent == "hidden")
458  {
459  OUString aStr(SvxResId(RID_STR_CONTROL));
460  OUString aUndoStr = SvxResId(RID_STR_UNDO_CONTAINER_INSERT).replaceAll("#", aStr);
461 
462  pFormModel->BegUndo(aUndoStr);
463  // slot was valid for (exactly) one selected form
464  OUString fControlName = FM_COMPONENT_HIDDEN;
465  NewControl( fControlName, *m_arrCurrentSelection.begin(), true );
466  pFormModel->EndUndo();
467  }
468  else if (sIdent == "cut")
469  doCut();
470  else if (sIdent == "copy")
471  doCopy();
472  else if (sIdent == "paste")
473  doPaste();
474  else if (sIdent == "delete")
475  DeleteSelection();
476  else if (sIdent == "taborder")
477  {
478  // this slot was effective for exactly one selected form
479  SvTreeListEntry* pSelectedForm = *m_arrCurrentSelection.begin();
480  DBG_ASSERT( IsFormEntry(pSelectedForm), "NavigatorTree::Command: This entry must be a FormEntry." );
481 
482  FmFormData* pFormData = static_cast<FmFormData*>(pSelectedForm->GetUserData());
483  const Reference< XForm >& xForm( pFormData->GetFormIface());
484 
485  Reference< XTabControllerModel > xTabController(xForm, UNO_QUERY);
486  if( !xTabController.is() )
487  break;
489  }
490  else if (sIdent == "props")
492  else if (sIdent == "rename")
493  {
494  // only allowed for one no-root-entry
495  EditEntry( *m_arrCurrentSelection.begin() );
496  }
497  else if (sIdent == "designmode")
498  {
499  pFormModel->SetOpenInDesignMode( !pFormModel->GetOpenInDesignMode() );
500  pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_OPEN_READONLY);
501  }
502  else if (sIdent == "controlfocus")
503  {
504  pFormModel->SetAutoControlFocus( !pFormModel->GetAutoControlFocus() );
505  pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_AUTOCONTROLFOCUS);
506  }
507  else if (FmXFormShell::isControlConversionSlot(sIdent))
508  {
509  FmControlData* pCurrent = static_cast<FmControlData*>((*m_arrCurrentSelection.begin())->GetUserData());
510  if (pFormShell->GetImpl()->executeControlConversionSlot_Lock(pCurrent->GetFormComponent(), sIdent))
512  }
513  }
514  bHandled = true;
515  }
516  break;
517  default: break;
518  }
519 
520  if (!bHandled)
521  SvTreeListBox::Command( rEvt );
522  }
523 
524 
526  {
527  if( !pEntryData ) return nullptr;
528  SvTreeListEntry* pCurEntry = First();
529  while( pCurEntry )
530  {
531  FmEntryData* pCurEntryData = static_cast<FmEntryData*>(pCurEntry->GetUserData());
532  if( pCurEntryData && pCurEntryData->IsEqualWithoutChildren(pEntryData) )
533  return pCurEntry;
534 
535  pCurEntry = Next( pCurEntry );
536  }
537 
538  return nullptr;
539  }
540 
541 
542  void NavigatorTree::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
543  {
544  if( dynamic_cast<const FmNavRemovedHint*>(&rHint) )
545  {
546  const FmNavRemovedHint* pRemovedHint = static_cast<const FmNavRemovedHint*>(&rHint);
547  FmEntryData* pEntryData = pRemovedHint->GetEntryData();
548  Remove( pEntryData );
549  }
550 
551  else if( dynamic_cast<const FmNavInsertedHint*>(&rHint) )
552  {
553  const FmNavInsertedHint* pInsertedHint = static_cast<const FmNavInsertedHint*>(&rHint);
554  FmEntryData* pEntryData = pInsertedHint->GetEntryData();
555  sal_uInt32 nRelPos = pInsertedHint->GetRelPos();
556  Insert( pEntryData, nRelPos );
557  }
558 
559  else if( dynamic_cast<const FmNavModelReplacedHint*>(&rHint) )
560  {
561  FmEntryData* pData = static_cast<const FmNavModelReplacedHint*>(&rHint)->GetEntryData();
562  SvTreeListEntry* pEntry = FindEntry( pData );
563  if (pEntry)
564  { // reset image
565  SetCollapsedEntryBmp( pEntry, pData->GetNormalImage() );
566  SetExpandedEntryBmp( pEntry, pData->GetNormalImage() );
567  }
568  }
569 
570  else if( dynamic_cast<const FmNavNameChangedHint*>(&rHint) )
571  {
572  const FmNavNameChangedHint* pNameChangedHint = static_cast<const FmNavNameChangedHint*>(&rHint);
573  SvTreeListEntry* pEntry = FindEntry( pNameChangedHint->GetEntryData() );
574  SetEntryText( pEntry, pNameChangedHint->GetNewName() );
575  }
576 
577  else if( dynamic_cast<const FmNavClearedHint*>(&rHint) )
578  {
580 
581  // default-entry "Forms"
582  Image aRootImage(StockImage::Yes, RID_SVXBMP_FORMS);
583  m_pRootEntry = InsertEntry( SvxResId(RID_STR_FORMS), aRootImage, aRootImage,
584  nullptr, false, 0 );
585  }
586  else if (dynamic_cast<const FmNavRequestSelectHint*>(&rHint))
587  {
588  FmNavRequestSelectHint* pershHint = const_cast<FmNavRequestSelectHint*>(static_cast<const FmNavRequestSelectHint*>(&rHint));
589  FmEntryDataArray& arredToSelect = pershHint->GetItems();
590  SynchronizeSelection(arredToSelect);
591 
592  if (pershHint->IsMixedSelection())
593  // in this case I deselect all, although the view had a mixed selection
594  // during next selection, I must adapt the navigator to the view
595  m_bPrevSelectionMixed = true;
596  }
597  }
598 
599 
601  {
602 
603  // insert current entry
604  SvTreeListEntry* pParentEntry = FindEntry( pEntryData->GetParent() );
605  SvTreeListEntry* pNewEntry;
606 
607  if( !pParentEntry )
608  pNewEntry = InsertEntry( pEntryData->GetText(),
609  pEntryData->GetNormalImage(), pEntryData->GetNormalImage(),
610  m_pRootEntry, false, nRelPos, pEntryData );
611 
612  else
613  pNewEntry = InsertEntry( pEntryData->GetText(),
614  pEntryData->GetNormalImage(), pEntryData->GetNormalImage(),
615  pParentEntry, false, nRelPos, pEntryData );
616 
617 
618  // If root-entry, expand root
619  if( !pParentEntry )
620  Expand( m_pRootEntry );
621 
622 
623  // insert children
624  FmEntryDataList* pChildList = pEntryData->GetChildList();
625  size_t nChildCount = pChildList->size();
626  for( size_t i = 0; i < nChildCount; i++ )
627  {
628  FmEntryData* pChildData = pChildList->at( i );
629  Insert( pChildData, TREELIST_APPEND );
630  }
631 
632  return pNewEntry;
633  }
634 
635 
636  void NavigatorTree::Remove( FmEntryData* pEntryData )
637  {
638  if( !pEntryData )
639  return;
640 
641  // entry for the data
642  SvTreeListEntry* pEntry = FindEntry( pEntryData );
643  if (!pEntry)
644  return;
645 
646  // delete entry from TreeListBox
647  // I'm not allowed, to treat the selection, which I trigger:
648  // select changes the MarkList of the view, if somebody else does this at the same time
649  // and removes a selection, we get a problem
650  // e.g. Group controls with open navigator
652 
653  // little problem: I remember the selected data, but if somebody deletes one of these entries,
654  // I get inconsistent... this would be bad
655  Select(pEntry, false);
656 
657  // selection can be modified during deletion,
658  // but because I disabled SelectionHandling, I have to do it later
659  sal_uIntPtr nExpectedSelectionCount = GetSelectionCount();
660 
661  GetModel()->Remove(pEntry);
662 
663  if (nExpectedSelectionCount != GetSelectionCount())
665 
666  // by default I treat the selection of course
668  }
669 
670 
672  {
673  FmEntryData* pEntryData = static_cast<FmEntryData*>(pEntry->GetUserData());
674  return !pEntryData || dynamic_cast<const FmFormData*>( pEntryData) != nullptr;
675  }
676 
677 
679  {
680  FmEntryData* pEntryData = static_cast<FmEntryData*>(pEntry->GetUserData());
681  return dynamic_cast<const FmControlData*>( pEntryData) != nullptr;
682  }
683 
684 
686  {
687  SvTreeListEntry* pFirstSelected = FirstSelected();
688  if ( !pFirstSelected || NextSelected( pFirstSelected ) )
689  // no selected entry, or at least two selected entries
690  return false;
691 
692  // get the clipboard
694 
696  return ( nAction == implAcceptDataTransfer( aClipboardContent.GetDataFlavorExVector(), nAction, pFirstSelected, false ) );
697  }
698 
699 
700  sal_Int8 NavigatorTree::implAcceptDataTransfer( const DataFlavorExVector& _rFlavors, sal_Int8 _nAction, SvTreeListEntry* _pTargetEntry, bool _bDnD )
701  {
702  // no target -> no drop
703  if (!_pTargetEntry)
704  return DND_ACTION_NONE;
705 
706  // format check
707  bool bHasDefControlFormat = OControlExchange::hasFieldExchangeFormat( _rFlavors );
708  bool bHasControlPathFormat = OControlExchange::hasControlPathFormat( _rFlavors );
709  bool bHasHiddenControlsFormat = OControlExchange::hasHiddenControlModelsFormat( _rFlavors );
710  if (!bHasDefControlFormat && !bHasControlPathFormat && !bHasHiddenControlsFormat)
711  return DND_ACTION_NONE;
712 
713  bool bSelfSource = _bDnD ? m_aControlExchange.isDragSource() : m_aControlExchange.isClipboardOwner();
714 
715  if ( bHasHiddenControlsFormat )
716  { // bHasHiddenControlsFormat means that only hidden controls are part of the data
717 
718  // hidden controls can be copied to a form only
719  if ((_pTargetEntry == m_pRootEntry) || !IsFormEntry(_pTargetEntry))
720  return DND_ACTION_NONE;
721 
722  return bSelfSource ? ( DND_ACTION_COPYMOVE & _nAction ) : DND_ACTION_COPY;
723  }
724 
725  if ( !bSelfSource )
726  {
727  // DnD or CnP crossing navigator boundaries
728  // The main problem here is that the current API does not allow us to sneak into the content which
729  // is to be inserted. So we have to allow it for the moment, but maybe reject later on (in the real drop).
730 
731  // TODO: this smart behaviour later on ... at the moment, we disallow data transfer crossing navigator
732  // boundaries.
733 
734  return DND_ACTION_NONE;
735  }
736 
738  "NavigatorTree::implAcceptDataTransfer: here only with source=dest!" );
739  // somebody changed the logic of this method ...
740 
741  // from here on, I can work with m_aControlExchange instead of _rData!
742 
743  bool bForeignCollection = m_aControlExchange->getFormsRoot().get() != GetNavModel()->GetFormPage()->GetForms().get();
744  if ( bForeignCollection )
745  {
746  // crossing shell/page boundaries, we can exchange hidden controls only
747  // But if we survived the checks above, we do not have hidden controls.
748  // -> no data transfer
749  DBG_ASSERT( !bHasHiddenControlsFormat, "NavigatorTree::implAcceptDataTransfer: still hidden controls format!" );
750  // somebody changed the logic of this method ...
751 
752  return DND_ACTION_COPY;
753  }
754 
755  if (DND_ACTION_MOVE != _nAction) // 'normal' controls within a shell are moved only (never copied)
756  return DND_ACTION_NONE;
757 
758  if ( m_bDragDataDirty || !bHasDefControlFormat )
759  {
760  if (!bHasControlPathFormat)
761  // I am in the shell/page, which has the controls, but I have no format,
762  // which survived the shell change (SVX_FM_CONTROLS_AS_PATH)
763  return DND_ACTION_NONE;
764 
765  // I must recreate the list of the ExchangeObjects, because the shell was changed during dragging
766  // (there are SvLBoxEntries in it, and we lost them during change)
768  m_bDragDataDirty = false;
769  }
770 
771  // List of dropped entries from DragServer
772  const ListBoxEntrySet& aDropped = m_aControlExchange->selected();
773  DBG_ASSERT(!aDropped.empty(), "NavigatorTree::implAcceptDataTransfer: no entries !");
774 
775  bool bDropTargetIsComponent = IsFormComponentEntry( _pTargetEntry );
776  //SvTreeListEntry* pDropTargetParent = GetParent( _pTargetEntry );
777 
778  // conditions to disallow the drop
779  // 0) the root entry is part of the list (can't DnD the root!)
780  // 1) one of the dragged entries is to be dropped onto its own parent
781  // 2) - " - is to be dropped onto itself
782  // 3) - " - is a Form and to be dropped onto one of its descendants
783  // 4) one of the entries is a control and to be dropped onto the root
784  // 5) a control or form will be dropped onto a control which is _not_ a sibling (dropping onto a sibling
785  // means moving the control)
786 
787  // collect the ancestors of the drop target (speeds up 3)
788  SvLBoxEntrySortedArray arrDropAnchestors;
789  SvTreeListEntry* pLoop = _pTargetEntry;
790  while (pLoop)
791  {
792  arrDropAnchestors.insert(pLoop);
793  pLoop = GetParent(pLoop);
794  }
795 
796  for (SvTreeListEntry* pCurrent : aDropped)
797  {
798  SvTreeListEntry* pCurrentParent = GetParent(pCurrent);
799 
800  // test for 0)
801  if (pCurrent == m_pRootEntry)
802  return DND_ACTION_NONE;
803 
804  // test for 1)
805  if ( _pTargetEntry == pCurrentParent )
806  return DND_ACTION_NONE;
807 
808  // test for 2)
809  if (pCurrent == _pTargetEntry)
810  return DND_ACTION_NONE;
811 
812  // test for 5)
813  // if ( bDropTargetIsComponent && (pDropTargetParent != pCurrentParent) )
814  if ( bDropTargetIsComponent ) // TODO : the line above can be inserted, if ExecuteDrop can handle inversion
815  return DND_ACTION_NONE;
816 
817  // test for 3)
818  if ( IsFormEntry(pCurrent) )
819  {
820  if ( arrDropAnchestors.find(pCurrent) != arrDropAnchestors.end() )
821  return DND_ACTION_NONE;
822  } else if ( IsFormComponentEntry(pCurrent) )
823  {
824  // test for 4)
825  if (_pTargetEntry == m_pRootEntry)
826  return DND_ACTION_NONE;
827  }
828  }
829 
830  return DND_ACTION_MOVE;
831  }
832 
833 
835  {
836  ::Point aDropPos = rEvt.maPosPixel;
837 
838  // first handle possible DropActions (Scroll and swing open)
839  if (rEvt.mbLeaving)
840  {
843  } else
844  {
845  bool bNeedTrigger = false;
846  // on the first entry ?
847  if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight()))
848  {
850  bNeedTrigger = true;
851  } else
852  // on the last one (respectively the area, an entry would tale, if it flush with the bottom ?
853  if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight()))
854  {
856  bNeedTrigger = true;
857  } else
858  { // on an entry with children, not swang open
859  SvTreeListEntry* pDroppedOn = GetEntry(aDropPos);
860  if (pDroppedOn && (GetChildCount(pDroppedOn) > 0) && !IsExpanded(pDroppedOn))
861  {
862  // -> swing open
864  bNeedTrigger = true;
865  }
866  }
867 
868  if (bNeedTrigger && (m_aTimerTriggered != aDropPos))
869  {
870  // restart counting
872  // remember pos, because I get AcceptDrops, although mouse hasn't moved
873  m_aTimerTriggered = aDropPos;
874  // start Timer
875  if (!m_aDropActionTimer.IsActive()) // exist Timer?
876  {
879  }
880  } else if (!bNeedTrigger)
882  }
883 
884  return implAcceptDataTransfer( GetDataFlavorExVector(), rEvt.mnAction, GetEntry( aDropPos ), true );
885  }
886 
887 
888  sal_Int8 NavigatorTree::implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, const ::Point& _rDropPos, bool _bDnD )
889  {
890  return implExecuteDataTransfer( _rData, _nAction, GetEntry( _rDropPos ), _bDnD );
891  }
892 
893 
894  sal_Int8 NavigatorTree::implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, SvTreeListEntry* _pTargetEntry, bool _bDnD )
895  {
896  const DataFlavorExVector& rDataFlavors = _rData.GetDataFlavorExVector();
897 
898  if ( DND_ACTION_NONE == implAcceptDataTransfer( rDataFlavors, _nAction, _pTargetEntry, _bDnD ) )
899  // under some platforms, it may happen that ExecuteDrop is called though AcceptDrop returned DND_ACTION_NONE
900  return DND_ACTION_NONE;
901 
902  // would be bad, if we scroll after drop
905 
906  if (!_pTargetEntry)
907  // no target -> no drop
908  return DND_ACTION_NONE;
909 
910  // format checks
911 #ifdef DBG_UTIL
912  bool bHasHiddenControlsFormat = OControlExchange::hasHiddenControlModelsFormat( rDataFlavors );
913  bool bForeignCollection = _rData.getFormsRoot().get() != GetNavModel()->GetFormPage()->GetForms().get();
914  DBG_ASSERT(!bForeignCollection || bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: invalid format (AcceptDrop shouldn't have let this pass) !");
915  DBG_ASSERT(bForeignCollection || !m_bDragDataDirty, "NavigatorTree::implExecuteDataTransfer: invalid state (shell changed since last exchange resync) !");
916  // this should be done in AcceptDrop: the list of controls is created in _rData
917  // and m_bDragDataDirty is reset
918 #endif
919 
920  if ( DND_ACTION_COPY == _nAction )
921  { // bHasHiddenControlsFormat means that only hidden controls are part of the data
922 #ifdef DBG_UTIL
923  DBG_ASSERT( bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: copy allowed for hidden controls only!" );
924 #endif
925  DBG_ASSERT( _pTargetEntry && ( _pTargetEntry != m_pRootEntry ) && IsFormEntry( _pTargetEntry ),
926  "NavigatorTree::implExecuteDataTransfer: should not be here!" );
927  // implAcceptDataTransfer should have caught both cases
928 
929 #ifdef DBG_UTIL
930  DBG_ASSERT(bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: only copying of hidden controls is supported !");
931  // should be caught by AcceptDrop
932 #endif
933 
934  // because i want to select all targets (and only them)
935  SelectAll(false);
936 
937  const Sequence< Reference< XInterface > >& aControls = _rData.hiddenControls();
938  sal_Int32 nCount = aControls.getLength();
939  const Reference< XInterface >* pControls = aControls.getConstArray();
940 
941  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
942  FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : nullptr;
943 
944  // within undo
945  if (pFormModel)
946  {
947  OUString aStr(SvxResId(RID_STR_CONTROL));
948  OUString aUndoStr = SvxResId(RID_STR_UNDO_CONTAINER_INSERT).replaceAll("#", aStr);
949  pFormModel->BegUndo(aUndoStr);
950  }
951 
952  // copy controls
953  for (sal_Int32 i=0; i<nCount; ++i)
954  {
955  // create new control
956  OUString fControlName = FM_COMPONENT_HIDDEN;
957  FmControlData* pNewControlData = NewControl( fControlName, _pTargetEntry, false);
958  Reference< XPropertySet > xNewPropSet( pNewControlData->GetPropertySet() );
959 
960  // copy properties form old control to new one
961  Reference< XPropertySet > xCurrent(pControls[i], UNO_QUERY);
962 #if (OSL_DEBUG_LEVEL > 0)
963  // check whether it is a hidden control
964  sal_Int16 nClassId = ::comphelper::getINT16(xCurrent->getPropertyValue(FM_PROP_CLASSID));
965  OSL_ENSURE(nClassId == FormComponentType::HIDDENCONTROL, "NavigatorTree::implExecuteDataTransfer: invalid control in drop list !");
966  // if SVX_FM_HIDDEN_CONTROLS-format exists, the sequence
967  // should only contain hidden controls
968 #endif // (OSL_DEBUG_LEVEL > 0)
969  Reference< XPropertySetInfo > xPropInfo( xCurrent->getPropertySetInfo());
970  const Sequence< Property> seqAllCurrentProps = xPropInfo->getProperties();
971  for (Property const & currentProp : seqAllCurrentProps)
972  {
973  if (((currentProp.Attributes & PropertyAttribute::READONLY) == 0) && (currentProp.Name != FM_PROP_NAME))
974  { // (read-only attribs aren't set, ditto name,
975  // NewControl defined it uniquely
976  xNewPropSet->setPropertyValue(currentProp.Name, xCurrent->getPropertyValue(currentProp.Name));
977  }
978  }
979 
980  SvTreeListEntry* pToSelect = FindEntry(pNewControlData);
981  Select(pToSelect);
982  if (i == 0)
983  SetCurEntry(pToSelect);
984  }
985 
986  if (pFormModel)
987  pFormModel->EndUndo();
988 
989  return _nAction;
990  }
991 
993  {
994  // can't do anything without the internal format here ... usually happens when doing DnD or CnP
995  // over navigator boundaries
996  return DND_ACTION_NONE;
997  }
998 
999  // some data for the target
1000  bool bDropTargetIsForm = IsFormEntry(_pTargetEntry);
1001  FmFormData* pTargetData = bDropTargetIsForm ? static_cast<FmFormData*>(_pTargetEntry->GetUserData()) : nullptr;
1002 
1003  DBG_ASSERT( DND_ACTION_COPY != _nAction, "NavigatorTree::implExecuteDataTransfer: somebody changed the logics!" );
1004 
1005  // list of dragged entries
1006  const ListBoxEntrySet aDropped = _rData.selected();
1007  DBG_ASSERT(!aDropped.empty(), "NavigatorTree::implExecuteDataTransfer: no entries!");
1008 
1009  // shell and model
1010  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1011  FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : nullptr;
1012  if (!pFormModel)
1013  return DND_ACTION_NONE;
1014 
1015  // for Undo
1016  const bool bUndo = pFormModel->IsUndoEnabled();
1017 
1018  if( bUndo )
1019  {
1020  OUString strUndoDescription(SvxResId(RID_STR_UNDO_CONTAINER_REPLACE));
1021  pFormModel->BegUndo(strUndoDescription);
1022  }
1023 
1024  // remove selection before adding an entry, so the mark doesn't flicker
1025  // -> lock action of selection
1027 
1028  // go through all dropped entries
1029  for ( ListBoxEntrySet::const_iterator dropped = aDropped.begin();
1030  dropped != aDropped.end();
1031  ++dropped
1032  )
1033  {
1034  // some data of the current element
1035  SvTreeListEntry* pCurrent = *dropped;
1036  DBG_ASSERT(pCurrent != nullptr, "NavigatorTree::implExecuteDataTransfer: invalid entry");
1037  DBG_ASSERT(GetParent(pCurrent) != nullptr, "NavigatorTree::implExecuteDataTransfer: invalid entry");
1038  // don't drag root
1039 
1040  FmEntryData* pCurrentUserData = static_cast<FmEntryData*>(pCurrent->GetUserData());
1041 
1042  Reference< XChild > xCurrentChild = pCurrentUserData->GetChildIFace();
1043  Reference< XIndexContainer > xContainer(xCurrentChild->getParent(), UNO_QUERY);
1044 
1045  FmFormData* pCurrentParentUserData = static_cast<FmFormData*>(pCurrentUserData->GetParent());
1046  DBG_ASSERT(pCurrentParentUserData == nullptr || dynamic_cast<const FmFormData*>(pCurrentUserData->GetParent()) != nullptr, "NavigatorTree::implExecuteDataTransfer: invalid parent");
1047 
1048  // remove from parent
1049  if (pCurrentParentUserData)
1050  pCurrentParentUserData->GetChildList()->removeNoDelete( pCurrentUserData );
1051  else
1052  GetNavModel()->GetRootList()->removeNoDelete( pCurrentUserData );
1053 
1054  // remove from container
1055  sal_Int32 nIndex = getElementPos(xContainer, xCurrentChild);
1056  GetNavModel()->m_pPropChangeList->Lock();
1057  // UndoAction for removal
1058  if ( bUndo && GetNavModel()->m_pPropChangeList->CanUndo())
1059  {
1060  pFormModel->AddUndo(std::make_unique<FmUndoContainerAction>(*pFormModel, FmUndoContainerAction::Removed,
1061  xContainer, xCurrentChild, nIndex));
1062  }
1063  else if( !GetNavModel()->m_pPropChangeList->CanUndo() )
1064  {
1065  FmUndoContainerAction::DisposeElement( xCurrentChild );
1066  }
1067 
1068  // copy events
1069  Reference< XEventAttacherManager > xManager(xContainer, UNO_QUERY);
1070  Sequence< ScriptEventDescriptor > aEvts;
1071 
1072  if (xManager.is() && nIndex >= 0)
1073  aEvts = xManager->getScriptEvents(nIndex);
1074  xContainer->removeByIndex(nIndex);
1075 
1076  // remove selection
1077  Select(pCurrent, false);
1078  // and delete it
1079  Remove(pCurrentUserData);
1080 
1081  // position in DropParents, where to insert dropped entries
1082  if (pTargetData)
1083  xContainer.set(pTargetData->GetElement(), UNO_QUERY);
1084  else
1085  xContainer = GetNavModel()->GetForms();
1086 
1087  // always insert at the end
1088  nIndex = xContainer->getCount();
1089 
1090  // UndoAction for insertion
1091  if ( bUndo && GetNavModel()->m_pPropChangeList->CanUndo())
1092  pFormModel->AddUndo(std::make_unique<FmUndoContainerAction>(*pFormModel, FmUndoContainerAction::Inserted,
1093  xContainer, xCurrentChild, nIndex));
1094 
1095  // insert in new container
1096  if (pTargetData)
1097  {
1098  // insert in a form needs a FormComponent
1099  xContainer->insertByIndex( nIndex,
1100  makeAny( Reference< XFormComponent >( xCurrentChild, UNO_QUERY ) ) );
1101  }
1102  else
1103  {
1104  xContainer->insertByIndex( nIndex,
1105  makeAny( Reference< XForm >( xCurrentChild, UNO_QUERY ) ) );
1106  }
1107 
1108  if (aEvts.hasElements())
1109  {
1110  xManager.set(xContainer, UNO_QUERY);
1111  if (xManager.is())
1112  xManager->registerScriptEvents(nIndex, aEvts);
1113  }
1114 
1115  GetNavModel()->m_pPropChangeList->UnLock();
1116 
1117  // give an entry the new parent
1118  pCurrentUserData->SetParent(pTargetData);
1119 
1120  // give parent the new child
1121  if (pTargetData)
1122  pTargetData->GetChildList()->insert( std::unique_ptr<FmEntryData>(pCurrentUserData), nIndex );
1123  else
1124  GetNavModel()->GetRootList()->insert( std::unique_ptr<FmEntryData>(pCurrentUserData), nIndex );
1125 
1126  // announce to myself and reselect
1127  SvTreeListEntry* pNew = Insert( pCurrentUserData, nIndex );
1128  if ( ( aDropped.begin() == dropped ) && pNew )
1129  {
1130  SvTreeListEntry* pParent = GetParent( pNew );
1131  if ( pParent )
1132  Expand( pParent );
1133  }
1134  }
1135 
1137 
1138  if( bUndo )
1139  pFormModel->EndUndo();
1140 
1141  // During the move, the markings of the underlying view did not change (because the view is not affected by the logical
1142  // hierarchy of the form/control models. But my selection changed - which means I have to adjust it according to the
1143  // view marks, again.
1145 
1146  // in addition, with the move of controls such things as "the current form" may have changed - force the shell
1147  // to update itself accordingly
1148  if( pFormShell && pFormShell->GetImpl() && pFormShell->GetFormView() )
1149  pFormShell->GetImpl()->DetermineSelection_Lock( pFormShell->GetFormView()->GetMarkedObjectList() );
1150 
1151  if ( m_aControlExchange.isClipboardOwner() && ( DND_ACTION_MOVE == _nAction ) )
1153 
1154  return _nAction;
1155  }
1156 
1157 
1159  {
1160  sal_Int8 nResult( DND_ACTION_NONE );
1161 
1163  nResult = implExecuteDataTransfer( *m_aControlExchange, rEvt.mnAction, rEvt.maPosPixel, true );
1164  else
1165  {
1166  OControlTransferData aDroppedData( rEvt.maDropEvent.Transferable );
1167  nResult = implExecuteDataTransfer( aDroppedData, rEvt.mnAction, rEvt.maPosPixel, true );
1168  }
1169 
1170  return nResult;
1171  }
1172 
1173 
1175  {
1176  try
1177  {
1179  {
1181  }
1182  else
1183  {
1184  // the clipboard content
1185  Reference< XClipboard > xClipboard( GetClipboard() );
1186  Reference< XTransferable > xTransferable;
1187  if ( xClipboard.is() )
1188  xTransferable = xClipboard->getContents();
1189 
1190  OControlTransferData aClipboardContent( xTransferable );
1191  implExecuteDataTransfer( aClipboardContent, DND_ACTION_COPY, FirstSelected(), false );
1192  }
1193  }
1194  catch( const Exception& )
1195  {
1196  TOOLS_WARN_EXCEPTION( "svx", "NavigatorTree::doPaste" );
1197  }
1198  }
1199 
1200 
1202  {
1204  {
1205  m_aControlExchange.setClipboardListener( LINK( this, NavigatorTree, OnClipboardAction ) );
1207  }
1208  }
1209 
1210 
1212  {
1213  SvTreeListEntry* pTypedEntry = _pEntry;
1214  if ( doingKeyboardCut() )
1215  m_aCutEntries.erase( pTypedEntry );
1216 
1218  {
1219  if ( 0 == m_aControlExchange->onEntryRemoved( pTypedEntry ) )
1220  {
1221  // last of the entries which we put into the clipboard has been deleted from the tree.
1222  // Give up the clipboard ownership.
1224  }
1225  }
1226  }
1227 
1228 
1230  {
1232  {
1233  m_aControlExchange.setClipboardListener( LINK( this, NavigatorTree, OnClipboardAction ) );
1235  m_bKeyboardCut = true;
1236 
1237  // mark all the entries we just "cut" into the clipboard as "nearly moved"
1238  for ( SvTreeListEntry* pEntry : m_arrCurrentSelection )
1239  {
1240  if ( pEntry )
1241  {
1242  m_aCutEntries.insert( pEntry );
1243  pEntry->SetFlags( pEntry->GetFlags() | SvTLEntryFlags::SEMITRANSPARENT );
1244  InvalidateEntry( pEntry );
1245  }
1246  }
1247  }
1248  }
1249 
1250 
1251  void NavigatorTree::KeyInput(const ::KeyEvent& rKEvt)
1252  {
1253  const vcl::KeyCode& rCode = rKEvt.GetKeyCode();
1254 
1255  // delete?
1256  if (rKEvt.GetKeyCode().GetCode() == KEY_DELETE && !rKEvt.GetKeyCode().GetModifier())
1257  {
1258  DeleteSelection();
1259  return;
1260  }
1261 
1262  // copy'n'paste?
1263  switch ( rCode.GetFunction() )
1264  {
1265  case KeyFuncType::CUT:
1266  doCut();
1267  break;
1268 
1269  case KeyFuncType::PASTE:
1270  if ( implAcceptPaste() )
1271  doPaste();
1272  break;
1273 
1274  case KeyFuncType::COPY:
1275  doCopy();
1276  break;
1277 
1278  default:
1279  break;
1280  }
1281 
1282  SvTreeListBox::KeyInput(rKEvt);
1283  }
1284 
1285 
1287  {
1288  if (!SvTreeListBox::EditingEntry( pEntry, rSelection ))
1289  return false;
1290 
1291  return (pEntry && (pEntry->GetUserData() != nullptr));
1292  // root, which isn't allowed to be renamed, has UserData=NULL
1293  }
1294 
1295 
1296  void NavigatorTree::NewForm( SvTreeListEntry const * pParentEntry )
1297  {
1298 
1299  // get ParentFormData
1300  if( !IsFormEntry(pParentEntry) )
1301  return;
1302 
1303  FmFormData* pParentFormData = static_cast<FmFormData*>(pParentEntry->GetUserData());
1304 
1305 
1306  // create new form
1308  Reference< XForm > xNewForm(xContext->getServiceManager()->createInstanceWithContext(FM_SUN_COMPONENT_FORM, xContext), UNO_QUERY);
1309  if (!xNewForm.is())
1310  return;
1311 
1312  Reference< XPropertySet > xPropertySet(xNewForm, UNO_QUERY);
1313  if (!xPropertySet.is())
1314  return;
1315 
1316  FmFormData* pNewFormData = new FmFormData(xNewForm, pParentFormData);
1317 
1318 
1319  // set name
1320  OUString aName = GenerateName(pNewFormData);
1321  pNewFormData->SetText(aName);
1322 
1323  try
1324  {
1325  xPropertySet->setPropertyValue( FM_PROP_NAME, makeAny(aName) );
1326  // a form should always have the command type table as default
1327  xPropertySet->setPropertyValue( FM_PROP_COMMANDTYPE, makeAny(sal_Int32(CommandType::TABLE)));
1328  }
1329  catch ( const Exception& )
1330  {
1331  OSL_FAIL("NavigatorTree::NewForm : could not set essential properties!");
1332  }
1333 
1334 
1335  // insert form
1336  GetNavModel()->Insert(pNewFormData, SAL_MAX_UINT32, true);
1337 
1338 
1339  // set new form as active
1340  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1341  if( pFormShell )
1342  {
1343  InterfaceBag aSelection;
1344  aSelection.insert( Reference<XInterface>( xNewForm, UNO_QUERY ) );
1345  pFormShell->GetImpl()->setCurrentSelection_Lock(aSelection);
1346 
1347  pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_PROPERTIES, true, true);
1348  }
1349  GetNavModel()->SetModified();
1350 
1351 
1352  // switch to EditMode
1353  SvTreeListEntry* pNewEntry = FindEntry( pNewFormData );
1354  EditEntry( pNewEntry );
1355  }
1356 
1357 
1358  FmControlData* NavigatorTree::NewControl( const OUString& rServiceName, SvTreeListEntry const * pParentEntry, bool bEditName )
1359  {
1360 
1361  // get ParentForm
1362  if (!GetNavModel()->GetFormShell())
1363  return nullptr;
1364  if (!IsFormEntry(pParentEntry))
1365  return nullptr;
1366 
1367  FmFormData* pParentFormData = static_cast<FmFormData*>(pParentEntry->GetUserData());
1368  Reference< XForm > xParentForm( pParentFormData->GetFormIface());
1369 
1370 
1371  // create new component
1373  Reference<XFormComponent> xNewComponent( xContext->getServiceManager()->createInstanceWithContext(rServiceName, xContext), UNO_QUERY);
1374  if (!xNewComponent.is())
1375  return nullptr;
1376 
1377  FmControlData* pNewFormControlData = new FmControlData(xNewComponent, pParentFormData);
1378 
1379 
1380  // set name
1381  OUString sName = FmFormPageImpl::setUniqueName( xNewComponent, xParentForm );
1382 
1383  pNewFormControlData->SetText( sName );
1384 
1385 
1386  // insert FormComponent
1387  GetNavModel()->Insert(pNewFormControlData, SAL_MAX_UINT32, true);
1388  GetNavModel()->SetModified();
1389 
1390  if (bEditName)
1391  {
1392 
1393  // switch to EditMode
1394  SvTreeListEntry* pNewEntry = FindEntry( pNewFormControlData );
1395  Select( pNewEntry );
1396  EditEntry( pNewEntry );
1397  }
1398 
1399  return pNewFormControlData;
1400  }
1401 
1402 
1403  OUString NavigatorTree::GenerateName( FmEntryData const * pEntryData )
1404  {
1405  const sal_uInt16 nMaxCount = 99;
1406  OUString aNewName;
1407 
1408 
1409  // create base name
1410  OUString aBaseName;
1411  if( dynamic_cast<const FmFormData*>( pEntryData) != nullptr )
1412  aBaseName = SvxResId( RID_STR_STDFORMNAME );
1413  else if( dynamic_cast<const FmControlData*>( pEntryData) != nullptr )
1414  aBaseName = SvxResId( RID_STR_CONTROL );
1415 
1416 
1417  // create new name
1418  FmFormData* pFormParentData = static_cast<FmFormData*>(pEntryData->GetParent());
1419 
1420  for( sal_Int32 i=0; i<nMaxCount; i++ )
1421  {
1422  aNewName = aBaseName;
1423  if( i>0 )
1424  {
1425  aNewName += " " + OUString::number(i);
1426  }
1427 
1428  if( GetNavModel()->FindData(aNewName, pFormParentData,false) == nullptr )
1429  break;
1430  }
1431 
1432  return aNewName;
1433  }
1434 
1435 
1436  bool NavigatorTree::EditedEntry( SvTreeListEntry* pEntry, const OUString& rNewText )
1437  {
1438  if (EditingCanceled())
1439  return true;
1440 
1441  GrabFocus();
1442  FmEntryData* pEntryData = static_cast<FmEntryData*>(pEntry->GetUserData());
1443  bool bRes = NavigatorTreeModel::Rename( pEntryData, rNewText);
1444  if( !bRes )
1445  {
1446  m_pEditEntry = pEntry;
1447  nEditEvent = Application::PostUserEvent( LINK(this, NavigatorTree, OnEdit), nullptr, true );
1448  } else
1449  SetCursor(pEntry, true);
1450 
1451  return bRes;
1452  }
1453 
1454 
1455  IMPL_LINK_NOARG(NavigatorTree, OnEdit, void*, void)
1456  {
1457  nEditEvent = nullptr;
1458  EditEntry( m_pEditEntry );
1459  m_pEditEntry = nullptr;
1460  }
1461 
1462 
1463  IMPL_LINK_NOARG(NavigatorTree, OnDropActionTimer, Timer *, void)
1464  {
1465  if (--m_aTimerCounter > 0)
1466  return;
1467 
1468  switch ( m_aDropActionType )
1469  {
1470  case DA_EXPANDNODE:
1471  {
1472  SvTreeListEntry* pToExpand = GetEntry(m_aTimerTriggered);
1473  if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand))
1474  // normally, we have to test, if the node is expanded,
1475  // but there is no method for this either in base class nor the model
1476  // the base class should tolerate it anyway
1477  Expand(pToExpand);
1478 
1479  // After expansion there is nothing to do like after scrolling
1480  m_aDropActionTimer.Stop();
1481  }
1482  break;
1483 
1484  case DA_SCROLLUP :
1485  ScrollOutputArea( 1 );
1486  m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
1487  break;
1488 
1489  case DA_SCROLLDOWN :
1490  ScrollOutputArea( -1 );
1491  m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
1492  break;
1493 
1494  }
1495  }
1496 
1497 
1498  IMPL_LINK_NOARG(NavigatorTree, OnEntrySelDesel, SvTreeListBox*, void)
1499  {
1500  m_sdiState = SDI_DIRTY;
1501 
1502  if (IsSelectionHandlingLocked())
1503  return;
1504 
1505  if (m_aSynchronizeTimer.IsActive())
1506  m_aSynchronizeTimer.Stop();
1507 
1508  m_aSynchronizeTimer.SetTimeout(EXPLORER_SYNC_DELAY);
1509  m_aSynchronizeTimer.Start();
1510  }
1511 
1512 
1513  IMPL_LINK_NOARG(NavigatorTree, OnSynchronizeTimer, Timer *, void)
1514  {
1515  SynchronizeMarkList();
1516  }
1517 
1518 
1519  IMPL_LINK_NOARG(NavigatorTree, OnClipboardAction, OLocalExchange&, void)
1520  {
1521  if ( !m_aControlExchange.isClipboardOwner() )
1522  {
1523  if ( doingKeyboardCut() )
1524  {
1525  for (SvTreeListEntry* pEntry : m_aCutEntries)
1526  {
1527  if ( !pEntry )
1528  continue;
1529 
1530  pEntry->SetFlags( pEntry->GetFlags() & ~SvTLEntryFlags::SEMITRANSPARENT );
1531  InvalidateEntry( pEntry );
1532  }
1533  ListBoxEntrySet aEmpty;
1534  m_aCutEntries.swap( aEmpty );
1535 
1536  m_bKeyboardCut = false;
1537  }
1538  }
1539  }
1540 
1541 
1543  {
1544  // at first i need the FormShell
1545  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1546  if (!pFormShell)
1547  // no shell -> impossible to set curObject -> leave
1548  return;
1549 
1551  SAL_WARN_IF(static_cast<size_t>(m_nFormsSelected + m_nControlsSelected
1552  + (m_bRootSelected ? 1 : 0)) != m_arrCurrentSelection.size(),
1553  "svx.form",
1554  "NavigatorTree::ShowSelectionProperties : selection meta data invalid !");
1555 
1556 
1557  InterfaceBag aSelection;
1558  bool bSetSelectionAsMarkList = false;
1559 
1560  if (m_bRootSelected)
1561  ; // no properties for the root, neither for single nor for multi selection
1562  else if ( m_nFormsSelected + m_nControlsSelected == 0 ) // none of the two should be less 0
1563  ; // no selection -> no properties
1564  else if ( m_nFormsSelected * m_nControlsSelected != 0 )
1565  ; // mixed selection -> no properties
1566  else
1567  { // either only forms, or only controls are selected
1568  if (m_arrCurrentSelection.size() == 1)
1569  {
1570  if (m_nFormsSelected > 0)
1571  { // exactly one form is selected
1572  FmFormData* pFormData = static_cast<FmFormData*>((*m_arrCurrentSelection.begin())->GetUserData());
1573  aSelection.insert( Reference< XInterface >( pFormData->GetFormIface(), UNO_QUERY ) );
1574  }
1575  else
1576  { // exactly one control is selected (whatever hidden or normal)
1577  FmEntryData* pEntryData = static_cast<FmEntryData*>((*m_arrCurrentSelection.begin())->GetUserData());
1578 
1579  aSelection.insert( Reference< XInterface >( pEntryData->GetElement(), UNO_QUERY ) );
1580  }
1581  }
1582  else
1583  { // it's a MultiSelection, so we must build a MultiSet
1584  if (m_nFormsSelected > 0)
1585  { // ... only forms
1586  // first of all collect PropertySet-Interfaces of the forms
1587  SvLBoxEntrySortedArray::const_iterator it = m_arrCurrentSelection.begin();
1588  for ( sal_Int32 i = 0; i < m_nFormsSelected; ++i )
1589  {
1590  FmFormData* pFormData = static_cast<FmFormData*>((*it)->GetUserData());
1591  aSelection.insert( pFormData->GetPropertySet().get() );
1592  ++it;
1593  }
1594  }
1595  else
1596  { // ... only controls
1598  { // a MultiSet for properties of hidden controls
1599  SvLBoxEntrySortedArray::const_iterator it = m_arrCurrentSelection.begin();
1600  for ( sal_Int32 i = 0; i < m_nHiddenControls; ++i )
1601  {
1602  FmEntryData* pEntryData = static_cast<FmEntryData*>((*it)->GetUserData());
1603  aSelection.insert( pEntryData->GetPropertySet().get() );
1604  ++it;
1605  }
1606  }
1607  else if (m_nHiddenControls == 0)
1608  { // only normal controls
1609  bSetSelectionAsMarkList = true;
1610  }
1611  }
1612  }
1613 
1614  }
1615 
1616  // and now my form and my SelObject
1617  if ( bSetSelectionAsMarkList )
1619  else
1620  pFormShell->GetImpl()->setCurrentSelection_Lock(aSelection);
1621 
1622  if (pFormShell->GetImpl()->IsPropBrwOpen_Lock() || bForce)
1623  {
1624  // and now deliver all to the PropertyBrowser
1625  pFormShell->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SfxCallMode::ASYNCHRON );
1626  }
1627  }
1628 
1629 
1631  {
1632  // of course, i can't delete root
1633  bool bRootSelected = IsSelected(m_pRootEntry);
1634  sal_uIntPtr nSelectedEntries = GetSelectionCount();
1635  if (bRootSelected && (nSelectedEntries > 1)) // root and other elements ?
1636  Select(m_pRootEntry, false); // yes -> remove root from selection
1637 
1638  if ((nSelectedEntries == 0) || bRootSelected) // still root ?
1639  return; // -> only selected element -> leave
1640 
1641  DBG_ASSERT(!m_bPrevSelectionMixed, "NavigatorTree::DeleteSelection() : delete permitted if mark and selection are inconsistent");
1642 
1643  // i need the FormModel later
1644  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1645  if (!pFormShell)
1646  return;
1647  FmFormModel* pFormModel = pFormShell->GetFormModel();
1648  if (!pFormModel)
1649  return;
1650 
1651  // now I have to safeguard the DeleteList: if you delete a form and a dependent element
1652  // - in this order - than the SvLBoxEntryPtr of the dependent element is already invalid,
1653  // when it should be deleted... you have to prohibit this GPF, that of course would happen,
1654  // so I take the 'normalized' list
1656 
1657  // see below for why we need this mapping from models to shapes
1658  FmFormView* pFormView = pFormShell->GetFormView();
1659  SdrPageView* pPageView = pFormView ? pFormView->GetSdrPageView() : nullptr;
1660  SdrPage* pPage = pPageView ? pPageView->GetPage() : nullptr;
1661  DBG_ASSERT( pPage, "NavigatorTree::DeleteSelection: invalid form page!" );
1662 
1663  MapModelToShape aModelShapes;
1664  if ( pPage )
1665  collectShapeModelMapping( pPage, aModelShapes );
1666 
1667  // problem: we have to use ExplorerModel::Remove, since only this one properly deletes Form objects.
1668  // But, the controls themself must be deleted via DeleteMarked (else, the Writer has some problems
1669  // somewhere). In case I'd first delete the structure, then the controls, the UNDO would not work
1670  // (since UNDO then would mean to first restore the controls, then the structure, means their parent
1671  // form). The other way round, the EntryDatas would be invalid, if I'd first delete the controls and
1672  // then go on to the structure. This means I have to delete the forms *after* the normal controls, so
1673  // that during UNDO, they're restored in the proper order.
1674  pFormShell->GetImpl()->EnableTrackProperties_Lock(false);
1675  for (SvLBoxEntrySortedArray::reverse_iterator it = m_arrCurrentSelection.rbegin();
1676  it != m_arrCurrentSelection.rend(); )
1677  {
1678  FmEntryData* pCurrent = static_cast<FmEntryData*>((*it)->GetUserData());
1679 
1680  // a form ?
1681  bool bIsForm = dynamic_cast<const FmFormData*>( pCurrent) != nullptr;
1682 
1683  // because deletion is done by the view, and i build on its MarkList,
1684  // but normally only direct controls, no indirect ones, are marked in a marked form,
1685  // I have to do it later
1686  if (bIsForm)
1687  MarkViewObj(static_cast<FmFormData*>(pCurrent), true/*deep*/);
1688 
1689  // a hidden control ?
1690  bool bIsHidden = IsHiddenControl(pCurrent);
1691 
1692  // keep forms and hidden controls, the rest not
1693  if (!bIsForm && !bIsHidden)
1694  {
1695  // well, no form and no hidden control -> we can remove it from m_arrCurrentSelection, as it will
1696  // be deleted automatically. This is because for every model (except forms and hidden control models)
1697  // there exist a shape, which is marked _if_and_only_if_ the model is selected in our tree.
1698  if ( aModelShapes.find( pCurrent->GetElement() ) != aModelShapes.end() )
1699  {
1700  // if there's a shape for the current entry, then either it is marked or it is in a
1701  // hidden layer (#i28502#), or something like this.
1702  // In the first case, it will be deleted below, in the second case, we currently don't
1703  // delete it, as there's no real (working!) API for this, neither in UNO nor in non-UNO.
1704  m_arrCurrentSelection.erase( --(it.base()) );
1705  }
1706  else
1707  ++it;
1708  // In case there is no shape for the current entry, we keep the entry in m_arrCurrentSelection,
1709  // since then we can definitely remove it.
1710  }
1711  else
1712  ++it;
1713  }
1714  pFormShell->GetImpl()->EnableTrackProperties_Lock(true);
1715 
1716  // let the view delete the marked controls
1717  pFormShell->GetFormView()->DeleteMarked();
1718 
1719  // start UNDO at this point. Unfortunately, this results in 2 UNDO actions, since DeleteMarked is
1720  // creating an own one. However, if we'd move it before DeleteMarked, Writer does not really like
1721  // this ... :(
1722  // #i31038#
1723  {
1724 
1725  // initialize UNDO
1726  OUString aUndoStr;
1727  if ( m_arrCurrentSelection.size() == 1 )
1728  {
1729  aUndoStr = SvxResId(RID_STR_UNDO_CONTAINER_REMOVE);
1730  if (m_nFormsSelected)
1731  aUndoStr = aUndoStr.replaceFirst( "#", SvxResId( RID_STR_FORM ) );
1732  else
1733  // it must be a control (else the root would be selected, but it cannot be deleted)
1734  aUndoStr = aUndoStr.replaceFirst( "#", SvxResId( RID_STR_CONTROL ) );
1735  }
1736  else
1737  {
1738  aUndoStr = SvxResId(RID_STR_UNDO_CONTAINER_REMOVE_MULTIPLE);
1739  aUndoStr = aUndoStr.replaceFirst( "#", OUString::number( m_arrCurrentSelection.size() ) );
1740  }
1741  pFormModel->BegUndo(aUndoStr);
1742  }
1743 
1744  // remove remaining structure
1745  for (const auto& rpSelection : m_arrCurrentSelection)
1746  {
1747  FmEntryData* pCurrent = static_cast<FmEntryData*>(rpSelection->GetUserData());
1748 
1749  // if the entry still has children, we skipped deletion of one of those children.
1750  // This may for instance be because the shape is in a hidden layer, where we're unable
1751  // to remove it
1752  if ( pCurrent->GetChildList()->size() )
1753  continue;
1754 
1755  // one remaining subtile problem, before deleting it : if it's a form and the shell
1756  // knows it as CurrentObject, I have to tell it something else
1757  if (dynamic_cast<const FmFormData*>( pCurrent) != nullptr)
1758  {
1759  Reference< XForm > xCurrentForm( static_cast< FmFormData* >( pCurrent )->GetFormIface() );
1760  if (pFormShell->GetImpl()->getCurrentForm_Lock() == xCurrentForm) // shell knows form to be deleted ?
1761  pFormShell->GetImpl()->forgetCurrentForm_Lock(); // -> take away ...
1762  }
1763  GetNavModel()->Remove(pCurrent, true);
1764  }
1765  pFormModel->EndUndo();
1766  }
1767 
1768 
1770  {
1771  DBG_ASSERT(sdiHow != SDI_DIRTY, "NavigatorTree::CollectSelectionData : ever thought about your parameter ? DIRTY ?");
1772  if (sdiHow == m_sdiState)
1773  return;
1774 
1775  m_arrCurrentSelection.clear();
1777  m_bRootSelected = false;
1778 
1779  SvTreeListEntry* pSelectionLoop = FirstSelected();
1780  while (pSelectionLoop)
1781  {
1782  // count different elements
1783  if (pSelectionLoop == m_pRootEntry)
1784  m_bRootSelected = true;
1785  else
1786  {
1787  if (IsFormEntry(pSelectionLoop))
1788  ++m_nFormsSelected;
1789  else
1790  {
1792  if (IsHiddenControl(static_cast<FmEntryData*>(pSelectionLoop->GetUserData())))
1794  }
1795  }
1796 
1797  if (sdiHow == SDI_NORMALIZED)
1798  {
1799  // don't take something with a selected ancestor
1800  if (pSelectionLoop == m_pRootEntry)
1801  m_arrCurrentSelection.insert(pSelectionLoop);
1802  else
1803  {
1804  SvTreeListEntry* pParentLoop = GetParent(pSelectionLoop);
1805  while (pParentLoop)
1806  {
1807  // actually i would have to test, if parent is part of m_arr_CurrentSelection ...
1808  // but if it's selected, then it's in m_arrCurrentSelection
1809  // or one of its ancestors, which was selected earlier.
1810  // In both cases IsSelected is enough
1811  if (IsSelected(pParentLoop))
1812  break;
1813  else
1814  {
1815  if (m_pRootEntry == pParentLoop)
1816  {
1817  // until root (exclusive), there was no selected parent -> entry belongs to normalized list
1818  m_arrCurrentSelection.insert(pSelectionLoop);
1819  break;
1820  }
1821  else
1822  pParentLoop = GetParent(pParentLoop);
1823  }
1824  }
1825  }
1826  }
1827  else if (sdiHow == SDI_NORMALIZED_FORMARK)
1828  {
1829  SvTreeListEntry* pParent = GetParent(pSelectionLoop);
1830  if (!pParent || !IsSelected(pParent) || IsFormEntry(pSelectionLoop))
1831  m_arrCurrentSelection.insert(pSelectionLoop);
1832  }
1833  else
1834  m_arrCurrentSelection.insert(pSelectionLoop);
1835 
1836 
1837  pSelectionLoop = NextSelected(pSelectionLoop);
1838  }
1839 
1840  m_sdiState = sdiHow;
1841  }
1842 
1843 
1845  {
1847  if (arredToSelect.empty())
1848  {
1849  SelectAll(false);
1850  }
1851  else
1852  {
1853  // compare current selection with requested SelectList
1854  SvTreeListEntry* pSelection = FirstSelected();
1855  while (pSelection)
1856  {
1857  FmEntryData* pCurrent = static_cast<FmEntryData*>(pSelection->GetUserData());
1858  if (pCurrent != nullptr)
1859  {
1860  FmEntryDataArray::iterator it = arredToSelect.find(pCurrent);
1861  if ( it != arredToSelect.end() )
1862  { // entry already selected, but also in SelectList
1863  // remove it from there
1864  arredToSelect.erase(it);
1865  } else
1866  { // entry selected, but not in SelectList -> remove selection
1867  Select(pSelection, false);
1868  // make it visible (maybe it's the only modification i do in this handler
1869  // so you should see it
1870  MakeVisible(pSelection);
1871  }
1872  }
1873  else
1874  Select(pSelection, false);
1875 
1876  pSelection = NextSelected(pSelection);
1877  }
1878 
1879  // now SelectList contains only entries, which have to be selected
1880  // two possibilities : 1) run through SelectList, get SvTreeListEntry for every entry and select it (is more intuitive)
1881  // 2) run through my SvLBoxEntries and select those, i can find in the SelectList
1882  // 1) needs =(k*n) (k=length of SelectList, n=number of entries),
1883  // plus the fact, that FindEntry uses extensive IsEqualWithoutChilden instead of comparing pointer to UserData
1884  // 2) needs =(n*log k), duplicates some code from FindEntry
1885  // This may be a frequently used code ( at every change in mark of the view!),
1886  // so i use latter one
1887  SvTreeListEntry* pLoop = First();
1888  FmEntryDataArray::const_iterator aEnd = arredToSelect.end();
1889  while(pLoop)
1890  {
1891  FmEntryData* pCurEntryData = static_cast<FmEntryData*>(pLoop->GetUserData());
1892  FmEntryDataArray::iterator it = arredToSelect.find(pCurEntryData);
1893  if (it != aEnd)
1894  {
1895  Select(pLoop);
1896  MakeVisible(pLoop);
1897  SetCursor(pLoop, true);
1898  }
1899 
1900  pLoop = Next(pLoop);
1901  }
1902  }
1904  }
1905 
1906 
1908  {
1909  // shell and view
1910  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1911  if(!pFormShell) return;
1912 
1913  FmFormView* pFormView = pFormShell->GetFormView();
1914  if (!pFormView) return;
1915 
1917  }
1918 
1919 
1921  {
1922  // i'll need this shell
1923  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1924  if (!pFormShell) return;
1925 
1927 
1928  // the view shouldn't notify now if MarkList changed
1929  pFormShell->GetImpl()->EnableTrackProperties_Lock(false);
1930 
1931  UnmarkAllViewObj();
1932 
1933  for (SvTreeListEntry* pSelectionLoop : m_arrCurrentSelection)
1934  {
1935  // When form selection, mark all controls of form
1936  if (IsFormEntry(pSelectionLoop) && (pSelectionLoop != m_pRootEntry))
1937  MarkViewObj(static_cast<FmFormData*>(pSelectionLoop->GetUserData()), false/*deep*/);
1938 
1939  // When control selection, mark Control-SdrObjects
1940  else if (IsFormComponentEntry(pSelectionLoop))
1941  {
1942  FmControlData* pControlData = static_cast<FmControlData*>(pSelectionLoop->GetUserData());
1943  if (pControlData)
1944  {
1945 
1946  // When HiddenControl no object can be selected
1947  Reference< XFormComponent > xFormComponent( pControlData->GetFormComponent());
1948  if (!xFormComponent.is())
1949  continue;
1950  Reference< XPropertySet > xSet(xFormComponent, UNO_QUERY);
1951  if (!xSet.is())
1952  continue;
1953 
1954  sal_uInt16 nClassId = ::comphelper::getINT16(xSet->getPropertyValue(FM_PROP_CLASSID));
1955  if (nClassId != FormComponentType::HIDDENCONTROL)
1956  MarkViewObj(pControlData);
1957  }
1958  }
1959  }
1960 
1961  // if PropertyBrowser is open, I have to adopt it according to my selection
1962  // (Not as MarkList of view : if a form is selected, all belonging controls are selected in the view
1963  // but of course i want to see the form-properties
1965 
1966  // reset flag at view
1967  pFormShell->GetImpl()->EnableTrackProperties_Lock(true);
1968 
1969  // if exactly one form is selected now, shell should notice it as CurrentForm
1970  // (if selection handling isn't locked, view cares about it in MarkListHasChanged
1971  // but mechanism doesn't work, if form is empty for example
1972  if ((m_arrCurrentSelection.size() == 1) && (m_nFormsSelected == 1))
1973  {
1974  FmFormData* pSingleSelectionData = dynamic_cast<FmFormData*>( static_cast< FmEntryData* >( FirstSelected()->GetUserData() ) );
1975  DBG_ASSERT( pSingleSelectionData, "NavigatorTree::SynchronizeMarkList: invalid selected form!" );
1976  if ( pSingleSelectionData )
1977  {
1978  InterfaceBag aSelection;
1979  aSelection.insert( Reference< XInterface >( pSingleSelectionData->GetFormIface(), UNO_QUERY ) );
1980  pFormShell->GetImpl()->setCurrentSelection_Lock(aSelection);
1981  }
1982  }
1983  }
1984 
1985 
1987  {
1988  if (pEntryData == nullptr) return false;
1989 
1990  Reference< XPropertySet > xProperties( pEntryData->GetPropertySet() );
1991  if (::comphelper::hasProperty(FM_PROP_CLASSID, xProperties))
1992  {
1993  Any aClassID = xProperties->getPropertyValue( FM_PROP_CLASSID );
1994  return (::comphelper::getINT16(aClassID) == FormComponentType::HIDDENCONTROL);
1995  }
1996  return false;
1997  }
1998 
1999 
2000  bool NavigatorTree::Select( SvTreeListEntry* pEntry, bool bSelect )
2001  {
2002  if (bSelect == IsSelected(pEntry)) // this happens sometimes, maybe base class is to exact ;)
2003  return true;
2004 
2005  return SvTreeListBox::Select(pEntry, bSelect );
2006  }
2007 
2008 
2010  {
2011  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
2012  if( !pFormShell )
2013  return;
2014  FmFormView* pFormView = pFormShell->GetFormView();
2015  pFormView->UnMarkAll();
2016  }
2017 
2018  void NavigatorTree::MarkViewObj(FmFormData const * pFormData, bool bDeep )
2019  {
2020  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
2021  if( !pFormShell )
2022  return;
2023 
2024  // first collect all sdrobjects
2025  ::std::set< Reference< XFormComponent > > aObjects;
2026  CollectObjects(pFormData,bDeep,aObjects);
2027 
2028 
2029  // find and select appropriate SdrObj in page
2030  FmFormView* pFormView = pFormShell->GetFormView();
2031  SdrPageView* pPageView = pFormView->GetSdrPageView();
2032  SdrPage* pPage = pPageView->GetPage();
2033  //FmFormPage* pFormPage = dynamic_cast< FmFormPage* >( pPage );
2034 
2035  SdrObjListIter aIter( pPage );
2036  while ( aIter.IsMore() )
2037  {
2038  SdrObject* pSdrObject = aIter.Next();
2039  FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject );
2040  if ( !pFormObject )
2041  continue;
2042 
2043  Reference< XFormComponent > xControlModel( pFormObject->GetUnoControlModel(),UNO_QUERY );
2044  if ( xControlModel.is() && aObjects.find(xControlModel) != aObjects.end() && !pFormView->IsObjMarked( pSdrObject ) )
2045  {
2046  // unfortunately, the writer doesn't like marking an already-marked object, again, so reset the mark first
2047  pFormView->MarkObj( pSdrObject, pPageView );
2048  }
2049  } // while ( aIter.IsMore() )
2050  // make the mark visible
2051  ::tools::Rectangle aMarkRect( pFormView->GetAllMarkedRect());
2052  for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
2053  {
2054  SdrPaintWindow* pPaintWindow = pFormView->GetPaintWindow( i );
2055  OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
2056  if ( ( OUTDEV_WINDOW == rOutDev.GetOutDevType() ) && !aMarkRect.IsEmpty() )
2057  {
2058  pFormView->MakeVisible( aMarkRect, static_cast<vcl::Window&>(rOutDev) );
2059  }
2060  } // for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
2061  }
2062 
2063  void NavigatorTree::CollectObjects(FmFormData const * pFormData, bool bDeep, ::std::set< Reference< XFormComponent > >& _rObjects)
2064  {
2065  FmEntryDataList* pChildList = pFormData->GetChildList();
2066  FmControlData* pControlData;
2067  for( size_t i = 0; i < pChildList->size(); ++i )
2068  {
2069  FmEntryData* pEntryData = pChildList->at( i );
2070  if( dynamic_cast<const FmControlData*>( pEntryData) != nullptr )
2071  {
2072  pControlData = static_cast<FmControlData*>(pEntryData);
2073  _rObjects.insert(pControlData->GetFormComponent());
2074  } // if( dynamic_cast<const FmControlData*>( pEntryData) != nullptr )
2075  else if (bDeep && (dynamic_cast<const FmFormData*>( pEntryData) != nullptr))
2076  CollectObjects(static_cast<FmFormData*>(pEntryData), bDeep, _rObjects);
2077  } // for( sal_uInt32 i=0; i<pChildList->Count(); i++ )
2078  }
2079 
2080  void NavigatorTree::MarkViewObj( FmControlData const * pControlData)
2081  {
2082  if( !pControlData )
2083  return;
2084  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
2085  if( !pFormShell )
2086  return;
2087 
2088 
2089  // find and select appropriate SdrObj
2090  FmFormView* pFormView = pFormShell->GetFormView();
2091  Reference< XFormComponent > xFormComponent( pControlData->GetFormComponent());
2092  SdrPageView* pPageView = pFormView->GetSdrPageView();
2093  SdrPage* pPage = pPageView->GetPage();
2094 
2095  bool bPaint = false;
2096  SdrObjListIter aIter( pPage );
2097  while ( aIter.IsMore() )
2098  {
2099  SdrObject* pSdrObject = aIter.Next();
2100  FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject );
2101  if ( !pFormObject )
2102  continue;
2103 
2104  Reference< XInterface > xControlModel( pFormObject->GetUnoControlModel() );
2105  if ( xControlModel != xFormComponent )
2106  continue;
2107 
2108  // mark the object
2109  if ( !pFormView->IsObjMarked( pSdrObject ) )
2110  // unfortunately, the writer doesn't like marking an already-marked object, again, so reset the mark first
2111  pFormView->MarkObj( pSdrObject, pPageView );
2112 
2113  bPaint = true;
2114 
2115  } // while ( aIter.IsMore() )
2116  if ( bPaint )
2117  {
2118  // make the mark visible
2119  ::tools::Rectangle aMarkRect( pFormView->GetAllMarkedRect());
2120  for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
2121  {
2122  SdrPaintWindow* pPaintWindow = pFormView->GetPaintWindow( i );
2123  OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
2124  if ( OUTDEV_WINDOW == rOutDev.GetOutDevType() )
2125  {
2126  pFormView->MakeVisible( aMarkRect, static_cast<vcl::Window&>(rOutDev) );
2127  }
2128  } // for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
2129  }
2130  }
2131 
2132 
2133 }
2134 
2135 
2136 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent &rEvt) override
SfxViewFrame * GetViewFrame() const
::std::set< css::uno::Reference< css::uno::XInterface > > InterfaceBag
Definition: fmtools.hxx:170
OutDevType GetOutDevType() const
const char *const aClassID
PopupMenu * GetPopupMenu(sal_uInt16 nItemId) const
SvTreeListEntry * NextSelected(SvTreeListEntry *pEntry) const
const css::datatransfer::dnd::DropTargetDropEvent maDropEvent
sal_Int32 nIndex
void SetItemImage(sal_uInt16 nItemId, const Image &rImage)
#define KEY_DELETE
void SetDeselectHdl(const Link< SvTreeListBox *, void > &rNewHdl)
void removeNoDelete(FmEntryData *pItem)
Definition: fmexpl.cxx:133
void SetAutoControlFocus(bool _bAutoControlFocus)
Definition: fmmodel.cxx:168
FmFormView * GetFormView() const
Definition: fmshell.hxx:115
#define DND_ACTION_COPY
SAL_DLLPRIVATE bool executeControlConversionSlot_Lock(const css::uno::Reference< css::form::XFormComponent > &_rxObject, const OString &rIdent)
executes a control conversion slot for a given object
void UpdateContent(FmFormShell *pFormShell)
FmXFormShell * GetImpl() const
Definition: fmshell.hxx:118
static OUString setUniqueName(const css::uno::Reference< css::form::XFormComponent > &xFormComponent, const css::uno::Reference< css::form::XForm > &xControls)
Definition: fmpgeimp.cxx:621
std::unique_ptr< ContentProperties > pData
bool implAllowExchange(sal_Int8 _nAction, bool *_pHasNonHidden=nullptr)
virtual void Command(const CommandEvent &rCEvt) override
void startDrag(sal_Int8 nDragSourceActions)
Definition: fmexch.cxx:353
AutoTimer m_aDropActionTimer
Definition: fmexpl.hxx:370
static void collectShapeModelMapping(SdrPage const *_pPage, MapModelToShape &_rMapping)
void CancelTextEditing()
void SetExpandedEntryBmp(SvTreeListEntry *_pEntry, const Image &_rImage)
long Height() const
signed char sal_Int8
SvTreeList * GetModel() const
const OUString & GetNewName() const
Definition: fmexpl.hxx:105
css::uno::Reference< css::datatransfer::clipboard::XClipboard > GetClipboard()
bool IsEditingActive() const
FmControlData * NewControl(const OUString &rServiceName, SvTreeListEntry const *pParentEntry, bool bEditName)
SfxDispatcher * GetDispatcher()
::std::vector< DataFlavorEx > DataFlavorExVector
sal_uIntPtr sal_uLong
void CollectSelectionData(SELDATA_ITEMS sdiHow)
FmEntryData * GetParent() const
Definition: fmexpl.hxx:158
void UpdateContent(const css::uno::Reference< css::form::XForms > &xForms)
ImplSVEvent * nEditEvent
Definition: fmexpl.hxx:383
static bool IsHiddenControl(FmEntryData const *pEntryData)
SvLBoxEntrySortedArray m_arrCurrentSelection
Definition: fmexpl.hxx:373
virtual Size GetSizePixel() const
NavigatorTreeModel * GetNavModel() const
Definition: fmexpl.hxx:472
FmFormPage * GetCurPage() const
Definition: fmshell.cxx:1150
sal_Int32 getElementPos(const Reference< css::container::XIndexAccess > &xCont, const Reference< XInterface > &xElement)
Definition: fmtools.cxx:162
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
#define DND_ACTION_COPYMOVE
virtual bool EditedEntry(SvTreeListEntry *pEntry, const OUString &rNewText) override
void SetCursor(SvTreeListEntry *pEntry, bool bForceNoSelect=false)
void SetEntryText(SvTreeListEntry *, const OUString &)
void SetCurEntry(SvTreeListEntry *_pEntry)
SvTreeListEntry * m_pEditEntry
Definition: fmexpl.hxx:381
OUString GenerateName(FmEntryData const *pEntryData)
void SetHelpId(const OString &)
virtual bool EditingEntry(SvTreeListEntry *pEntry, Selection &) override
bool GetAutoControlFocus() const
Definition: fmmodel.hxx:64
void Invalidate(sal_uInt16 nId)
static bool IsFormComponentEntry(SvTreeListEntry const *pEntry)
void CollectObjects(FmFormData const *pFormData, bool bDeep,::std::set< css::uno::Reference< css::form::XFormComponent > > &_rObjects)
FmEntryData * GetEntryData() const
Definition: fmexpl.hxx:91
SvTreeListEntry * GetCurEntry() const
FmEntryDataList * GetRootList() const
Definition: fmexpl.hxx:355
::std::set< SvTreeListEntry * > ListBoxEntrySet
Definition: fmexch.hxx:42
void SetOpenInDesignMode(bool _bOpenDesignMode)
Definition: fmmodel.cxx:143
virtual void StartDrag(sal_Int8 nAction, const Point &rPosPixel) override
void BegUndo()
Definition: svdmodel.cxx:425
SvTreeListEntry * FindEntry(FmEntryData *pEntryData)
OString const & GetCurItemIdent() const
FmFormModel * GetFormModel() const
Definition: fmshell.hxx:116
SvTLEntryFlags
void MakeVisible(SvTreeListEntry *pEntry)
#define DND_ACTION_MOVE
bool IsActive() const
#define FM_PROP_NAME
Definition: fmprop.hxx:29
#define SAL_MAX_UINT32
void insert(std::unique_ptr< FmEntryData > pItem, size_t Index)
Definition: fmexpl.cxx:147
const css::uno::Reference< css::uno::XInterface > & GetElement() const
Definition: fmexpl.hxx:166
bool IsMore() const
Definition: svditer.hxx:62
bool isDataExchangeActive() const
Definition: fmexch.hxx:109
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:28
void UnlockSelectionHandling()
Definition: fmexpl.hxx:436
OUTDEV_WINDOW
SvTreeListEntry * FirstSelected() const
WinBits const WB_HSCROLL
bool IsMouseEvent() const
void SetDragDropMode(DragDropMode)
const DataFlavorExVector & GetDataFlavorExVector() const
SAL_DLLPRIVATE void checkControlConversionSlotsForCurrentSelection_Lock(Menu &rMenu)
enables or disables all conversion slots in a menu, according to the current selection ...
Definition: fmshimp.cxx:1304
void AddUndo(std::unique_ptr< SdrUndoAction > pUndo)
Definition: svdmodel.cxx:559
virtual void KeyInput(const KeyEvent &rKEvt) override
int nCount
#define DND_ACTION_NONE
#define FM_PROP_CLASSID
Definition: fmprop.hxx:30
SvTreeListEntry * NextSibling() const
static TransferableDataHelper CreateFromSystemClipboard(vcl::Window *pWindow)
FmEntryData * GetEntryData() const
Definition: fmexpl.hxx:104
void SetCollapsedEntryBmp(SvTreeListEntry *_pEntry, const Image &_rImage)
const css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > & hiddenControls() const
Definition: fmexch.hxx:185
FmEntryData * at(size_t Index)
Definition: fmexpl.hxx:192
void SelectAll(bool bSelect, bool bPaint=true)
::svxform::OControlExchangeHelper m_aControlExchange
Definition: fmexpl.hxx:377
sal_uInt32 GetRelPos() const
Definition: fmexpl.hxx:67
void SetSelectHdl(const Link< SvTreeListBox *, void > &rNewHdl)
FmFormShell * GetFormShell() const
Definition: fmexpl.hxx:351
void SetText(const OUString &rText)
Definition: fmexpl.hxx:152
SAL_DLLPRIVATE bool isSolelySelected_Lock(const css::uno::Reference< css::uno::XInterface > &_rxObject)
determines whether the current selection consists of exactly the given object
Definition: fmshimp.cxx:2015
short GetEntryHeight() const
void copyToClipboard() const
Definition: fmexch.cxx:360
FmFormPage * GetFormPage() const
Definition: fmexpl.hxx:352
void EnableInplaceEditing(bool bEnable)
virtual void dispose() override
sal_Int16 getINT16(const Any &_rAny)
sal_uInt32 PaintWindowCount() const
Definition: svdpntv.hxx:228
void SetPopupMenu(sal_uInt16 nItemId, PopupMenu *pMenu)
static void DisposeElement(const css::uno::Reference< css::uno::XInterface > &xElem)
Definition: fmundo.cxx:1072
SvTreeListEntry * Insert(FmEntryData *pEntryData, sal_uLong nRelPos)
sal_uInt16 m_nFormsSelected
Definition: fmexpl.hxx:390
static void RemoveUserEvent(ImplSVEvent *nUserEvent)
virtual ~NavigatorTree() override
virtual void KeyInput(const KeyEvent &rKEvt) override
void SetParent(FmEntryData *pParentData)
Definition: fmexpl.hxx:153
std::set< FmEntryData * > FmEntryDataArray
Definition: fmexpl.hxx:204
bool EditingCanceled() const
virtual bool IsEqualWithoutChildren(FmEntryData *pEntryData)
Definition: fmexpl.cxx:211
SELDATA_ITEMS m_sdiState
Definition: fmexpl.hxx:385
const OUString & GetText() const
Definition: fmexpl.hxx:157
#define TOOLS_WARN_EXCEPTION(area, stream)
virtual bool EditingEntry(SvTreeListEntry *pEntry, Selection &)
#define HID_FORM_NAVIGATOR
Definition: helpids.h:44
static SAL_DLLPRIVATE std::unique_ptr< VclBuilder > GetConversionMenu_Lock()
Definition: fmshimp.cxx:1025
#define DBG_ASSERT(sCon, aError)
bool Remove(const SvTreeListEntry *pEntry)
SVX_DLLPRIVATE void setClipboardListener(const Link< OLocalExchange &, void > &_rListener)
Definition: fmexch.hxx:112
const css::uno::Reference< css::form::XForm > & GetFormIface() const
Definition: fmexpl.hxx:233
bool IsUndoEnabled() const
returns true if undo is currently enabled This returns false if undo was disabled using EnableUndo( f...
Definition: svdmodel.cxx:590
OUString sName
virtual sal_Int8 AcceptDrop(const AcceptDropEvent &rEvt) override
const Image & GetNormalImage() const
Definition: fmexpl.hxx:155
void Insert(FmEntryData *pEntryData, sal_uInt32 nRelPos=SAL_MAX_UINT32, bool bAlterModel=false)
virtual void MakeVisible(const tools::Rectangle &rRect, vcl::Window &rWin)
Definition: svdpntv.cxx:1019
bool isDragSource() const
Definition: fmexch.hxx:107
void addHiddenControlsFormat(const css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > &seqInterfaces)
Definition: fmexch.cxx:203
FmEntryData * GetEntryData() const
Definition: fmexpl.hxx:66
SfxBindings & GetBindings()
int i
SAL_DLLPRIVATE const css::uno::Reference< css::form::XForm > & getCurrentForm_Lock() const
returns the currently selected form, or the form which all currently selected controls belong to...
Definition: fmshimp.hxx:371
bool GetOpenInDesignMode() const
Definition: fmmodel.hxx:61
sal_uInt16 GetItemId(sal_uInt16 nPos) const
const SdrMarkList & GetMarkedObjectList() const
Definition: svdmrkv.hxx:243
::std::map< Reference< XInterface >, SdrObject * > MapModelToShape
bool IsSelected(SvTreeListEntry *pEntry) const
SvTreeListEntry * FirstChild(SvTreeListEntry *pParent) const
void * GetUserData() const
CommandEventId GetCommand() const
SvTreeListEntry * m_pRootEntry
Definition: fmexpl.hxx:380
void ShowSelectionProperties(bool bForce=false)
virtual void Start() override
const css::uno::Reference< css::form::XFormComponent > & GetFormComponent() const
Definition: fmexpl.hxx:255
const css::uno::Reference< css::form::XForms > & getFormsRoot() const
Definition: fmexch.hxx:188
virtual void Command(const CommandEvent &rEvt) override
void buildPathFormat(SvTreeListBox const *pTreeBox, SvTreeListEntry const *pRoot)
Definition: fmexch.cxx:209
virtual SvTreeListEntry * InsertEntry(const OUString &rText, SvTreeListEntry *pParent=nullptr, bool bChildrenOnDemand=false, sal_uLong nPos=TREELIST_APPEND, void *pUserData=nullptr)
css::uno::Reference< css::form::XForms > GetForms() const
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
static OUString getUIRootDir()
bool IsMixedSelection() const
Definition: fmexpl.hxx:217
void MarkViewObj(FmFormData const *pFormData, bool bDeep)
static bool Rename(FmEntryData *pEntryData, const OUString &rNewText)
static bool hasFieldExchangeFormat(const DataFlavorExVector &_rFormats)
Definition: fmexch.hxx:230
virtual bool Expand(SvTreeListEntry *pParent)
Abstract DrawObject.
Definition: svdobj.hxx:312
void SetTimeout(sal_uInt64 nTimeoutMs)
KeyFuncType GetFunction() const
void GrabFocus()
SAL_DLLPRIVATE bool setCurrentSelection_Lock(const InterfaceBag &rSelection)
announces a new "current selection"
Definition: fmshimp.cxx:1937
vcl::Window * GetParent() const
static SAL_DLLPRIVATE bool isControlConversionSlot(const OString &rIdent)
checks whether the given slot id denotes a control conversion slot
Definition: fmshimp.cxx:1050
SfxViewShell * GetViewShell() const
SAL_DLLPRIVATE bool setCurrentSelectionFromMark_Lock(const SdrMarkList &rMarkList)
sets a new current selection as indicated by a mark list
Definition: fmshimp.cxx:1920
const tools::Rectangle & GetAllMarkedRect() const
Definition: svdmrkv.hxx:410
void EnableItem(sal_uInt16 nItemId, bool bEnable=true)
Point GetEntryPosition(SvTreeListEntry *) const
static bool hasHiddenControlModelsFormat(const DataFlavorExVector &_rFormats)
Definition: fmexch.hxx:240
static SAL_DLLPRIVATE FmFormObj * GetFormObject(SdrObject *_pSdrObject)
returns the FmFormObj behind the given SdrObject
Definition: fmobj.cxx:582
const Point & GetMousePosPixel() const
SvTreeListEntry * Next(SvTreeListEntry *pEntry) const
void EndUndo()
Definition: svdmodel.cxx:496
IMPL_LINK_NOARG(XFormsPage, TbxSelectHdl, ToolBox *, void)
Definition: datanavi.cxx:401
size_t size() const
Definition: fmexpl.hxx:195
WinBits const WB_HASLINES
bool IsExpanded(SvTreeListEntry *pEntry) const
#define FM_SUN_COMPONENT_FORM
Definition: fmservs.hxx:56
SvTreeListEntry * First() const
SdrObject * Next()
Definition: svditer.hxx:63
SAL_DLLPRIVATE bool IsPropBrwOpen_Lock() const
Definition: fmshimp.cxx:2694
sal_uInt16 GetChildCount() const
void SetSelectionMode(SelectionMode)
bool isClipboardOwner() const
Definition: fmexch.hxx:108
void Stop()
const css::uno::Reference< css::container::XChild > & GetChildIFace() const
Definition: fmexpl.hxx:176
std::unique_ptr< NavigatorTreeModel > m_pNavModel
Definition: fmexpl.hxx:379
const ListBoxEntrySet & selected() const
Definition: fmexch.hxx:183
void setFocusEntry(SvTreeListEntry *_pFocusEntry)
Definition: fmexch.cxx:197
sal_Int8 implExecuteDataTransfer(const OControlTransferData &_rData, sal_Int8 _nAction, const Point &_rDropPos, bool _bDnD)
unsigned short m_aTimerCounter
Definition: fmexpl.hxx:394
#define SAL_WARN_IF(condition, area, stream)
WinBits const WB_BORDER
SdrPage * GetPage() const
Definition: svdpagv.hxx:171
SAL_DLLPRIVATE void forgetCurrentForm_Lock()
Definition: fmshimp.cxx:2021
static bool hasControlPathFormat(const DataFlavorExVector &_rFormats)
Definition: fmexch.hxx:235
size_t onEntryRemoved(SvTreeListEntry *_pEntry)
notifies the data transfer object that a certain entry has been removed from the owning tree ...
Definition: fmexch.cxx:184
OUString aName
void LockSelectionHandling()
Definition: fmexpl.hxx:435
SvTreeListEntry * GetEntry(SvTreeListEntry *pParent, sal_uLong nPos) const
virtual void DeleteMarked()
Definition: svdview.cxx:1376
NavigatorTree(vcl::Window *pParent)
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
void InvalidateEntry(SvTreeListEntry *)
void EndSelection()
void SetNodeBitmaps(const Image &rCollapsedNodeBmp, const Image &rExpandedNodeBmp)
Reference< XComponentContext > getProcessComponentContext()
#define FM_COMPONENT_HIDDEN
Definition: fmservs.hxx:50
const css::uno::Reference< css::beans::XPropertySet > & GetPropertySet() const
Definition: fmexpl.hxx:171
void SetInvokeHandler(const Link< Timer *, void > &rLink)
PopupMenu * get_menu(const OString &sID)
#define FM_PROP_COMMANDTYPE
Definition: fmprop.hxx:118
bool implPrepareExchange(sal_Int8 _nAction)
virtual void ModelHasRemoved(SvTreeListEntry *_pEntry) override
std::set< SvTreeListEntry * > SvLBoxEntrySortedArray
Definition: fmexpl.hxx:362
void EditEntry(SvTreeListEntry *pEntry)
SAL_DLLPRIVATE void EnableTrackProperties_Lock(bool bEnable)
Definition: fmshimp.hxx:279
SdrPageView * GetSdrPageView() const
Definition: svdpntv.hxx:310
const css::uno::Reference< css::awt::XControlModel > & GetUnoControlModel() const
Definition: svdouno.hxx:91
FmEntryDataArray & GetItems()
Definition: fmexpl.hxx:220
virtual void dispose() override
WinBits const WB_HASBUTTONS
bool hasProperty(const OUString &_rName, const Reference< XPropertySet > &_rxSet)
sal_uInt16 m_nControlsSelected
Definition: fmexpl.hxx:391
class FmSearchEngine - Impl class for FmSearchDialog
bool MarkObj(const Point &rPnt, short nTol=-2, bool bToggle=false, bool bDeep=false)
Definition: svdmrkv.cxx:1673
const DataFlavorExVector & GetDataFlavorExVector() const
Definition: fmexch.hxx:192
DROP_ACTION m_aDropActionType
Definition: fmexpl.hxx:387
void buildListFromPath(SvTreeListBox const *pTreeBox, SvTreeListEntry *pRoot)
Definition: fmexch.cxx:248
virtual bool Select(SvTreeListEntry *pEntry, bool bSelect=true)
const SfxPoolItem * Execute(sal_uInt16 nSlot, SfxCallMode nCall=SfxCallMode::SLOT, const SfxPoolItem **pArgs=nullptr, sal_uInt16 nModi=0, const SfxPoolItem **pInternalArgs=nullptr)
void Remove(FmEntryData *pEntryData)
A SdrPage contains exactly one SdrObjList and a description of the physical page dimensions (size / m...
Definition: svdpage.hxx:366
const css::uno::Reference< css::form::XForms > & GetForms(bool _bForceCreate=true) const
Definition: fmpage.cxx:90
void BroadcastMarkedObjects(const SdrMarkList &mlMarked)
ListBoxEntrySet m_aCutEntries
Definition: fmexpl.hxx:375
sal_Int8 mnAction
virtual bool Select(SvTreeListEntry *pEntry, bool bSelect=true) override
sal_Int8 implAcceptDataTransfer(const DataFlavorExVector &_rFlavors, sal_Int8 _nAction, SvTreeListEntry *_pTargetEntry, bool _bDnD)
sal_uLong GetSelectionCount() const
SAL_DLLPRIVATE void ExecuteTabOrderDialog_Lock(const css::uno::Reference< css::awt::XTabControllerModel > &_rxForForm)
Definition: fmshimp.cxx:1390
rtl::Reference< OFormComponentObserver > m_pPropChangeList
Definition: fmexpl.hxx:314
aStr
OutputDevice & GetOutputDevice() const
sal_uInt16 m_nHiddenControls
Definition: fmexpl.hxx:392
void setFormsRoot(const css::uno::Reference< css::form::XForms > &_rxFormsRoot)
Definition: fmexch.hxx:166
void UnMarkAll(SdrPageView const *pPV=nullptr)
Definition: svdmrkv.hxx:309
SdrPaintWindow * GetPaintWindow(sal_uInt32 nIndex) const
Definition: svdpntv.cxx:77
SAL_DLLPRIVATE bool isEnhancedForm_Lock() const
Definition: fmshimp.cxx:678
bool doingKeyboardCut() const
Definition: fmexpl.hxx:505
static bool IsFormEntry(SvTreeListEntry const *pEntry)
FmEntryDataList * GetChildList() const
Definition: fmexpl.hxx:159
long Y() const
void NewForm(SvTreeListEntry const *pParentEntry)
#define TREELIST_APPEND
void addSelectedEntry(SvTreeListEntry *_pEntry)
Definition: fmexch.cxx:191
void Remove(FmEntryData *pEntryData, bool bAlterModel=false)
bool IsObjMarked(SdrObject const *pObj) const
Definition: svdmrkv.cxx:1935
const DataFlavorExVector & GetDataFlavorExVector() const
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)