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  ,m_aControlExchange()
135  ,nEditEvent(nullptr)
136  ,m_sdiState(SDI_DIRTY)
137  ,m_nSelectLock(0)
138  ,m_nFormsSelected(0)
139  ,m_nControlsSelected(0)
140  ,m_nHiddenControls(0)
141  ,m_bDragDataDirty(false)
142  ,m_bPrevSelectionMixed(false)
143  ,m_bRootSelected(false)
144  ,m_bInitialUpdate(true)
145  ,m_bKeyboardCut( false )
146  ,m_bEditing( false )
147  {
148  m_xTreeView->set_help_id(HID_FORM_NAVIGATOR);
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 (dynamic_cast<const FmNavRequestSelectHint*>(&rHint))
599  {
600  FmNavRequestSelectHint* pershHint = const_cast<FmNavRequestSelectHint*>(static_cast<const FmNavRequestSelectHint*>(&rHint));
601  FmEntryDataArray& arredToSelect = pershHint->GetItems();
602  SynchronizeSelection(arredToSelect);
603 
604  if (pershHint->IsMixedSelection())
605  // in this case I deselect all, although the view had a mixed selection
606  // during next selection, I must adapt the navigator to the view
607  m_bPrevSelectionMixed = true;
608  }
609  }
610 
611  std::unique_ptr<weld::TreeIter> NavigatorTree::Insert(FmEntryData* pEntryData, int nRelPos)
612  {
613  // insert current entry
614  std::unique_ptr<weld::TreeIter> xParentEntry = FindEntry( pEntryData->GetParent() );
615  std::unique_ptr<weld::TreeIter> xNewEntry(m_xTreeView->make_iterator());
616  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntryData)));
617 
618  if(!xParentEntry)
619  {
620  m_xTreeView->insert(m_xRootEntry.get(), nRelPos, &pEntryData->GetText(), &sId,
621  nullptr, nullptr, false, xNewEntry.get());
622  }
623  else
624  {
625  m_xTreeView->insert(xParentEntry.get(), nRelPos, &pEntryData->GetText(), &sId,
626  nullptr, nullptr, false, xNewEntry.get());
627  }
628 
629  m_xTreeView->set_image(*xNewEntry, pEntryData->GetNormalImage());
630  m_xTreeView->set_sensitive(*xNewEntry, true);
631 
632  // If root-entry, expand root
633  if (!xParentEntry)
634  m_xTreeView->expand_row(*m_xRootEntry);
635 
636  // insert children
637  FmEntryDataList* pChildList = pEntryData->GetChildList();
638  size_t nChildCount = pChildList->size();
639  for( size_t i = 0; i < nChildCount; i++ )
640  {
641  FmEntryData* pChildData = pChildList->at( i );
642  Insert(pChildData, -1);
643  }
644 
645  return xNewEntry;
646  }
647 
648  void NavigatorTree::Remove( FmEntryData* pEntryData )
649  {
650  if( !pEntryData )
651  return;
652 
653  // entry for the data
654  std::unique_ptr<weld::TreeIter> xEntry = FindEntry(pEntryData);
655  if (!xEntry)
656  return;
657 
658  // delete entry from TreeListBox
659  // I'm not allowed, to treat the selection, which I trigger:
660  // select changes the MarkList of the view, if somebody else does this at the same time
661  // and removes a selection, we get a problem
662  // e.g. Group controls with open navigator
664 
665  // little problem: I remember the selected data, but if somebody deletes one of these entries,
666  // I get inconsistent... this would be bad
667  m_xTreeView->unselect(*xEntry);
668 
669  // selection can be modified during deletion,
670  // but because I disabled SelectionHandling, I have to do it later
671  auto nExpectedSelectionCount = m_xTreeView->count_selected_rows();
672 
673  ModelHasRemoved(xEntry.get());
674  m_xTreeView->remove(*xEntry);
675 
676  if (nExpectedSelectionCount != m_xTreeView->count_selected_rows())
678 
679  // by default I treat the selection of course
681  }
682 
684  {
685  FmEntryData* pEntryData = reinterpret_cast<FmEntryData*>(m_xTreeView->get_id(rEntry).toInt64());
686  return !pEntryData || dynamic_cast<const FmFormData*>( pEntryData) != nullptr;
687  }
688 
690  {
691  FmEntryData* pEntryData = reinterpret_cast<FmEntryData*>(m_xTreeView->get_id(rEntry).toInt64());
692  return dynamic_cast<const FmControlData*>( pEntryData) != nullptr;
693  }
694 
696  {
697  auto nSelectedEntries = m_xTreeView->count_selected_rows();
698  if (nSelectedEntries != 1)
699  // no selected entry, or at least two selected entries
700  return false;
701 
702  // get the clipboard
704 
705  sal_Int8 nAction = m_aControlExchange.isClipboardOwner() && doingKeyboardCut( ) ? DND_ACTION_MOVE : DND_ACTION_COPY;
706  std::unique_ptr<weld::TreeIter> xSelected(m_xTreeView->make_iterator());
707  if (!m_xTreeView->get_selected(xSelected.get()))
708  xSelected.reset();
709  return nAction == implAcceptDataTransfer(aClipboardContent.GetDataFlavorExVector(), nAction, xSelected.get(), false);
710  }
711 
712  sal_Int8 NavigatorTree::implAcceptDataTransfer( const DataFlavorExVector& _rFlavors, sal_Int8 _nAction, const weld::TreeIter* _pTargetEntry, bool _bDnD )
713  {
714  // no target -> no drop
715  if (!_pTargetEntry)
716  return DND_ACTION_NONE;
717 
718  // format check
719  bool bHasDefControlFormat = OControlExchange::hasFieldExchangeFormat( _rFlavors );
720  bool bHasControlPathFormat = OControlExchange::hasControlPathFormat( _rFlavors );
721  bool bHasHiddenControlsFormat = OControlExchange::hasHiddenControlModelsFormat( _rFlavors );
722  if (!bHasDefControlFormat && !bHasControlPathFormat && !bHasHiddenControlsFormat)
723  return DND_ACTION_NONE;
724 
725  bool bSelfSource = _bDnD ? m_aControlExchange.isDragSource() : m_aControlExchange.isClipboardOwner();
726 
727  if ( bHasHiddenControlsFormat )
728  { // bHasHiddenControlsFormat means that only hidden controls are part of the data
729 
730  // hidden controls can be copied to a form only
731  if (m_xTreeView->iter_compare(*_pTargetEntry, *m_xRootEntry) == 0 || !IsFormEntry(*_pTargetEntry))
732  return DND_ACTION_NONE;
733 
734  return bSelfSource ? ( DND_ACTION_COPYMOVE & _nAction ) : DND_ACTION_COPY;
735  }
736 
737  if ( !bSelfSource )
738  {
739  // DnD or CnP crossing navigator boundaries
740  // The main problem here is that the current API does not allow us to sneak into the content which
741  // is to be inserted. So we have to allow it for the moment, but maybe reject later on (in the real drop).
742 
743  // TODO: this smart behaviour later on ... at the moment, we disallow data transfer crossing navigator
744  // boundaries.
745 
746  return DND_ACTION_NONE;
747  }
748 
749  DBG_ASSERT( _bDnD ? m_aControlExchange.isDragSource() : m_aControlExchange.isClipboardOwner(),
750  "NavigatorTree::implAcceptDataTransfer: here only with source=dest!" );
751  // somebody changed the logic of this method ...
752 
753  // from here on, I can work with m_aControlExchange instead of _rData!
754 
755  bool bForeignCollection = m_aControlExchange->getFormsRoot().get() != GetNavModel()->GetFormPage()->GetForms().get();
756  if ( bForeignCollection )
757  {
758  // crossing shell/page boundaries, we can exchange hidden controls only
759  // But if we survived the checks above, we do not have hidden controls.
760  // -> no data transfer
761  DBG_ASSERT( !bHasHiddenControlsFormat, "NavigatorTree::implAcceptDataTransfer: still hidden controls format!" );
762  // somebody changed the logic of this method ...
763 
764  return DND_ACTION_COPY;
765  }
766 
767  if (DND_ACTION_MOVE != _nAction) // 'normal' controls within a shell are moved only (never copied)
768  return DND_ACTION_NONE;
769 
770  if ( m_bDragDataDirty || !bHasDefControlFormat )
771  {
772  if (!bHasControlPathFormat)
773  // I am in the shell/page, which has the controls, but I have no format,
774  // which survived the shell change (SVX_FM_CONTROLS_AS_PATH)
775  return DND_ACTION_NONE;
776 
777  // I must recreate the list of the ExchangeObjects, because the shell was changed during dragging
778  // (there are SvLBoxEntries in it, and we lost them during change)
780  m_bDragDataDirty = false;
781  }
782 
783  // List of dropped entries from DragServer
784  const ListBoxEntrySet& rDropped = m_aControlExchange->selected();
785  DBG_ASSERT(!rDropped.empty(), "NavigatorTree::implAcceptDataTransfer: no entries !");
786 
787  bool bDropTargetIsComponent = IsFormComponentEntry( *_pTargetEntry );
788 
789  // conditions to disallow the drop
790  // 0) the root entry is part of the list (can't DnD the root!)
791  // 1) one of the dragged entries is to be dropped onto its own parent
792  // 2) - " - is to be dropped onto itself
793  // 3) - " - is a Form and to be dropped onto one of its descendants
794  // 4) one of the entries is a control and to be dropped onto the root
795  // 5) a control or form will be dropped onto a control which is _not_ a sibling (dropping onto a sibling
796  // means moving the control)
797 
798  // collect the ancestors of the drop target (speeds up 3)
799  SvLBoxEntrySortedArray arrDropAncestors;
800  std::unique_ptr<weld::TreeIter> xLoop(m_xTreeView->make_iterator(_pTargetEntry));
801  do
802  {
803  arrDropAncestors.emplace(m_xTreeView->make_iterator(xLoop.get()));
804  }
805  while (m_xTreeView->iter_parent(*xLoop));
806 
807  for (const auto& rCurrent : rDropped)
808  {
809  // test for 0)
810  if (m_xTreeView->iter_compare(*rCurrent, *m_xRootEntry) == 0)
811  return DND_ACTION_NONE;
812 
813  std::unique_ptr<weld::TreeIter> xCurrentParent(m_xTreeView->make_iterator(rCurrent.get()));
814  m_xTreeView->iter_parent(*xCurrentParent);
815 
816  // test for 1)
817  if (m_xTreeView->iter_compare(*_pTargetEntry, *xCurrentParent) == 0)
818  return DND_ACTION_NONE;
819 
820  // test for 2)
821  if (m_xTreeView->iter_compare(*rCurrent, *_pTargetEntry) == 0)
822  return DND_ACTION_NONE;
823 
824  // test for 5)
825  if (bDropTargetIsComponent)
826  return DND_ACTION_NONE;
827 
828  // test for 3)
829  if (IsFormEntry(*rCurrent))
830  {
831  auto aIter = std::find_if(arrDropAncestors.begin(), arrDropAncestors.end(),
832  [this, &rCurrent](const auto& rElem) {
833  return m_xTreeView->iter_compare(*rElem, *rCurrent) == 0;
834  });
835 
836  if ( aIter != arrDropAncestors.end() )
837  return DND_ACTION_NONE;
838  }
839  else if (IsFormComponentEntry(*rCurrent))
840  {
841  // test for 4)
842  if (m_xTreeView->iter_compare(*_pTargetEntry, *m_xRootEntry) == 0)
843  return DND_ACTION_NONE;
844  }
845  }
846  return DND_ACTION_MOVE;
847  }
848 
850  {
851  ::Point aDropPos = rEvt.maPosPixel;
852  std::unique_ptr<weld::TreeIter> xDropTarget(m_xTreeView->make_iterator());
853  // get_dest_row_at_pos with false cause we must drop exactly "on" a form to paste a control into it
854  if (!m_xTreeView->get_dest_row_at_pos(aDropPos, xDropTarget.get(), false))
855  xDropTarget.reset();
856  return implAcceptDataTransfer(m_aDropTargetHelper.GetDataFlavorExVector(), rEvt.mnAction, xDropTarget.get(), true);
857  }
858 
859  sal_Int8 NavigatorTree::implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, const ::Point& _rDropPos, bool _bDnD )
860  {
861  std::unique_ptr<weld::TreeIter> xDrop(m_xTreeView->make_iterator());
862  // get_dest_row_at_pos with false cause we must drop exactly "on" a form to paste a control into it
863  if (!m_xTreeView->get_dest_row_at_pos(_rDropPos, xDrop.get(), false))
864  xDrop.reset();
865  return implExecuteDataTransfer( _rData, _nAction, xDrop.get(), _bDnD );
866  }
867 
868  sal_Int8 NavigatorTree::implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, const weld::TreeIter* _pTargetEntry, bool _bDnD )
869  {
870  const DataFlavorExVector& rDataFlavors = _rData.GetDataFlavorExVector();
871 
872  if ( DND_ACTION_NONE == implAcceptDataTransfer( rDataFlavors, _nAction, _pTargetEntry, _bDnD ) )
873  // under some platforms, it may happen that ExecuteDrop is called though AcceptDrop returned DND_ACTION_NONE
874  return DND_ACTION_NONE;
875 
876  if (!_pTargetEntry)
877  // no target -> no drop
878  return DND_ACTION_NONE;
879 
880  // format checks
881 #ifdef DBG_UTIL
882  bool bHasHiddenControlsFormat = OControlExchange::hasHiddenControlModelsFormat( rDataFlavors );
883  bool bForeignCollection = _rData.getFormsRoot().get() != GetNavModel()->GetFormPage()->GetForms().get();
884  DBG_ASSERT(!bForeignCollection || bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: invalid format (AcceptDrop shouldn't have let this pass) !");
885  DBG_ASSERT(bForeignCollection || !m_bDragDataDirty, "NavigatorTree::implExecuteDataTransfer: invalid state (shell changed since last exchange resync) !");
886  // this should be done in AcceptDrop: the list of controls is created in _rData
887  // and m_bDragDataDirty is reset
888 #endif
889 
890  if ( DND_ACTION_COPY == _nAction )
891  { // bHasHiddenControlsFormat means that only hidden controls are part of the data
892 #ifdef DBG_UTIL
893  DBG_ASSERT( bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: copy allowed for hidden controls only!" );
894 #endif
895  DBG_ASSERT( _pTargetEntry && m_xTreeView->iter_compare(*_pTargetEntry, *m_xRootEntry) != 0 && IsFormEntry( *_pTargetEntry ),
896  "NavigatorTree::implExecuteDataTransfer: should not be here!" );
897  // implAcceptDataTransfer should have caught both cases
898 
899 #ifdef DBG_UTIL
900  DBG_ASSERT(bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: only copying of hidden controls is supported !");
901  // should be caught by AcceptDrop
902 #endif
903 
904  // because i want to select all targets (and only them)
905  m_xTreeView->unselect_all();
906 
907  const Sequence< Reference< XInterface > >& aControls = _rData.hiddenControls();
908  sal_Int32 nCount = aControls.getLength();
909  const Reference< XInterface >* pControls = aControls.getConstArray();
910 
911  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
912  FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : nullptr;
913 
914  // within undo
915  if (pFormModel)
916  {
917  OUString aStr(SvxResId(RID_STR_CONTROL));
918  OUString aUndoStr = SvxResId(RID_STR_UNDO_CONTAINER_INSERT).replaceAll("#", aStr);
919  pFormModel->BegUndo(aUndoStr);
920  }
921 
922  // copy controls
923  for (sal_Int32 i=0; i<nCount; ++i)
924  {
925  // create new control
926  FmControlData* pNewControlData = NewControl( FM_COMPONENT_HIDDEN, *_pTargetEntry, false);
927  Reference< XPropertySet > xNewPropSet( pNewControlData->GetPropertySet() );
928 
929  // copy properties form old control to new one
930  Reference< XPropertySet > xCurrent(pControls[i], UNO_QUERY);
931 #if (OSL_DEBUG_LEVEL > 0)
932  // check whether it is a hidden control
933  sal_Int16 nClassId = ::comphelper::getINT16(xCurrent->getPropertyValue(FM_PROP_CLASSID));
934  OSL_ENSURE(nClassId == FormComponentType::HIDDENCONTROL, "NavigatorTree::implExecuteDataTransfer: invalid control in drop list !");
935  // if SVX_FM_HIDDEN_CONTROLS-format exists, the sequence
936  // should only contain hidden controls
937 #endif // (OSL_DEBUG_LEVEL > 0)
938  Reference< XPropertySetInfo > xPropInfo( xCurrent->getPropertySetInfo());
939  const Sequence< Property> seqAllCurrentProps = xPropInfo->getProperties();
940  for (Property const & currentProp : seqAllCurrentProps)
941  {
942  if (((currentProp.Attributes & PropertyAttribute::READONLY) == 0) && (currentProp.Name != FM_PROP_NAME))
943  { // (read-only attribs aren't set, ditto name,
944  // NewControl defined it uniquely
945  xNewPropSet->setPropertyValue(currentProp.Name, xCurrent->getPropertyValue(currentProp.Name));
946  }
947  }
948 
949  std::unique_ptr<weld::TreeIter> xToSelect = FindEntry(pNewControlData);
950  m_xTreeView->select(*xToSelect);
951  if (i == 0)
952  m_xTreeView->set_cursor(*xToSelect);
953  }
954 
955  if (pFormModel)
956  pFormModel->EndUndo();
957 
958  return _nAction;
959  }
960 
962  {
963  // can't do anything without the internal format here ... usually happens when doing DnD or CnP
964  // over navigator boundaries
965  return DND_ACTION_NONE;
966  }
967 
968  // some data for the target
969  bool bDropTargetIsForm = IsFormEntry(*_pTargetEntry);
970  FmFormData* pTargetData = bDropTargetIsForm ? reinterpret_cast<FmFormData*>(m_xTreeView->get_id(*_pTargetEntry).toInt64()) : nullptr;
971 
972  DBG_ASSERT( DND_ACTION_COPY != _nAction, "NavigatorTree::implExecuteDataTransfer: somebody changed the logics!" );
973 
974  // list of dragged entries
975  const ListBoxEntrySet& rDropped = _rData.selected();
976  DBG_ASSERT(!rDropped.empty(), "NavigatorTree::implExecuteDataTransfer: no entries!");
977 
978  // make a copy because rDropped is updated on deleting an entry which we do in the processing loop
979  ListBoxEntrySet aDropped;
980  for (const auto& rEntry : rDropped)
981  aDropped.emplace(m_xTreeView->make_iterator(rEntry.get()));
982 
983  // shell and model
984  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
985  FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : nullptr;
986  if (!pFormModel)
987  return DND_ACTION_NONE;
988 
989  // for Undo
990  const bool bUndo = pFormModel->IsUndoEnabled();
991 
992  if( bUndo )
993  {
994  OUString strUndoDescription(SvxResId(RID_STR_UNDO_CONTAINER_REPLACE));
995  pFormModel->BegUndo(strUndoDescription);
996  }
997 
998  // remove selection before adding an entry, so the mark doesn't flicker
999  // -> lock action of selection
1001 
1002  // go through all dropped entries
1003  for ( ListBoxEntrySet::const_iterator dropped = aDropped.begin();
1004  dropped != aDropped.end();
1005  ++dropped
1006  )
1007  {
1008  bool bFirstEntry = aDropped.begin() == dropped;
1009 
1010  // some data of the current element
1011  const auto& rCurrent = *dropped;
1012  DBG_ASSERT(rCurrent, "NavigatorTree::implExecuteDataTransfer: invalid entry");
1013  DBG_ASSERT(m_xTreeView->get_iter_depth(*rCurrent) != 0, "NavigatorTree::implExecuteDataTransfer: invalid entry");
1014  // don't drag root
1015 
1016  FmEntryData* pCurrentUserData = reinterpret_cast<FmEntryData*>(m_xTreeView->get_id(*rCurrent).toInt64());
1017 
1018  Reference< XChild > xCurrentChild = pCurrentUserData->GetChildIFace();
1019  Reference< XIndexContainer > xContainer(xCurrentChild->getParent(), UNO_QUERY);
1020 
1021  FmFormData* pCurrentParentUserData = static_cast<FmFormData*>(pCurrentUserData->GetParent());
1022  DBG_ASSERT(pCurrentParentUserData == nullptr || dynamic_cast<const FmFormData*>(pCurrentUserData->GetParent()) != nullptr, "NavigatorTree::implExecuteDataTransfer: invalid parent");
1023 
1024  // remove from parent
1025  if (pCurrentParentUserData)
1026  pCurrentParentUserData->GetChildList()->removeNoDelete( pCurrentUserData );
1027  else
1028  GetNavModel()->GetRootList()->removeNoDelete( pCurrentUserData );
1029 
1030  // remove from container
1031  sal_Int32 nIndex = getElementPos(xContainer, xCurrentChild);
1032  GetNavModel()->m_pPropChangeList->Lock();
1033  // UndoAction for removal
1034  if ( bUndo && GetNavModel()->m_pPropChangeList->CanUndo())
1035  {
1036  pFormModel->AddUndo(std::make_unique<FmUndoContainerAction>(*pFormModel, FmUndoContainerAction::Removed,
1037  xContainer, xCurrentChild, nIndex));
1038  }
1039  else if( !GetNavModel()->m_pPropChangeList->CanUndo() )
1040  {
1041  FmUndoContainerAction::DisposeElement( xCurrentChild );
1042  }
1043 
1044  // copy events
1045  Reference< XEventAttacherManager > xManager(xContainer, UNO_QUERY);
1046  Sequence< ScriptEventDescriptor > aEvts;
1047 
1048  if (xManager.is() && nIndex >= 0)
1049  aEvts = xManager->getScriptEvents(nIndex);
1050  xContainer->removeByIndex(nIndex);
1051 
1052  // remove selection
1053  m_xTreeView->unselect(*rCurrent);
1054  // and delete it
1055  Remove(pCurrentUserData);
1056 
1057  // position in DropParents, where to insert dropped entries
1058  if (pTargetData)
1059  xContainer.set(pTargetData->GetElement(), UNO_QUERY);
1060  else
1061  xContainer = GetNavModel()->GetForms();
1062 
1063  // always insert at the end
1064  nIndex = xContainer->getCount();
1065 
1066  // UndoAction for insertion
1067  if ( bUndo && GetNavModel()->m_pPropChangeList->CanUndo())
1068  pFormModel->AddUndo(std::make_unique<FmUndoContainerAction>(*pFormModel, FmUndoContainerAction::Inserted,
1069  xContainer, xCurrentChild, nIndex));
1070 
1071  // insert in new container
1072  if (pTargetData)
1073  {
1074  // insert in a form needs a FormComponent
1075  xContainer->insertByIndex( nIndex,
1076  makeAny( Reference< XFormComponent >( xCurrentChild, UNO_QUERY ) ) );
1077  }
1078  else
1079  {
1080  xContainer->insertByIndex( nIndex,
1081  makeAny( Reference< XForm >( xCurrentChild, UNO_QUERY ) ) );
1082  }
1083 
1084  if (aEvts.hasElements())
1085  {
1086  xManager.set(xContainer, UNO_QUERY);
1087  if (xManager.is())
1088  xManager->registerScriptEvents(nIndex, aEvts);
1089  }
1090 
1091  GetNavModel()->m_pPropChangeList->UnLock();
1092 
1093  // give an entry the new parent
1094  pCurrentUserData->SetParent(pTargetData);
1095 
1096  // give parent the new child
1097  if (pTargetData)
1098  pTargetData->GetChildList()->insert( std::unique_ptr<FmEntryData>(pCurrentUserData), nIndex );
1099  else
1100  GetNavModel()->GetRootList()->insert( std::unique_ptr<FmEntryData>(pCurrentUserData), nIndex );
1101 
1102  // announce to myself and reselect
1103  std::unique_ptr<weld::TreeIter> xNew = Insert( pCurrentUserData, nIndex );
1104  if (bFirstEntry && xNew)
1105  {
1106  if (m_xTreeView->iter_parent(*xNew))
1107  m_xTreeView->expand_row(*xNew);
1108  }
1109  }
1110 
1112 
1113  if( bUndo )
1114  pFormModel->EndUndo();
1115 
1116  // During the move, the markings of the underlying view did not change (because the view is not affected by the logical
1117  // hierarchy of the form/control models. But my selection changed - which means I have to adjust it according to the
1118  // view marks, again.
1120 
1121  // in addition, with the move of controls such things as "the current form" may have changed - force the shell
1122  // to update itself accordingly
1123  if( pFormShell && pFormShell->GetImpl() && pFormShell->GetFormView() )
1124  pFormShell->GetImpl()->DetermineSelection_Lock( pFormShell->GetFormView()->GetMarkedObjectList() );
1125 
1126  if ( m_aControlExchange.isClipboardOwner() && ( DND_ACTION_MOVE == _nAction ) )
1127  m_aControlExchange->clear();
1128 
1129  return _nAction;
1130  }
1131 
1133  {
1134  sal_Int8 nResult( DND_ACTION_NONE );
1135  if ( m_aControlExchange.isDragSource() )
1136  nResult = implExecuteDataTransfer( *m_aControlExchange, rEvt.mnAction, rEvt.maPosPixel, true );
1137  else
1138  {
1139  OControlTransferData aDroppedData( rEvt.maDropEvent.Transferable );
1140  nResult = implExecuteDataTransfer( aDroppedData, rEvt.mnAction, rEvt.maPosPixel, true );
1141  }
1142  return nResult;
1143  }
1144 
1146  {
1147  std::unique_ptr<weld::TreeIter> xSelected(m_xTreeView->make_iterator());
1148  if (!m_xTreeView->get_selected(xSelected.get()))
1149  xSelected.reset();
1150 
1151  try
1152  {
1153  if ( m_aControlExchange.isClipboardOwner() )
1154  {
1156  }
1157  else
1158  {
1159  // the clipboard content
1160  Reference< XClipboard > xClipboard( GetSystemClipboard() );
1161  Reference< XTransferable > xTransferable;
1162  if ( xClipboard.is() )
1163  xTransferable = xClipboard->getContents();
1164 
1165  OControlTransferData aClipboardContent( xTransferable );
1166  implExecuteDataTransfer( aClipboardContent, DND_ACTION_COPY, xSelected.get(), false );
1167  }
1168  }
1169  catch( const Exception& )
1170  {
1171  TOOLS_WARN_EXCEPTION( "svx", "NavigatorTree::doPaste" );
1172  }
1173  }
1174 
1176  {
1178  {
1179  m_aControlExchange.setClipboardListener( LINK( this, NavigatorTree, OnClipboardAction ) );
1180  m_aControlExchange.copyToClipboard( );
1181  }
1182  }
1183 
1185  {
1186  if (doingKeyboardCut())
1187  {
1188  auto aIter = std::find_if(m_aCutEntries.begin(), m_aCutEntries.end(),
1189  [this, pTypedEntry](const auto& rElem) {
1190  return m_xTreeView->iter_compare(*rElem, *pTypedEntry) == 0;
1191  });
1192  if (aIter != m_aCutEntries.end())
1193  m_aCutEntries.erase(aIter);
1194  }
1195 
1196  if (m_aControlExchange.isDataExchangeActive())
1197  {
1198  if (0 == m_aControlExchange->onEntryRemoved(m_xTreeView.get(), pTypedEntry))
1199  {
1200  // last of the entries which we put into the clipboard has been deleted from the tree.
1201  // Give up the clipboard ownership.
1202  m_aControlExchange.clear();
1203  }
1204  }
1205  }
1206 
1208  {
1210  return;
1211 
1212  m_aControlExchange.setClipboardListener( LINK( this, NavigatorTree, OnClipboardAction ) );
1213  m_aControlExchange.copyToClipboard( );
1214  m_bKeyboardCut = true;
1215 
1216  // mark all the entries we just "cut" into the clipboard as "nearly moved"
1217  for (const auto& rEntry : m_arrCurrentSelection )
1218  {
1219  if (!rEntry)
1220  continue;
1221  m_aCutEntries.emplace(m_xTreeView->make_iterator(rEntry.get()));
1222  m_xTreeView->set_sensitive(*rEntry, false);
1223  }
1224  }
1225 
1226  IMPL_LINK(NavigatorTree, KeyInputHdl, const ::KeyEvent&, rKEvt, bool)
1227  {
1228  const vcl::KeyCode& rCode = rKEvt.GetKeyCode();
1229 
1230  // delete?
1231  if (rCode.GetCode() == KEY_DELETE && !rCode.GetModifier())
1232  {
1233  DeleteSelection();
1234  return true;
1235  }
1236 
1237  // copy'n'paste?
1238  switch ( rCode.GetFunction() )
1239  {
1240  case KeyFuncType::CUT:
1241  doCut();
1242  break;
1243 
1244  case KeyFuncType::PASTE:
1245  if ( implAcceptPaste() )
1246  doPaste();
1247  break;
1248 
1249  case KeyFuncType::COPY:
1250  doCopy();
1251  break;
1252 
1253  default:
1254  break;
1255  }
1256 
1257  return false;
1258  }
1259 
1260  IMPL_LINK(NavigatorTree, EditingEntryHdl, const weld::TreeIter&, rIter, bool)
1261  {
1262  // root, which isn't allowed to be renamed, has UserData=NULL
1263  m_bEditing = !m_xTreeView->get_id(rIter).isEmpty();
1264  return m_bEditing;
1265  }
1266 
1267  void NavigatorTree::NewForm(const weld::TreeIter& rParentEntry)
1268  {
1269  // get ParentFormData
1270  if (!IsFormEntry(rParentEntry))
1271  return;
1272 
1273  FmFormData* pParentFormData = reinterpret_cast<FmFormData*>(m_xTreeView->get_id(rParentEntry).toInt64());
1274 
1275 
1276  // create new form
1278  Reference< XForm > xNewForm(xContext->getServiceManager()->createInstanceWithContext(FM_SUN_COMPONENT_FORM, xContext), UNO_QUERY);
1279  if (!xNewForm.is())
1280  return;
1281 
1282  Reference< XPropertySet > xPropertySet(xNewForm, UNO_QUERY);
1283  if (!xPropertySet.is())
1284  return;
1285 
1286  FmFormData* pNewFormData = new FmFormData(xNewForm, pParentFormData);
1287 
1288 
1289  // set name
1290  OUString aName = GenerateName(pNewFormData);
1291  pNewFormData->SetText(aName);
1292 
1293  try
1294  {
1295  xPropertySet->setPropertyValue( FM_PROP_NAME, makeAny(aName) );
1296  // a form should always have the command type table as default
1297  xPropertySet->setPropertyValue( FM_PROP_COMMANDTYPE, makeAny(sal_Int32(CommandType::TABLE)));
1298  }
1299  catch ( const Exception& )
1300  {
1301  OSL_FAIL("NavigatorTree::NewForm : could not set essential properties!");
1302  }
1303 
1304 
1305  // insert form
1306  GetNavModel()->Insert(pNewFormData, SAL_MAX_UINT32, true);
1307 
1308 
1309  // set new form as active
1310  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1311  if( pFormShell )
1312  {
1313  InterfaceBag aSelection;
1314  aSelection.insert( Reference<XInterface>( xNewForm, UNO_QUERY ) );
1315  pFormShell->GetImpl()->setCurrentSelection_Lock(aSelection);
1316 
1317  pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_PROPERTIES, true, true);
1318  }
1319  GetNavModel()->SetModified();
1320 
1321  // switch to EditMode
1322  std::unique_ptr<weld::TreeIter> xNewEntry = FindEntry(pNewFormData);
1323  m_xTreeView->start_editing(*xNewEntry);
1324  m_bEditing = true;
1325  }
1326 
1327  FmControlData* NavigatorTree::NewControl(const OUString& rServiceName, const weld::TreeIter& rParentEntry, bool bEditName)
1328  {
1329  // get ParentForm
1330  if (!GetNavModel()->GetFormShell())
1331  return nullptr;
1332  if (!IsFormEntry(rParentEntry))
1333  return nullptr;
1334 
1335  FmFormData* pParentFormData = reinterpret_cast<FmFormData*>(m_xTreeView->get_id(rParentEntry).toInt64());
1336  Reference<XForm> xParentForm(pParentFormData->GetFormIface());
1337 
1338  // create new component
1340  Reference<XFormComponent> xNewComponent( xContext->getServiceManager()->createInstanceWithContext(rServiceName, xContext), UNO_QUERY);
1341  if (!xNewComponent.is())
1342  return nullptr;
1343 
1344  FmControlData* pNewFormControlData = new FmControlData(xNewComponent, pParentFormData);
1345 
1346  // set name
1347  OUString sName = FmFormPageImpl::setUniqueName( xNewComponent, xParentForm );
1348 
1349  pNewFormControlData->SetText( sName );
1350 
1351  // insert FormComponent
1352  GetNavModel()->Insert(pNewFormControlData, SAL_MAX_UINT32, true);
1353  GetNavModel()->SetModified();
1354 
1355  if (bEditName)
1356  {
1357  // switch to EditMode
1358  std::unique_ptr<weld::TreeIter> xNewEntry = FindEntry( pNewFormControlData );
1359  m_xTreeView->select(*xNewEntry);
1360 
1361  m_xTreeView->start_editing(*xNewEntry);
1362  m_bEditing = true;
1363  }
1364 
1365  return pNewFormControlData;
1366  }
1367 
1368  OUString NavigatorTree::GenerateName( FmEntryData const * pEntryData )
1369  {
1370  const sal_uInt16 nMaxCount = 99;
1371  OUString aNewName;
1372 
1373  // create base name
1374  OUString aBaseName;
1375  if( dynamic_cast<const FmFormData*>( pEntryData) != nullptr )
1376  aBaseName = SvxResId( RID_STR_STDFORMNAME );
1377  else if( dynamic_cast<const FmControlData*>( pEntryData) != nullptr )
1378  aBaseName = SvxResId( RID_STR_CONTROL );
1379 
1380 
1381  // create new name
1382  FmFormData* pFormParentData = static_cast<FmFormData*>(pEntryData->GetParent());
1383 
1384  for( sal_Int32 i=0; i<nMaxCount; i++ )
1385  {
1386  aNewName = aBaseName;
1387  if( i>0 )
1388  {
1389  aNewName += " " + OUString::number(i);
1390  }
1391 
1392  if( GetNavModel()->FindData(aNewName, pFormParentData,false) == nullptr )
1393  break;
1394  }
1395 
1396  return aNewName;
1397  }
1398 
1399  IMPL_LINK(NavigatorTree, EditedEntryHdl, const IterString&, rIterString, bool)
1400  {
1401  m_bEditing = false;
1402 
1403  const weld::TreeIter& rIter = rIterString.first;
1404 
1405  FmEntryData* pEntryData = reinterpret_cast<FmEntryData*>(m_xTreeView->get_id(rIter).toInt64());
1406  bool bRes = NavigatorTreeModel::Rename(pEntryData, rIterString.second);
1407  if (!bRes)
1408  {
1409  m_xEditEntry = m_xTreeView->make_iterator(&rIter);
1410  nEditEvent = Application::PostUserEvent(LINK(this, NavigatorTree, OnEdit));
1411  }
1412 
1413  return bRes;
1414  }
1415 
1416  IMPL_LINK_NOARG(NavigatorTree, OnEdit, void*, void)
1417  {
1418  nEditEvent = nullptr;
1419  m_xTreeView->start_editing(*m_xEditEntry);
1420  m_bEditing = true;
1421  m_xEditEntry.reset();
1422  }
1423 
1425  {
1426  m_sdiState = SDI_DIRTY;
1427 
1428  if (IsSelectionHandlingLocked())
1429  return;
1430 
1431  if (m_aSynchronizeTimer.IsActive())
1432  m_aSynchronizeTimer.Stop();
1433 
1434  m_aSynchronizeTimer.SetTimeout(EXPLORER_SYNC_DELAY);
1435  m_aSynchronizeTimer.Start();
1436  }
1437 
1438  IMPL_LINK_NOARG(NavigatorTree, OnSynchronizeTimer, Timer *, void)
1439  {
1440  SynchronizeMarkList();
1441  }
1442 
1443  IMPL_LINK_NOARG(NavigatorTree, OnClipboardAction, OLocalExchange&, void)
1444  {
1445  if ( m_aControlExchange.isClipboardOwner() )
1446  return;
1447 
1448  if ( !doingKeyboardCut() )
1449  return;
1450 
1451  for (const auto& rEntry : m_aCutEntries)
1452  {
1453  if (!rEntry)
1454  continue;
1455  m_xTreeView->set_sensitive(*rEntry, true);
1456  }
1457  ListBoxEntrySet aEmpty;
1458  m_aCutEntries.swap( aEmpty );
1459 
1460  m_bKeyboardCut = false;
1461  }
1462 
1464  {
1465  // at first i need the FormShell
1466  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1467  if (!pFormShell)
1468  // no shell -> impossible to set curObject -> leave
1469  return;
1470 
1472  SAL_WARN_IF(static_cast<size_t>(m_nFormsSelected + m_nControlsSelected
1473  + (m_bRootSelected ? 1 : 0)) != m_arrCurrentSelection.size(),
1474  "svx.form",
1475  "NavigatorTree::ShowSelectionProperties : selection meta data invalid !");
1476 
1477 
1478  InterfaceBag aSelection;
1479  bool bSetSelectionAsMarkList = false;
1480 
1481  if (m_bRootSelected)
1482  ; // no properties for the root, neither for single nor for multi selection
1483  else if ( m_nFormsSelected + m_nControlsSelected == 0 ) // none of the two should be less 0
1484  ; // no selection -> no properties
1485  else if ( m_nFormsSelected * m_nControlsSelected != 0 )
1486  ; // mixed selection -> no properties
1487  else
1488  { // either only forms, or only controls are selected
1489  if (m_arrCurrentSelection.size() == 1)
1490  {
1491  const std::unique_ptr<weld::TreeIter>& rIter = *m_arrCurrentSelection.begin();
1492  if (m_nFormsSelected > 0)
1493  { // exactly one form is selected
1494  FmFormData* pFormData = reinterpret_cast<FmFormData*>(m_xTreeView->get_id(*rIter).toInt64());
1495  aSelection.insert( Reference< XInterface >( pFormData->GetFormIface(), UNO_QUERY ) );
1496  }
1497  else
1498  { // exactly one control is selected (whatever hidden or normal)
1499  FmEntryData* pEntryData = reinterpret_cast<FmEntryData*>(m_xTreeView->get_id(*rIter).toInt64());
1500 
1501  aSelection.insert( Reference< XInterface >( pEntryData->GetElement(), UNO_QUERY ) );
1502  }
1503  }
1504  else
1505  { // it's a MultiSelection, so we must build a MultiSet
1506  if (m_nFormsSelected > 0)
1507  { // ... only forms
1508  // first of all collect PropertySet-Interfaces of the forms
1509  SvLBoxEntrySortedArray::const_iterator it = m_arrCurrentSelection.begin();
1510  for ( sal_Int32 i = 0; i < m_nFormsSelected; ++i )
1511  {
1512  const std::unique_ptr<weld::TreeIter>& rIter = *it;
1513  FmFormData* pFormData = reinterpret_cast<FmFormData*>(m_xTreeView->get_id(*rIter).toInt64());
1514  aSelection.insert( pFormData->GetPropertySet().get() );
1515  ++it;
1516  }
1517  }
1518  else
1519  { // ... only controls
1521  { // a MultiSet for properties of hidden controls
1522  SvLBoxEntrySortedArray::const_iterator it = m_arrCurrentSelection.begin();
1523  for ( sal_Int32 i = 0; i < m_nHiddenControls; ++i )
1524  {
1525  const std::unique_ptr<weld::TreeIter>& rIter = *it;
1526  FmEntryData* pEntryData = reinterpret_cast<FmEntryData*>(m_xTreeView->get_id(*rIter).toInt64());
1527  aSelection.insert( pEntryData->GetPropertySet().get() );
1528  ++it;
1529  }
1530  }
1531  else if (m_nHiddenControls == 0)
1532  { // only normal controls
1533  bSetSelectionAsMarkList = true;
1534  }
1535  }
1536  }
1537 
1538  }
1539 
1540  // and now my form and my SelObject
1541  if ( bSetSelectionAsMarkList )
1542  pFormShell->GetImpl()->setCurrentSelectionFromMark_Lock(pFormShell->GetFormView()->GetMarkedObjectList());
1543  else
1544  pFormShell->GetImpl()->setCurrentSelection_Lock(aSelection);
1545 
1546  if (pFormShell->GetImpl()->IsPropBrwOpen_Lock() || bForce)
1547  {
1548  // and now deliver all to the PropertyBrowser
1549  pFormShell->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SfxCallMode::ASYNCHRON );
1550  }
1551  }
1552 
1553 
1555  {
1556  // of course, i can't delete root
1557  bool bRootSelected = m_xTreeView->is_selected(*m_xRootEntry);
1558  auto nSelectedEntries = m_xTreeView->count_selected_rows();
1559  if (bRootSelected && (nSelectedEntries > 1)) // root and other elements ?
1560  m_xTreeView->unselect(*m_xRootEntry); // yes -> remove root from selection
1561 
1562  if ((nSelectedEntries == 0) || bRootSelected) // still root ?
1563  return; // -> only selected element -> leave
1564 
1565  DBG_ASSERT(!m_bPrevSelectionMixed, "NavigatorTree::DeleteSelection() : delete permitted if mark and selection are inconsistent");
1566 
1567  // i need the FormModel later
1568  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1569  if (!pFormShell)
1570  return;
1571  FmFormModel* pFormModel = pFormShell->GetFormModel();
1572  if (!pFormModel)
1573  return;
1574 
1575  // now I have to safeguard the DeleteList: if you delete a form and a dependent element
1576  // - in this order - than the SvLBoxEntryPtr of the dependent element is already invalid,
1577  // when it should be deleted... you have to prohibit this GPF, that of course would happen,
1578  // so I take the 'normalized' list
1580 
1581  // see below for why we need this mapping from models to shapes
1582  FmFormView* pFormView = pFormShell->GetFormView();
1583  SdrPageView* pPageView = pFormView ? pFormView->GetSdrPageView() : nullptr;
1584  SdrPage* pPage = pPageView ? pPageView->GetPage() : nullptr;
1585  DBG_ASSERT( pPage, "NavigatorTree::DeleteSelection: invalid form page!" );
1586 
1587  MapModelToShape aModelShapes;
1588  if ( pPage )
1589  collectShapeModelMapping( pPage, aModelShapes );
1590 
1591  // problem: we have to use ExplorerModel::Remove, since only this one properly deletes Form objects.
1592  // But, the controls themself must be deleted via DeleteMarked (else, the Writer has some problems
1593  // somewhere). In case I'd first delete the structure, then the controls, the UNDO would not work
1594  // (since UNDO then would mean to first restore the controls, then the structure, means their parent
1595  // form). The other way round, the EntryDatas would be invalid, if I'd first delete the controls and
1596  // then go on to the structure. This means I have to delete the forms *after* the normal controls, so
1597  // that during UNDO, they're restored in the proper order.
1598  pFormShell->GetImpl()->EnableTrackProperties_Lock(false);
1599  for (SvLBoxEntrySortedArray::reverse_iterator it = m_arrCurrentSelection.rbegin();
1600  it != m_arrCurrentSelection.rend(); )
1601  {
1602  const std::unique_ptr<weld::TreeIter>& rIter = *it;
1603  FmEntryData* pCurrent = reinterpret_cast<FmEntryData*>(m_xTreeView->get_id(*rIter).toInt64());
1604 
1605  // a form ?
1606  bool bIsForm = dynamic_cast<const FmFormData*>( pCurrent) != nullptr;
1607 
1608  // because deletion is done by the view, and i build on its MarkList,
1609  // but normally only direct controls, no indirect ones, are marked in a marked form,
1610  // I have to do it later
1611  if (bIsForm)
1612  MarkViewObj(static_cast<FmFormData*>(pCurrent), true/*deep*/);
1613 
1614  // a hidden control ?
1615  bool bIsHidden = IsHiddenControl(pCurrent);
1616 
1617  // keep forms and hidden controls, the rest not
1618  if (!bIsForm && !bIsHidden)
1619  {
1620  // well, no form and no hidden control -> we can remove it from m_arrCurrentSelection, as it will
1621  // be deleted automatically. This is because for every model (except forms and hidden control models)
1622  // there exist a shape, which is marked _if_and_only_if_ the model is selected in our tree.
1623  if ( aModelShapes.find( pCurrent->GetElement() ) != aModelShapes.end() )
1624  {
1625  // if there's a shape for the current entry, then either it is marked or it is in a
1626  // hidden layer (#i28502#), or something like this.
1627  // In the first case, it will be deleted below, in the second case, we currently don't
1628  // delete it, as there's no real (working!) API for this, neither in UNO nor in non-UNO.
1629  m_arrCurrentSelection.erase( --(it.base()) );
1630  }
1631  else
1632  ++it;
1633  // In case there is no shape for the current entry, we keep the entry in m_arrCurrentSelection,
1634  // since then we can definitely remove it.
1635  }
1636  else
1637  ++it;
1638  }
1639  pFormShell->GetImpl()->EnableTrackProperties_Lock(true);
1640 
1641  // let the view delete the marked controls
1642  pFormShell->GetFormView()->DeleteMarked();
1643 
1644  // start UNDO at this point. Unfortunately, this results in 2 UNDO actions, since DeleteMarked is
1645  // creating an own one. However, if we'd move it before DeleteMarked, Writer does not really like
1646  // this ... :(
1647  // #i31038#
1648  {
1649 
1650  // initialize UNDO
1651  OUString aUndoStr;
1652  if ( m_arrCurrentSelection.size() == 1 )
1653  {
1654  aUndoStr = SvxResId(RID_STR_UNDO_CONTAINER_REMOVE);
1655  if (m_nFormsSelected)
1656  aUndoStr = aUndoStr.replaceFirst( "#", SvxResId( RID_STR_FORM ) );
1657  else
1658  // it must be a control (else the root would be selected, but it cannot be deleted)
1659  aUndoStr = aUndoStr.replaceFirst( "#", SvxResId( RID_STR_CONTROL ) );
1660  }
1661  else
1662  {
1663  aUndoStr = SvxResId(RID_STR_UNDO_CONTAINER_REMOVE_MULTIPLE);
1664  aUndoStr = aUndoStr.replaceFirst( "#", OUString::number( m_arrCurrentSelection.size() ) );
1665  }
1666  pFormModel->BegUndo(aUndoStr);
1667  }
1668 
1669  // remove remaining structure
1670  for (const auto& rpSelection : m_arrCurrentSelection)
1671  {
1672  FmEntryData* pCurrent = reinterpret_cast<FmEntryData*>(m_xTreeView->get_id(*rpSelection).toInt64());
1673 
1674  // if the entry still has children, we skipped deletion of one of those children.
1675  // This may for instance be because the shape is in a hidden layer, where we're unable
1676  // to remove it
1677  if ( pCurrent->GetChildList()->size() )
1678  continue;
1679 
1680  // one remaining subtile problem, before deleting it : if it's a form and the shell
1681  // knows it as CurrentObject, I have to tell it something else
1682  if (auto pFormData = dynamic_cast<FmFormData*>( pCurrent))
1683  {
1684  Reference< XForm > xCurrentForm( pFormData->GetFormIface() );
1685  if (pFormShell->GetImpl()->getCurrentForm_Lock() == xCurrentForm) // shell knows form to be deleted ?
1686  pFormShell->GetImpl()->forgetCurrentForm_Lock(); // -> take away ...
1687  }
1688  GetNavModel()->Remove(pCurrent, true);
1689  }
1690  pFormModel->EndUndo();
1691  }
1692 
1693 
1695  {
1696  DBG_ASSERT(sdiHow != SDI_DIRTY, "NavigatorTree::CollectSelectionData : ever thought about your parameter ? DIRTY ?");
1697  if (sdiHow == m_sdiState)
1698  return;
1699 
1700  m_arrCurrentSelection.clear();
1702  m_bRootSelected = false;
1703 
1704  m_xTreeView->selected_foreach([this, sdiHow](weld::TreeIter& rSelectionLoop){
1705  // count different elements
1706  if (m_xTreeView->iter_compare(rSelectionLoop, *m_xRootEntry) == 0)
1707  m_bRootSelected = true;
1708  else
1709  {
1710  if (IsFormEntry(rSelectionLoop))
1711  ++m_nFormsSelected;
1712  else
1713  {
1715  if (IsHiddenControl(reinterpret_cast<FmEntryData*>(m_xTreeView->get_id(rSelectionLoop).toInt64())))
1717  }
1718  }
1719 
1720  if (sdiHow == SDI_NORMALIZED)
1721  {
1722  // don't take something with a selected ancestor
1723  if (m_xTreeView->iter_compare(rSelectionLoop, *m_xRootEntry) == 0)
1724  m_arrCurrentSelection.emplace(m_xTreeView->make_iterator(&rSelectionLoop));
1725  else
1726  {
1727  std::unique_ptr<weld::TreeIter> xParentLoop(m_xTreeView->make_iterator(&rSelectionLoop));
1728  bool bParentLoop = m_xTreeView->iter_parent(*xParentLoop);
1729  while (bParentLoop)
1730  {
1731  // actually i would have to test, if parent is part of m_arr_CurrentSelection ...
1732  // but if it's selected, then it's in m_arrCurrentSelection
1733  // or one of its ancestors, which was selected earlier.
1734  // In both cases IsSelected is enough
1735  if (m_xTreeView->is_selected(*xParentLoop))
1736  break;
1737  else
1738  {
1739  if (m_xTreeView->iter_compare(*xParentLoop, *m_xRootEntry) == 0)
1740  {
1741  // until root (exclusive), there was no selected parent -> entry belongs to normalized list
1742  m_arrCurrentSelection.emplace(m_xTreeView->make_iterator(&rSelectionLoop));
1743  break;
1744  }
1745  else
1746  bParentLoop = m_xTreeView->iter_parent(*xParentLoop);
1747  }
1748  }
1749  }
1750  }
1751  else if (sdiHow == SDI_NORMALIZED_FORMARK)
1752  {
1753  std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rSelectionLoop));
1754  bool bParent = m_xTreeView->iter_parent(*xParent);
1755  if (!bParent || !m_xTreeView->is_selected(*xParent) || IsFormEntry(rSelectionLoop))
1756  m_arrCurrentSelection.emplace(m_xTreeView->make_iterator(&rSelectionLoop));
1757  }
1758  else
1759  m_arrCurrentSelection.emplace(m_xTreeView->make_iterator(&rSelectionLoop));
1760 
1761  return false;
1762  });
1763 
1764  m_sdiState = sdiHow;
1765  }
1766 
1768  {
1770  if (arredToSelect.empty())
1771  {
1772  m_xTreeView->unselect_all();
1773  }
1774  else
1775  {
1776  // compare current selection with requested SelectList
1777  m_xTreeView->selected_foreach([this, &arredToSelect](weld::TreeIter& rSelection) {
1778  FmEntryData* pCurrent = reinterpret_cast<FmEntryData*>(m_xTreeView->get_id(rSelection).toInt64());
1779  if (pCurrent != nullptr)
1780  {
1781  FmEntryDataArray::iterator it = arredToSelect.find(pCurrent);
1782  if ( it != arredToSelect.end() )
1783  { // entry already selected, but also in SelectList
1784  // remove it from there
1785  arredToSelect.erase(it);
1786  } else
1787  { // entry selected, but not in SelectList -> remove selection
1788  m_xTreeView->unselect(rSelection);
1789  // make it visible (maybe it's the only modification i do in this handler
1790  // so you should see it
1791  m_xTreeView->scroll_to_row(rSelection);
1792  }
1793  }
1794  else
1795  m_xTreeView->unselect(rSelection);
1796 
1797  return false;
1798  });
1799 
1800  // now SelectList contains only entries, which have to be selected
1801  // two possibilities : 1) run through SelectList, get SvTreeListEntry for every entry and select it (is more intuitive)
1802  // 2) run through my SvLBoxEntries and select those, i can find in the SelectList
1803  // 1) needs =(k*n) (k=length of SelectList, n=number of entries),
1804  // plus the fact, that FindEntry uses extensive IsEqualWithoutChilden instead of comparing pointer to UserData
1805  // 2) needs =(n*log k), duplicates some code from FindEntry
1806  // This may be a frequently used code ( at every change in mark of the view!),
1807  // so i use latter one
1808  m_xTreeView->all_foreach([this, &arredToSelect](weld::TreeIter& rLoop){
1809  FmEntryData* pCurEntryData = reinterpret_cast<FmEntryData*>(m_xTreeView->get_id(rLoop).toInt64());
1810  FmEntryDataArray::iterator it = arredToSelect.find(pCurEntryData);
1811  if (it != arredToSelect.end())
1812  {
1813  m_xTreeView->select(rLoop);
1814  m_xTreeView->scroll_to_row(rLoop);
1815  }
1816 
1817  return false;
1818  });
1819  }
1821  }
1822 
1823 
1825  {
1826  // shell and view
1827  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1828  if(!pFormShell) return;
1829 
1830  FmFormView* pFormView = pFormShell->GetFormView();
1831  if (!pFormView) return;
1832 
1834  }
1835 
1836 
1838  {
1839  // i'll need this shell
1840  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1841  if (!pFormShell) return;
1842 
1844 
1845  // the view shouldn't notify now if MarkList changed
1846  pFormShell->GetImpl()->EnableTrackProperties_Lock(false);
1847 
1848  UnmarkAllViewObj();
1849 
1850  for (auto& rSelectionLoop : m_arrCurrentSelection)
1851  {
1852  // When form selection, mark all controls of form
1853  if (IsFormEntry(*rSelectionLoop) && m_xTreeView->iter_compare(*rSelectionLoop, *m_xRootEntry) != 0)
1854  MarkViewObj(reinterpret_cast<FmFormData*>(m_xTreeView->get_id(*rSelectionLoop).toInt64()), false/*deep*/);
1855 
1856  // When control selection, mark Control-SdrObjects
1857  else if (IsFormComponentEntry(*rSelectionLoop))
1858  {
1859  FmControlData* pControlData = reinterpret_cast<FmControlData*>(m_xTreeView->get_id(*rSelectionLoop).toInt64());
1860  if (pControlData)
1861  {
1862 
1863  // When HiddenControl no object can be selected
1864  Reference< XFormComponent > xFormComponent( pControlData->GetFormComponent());
1865  if (!xFormComponent.is())
1866  continue;
1867  Reference< XPropertySet > xSet(xFormComponent, UNO_QUERY);
1868  if (!xSet.is())
1869  continue;
1870 
1871  sal_uInt16 nClassId = ::comphelper::getINT16(xSet->getPropertyValue(FM_PROP_CLASSID));
1872  if (nClassId != FormComponentType::HIDDENCONTROL)
1873  MarkViewObj(pControlData);
1874  }
1875  }
1876  }
1877 
1878  // if PropertyBrowser is open, I have to adopt it according to my selection
1879  // (Not as MarkList of view : if a form is selected, all belonging controls are selected in the view
1880  // but of course i want to see the form-properties
1882 
1883  // reset flag at view
1884  pFormShell->GetImpl()->EnableTrackProperties_Lock(true);
1885 
1886  // if exactly one form is selected now, shell should notice it as CurrentForm
1887  // (if selection handling isn't locked, view cares about it in MarkListHasChanged
1888  // but mechanism doesn't work, if form is empty for example
1889  if ((m_arrCurrentSelection.size() != 1) || (m_nFormsSelected != 1))
1890  return;
1891 
1892  std::unique_ptr<weld::TreeIter> xSelected(m_xTreeView->make_iterator());
1893  if (!m_xTreeView->get_selected(xSelected.get()))
1894  xSelected.reset();
1895  FmFormData* pSingleSelectionData = xSelected ? dynamic_cast<FmFormData*>(reinterpret_cast<FmEntryData*>(m_xTreeView->get_id(*xSelected).toInt64()))
1896  : nullptr;
1897  DBG_ASSERT( pSingleSelectionData, "NavigatorTree::SynchronizeMarkList: invalid selected form!" );
1898  if ( pSingleSelectionData )
1899  {
1900  InterfaceBag aSelection;
1901  aSelection.insert( Reference< XInterface >( pSingleSelectionData->GetFormIface(), UNO_QUERY ) );
1902  pFormShell->GetImpl()->setCurrentSelection_Lock(aSelection);
1903  }
1904  }
1905 
1907  {
1908  if (pEntryData == nullptr) return false;
1909 
1910  Reference< XPropertySet > xProperties( pEntryData->GetPropertySet() );
1911  if (::comphelper::hasProperty(FM_PROP_CLASSID, xProperties))
1912  {
1913  Any aClassID = xProperties->getPropertyValue( FM_PROP_CLASSID );
1914  return (::comphelper::getINT16(aClassID) == FormComponentType::HIDDENCONTROL);
1915  }
1916  return false;
1917  }
1918 
1920  {
1921  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1922  if( !pFormShell )
1923  return;
1924  FmFormView* pFormView = pFormShell->GetFormView();
1925  pFormView->UnMarkAll();
1926  }
1927 
1928  void NavigatorTree::MarkViewObj(FmFormData const * pFormData, bool bDeep )
1929  {
1930  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1931  if( !pFormShell )
1932  return;
1933 
1934  // first collect all sdrobjects
1935  ::std::set< Reference< XFormComponent > > aObjects;
1936  CollectObjects(pFormData,bDeep,aObjects);
1937 
1938 
1939  // find and select appropriate SdrObj in page
1940  FmFormView* pFormView = pFormShell->GetFormView();
1941  SdrPageView* pPageView = pFormView->GetSdrPageView();
1942  SdrPage* pPage = pPageView->GetPage();
1943  //FmFormPage* pFormPage = dynamic_cast< FmFormPage* >( pPage );
1944 
1945  SdrObjListIter aIter( pPage );
1946  while ( aIter.IsMore() )
1947  {
1948  SdrObject* pSdrObject = aIter.Next();
1949  FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject );
1950  if ( !pFormObject )
1951  continue;
1952 
1953  Reference< XFormComponent > xControlModel( pFormObject->GetUnoControlModel(),UNO_QUERY );
1954  if ( xControlModel.is() && aObjects.find(xControlModel) != aObjects.end() && !pFormView->IsObjMarked( pSdrObject ) )
1955  {
1956  // unfortunately, the writer doesn't like marking an already-marked object, again, so reset the mark first
1957  pFormView->MarkObj( pSdrObject, pPageView );
1958  }
1959  } // while ( aIter.IsMore() )
1960  // make the mark visible
1961  ::tools::Rectangle aMarkRect( pFormView->GetAllMarkedRect());
1962  for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
1963  {
1964  SdrPaintWindow* pPaintWindow = pFormView->GetPaintWindow( i );
1965  OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
1966  if ( ( OUTDEV_WINDOW == rOutDev.GetOutDevType() ) && !aMarkRect.IsEmpty() )
1967  {
1968  pFormView->MakeVisible( aMarkRect, static_cast<vcl::Window&>(rOutDev) );
1969  }
1970  } // for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
1971  }
1972 
1973  void NavigatorTree::CollectObjects(FmFormData const * pFormData, bool bDeep, ::std::set< Reference< XFormComponent > >& _rObjects)
1974  {
1975  FmEntryDataList* pChildList = pFormData->GetChildList();
1976  for( size_t i = 0; i < pChildList->size(); ++i )
1977  {
1978  FmEntryData* pEntryData = pChildList->at( i );
1979  if( auto pControlData = dynamic_cast<FmControlData*>( pEntryData) )
1980  {
1981  _rObjects.insert(pControlData->GetFormComponent());
1982  } // if( dynamic_cast<const FmControlData*>( pEntryData) != nullptr )
1983  else if (bDeep)
1984  if (auto pEntryFormData = dynamic_cast<FmFormData*>( pEntryData))
1985  CollectObjects(pEntryFormData, bDeep, _rObjects);
1986  } // for( sal_uInt32 i=0; i<pChildList->Count(); i++ )
1987  }
1988 
1989  void NavigatorTree::MarkViewObj( FmControlData const * pControlData)
1990  {
1991  if( !pControlData )
1992  return;
1993  FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1994  if( !pFormShell )
1995  return;
1996 
1997 
1998  // find and select appropriate SdrObj
1999  FmFormView* pFormView = pFormShell->GetFormView();
2000  Reference< XFormComponent > xFormComponent( pControlData->GetFormComponent());
2001  SdrPageView* pPageView = pFormView->GetSdrPageView();
2002  SdrPage* pPage = pPageView->GetPage();
2003 
2004  bool bPaint = false;
2005  SdrObjListIter aIter( pPage );
2006  while ( aIter.IsMore() )
2007  {
2008  SdrObject* pSdrObject = aIter.Next();
2009  FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject );
2010  if ( !pFormObject )
2011  continue;
2012 
2013  Reference< XInterface > xControlModel( pFormObject->GetUnoControlModel() );
2014  if ( xControlModel != xFormComponent )
2015  continue;
2016 
2017  // mark the object
2018  if ( !pFormView->IsObjMarked( pSdrObject ) )
2019  // unfortunately, the writer doesn't like marking an already-marked object, again, so reset the mark first
2020  pFormView->MarkObj( pSdrObject, pPageView );
2021 
2022  bPaint = true;
2023 
2024  } // while ( aIter.IsMore() )
2025  if ( !bPaint )
2026  return;
2027 
2028  // make the mark visible
2029  ::tools::Rectangle aMarkRect( pFormView->GetAllMarkedRect());
2030  for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
2031  {
2032  SdrPaintWindow* pPaintWindow = pFormView->GetPaintWindow( i );
2033  OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
2034  if ( OUTDEV_WINDOW == rOutDev.GetOutDevType() )
2035  {
2036  pFormView->MakeVisible( aMarkRect, static_cast<vcl::Window&>(rOutDev) );
2037  }
2038  } // for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
2039  }
2040 
2041 
2042 }
2043 
2044 
2045 /* 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
void removeNoDelete(FmEntryData *pItem)
Definition: fmexpl.cxx:113
bool IsFormEntry(const weld::TreeIter &rEntry)
void SetAutoControlFocus(bool _bAutoControlFocus)
Definition: fmmodel.cxx:168
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
static weld::Builder * CreateBuilder(weld::Widget *pParent, const OUString &rUIFile, bool bMobile=false)
IMPL_LINK_NOARG(XFormsPage, ItemSelectHdl, weld::TreeView &, void)
Definition: datanavi.cxx:241
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:127
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
#define DND_ACTION_COPYMOVE
sal_uInt16 GetCode() const
css::uno::Reference< css::datatransfer::clipboard::XClipboard > VCL_DLLPUBLIC GetSystemClipboard()
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:143
void BegUndo()
Definition: svdmodel.cxx:412
FmFormModel * GetFormModel() const
Definition: fmshell.hxx:116
IMPL_LINK(XFormsPage, PopupMenuHdl, const CommandEvent &, rCEvt, bool)
Definition: datanavi.cxx:134
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
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:25
void UnlockSelectionHandling()
Definition: fmexpl.hxx:444
OUTDEV_WINDOW
const DataFlavorExVector & GetDataFlavorExVector() const
void AddUndo(std::unique_ptr< SdrUndoAction > pUndo)
Definition: svdmodel.cxx:546
int nCount
#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:222
static void DisposeElement(const css::uno::Reference< css::uno::XInterface > &xElem)
Definition: fmundo.cxx:1066
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:577
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:999
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 IsMixedSelection() const
Definition: fmexpl.hxx:215
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:260
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:483
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:171
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:1367
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:303
FmEntryDataArray & GetItems()
Definition: fmexpl.hxx:218
bool hasProperty(const OUString &_rName, const Reference< XPropertySet > &_rxSet)
OUString sId
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:1703
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:84
void BroadcastMarkedObjects(const SdrMarkList &mlMarked)
ListBoxEntrySet m_aCutEntries
Definition: fmexpl.hxx:386
std::pair< const_iterator, bool > insert(Value &&x)
sal_Int8 mnAction
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:71
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:1970
const DataFlavorExVector & GetDataFlavorExVector() const
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)