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