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