xref: /core/sw/source/uibase/utlui/navipi.cxx (revision 15f7be5f73a3141d875824a1167e3b452fc1f898)
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 <comphelper/string.hxx>
21 #include <svl/urlbmk.hxx>
22 #include <svl/stritem.hxx>
23 #include <vcl/graphicfilter.hxx>
24 #include <sot/formats.hxx>
25 #include <sot/filelist.hxx>
26 #include <sfx2/event.hxx>
27 #include <sfx2/dispatch.hxx>
28 #include <sfx2/viewfrm.hxx>
29 #include <tools/urlobj.hxx>
30 #include <osl/diagnose.h>
31 #include <swtypes.hxx>
32 #include <swmodule.hxx>
33 #include <view.hxx>
34 #include <navicfg.hxx>
35 #include <wrtsh.hxx>
36 #include <docsh.hxx>
37 #include <navipi.hxx>
38 #include <edtwin.hxx>
39 #include <sfx2/app.hxx>
40 #include <cmdid.h>
41 #include <helpids.h>
42 
43 #include <strings.hrc>
44 #include <bitmaps.hlst>
45 
46 #include <memory>
47 
48 #include <o3tl/enumrange.hxx>
49 
50 #include <workctrl.hxx>
51 
52 #include <comphelper/lok.hxx>
53 
54 #include <swcont.hxx>
55 #include <content.hxx>
56 #include <vcl/jsdialog/executor.hxx>
57 
58 using namespace ::com::sun::star::uno;
59 using namespace ::com::sun::star::frame;
60 
61 // Filter the control characters out of the Outline-Entry
CleanEntry(const OUString & rEntry)62 OUString SwNavigationPI::CleanEntry(const OUString& rEntry)
63 {
64     if (rEntry.isEmpty())
65         return rEntry;
66 
67     OUStringBuffer aEntry(rEntry);
68     for (sal_Int32 i = 0; i < rEntry.getLength(); ++i)
69         if(aEntry[i] == 10 || aEntry[i] == 9)
70             aEntry[i] = 0x20;
71 
72     return aEntry.makeStringAndClear();
73 }
74 
75 // Execution of the drag operation with and without the children.
76 
MoveOutline(SwOutlineNodes::size_type nSource,SwOutlineNodes::size_type nTarget)77 void SwNavigationPI::MoveOutline(SwOutlineNodes::size_type nSource, SwOutlineNodes::size_type nTarget)
78 {
79     SwView *pView = GetCreateView();
80     if (!pView)
81         return;
82     SwWrtShell &rSh = pView->GetWrtShell();
83     if (nTarget == SwOutlineNodes::npos)
84         nTarget = 0;
85     else if (nTarget < nSource)
86         nTarget++;
87     if ( !rSh.IsOutlineMovable( nSource ))
88         return;
89 
90     SwOutlineNodes::difference_type nMove = nTarget-nSource; //( nDir<0 ) ? 1 : 0 ;
91     rSh.GotoOutline(nSource);
92     rSh.MakeOutlineSel(nSource, nSource, true);
93     // While moving, the selected children does not counting.
94     const SwOutlineNodes::size_type nLastOutlinePos = rSh.GetOutlinePos(MAXLEVEL);
95     if(nMove > 1 && nLastOutlinePos < nTarget)
96     {
97         if(!rSh.IsCursorPtAtEnd())
98             rSh.SwapPam();
99         nMove -= nLastOutlinePos - nSource;
100     }
101     if( nMove < 1 || nLastOutlinePos < nTarget )
102         rSh.MoveOutlinePara( nMove );
103     rSh.ClearMark();
104     rSh.GotoOutline( nSource + nMove);
105 
106 }
107 
108 // After goto cancel the status frame selection
lcl_UnSelectFrame(SwWrtShell * pSh)109 static void lcl_UnSelectFrame(SwWrtShell *pSh)
110 {
111     if (pSh->IsFrameSelected())
112     {
113         pSh->UnSelectFrame();
114         pSh->LeaveSelFrameMode();
115     }
116 }
117 
118 // Select the document view
IMPL_LINK(SwNavigationPI,DocListBoxSelectHdl,weld::ComboBox &,rBox,void)119 IMPL_LINK(SwNavigationPI, DocListBoxSelectHdl, weld::ComboBox&, rBox, void)
120 {
121     int nEntryIdx = rBox.get_active();
122     SwView *pView ;
123     pView = SwModule::GetFirstView();
124     while (nEntryIdx-- && pView)
125     {
126         pView = SwModule::GetNextView(pView);
127     }
128     if(!pView)
129     {
130         nEntryIdx == 0 ?
131             m_xContentTree->ShowHiddenShell():
132                 m_xContentTree->ShowActualView();
133 
134     }
135     else
136     {
137         m_xContentTree->SetConstantShell(pView->GetWrtShellPtr());
138     }
139 }
140 
UpdateNavigateBy()141 void SwNavigationPI::UpdateNavigateBy()
142 {
143     if (!m_pNavigateByComboBox)
144         return;
145     SfxUInt32Item aParam(FN_NAV_ELEMENT, m_pNavigateByComboBox->get_active_id().toUInt32());
146     const SfxPoolItem* aArgs[2];
147     aArgs[0] = &aParam;
148     aArgs[1] = nullptr;
149     SfxDispatcher* pDispatcher = GetCreateView()->GetFrame()->GetDispatcher();
150     pDispatcher->Execute(FN_NAV_ELEMENT, SfxCallMode::SYNCHRON, aArgs);
151 }
152 
IMPL_LINK(SwNavigationPI,NavigateByComboBoxSelectHdl,weld::ComboBox &,rComboBox,void)153 IMPL_LINK(SwNavigationPI, NavigateByComboBoxSelectHdl, weld::ComboBox&, rComboBox, void)
154 {
155     m_xContentTree->SelectContentType(rComboBox.get_active_text());
156     UpdateNavigateBy();
157 }
158 
SetContent3And4ToolBoxVisibility()159 void SwNavigationPI::SetContent3And4ToolBoxVisibility()
160 {
161     if (IsGlobalMode())
162         return;
163     bool bIsMoveTypePage = SwView::GetMoveType() == NID_PGE;
164     m_xContent3ToolBox->set_visible(!bIsMoveTypePage);
165     m_xContent4ToolBox->set_visible(bIsMoveTypePage);
166 }
167 
168 // Filling of the list box for outline view or documents
169 // The PI will be set to full size
FillBox()170 void SwNavigationPI::FillBox()
171 {
172     if(m_pContentWrtShell)
173     {
174         m_xContentTree->SetHiddenShell( m_pContentWrtShell );
175         m_xContentTree->Display(  false );
176     }
177     else
178     {
179         SwView *pView = GetCreateView();
180         if(!pView)
181         {
182             m_xContentTree->SetActiveShell(nullptr);
183         }
184         else if( pView != m_pActContView)
185         {
186             SwWrtShell* pWrtShell = pView->GetWrtShellPtr();
187             m_xContentTree->SetActiveShell(pWrtShell);
188         }
189         else
190             m_xContentTree->Display( true );
191         m_pActContView = pView;
192         if (m_pActContView)
193             m_xContentTree->UpdateTracking();
194     }
195 }
196 
197 // Select handler of the toolboxes
IMPL_LINK(SwNavigationPI,ToolBoxSelectHdl,const OUString &,rCommand,void)198 IMPL_LINK(SwNavigationPI, ToolBoxSelectHdl, const OUString&, rCommand, void)
199 {
200     SwView *pView = GetCreateView();
201     if (!pView)
202         return;
203     SwWrtShell &rSh = pView->GetWrtShell();
204     // Get MouseModifier for Outline-Move
205 
206     int nFuncId = 0;
207     bool bFocusToDoc = false;
208     if (rCommand == "root")
209     {
210         m_xContentTree->ToggleToRoot();
211     }
212     else if (rCommand == "listbox")
213     {
214         if (ParentIsFloatingWindow(m_xNavigatorDlg))
215         {
216             if (IsZoomedIn())
217             {
218                 ZoomOut();
219             }
220             else
221             {
222                 ZoomIn();
223             }
224         }
225         return;
226     }
227     // Functions that will trigger a direct action.
228     else if (rCommand == "footer")
229     {
230         rSh.MoveCursor();
231         const FrameTypeFlags eType = rSh.GetFrameType(nullptr,false);
232         if (eType & FrameTypeFlags::FOOTER)
233         {
234             if (rSh.EndPg())
235                 nFuncId = FN_END_OF_PAGE;
236         }
237         else if (rSh.GotoFooterText())
238             nFuncId = FN_TO_FOOTER;
239         bFocusToDoc = true;
240     }
241     else if (rCommand == "header")
242     {
243         rSh.MoveCursor();
244         const FrameTypeFlags eType = rSh.GetFrameType(nullptr,false);
245         if (eType & FrameTypeFlags::HEADER)
246         {
247             if (rSh.SttPg())
248                 nFuncId = FN_START_OF_PAGE;
249         }
250         else if (rSh.GotoHeaderText())
251             nFuncId = FN_TO_HEADER;
252         bFocusToDoc = true;
253     }
254     else if (rCommand == "anchor")
255     {
256         rSh.MoveCursor();
257         const FrameTypeFlags eFrameType = rSh.GetFrameType(nullptr,false);
258             // Jump from the footnote to the anchor.
259         if (eFrameType & FrameTypeFlags::FOOTNOTE)
260         {
261             if (rSh.GotoFootnoteAnchor())
262                 nFuncId = FN_FOOTNOTE_TO_ANCHOR;
263         }
264             // Otherwise, jump to the first footnote text;
265             // go to the next footnote if this is not possible;
266             // if this is also not possible got to the footnote before.
267         else
268         {
269             if (rSh.GotoFootnoteText())
270                 nFuncId = FN_FOOTNOTE_TO_ANCHOR;
271             else if (rSh.GotoNextFootnoteAnchor())
272                 nFuncId = FN_NEXT_FOOTNOTE;
273             else if (rSh.GotoPrevFootnoteAnchor())
274                 nFuncId = FN_PREV_FOOTNOTE;
275         }
276         bFocusToDoc = true;
277     }
278     else if (rCommand == "reminder")
279     {
280         rSh.GetView().GetViewFrame().GetDispatcher()->Execute(FN_SET_REMINDER, SfxCallMode::ASYNCHRON);
281     }
282     else if (rCommand == "movedown" ||
283              rCommand == "moveup" ||
284              rCommand == "edit")
285     {
286         if (IsGlobalMode())
287             m_xGlobalTree->ExecCommand(rCommand);
288     }
289     else if (rCommand == "contenttoggle" || rCommand == "globaltoggle")
290     {
291         ToggleTree();
292         bool bGlobalMode = IsGlobalMode();
293         m_pConfig->SetGlobalActive(bGlobalMode);
294         m_xGlobalToolBox->set_item_active(u"globaltoggle"_ustr, bGlobalMode);
295     }
296     else if (rCommand == "save")
297     {
298         bool bSave = rSh.IsGlblDocSaveLinks();
299         rSh.SetGlblDocSaveLinks( !bSave );
300         m_xGlobalToolBox->set_item_active(rCommand, !bSave);
301     }
302     else if (rCommand == "headings")
303         m_xContent5ToolBox->set_menu_item_active(u"headings"_ustr, !m_xContent5ToolBox->get_menu_item_active(u"headings"_ustr));
304     else if (rCommand == "update")
305         m_xGlobalToolBox->set_menu_item_active(u"update"_ustr, !m_xGlobalToolBox->get_menu_item_active(u"update"_ustr));
306     else if (rCommand == "insert")
307         m_xGlobalToolBox->set_menu_item_active(u"insert"_ustr, !m_xGlobalToolBox->get_menu_item_active(u"insert"_ustr));
308 
309     if (nFuncId)
310         lcl_UnSelectFrame(&rSh);
311     if (bFocusToDoc)
312         pView->GetEditWin().GrabFocus();
313 }
314 
315 // Click handler of the toolboxes
IMPL_LINK(SwNavigationPI,ToolBoxClickHdl,const OUString &,rCommand,void)316 IMPL_LINK(SwNavigationPI, ToolBoxClickHdl, const OUString&, rCommand, void)
317 {
318     if (!m_xGlobalToolBox->get_menu_item_active(rCommand))
319         return;
320 
321     if (rCommand == "update")
322         m_xGlobalTree->TbxMenuHdl(rCommand, *m_xUpdateMenu);
323     else if (rCommand == "insert")
324         m_xGlobalTree->TbxMenuHdl(rCommand, *m_xInsertMenu);
325 }
326 
IMPL_LINK(SwNavigationPI,GlobalMenuSelectHdl,const OUString &,rIdent,void)327 IMPL_LINK(SwNavigationPI, GlobalMenuSelectHdl, const OUString&, rIdent, void)
328 {
329     m_xGlobalTree->ExecuteContextMenuAction(rIdent);
330 }
331 
IMPL_LINK(SwNavigationPI,ToolBox5DropdownClickHdl,const OUString &,rCommand,void)332 IMPL_LINK(SwNavigationPI, ToolBox5DropdownClickHdl, const OUString&, rCommand, void)
333 {
334     if (!m_xContent5ToolBox->get_menu_item_active(rCommand))
335         return;
336 
337     if (rCommand == "headings")
338         m_xHeadingsMenu->set_active(OUString::number(m_xContentTree->GetOutlineLevel()), true);
339 }
340 
ZoomOut()341 void SwNavigationPI::ZoomOut()
342 {
343     if (!IsZoomedIn())
344         return;
345     SfxNavigator* pNav = m_xNavigatorDlg.get();
346     if (!pNav)
347         return;
348     m_bIsZoomedIn = false;
349     FillBox();
350     if (IsGlobalMode())
351     {
352         m_xGlobalBox->show();
353         m_xGlobalTree->ShowTree();
354     }
355     else
356     {
357         m_xContentBox->show();
358         m_xContentTree->ShowTree();
359         m_xDocListBox->show();
360     }
361 
362     pNav->InvalidateChildSizeCache();
363     Size aOptimalSize(pNav->GetOptimalSize());
364     Size aNewSize(pNav->GetOutputSizePixel());
365     aNewSize.setHeight( m_aExpandedSize.Height() );
366     pNav->SetMinOutputSizePixel(aOptimalSize);
367     pNav->SetOutputSizePixel(aNewSize);
368 
369     m_xContentTree->UpdateContentFunctionsToolbar(); // Enable toolbox
370     m_pConfig->SetSmall(false);
371     m_xContent6ToolBox->set_item_active(u"listbox"_ustr, true);
372 }
373 
ZoomIn()374 void SwNavigationPI::ZoomIn()
375 {
376     if (IsZoomedIn())
377         return;
378     SfxNavigator* pNav = m_xNavigatorDlg.get();
379     if (!pNav)
380         return;
381 
382     m_aExpandedSize = m_xNavigatorDlg->GetSizePixel();
383 
384     m_xContentBox->hide();
385     m_xContentTree->HideTree();
386     m_xGlobalBox->hide();
387     m_xGlobalTree->HideTree();
388     m_xDocListBox->hide();
389     m_bIsZoomedIn = true;
390 
391     pNav->InvalidateChildSizeCache();
392     Size aOptimalSize(pNav->GetOptimalSize());
393     Size aNewSize(pNav->GetOutputSizePixel());
394     aNewSize.setHeight( aOptimalSize.Height() );
395     pNav->SetMinOutputSizePixel(aOptimalSize);
396     pNav->SetOutputSizePixel(aNewSize);
397 
398     m_xContentTree->UpdateContentFunctionsToolbar(); // Enable toolbox
399 
400     m_pConfig->SetSmall(true);
401     m_xContent6ToolBox->set_item_active(u"listbox"_ustr, false);
402 }
403 
Create(weld::Widget * pParent,const css::uno::Reference<css::frame::XFrame> & rxFrame,SfxBindings * pBindings)404 std::unique_ptr<PanelLayout> SwNavigationPI::Create(weld::Widget* pParent,
405     const css::uno::Reference<css::frame::XFrame>& rxFrame,
406     SfxBindings* pBindings)
407 {
408     if( pParent == nullptr )
409         throw css::lang::IllegalArgumentException(u"no parent window given to SwNavigationPI::Create"_ustr, nullptr, 0);
410     if( !rxFrame.is() )
411         throw css::lang::IllegalArgumentException(u"no XFrame given to SwNavigationPI::Create"_ustr, nullptr, 0);
412     if( pBindings == nullptr )
413         throw css::lang::IllegalArgumentException(u"no SfxBindings given to SwNavigationPI::Create"_ustr, nullptr, 0);
414     return std::make_unique<SwNavigationPI>(pParent, rxFrame, pBindings, nullptr);
415 }
416 
SwNavigationPI(weld::Widget * pParent,const css::uno::Reference<css::frame::XFrame> & rxFrame,SfxBindings * _pBindings,SfxNavigator * pNavigatorDlg)417 SwNavigationPI::SwNavigationPI(weld::Widget* pParent,
418     const css::uno::Reference<css::frame::XFrame>& rxFrame,
419     SfxBindings* _pBindings, SfxNavigator* pNavigatorDlg)
420     : PanelLayout(pParent, u"NavigatorPanel"_ustr, u"modules/swriter/ui/navigatorpanel.ui"_ustr)
421     , m_aDocFullName(SID_DOCFULLNAME, *_pBindings, *this)
422     , m_aPageStats(FN_STAT_PAGE, *_pBindings, *this)
423     , m_aNavElement(FN_NAV_ELEMENT, *_pBindings, *this)
424     , m_xFrame(rxFrame)
425     , m_xContent1ToolBox(m_xBuilder->weld_toolbar(u"content1"_ustr))
426     , m_xContent2ToolBox(m_xBuilder->weld_toolbar(u"content2"_ustr))
427     , m_xContent3ToolBox(m_xBuilder->weld_toolbar(u"content3"_ustr))
428     , m_xContent4ToolBox(m_xBuilder->weld_toolbar(u"content4"_ustr))
429     , m_xContent5ToolBox(m_xBuilder->weld_toolbar(u"content5"_ustr))
430     , m_xContent6ToolBox(m_xBuilder->weld_toolbar(u"content6"_ustr))
431     , m_xContent2Dispatch(new ToolbarUnoDispatcher(*m_xContent2ToolBox, *m_xBuilder, rxFrame))
432     , m_xContent3Dispatch(new ToolbarUnoDispatcher(*m_xContent3ToolBox, *m_xBuilder, rxFrame))
433     , m_xHeadingsMenu(m_xBuilder->weld_menu(u"headingsmenu"_ustr))
434     , m_xUpdateMenu(m_xBuilder->weld_menu(u"updatemenu"_ustr))
435     , m_xInsertMenu(m_xBuilder->weld_menu(u"insertmenu"_ustr))
436     , m_xGlobalToolBox(m_xBuilder->weld_toolbar(u"global"_ustr))
437     , m_xGotoPageSpinButton(m_xBuilder->weld_spin_button(u"gotopage"_ustr))
438     , m_xContentBox(m_xBuilder->weld_widget(u"contentbox"_ustr))
439     , m_xContentTree(new SwContentTree(m_xBuilder->weld_tree_view(u"contenttree"_ustr), this))
440     , m_xGlobalBox(m_xBuilder->weld_widget(u"globalbox"_ustr))
441     , m_xGlobalTree(new SwGlobalTree(m_xBuilder->weld_tree_view(u"globaltree"_ustr), this))
442     , m_xDocListBox(m_xBuilder->weld_combo_box(u"documents"_ustr))
443     , m_xNavigatorDlg(pNavigatorDlg)
444     , m_pContentView(nullptr)
445     , m_pContentWrtShell(nullptr)
446     , m_pActContView(nullptr)
447     , m_pCreateView(nullptr)
448     , m_pConfig(SwModule::get()->GetNavigationConfig())
449     , m_rBindings(*_pBindings)
450     , m_bIsZoomedIn(false)
451     , m_bGlobalMode(false)
452 {
453     InitContentFunctionsToolbar();
454     if (comphelper::LibreOfficeKit::isActive())
455     {
456         sal_uInt64 nShellId = reinterpret_cast<sal_uInt64>(SfxViewShell::Current());
457         jsdialog::SendNavigatorForView(nShellId);
458     }
459 
460     m_xContainer->connect_container_focus_changed(LINK(this, SwNavigationPI, SetFocusChildHdl));
461 
462     Reference<XToolbarController> xController =
463             m_xContent2Dispatch->GetControllerForCommand(u".uno:NavElement"_ustr);
464     NavElementToolBoxControl* pToolBoxControl =
465             dynamic_cast<NavElementToolBoxControl*>(xController.get());
466 
467     // In case of LOK, the xController may not a NavElementToolBoxControl
468     if (comphelper::LibreOfficeKit::isActive() && !pToolBoxControl)
469     {
470         m_pNavigateByComboBox = nullptr;
471     }
472     else
473     {
474         assert(pToolBoxControl);
475         m_pNavigateByComboBox = pToolBoxControl->GetComboBox();
476         SetContent3And4ToolBoxVisibility();
477     }
478 
479     // Restore content tree settings before calling UpdateInitShow. UpdateInitShow calls Fillbox,
480     // which calls Display and UpdateTracking. Incorrect outline levels could be displayed and
481     // unexpected content tracking could occur if these content tree settings are not done before.
482     m_xContentTree->SetOutlineLevel(static_cast<sal_uInt8>(m_pConfig->GetOutlineLevel()));
483     m_xContentTree->SetOutlineTracking(static_cast<sal_uInt8>(m_pConfig->GetOutlineTracking()));
484     for (ContentTypeId eCntTypeId : o3tl::enumrange<ContentTypeId>())
485     {
486         if (eCntTypeId != ContentTypeId::OUTLINE)
487             m_xContentTree->SetContentTypeTracking(
488                         eCntTypeId, m_pConfig->IsContentTypeTrack(eCntTypeId));
489     }
490 
491     if (const ContentTypeId nRootType = m_pConfig->GetRootType();
492             nRootType != ContentTypeId::UNKNOWN)
493     {
494         m_xContentTree->SetRootType(nRootType);
495         m_xContent5ToolBox->set_item_active(u"root"_ustr, true);
496         if (nRootType == ContentTypeId::OUTLINE || nRootType == ContentTypeId::DRAWOBJECT)
497             m_xContentTree->set_selection_mode(SelectionMode::Multiple);
498         else
499             m_xContentTree->set_selection_mode(SelectionMode::Single);
500     }
501     else
502         m_xContentTree->set_selection_mode(SelectionMode::Single);
503 
504     UpdateInitShow();
505 
506     GetCreateView();
507 
508     m_xContent1ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
509     m_xContent2ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
510     m_xContent3ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
511     m_xContent4ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
512     m_xContent5ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
513     m_xContent6ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
514     m_xGlobalToolBox->set_help_id(HID_NAVIGATOR_GLOBAL_TOOLBOX);
515     m_xDocListBox->set_help_id(HID_NAVIGATOR_LISTBOX);
516     m_xDocListBox->set_size_request(42, -1); // set a nominal width so it takes width of surroundings
517 
518     bool bFloatingNavigator = ParentIsFloatingWindow(m_xNavigatorDlg);
519 
520     m_xContentTree->ShowTree();
521     m_xContent6ToolBox->set_item_active(u"listbox"_ustr, true);
522     m_xContent6ToolBox->set_item_sensitive(u"listbox"_ustr, bFloatingNavigator);
523 
524 //  TreeListBox for global document
525     m_xGlobalTree->set_selection_mode(SelectionMode::Multiple);
526 
527 //  Handler
528     Link<const OUString&, void> aLk = LINK(this, SwNavigationPI, ToolBoxSelectHdl);
529     m_xContent1ToolBox->connect_clicked(aLk);
530     m_xContent5ToolBox->connect_clicked(aLk);
531     m_xContent6ToolBox->connect_clicked(aLk);
532     m_xGlobalToolBox->connect_clicked(aLk);
533     m_xDocListBox->connect_changed(LINK(this, SwNavigationPI, DocListBoxSelectHdl));
534     m_xContent5ToolBox->set_item_menu(u"headings"_ustr, m_xHeadingsMenu.get());
535     m_xHeadingsMenu->connect_activate(LINK(this, SwNavigationPI, HeadingsMenuSelectHdl));
536     m_xContent5ToolBox->connect_menu_toggled(LINK(this, SwNavigationPI, ToolBox5DropdownClickHdl));
537     m_xGlobalToolBox->set_item_menu(u"update"_ustr, m_xUpdateMenu.get());
538     m_xUpdateMenu->connect_activate(LINK(this, SwNavigationPI, GlobalMenuSelectHdl));
539     m_xGlobalToolBox->set_item_menu(u"insert"_ustr, m_xInsertMenu.get());
540     m_xInsertMenu->connect_activate(LINK(this, SwNavigationPI, GlobalMenuSelectHdl));
541     m_xGlobalToolBox->connect_menu_toggled(LINK(this, SwNavigationPI, ToolBoxClickHdl));
542     m_xGlobalToolBox->set_item_active(u"globaltoggle"_ustr, true);
543     if (m_pNavigateByComboBox)
544         m_pNavigateByComboBox->connect_changed(
545             LINK(this, SwNavigationPI, NavigateByComboBoxSelectHdl));
546     m_xGotoPageSpinButton->connect_value_changed(
547         LINK(this, SwNavigationPI, GotoPageSpinButtonValueChangedHdl));
548 
549     StartListening(*SfxGetpApp());
550 
551     if(IsGlobalDoc())
552     {
553         SwView *pActView = GetCreateView();
554         if (pActView && pActView->GetWrtShellPtr())
555             m_xGlobalToolBox->set_item_active(u"save"_ustr,
556                         pActView->GetWrtShellPtr()->IsGlblDocSaveLinks());
557         if (m_pConfig->IsGlobalActive())
558             ToggleTree();
559         else
560             m_xContent1ToolBox->set_visible(true);
561         if (bFloatingNavigator)
562             m_xGlobalTree->grab_focus();
563     }
564     else if (bFloatingNavigator)
565         m_xContentTree->grab_focus();
566 
567     m_xContentTree->set_accessible_name(SwResId(STR_ACCESS_TL_CONTENT));
568     m_xGlobalTree->set_accessible_name(SwResId(STR_ACCESS_TL_GLOBAL));
569     m_xDocListBox->set_accessible_name(SwResId(STR_ACTIVE_VIEW));
570 
571     m_aExpandedSize = m_xContainer->get_preferred_size();
572 
573     if(comphelper::LibreOfficeKit::isActive())
574     {
575         m_xBuilder->weld_container(u"gridcontent16"_ustr)->hide();
576         m_xDocListBox->hide();
577         m_xGlobalBox->hide();
578         m_xGlobalToolBox->hide();
579         m_xGlobalTree->HideTree();
580 
581         //Open Headings by default
582         SwView *pView = GetCreateView();
583         if (pView && pView->m_nNaviExpandedStatus < 0)
584         {
585             pView->m_nNaviExpandedStatus = 1;
586             m_xContentTree->ExpandAllHeadings();
587         }
588     }
589 }
590 
InitContentFunctionsToolbar()591 void SwNavigationPI::InitContentFunctionsToolbar()
592 {
593     m_xHeadingsContentFunctionsToolbar
594         = m_xBuilder->weld_toolbar("HeadingsContentFunctionButtonsToolbar");
595     m_xDeleteFunctionToolbar = m_xBuilder->weld_toolbar("DeleteFunctionButtonToolbar");
596 
597     const OUString sContentTypes[]
598         = { "Headings",  "Tables",         "Frames",     "Images",     "OLEobjects",
599             "Bookmarks", "Sections",       "Hyperlinks", "References", "Indexes",
600             "Comments",  "Drawingobjects", "Fields",     "Footnotes",  "Endnotes" };
601 
602     for (ContentTypeId eContentTypeId : o3tl::enumrange<ContentTypeId>())
603     {
604         if (eContentTypeId == ContentTypeId::OUTLINE)
605             continue;
606         m_aContentTypeUnoToolbarMap[eContentTypeId] = m_xBuilder->weld_toolbar(
607             sContentTypes[static_cast<int>(eContentTypeId)] + "ContentTypeUnoToolbar");
608         m_aContentTypeToolbarUnoDispatcherMap[eContentTypeId]
609             = std::make_unique<ToolbarUnoDispatcher>(*m_aContentTypeUnoToolbarMap[eContentTypeId],
610                                                      *m_xBuilder, m_xFrame);
611         m_aContentUnoToolbarMap[eContentTypeId] = m_xBuilder->weld_toolbar(
612             sContentTypes[static_cast<int>(eContentTypeId)] + "ContentUnoToolbar");
613         m_aContentToolbarUnoDispatcherMap[eContentTypeId] = std::make_unique<ToolbarUnoDispatcher>(
614             *m_aContentUnoToolbarMap[eContentTypeId], *m_xBuilder, m_xFrame);
615     }
616 
617     Link<const OUString&, void> aLink
618         = LINK(this,SwNavigationPI, ContentFunctionsToolbarSelectHdl);
619     m_xHeadingsContentFunctionsToolbar->connect_clicked(aLink);
620     m_xDeleteFunctionToolbar->connect_clicked(aLink);
621 }
622 
623 namespace
624 {
lcl_ToolbarHasItemWithIdent(const weld::Toolbar & rToolbar,std::u16string_view rIdent)625 bool lcl_ToolbarHasItemWithIdent(const weld::Toolbar& rToolbar, std::u16string_view rIdent)
626 {
627     for (auto i = 0; i < rToolbar.get_n_items(); i++)
628     {
629         if (rToolbar.get_item_ident(i) == rIdent)
630             return true;
631     }
632     return false;
633 }
634 }
635 
UpdateContentFunctionsToolbar()636 void SwNavigationPI::UpdateContentFunctionsToolbar()
637 {
638     m_xHeadingsContentFunctionsToolbar->hide();
639     for (ContentTypeId eContentTypeId : o3tl::enumrange<ContentTypeId>())
640     {
641         if (eContentTypeId == ContentTypeId::OUTLINE)
642             continue;
643         m_aContentTypeUnoToolbarMap[eContentTypeId]->hide();
644         m_aContentUnoToolbarMap[eContentTypeId]->hide();
645     }
646     m_xDeleteFunctionToolbar->hide();
647 
648     weld::TreeView& rTreeView = m_xContentTree->get_widget();
649 
650     if (IsZoomedIn() || !rTreeView.is_visible())
651         return;
652 
653     std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
654     if (!rTreeView.get_selected(xEntry.get()))
655         return;
656 
657     bool bUseDeleteFunctionsToolbar = true;
658     ContentTypeId eContentTypeId = ContentTypeId::UNKNOWN;
659 
660     const bool bContentType
661         = weld::fromId<const SwTypeNumber*>(rTreeView.get_id(*xEntry))->GetTypeId() == 1;
662 
663     if (bContentType)
664     {
665         const SwContentType* pContentType = weld::fromId<SwContentType*>(rTreeView.get_id(*xEntry));
666         eContentTypeId = pContentType->GetType();
667         if (eContentTypeId == ContentTypeId::OUTLINE)
668             return;
669         weld::Toolbar& rContentTypeToolbar = *m_aContentTypeUnoToolbarMap[eContentTypeId];
670         if (rContentTypeToolbar.get_n_items())
671         {
672             if (eContentTypeId == ContentTypeId::POSTIT)
673             {
674                 // prefer .uno:DeleteAllNotes over delete functions toolbar
675                 bUseDeleteFunctionsToolbar
676                     = !lcl_ToolbarHasItemWithIdent(rContentTypeToolbar, u".uno:DeleteAllNotes");
677             }
678             rContentTypeToolbar.show();
679         }
680     }
681     else
682     {
683         const SwContentType* pContentType
684             = weld::fromId<SwContent*>(rTreeView.get_id(*xEntry))->GetParent();
685         eContentTypeId = pContentType->GetType();
686         if (eContentTypeId == ContentTypeId::OUTLINE)
687         {
688             // todo: make buttons sensitive to movability (think position and protection)
689             m_xHeadingsContentFunctionsToolbar->show();
690         }
691         else if (m_xContentTree->IsSelectedEntryCurrentDocCursorPosition(*xEntry))
692         {
693             weld::Toolbar& rContentTypeToolbar = *m_aContentUnoToolbarMap[eContentTypeId];
694             if (rContentTypeToolbar.get_n_items())
695             {
696                 if (eContentTypeId == ContentTypeId::TABLE)
697                 {
698                     // prefer .uno:DeleteTable over delete functions toolbar
699                     bUseDeleteFunctionsToolbar
700                         = !lcl_ToolbarHasItemWithIdent(rContentTypeToolbar, u".uno:DeleteTable");
701                 }
702                 else if (eContentTypeId == ContentTypeId::INDEX)
703                 {
704                     // prefer .uno:RemoveTableOf over delete functions toolbar
705                     bUseDeleteFunctionsToolbar
706                         = !lcl_ToolbarHasItemWithIdent(rContentTypeToolbar, u".uno:RemoveTableOf");
707                 }
708                 rContentTypeToolbar.show();
709             }
710         }
711     }
712 
713     if (bUseDeleteFunctionsToolbar && m_xContentTree->IsDeletable(*xEntry))
714     {
715         OUString sToolTip;
716         switch (eContentTypeId)
717         {
718             case ContentTypeId::OUTLINE:
719                 sToolTip = SwResId(STR_DELETE_OUTLINE);
720                 break;
721             case ContentTypeId::TABLE:
722                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_TABLES : STR_DELETE_TABLE);
723                 break;
724             case ContentTypeId::FRAME:
725                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_FRAMES : STR_DELETE_FRAME);
726                 break;
727             case ContentTypeId::GRAPHIC:
728                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_GRAPHIC : STR_DELETE_GRAPHIC);
729                 break;
730             case ContentTypeId::OLE:
731                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_OLE_OBJECTS : STR_DELETE_OLE_OBJECT);
732                 break;
733             case ContentTypeId::BOOKMARK:
734                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_BOOKMARKS : STR_DELETE_BOOKMARK);
735                 break;
736             case ContentTypeId::REGION:
737                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_REGIONS : STR_DELETE_REGION);
738                 break;
739             case ContentTypeId::URLFIELD:
740                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_URLFIELDS : STR_DELETE_URLFIELD);
741                 break;
742             case ContentTypeId::REFERENCE:
743                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_REFERENCES : STR_DELETE_REFERENCE);
744                 break;
745             case ContentTypeId::INDEX:
746                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_INDEXES : STR_DELETE_INDEX);
747                 break;
748             case ContentTypeId::POSTIT:
749                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_POSTITS : STR_DELETE_POSTIT);
750                 break;
751             case ContentTypeId::DRAWOBJECT:
752                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_DRAWOBJECTS : STR_DELETE_DRAWOBJECT);
753                 break;
754             case ContentTypeId::TEXTFIELD:
755                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_TEXTFIELDS : STR_DELETE_TEXTFIELD);
756                 break;
757             case ContentTypeId::FOOTNOTE:
758                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_FOOTNOTES : STR_DELETE_FOOTNOTE);
759                 break;
760             case ContentTypeId::ENDNOTE:
761                 sToolTip = SwResId(bContentType ? STR_DELETE_ALL_ENDNOTES : STR_DELETE_ENDNOTE);
762                 break;
763             default:
764                 break;
765         }
766         if (!sToolTip.isEmpty())
767         {
768             m_xDeleteFunctionToolbar->set_item_tooltip_text("delete", sToolTip);
769             m_xDeleteFunctionToolbar->show();
770         }
771     }
772 }
773 
IMPL_LINK(SwNavigationPI,ContentFunctionsToolbarSelectHdl,const OUString &,rCommand,void)774 IMPL_LINK(SwNavigationPI, ContentFunctionsToolbarSelectHdl, const OUString&, rCommand, void)
775 {
776     weld::TreeView& rTreeView = m_xContentTree->get_widget();
777 
778     std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
779     if (!rTreeView.get_selected(xEntry.get()))
780         return;
781 
782     const bool bContentEntry
783         = weld::fromId<const SwTypeNumber*>(rTreeView.get_id(*xEntry))->GetTypeId() == 0;
784 
785     if (bContentEntry)
786     {
787         SwContent* pContent = weld::fromId<SwContent*>(rTreeView.get_id(*xEntry));
788         if (pContent)
789             m_xContentTree->GotoContent(pContent);
790     }
791 
792     if (rCommand == "chapterdown" || rCommand == "chapterup" || rCommand == "promote"
793         || rCommand == "demote")
794     {
795         // Get MouseModifier for Outline-Move
796         // Standard: sublevels are taken
797         // do not take sublevels with Ctrl
798         bool bOutlineWithChildren = (KEY_MOD1 != m_xContent6ToolBox->get_modifier_state());
799         m_xContentTree->ExecCommand(rCommand, bOutlineWithChildren);
800     }
801     else if (rCommand == "delete")
802     {
803         if (!bContentEntry)
804         {
805             m_xContentTree->DeleteAllContentOfEntryContentType(*xEntry);
806         }
807         else
808         {
809             m_xContentTree->EditEntry(*xEntry, EditEntryMode::DELETE);
810         }
811     }
812 }
813 
GetFrameWeld() const814 weld::Window* SwNavigationPI::GetFrameWeld() const
815 {
816     if (m_xNavigatorDlg)
817         return m_xNavigatorDlg->GetFrameWeld();
818     return PanelLayout::GetFrameWeld();
819 }
820 
IMPL_LINK_NOARG(SwNavigationPI,GotoPageSpinButtonValueChangedHdl,weld::SpinButton &,void)821 IMPL_LINK_NOARG(SwNavigationPI, GotoPageSpinButtonValueChangedHdl, weld::SpinButton&, void)
822 {
823     auto nPage = m_xGotoPageSpinButton->get_value();
824     SwView *pView = GetCreateView();
825     SwWrtShell &rSh = pView->GetWrtShell();
826     auto nPageCount = rSh.GetPageCount();
827     if (nPage > nPageCount)
828     {
829         nPage = nPageCount;
830         m_xGotoPageSpinButton->set_text(OUString::number(nPage));
831     }
832     rSh.LockView(true);
833     rSh.GotoPage(nPage, false);
834     // adjust the visible area so that the top of the page is at the top of the view
835     const Point aPt(pView->GetVisArea().Left(), rSh.GetPagePos(nPage).Y());
836     pView->SetVisArea(aPt);
837     rSh.LockView(false);
838 }
839 
~SwNavigationPI()840 SwNavigationPI::~SwNavigationPI()
841 {
842     if (IsGlobalDoc() && !IsGlobalMode())
843     {
844         SwView *pView = GetCreateView();
845         SwWrtShell &rSh = pView->GetWrtShell();
846         if (!rSh.IsAllProtect())
847             pView->GetDocShell()->SetReadOnlyUI(false);
848     }
849 
850     EndListening(*SfxGetpApp());
851 
852     if (m_oObjectShell)
853     {
854         if (m_oObjectShell->Is())
855             (*m_oObjectShell)->DoClose();
856         m_oObjectShell.reset();
857     }
858 
859     m_xDocListBox.reset();
860     m_xGlobalTree.reset();
861     m_xGlobalBox.reset();
862     m_xContentTree.reset();
863     m_xContentBox.reset();
864     m_xGlobalToolBox.reset();
865     m_xGotoPageSpinButton.reset();
866     m_xHeadingsMenu.reset();
867     m_xUpdateMenu.reset();
868     m_xInsertMenu.reset();
869     m_xContent2Dispatch.reset();
870     m_xContent3Dispatch.reset();
871     m_xContent1ToolBox.reset();
872     m_xContent2ToolBox.reset();
873     m_xContent3ToolBox.reset();
874     m_xContent4ToolBox.reset();
875     m_xContent5ToolBox.reset();
876     m_xContent6ToolBox.reset();
877 
878     m_aDocFullName.dispose();
879     m_aPageStats.dispose();
880     m_aNavElement.dispose();
881 }
882 
NotifyItemUpdate(sal_uInt16 nSID,SfxItemState,const SfxPoolItem *)883 void SwNavigationPI::NotifyItemUpdate(sal_uInt16 nSID, SfxItemState /*eState*/,
884                                       const SfxPoolItem* /*pState*/)
885 {
886     switch (nSID)
887     {
888         case SID_DOCFULLNAME:
889         {
890             SwView *pActView = GetCreateView();
891             if(pActView)
892             {
893                 SwWrtShell* pWrtShell = pActView->GetWrtShellPtr();
894                 m_xContentTree->SetActiveShell(pWrtShell);
895                 if (IsGlobalDoc())
896                 {
897                     m_xGlobalToolBox->set_item_active(u"save"_ustr, pWrtShell->IsGlblDocSaveLinks());
898                 }
899             }
900             else
901             {
902                 m_xContentTree->SetActiveShell(nullptr);
903             }
904             UpdateListBox();
905         }
906         break;
907         case FN_NAV_ELEMENT:
908             SetContent3And4ToolBoxVisibility();
909             [[fallthrough]];
910         case FN_STAT_PAGE:
911         {
912             if (SwView::GetMoveType() == NID_PGE)
913             {
914                 SwView *pView = GetCreateView();
915                 if (pView)
916                 {
917                     SwWrtShell& rSh = pView->GetWrtShell();
918                     if (rSh.GetViewOptions()->IsMultipageView())
919                         // maybe set the spin button text to the page that has the cursor?
920                         break;
921                     SwVisiblePageNumbers aVisiblePageNumbers;
922                     rSh.GetFirstLastVisPageNumbers(aVisiblePageNumbers, *pView);
923                     m_xGotoPageSpinButton->set_text(OUString::number(aVisiblePageNumbers.nFirstPhy));
924                 }
925             }
926         }
927     }
928 }
929 
UpdateInitShow()930 void SwNavigationPI::UpdateInitShow()
931 {
932     // if the parent isn't a float, then the navigator is displayed in
933     // the sidebar or is otherwise docked. While the navigator could change
934     // its size, the sidebar can not, and the navigator would just waste
935     // space. Therefore disable this button.
936     bool bParentIsFloatingWindow(ParentIsFloatingWindow(m_xNavigatorDlg));
937     m_xContent6ToolBox->set_item_sensitive(u"listbox"_ustr, bParentIsFloatingWindow);
938     // show content if docked
939     if (!bParentIsFloatingWindow && IsZoomedIn())
940         ZoomOut();
941     if (!IsZoomedIn())
942         FillBox();
943 }
944 
IMPL_LINK_NOARG(SwNavigationPI,SetFocusChildHdl,weld::Container &,void)945 IMPL_LINK_NOARG(SwNavigationPI, SetFocusChildHdl, weld::Container&, void)
946 {
947     // update documents listbox
948     UpdateListBox();
949 }
950 
951 // Notification on modified DocInfo
Notify(SfxBroadcaster & rBrdc,const SfxHint & rHint)952 void SwNavigationPI::Notify( SfxBroadcaster& rBrdc, const SfxHint& rHint )
953 {
954     if(&rBrdc == m_pCreateView)
955     {
956         if (rHint.GetId() == SfxHintId::Dying)
957         {
958             EndListening(*m_pCreateView);
959             m_pCreateView = nullptr;
960             m_xContentTree->SetActiveShell(nullptr);
961         }
962     }
963     else
964     {
965         if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
966         {
967             SfxEventHintId eEventId = static_cast<const SfxEventHint&>(rHint).GetEventId();
968             if (eEventId == SfxEventHintId::OpenDoc)
969             {
970                 SwView *pActView = GetCreateView();
971                 if(pActView)
972                 {
973                     SwWrtShell* pWrtShell = pActView->GetWrtShellPtr();
974                     m_xContentTree->SetActiveShell(pWrtShell);
975                     if (m_xGlobalTree->get_visible())
976                     {
977                         bool bUpdateAll = m_xGlobalTree->Update(false);
978                         // If no update is needed, then update the font colors
979                         // at the entries of broken links.
980                         m_xGlobalTree->Display(!bUpdateAll);
981                     }
982                 }
983             }
984         }
985     }
986 }
987 
IMPL_LINK(SwNavigationPI,HeadingsMenuSelectHdl,const OUString &,rMenuId,void)988 IMPL_LINK( SwNavigationPI, HeadingsMenuSelectHdl, const OUString&, rMenuId, void )
989 {
990     if (!rMenuId.isEmpty())
991         m_xContentTree->SetOutlineLevel(rMenuId.toUInt32());
992 }
993 
UpdateListBox()994 void SwNavigationPI::UpdateListBox()
995 {
996     if (!m_xDocListBox) // disposed
997         return;
998 
999     m_xDocListBox->freeze();
1000     m_xDocListBox->clear();
1001     SwView *pActView = GetCreateView();
1002     bool bDisable = pActView == nullptr;
1003     SwView *pView = SwModule::GetFirstView();
1004     sal_Int32 nCount = 0;
1005     sal_Int32 nAct = 0;
1006     sal_Int32 nConstPos = 0;
1007     const SwView* pConstView = m_xContentTree->IsConstantView() &&
1008                                 m_xContentTree->GetActiveWrtShell() ?
1009                                     &m_xContentTree->GetActiveWrtShell()->GetView():
1010                                         nullptr;
1011     while (pView)
1012     {
1013         SfxObjectShell* pDoc = pView->GetDocShell();
1014         // #i53333# don't show help pages here
1015         if ( !pDoc->IsHelpDocument() )
1016         {
1017             OUString sEntry = pDoc->GetTitle() + " (";
1018             if (pView == pActView)
1019             {
1020                 nAct = nCount;
1021                 sEntry += SwResId(STR_ACTIVE);
1022             }
1023             else
1024                 sEntry += SwResId(STR_INACTIVE);
1025             sEntry += ")";
1026             m_xDocListBox->append_text(sEntry);
1027 
1028             if (pConstView && pView == pConstView)
1029                 nConstPos = nCount;
1030 
1031             nCount++;
1032         }
1033         pView = SwModule::GetNextView(pView);
1034     }
1035     m_xDocListBox->append_text(SwResId(STR_ACTIVE_VIEW)); // "Active Window"
1036     nCount++;
1037 
1038     if (SwWrtShell* pHiddenWrtShell = m_xContentTree->GetHiddenWrtShell())
1039     {
1040         OUString sEntry = pHiddenWrtShell->GetView().GetDocShell()->GetTitle() +
1041                 " (" + SwResId(STR_HIDDEN) + ")";
1042         m_xDocListBox->append_text(sEntry);
1043         bDisable = false;
1044     }
1045 
1046     m_xDocListBox->thaw();
1047 
1048     if(m_xContentTree->IsActiveView())
1049     {
1050         //Either the name of the current Document or "Active Document".
1051         m_xDocListBox->set_active(pActView ? nAct : --nCount);
1052     }
1053     else if(m_xContentTree->IsHiddenView())
1054     {
1055         m_xDocListBox->set_active(nCount);
1056     }
1057     else
1058         m_xDocListBox->set_active(nConstPos);
1059 
1060     m_xDocListBox->set_sensitive(!bDisable);
1061 }
1062 
IMPL_LINK(SwNavigationPI,DoneLink,SfxPoolItem const *,pItem,void)1063 IMPL_LINK(SwNavigationPI, DoneLink, SfxPoolItem const *, pItem, void)
1064 {
1065     const SfxViewFrameItem* pFrameItem = dynamic_cast<SfxViewFrameItem const *>( pItem  );
1066     if( !pFrameItem )
1067         return;
1068 
1069     SfxViewFrame* pFrame =  pFrameItem->GetFrame();
1070     if(pFrame)
1071     {
1072         m_xContentTree->clear();
1073         m_pContentView = dynamic_cast<SwView*>( pFrame->GetViewShell() );
1074         OSL_ENSURE(m_pContentView, "no SwView");
1075         if(m_pContentView)
1076             m_pContentWrtShell = m_pContentView->GetWrtShellPtr();
1077         else
1078             m_pContentWrtShell = nullptr;
1079         m_oObjectShell.emplace( pFrame->GetObjectShell() );
1080         FillBox();
1081     }
1082 }
1083 
CreateDropFileName(const TransferableDataHelper & rData)1084 OUString SwNavigationPI::CreateDropFileName( const TransferableDataHelper& rData )
1085 {
1086     OUString sFileName;
1087     SotClipboardFormatId nFormat;
1088     if( rData.HasFormat( nFormat = SotClipboardFormatId::FILE_LIST ))
1089     {
1090         FileList aFileList;
1091         rData.GetFileList( nFormat, aFileList );
1092         sFileName = aFileList.GetFile( 0 );
1093     }
1094     else if( rData.HasFormat( nFormat = SotClipboardFormatId::STRING ) ||
1095               rData.HasFormat( nFormat = SotClipboardFormatId::SIMPLE_FILE ) ||
1096              rData.HasFormat( nFormat = SotClipboardFormatId::FILENAME ))
1097     {
1098         (void)rData.GetString(nFormat, sFileName);
1099     }
1100     else if( rData.HasFormat( nFormat = SotClipboardFormatId::SOLK ) ||
1101                 rData.HasFormat( nFormat = SotClipboardFormatId::NETSCAPE_BOOKMARK )||
1102                 rData.HasFormat( nFormat = SotClipboardFormatId::FILECONTENT ) ||
1103                 rData.HasFormat( nFormat = SotClipboardFormatId::FILEGRPDESCRIPTOR ) ||
1104                 rData.HasFormat( nFormat = SotClipboardFormatId::UNIFORMRESOURCELOCATOR ))
1105     {
1106         INetBookmark aBkmk { OUString(), OUString() };
1107         if (rData.GetINetBookmark(nFormat, aBkmk))
1108             sFileName = aBkmk.GetURL();
1109     }
1110     if( !sFileName.isEmpty() )
1111     {
1112         sFileName = INetURLObject( sFileName ).GetMainURL( INetURLObject::DecodeMechanism::NONE );
1113     }
1114     return sFileName;
1115 }
1116 
AcceptDrop()1117 sal_Int8 SwNavigationPI::AcceptDrop()
1118 {
1119     return ( !m_xContentTree->IsInDrag() &&
1120         ( m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE ) ||
1121           m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::STRING ) ||
1122           m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::SOLK ) ||
1123            m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK )||
1124            m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::FILECONTENT ) ||
1125            m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::FILEGRPDESCRIPTOR ) ||
1126            m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) ||
1127            m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::FILENAME )))
1128         ? DND_ACTION_COPY
1129         : DND_ACTION_NONE;
1130 }
1131 
ExecuteDrop(const ExecuteDropEvent & rEvt)1132 sal_Int8 SwNavigationPI::ExecuteDrop( const ExecuteDropEvent& rEvt )
1133 {
1134     TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
1135     sal_Int8 nRet = DND_ACTION_NONE;
1136     if (m_xContentTree->IsInDrag())
1137         return nRet;
1138 
1139     OUString sFileName = SwNavigationPI::CreateDropFileName(aData);
1140     if (sFileName.isEmpty())
1141         return nRet;
1142 
1143     INetURLObject aTemp(sFileName);
1144     GraphicDescriptor aDesc(aTemp);
1145     if (aDesc.Detect())   // accept no graphics
1146         return nRet;
1147 
1148     if (-1 != sFileName.indexOf('#'))
1149         return nRet;
1150 
1151     if (m_sContentFileName.isEmpty() || m_sContentFileName != sFileName)
1152     {
1153         nRet = rEvt.mnAction;
1154         sFileName = comphelper::string::stripEnd(sFileName, 0);
1155         m_sContentFileName = sFileName;
1156         if(m_oObjectShell)
1157         {
1158             m_xContentTree->SetHiddenShell( nullptr );
1159             (*m_oObjectShell)->DoClose();
1160             m_oObjectShell.reset();
1161         }
1162         SfxStringItem aFileItem(SID_FILE_NAME, sFileName );
1163         SfxStringItem aOptionsItem( SID_OPTIONS, u"HRC"_ustr );
1164         SfxLinkItem aLink( SID_DONELINK,
1165                             LINK( this, SwNavigationPI, DoneLink ) );
1166         if (SwView* pView = GetActiveView())
1167             pView->GetViewFrame().GetDispatcher()->ExecuteList(
1168                         SID_OPENDOC, SfxCallMode::ASYNCHRON,
1169                         { &aFileItem, &aOptionsItem, &aLink });
1170     }
1171     return nRet;
1172 }
1173 
1174 // toggle between showing the global tree or the content tree
ToggleTree()1175 void SwNavigationPI::ToggleTree()
1176 {
1177     if (comphelper::LibreOfficeKit::isActive())
1178     {
1179         m_xGlobalTree->HideTree();
1180         return;
1181     }
1182 
1183     bool bGlobalDoc = IsGlobalDoc();
1184     if (!IsGlobalMode() && bGlobalDoc)
1185     {
1186         // toggle to global mode
1187         if (IsZoomedIn())
1188             ZoomOut();
1189         m_xGlobalBox->show();
1190         m_xGlobalTree->ShowTree();
1191         m_xGlobalToolBox->show();
1192         m_xContentBox->hide();
1193         m_xContentTree->HideTree();
1194         m_xContent1ToolBox->hide();
1195         m_xContent2ToolBox->hide();
1196         m_xContent3ToolBox->hide();
1197         m_xContent4ToolBox->hide();
1198         m_xContent5ToolBox->hide();
1199         m_xContent6ToolBox->hide();
1200         m_xDocListBox->hide();
1201         SetGlobalMode(true);
1202     }
1203     else
1204     {
1205         m_xGlobalBox->hide();
1206         m_xGlobalTree->HideTree();
1207         m_xGlobalToolBox->hide();
1208         SetGlobalMode(false);
1209         if (!IsZoomedIn())
1210         {
1211             m_xContentBox->show();
1212             m_xContentTree->ShowTree();
1213             m_xContent1ToolBox->show();
1214             m_xContent2ToolBox->show();
1215             SetContent3And4ToolBoxVisibility();
1216             m_xContent5ToolBox->show();
1217             m_xContent6ToolBox->show();
1218             m_xDocListBox->show();
1219         }
1220     }
1221 }
1222 
IsGlobalDoc() const1223 bool SwNavigationPI::IsGlobalDoc() const
1224 {
1225     bool bRet = false;
1226     SwView *pView = GetCreateView();
1227     if (pView)
1228     {
1229         SwWrtShell &rSh = pView->GetWrtShell();
1230         bRet = rSh.IsGlobalDoc();
1231     }
1232     return bRet;
1233 }
1234 
SelectNavigateByContentType(const OUString & rContentTypeName)1235 void SwNavigationPI::SelectNavigateByContentType(const OUString& rContentTypeName)
1236 {
1237     if (!m_pNavigateByComboBox)
1238         return;
1239     if (auto nPos = m_pNavigateByComboBox->find_text(rContentTypeName); nPos != -1)
1240     {
1241         m_pNavigateByComboBox->set_active(nPos);
1242         UpdateNavigateBy();
1243     }
1244 }
1245 
GetCreateView() const1246 SwView*  SwNavigationPI::GetCreateView() const
1247 {
1248     if (!m_pCreateView)
1249     {
1250         SwView* pView = SwModule::GetFirstView();
1251         while (pView)
1252         {
1253             if(&pView->GetViewFrame().GetBindings() == &m_rBindings)
1254             {
1255                 const_cast<SwNavigationPI*>(this)->m_pCreateView = pView;
1256                 const_cast<SwNavigationPI*>(this)->StartListening(*m_pCreateView);
1257                 break;
1258             }
1259             pView = SwModule::GetNextView(pView);
1260         }
1261     }
1262     return m_pCreateView;
1263 }
1264 
SwNavigatorWin(SfxBindings * _pBindings,SfxChildWindow * _pMgr,vcl::Window * pParent,SfxChildWinInfo * pInfo)1265 SwNavigatorWin::SwNavigatorWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr,
1266                                vcl::Window* pParent, SfxChildWinInfo* pInfo)
1267     : SfxNavigator(_pBindings, _pMgr, pParent, pInfo)
1268     , m_xNavi(std::make_unique<SwNavigationPI>(m_xContainer.get(), _pBindings->GetActiveFrame(), _pBindings, this))
1269 {
1270     _pBindings->Invalidate(SID_NAVIGATOR);
1271 
1272     SwNavigationConfig* pNaviConfig = SwModule::get()->GetNavigationConfig();
1273 
1274     SetMinOutputSizePixel(GetOptimalSize());
1275     if (pNaviConfig->IsSmall())
1276         m_xNavi->ZoomIn();
1277 }
1278 
StateChanged(StateChangedType nStateChange)1279 void SwNavigatorWin::StateChanged(StateChangedType nStateChange)
1280 {
1281     SfxNavigator::StateChanged(nStateChange);
1282     if (nStateChange == StateChangedType::InitShow)
1283         m_xNavi->UpdateInitShow();
1284 }
1285 
1286 SFX_IMPL_DOCKINGWINDOW_WITHID(SwNavigatorWrapper, SID_NAVIGATOR);
1287 
SwNavigatorWrapper(vcl::Window * _pParent,sal_uInt16 nId,SfxBindings * pBindings,SfxChildWinInfo * pInfo)1288 SwNavigatorWrapper::SwNavigatorWrapper(vcl::Window *_pParent, sal_uInt16 nId,
1289                                        SfxBindings* pBindings, SfxChildWinInfo* pInfo)
1290     : SfxNavigatorWrapper(_pParent, nId)
1291 {
1292     SetWindow(VclPtr<SwNavigatorWin>::Create(pBindings, this, _pParent, pInfo));
1293     Initialize();
1294 }
1295 
1296 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1297