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