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