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