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