Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / uibase / utlui / navipi.cxx
blob399e3824bf76de07e0a5607d5b8e09606931d2d2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
43 #include <strings.hrc>
44 #include <bitmaps.hlst>
46 #include <memory>
48 #include <o3tl/enumrange.hxx>
50 #include <workctrl.hxx>
52 #include <comphelper/lok.hxx>
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::frame;
57 // Filter the control characters out of the Outline-Entry
58 OUString SwNavigationPI::CleanEntry(const OUString& rEntry)
60 if (rEntry.isEmpty())
61 return rEntry;
63 OUStringBuffer aEntry(rEntry);
64 for (sal_Int32 i = 0; i < rEntry.getLength(); ++i)
65 if(aEntry[i] == 10 || aEntry[i] == 9)
66 aEntry[i] = 0x20;
68 return aEntry.makeStringAndClear();
71 // Execution of the drag operation with and without the children.
73 void SwNavigationPI::MoveOutline(SwOutlineNodes::size_type nSource, SwOutlineNodes::size_type nTarget)
75 SwView *pView = GetCreateView();
76 SwWrtShell &rSh = pView->GetWrtShell();
77 if(nTarget < nSource || nTarget == SwOutlineNodes::npos)
78 nTarget ++;
79 if ( !rSh.IsOutlineMovable( nSource ))
80 return;
82 SwOutlineNodes::difference_type nMove = nTarget-nSource; //( nDir<0 ) ? 1 : 0 ;
83 rSh.GotoOutline(nSource);
84 rSh.MakeOutlineSel(nSource, nSource, true);
85 // While moving, the selected children does not counting.
86 const SwOutlineNodes::size_type nLastOutlinePos = rSh.GetOutlinePos(MAXLEVEL);
87 if(nMove > 1 && nLastOutlinePos < nTarget)
89 if(!rSh.IsCursorPtAtEnd())
90 rSh.SwapPam();
91 nMove -= nLastOutlinePos - nSource;
93 if( nMove < 1 || nLastOutlinePos < nTarget )
94 rSh.MoveOutlinePara( nMove );
95 rSh.ClearMark();
96 rSh.GotoOutline( nSource + nMove);
100 // After goto cancel the status frame selection
101 static void lcl_UnSelectFrame(SwWrtShell *pSh)
103 if (pSh->IsFrameSelected())
105 pSh->UnSelectFrame();
106 pSh->LeaveSelFrameMode();
110 // Select the document view
111 IMPL_LINK(SwNavigationPI, DocListBoxSelectHdl, weld::ComboBox&, rBox, void)
113 int nEntryIdx = rBox.get_active();
114 SwView *pView ;
115 pView = SwModule::GetFirstView();
116 while (nEntryIdx-- && pView)
118 pView = SwModule::GetNextView(pView);
120 if(!pView)
122 nEntryIdx == 0 ?
123 m_xContentTree->ShowHiddenShell():
124 m_xContentTree->ShowActualView();
127 else
129 m_xContentTree->SetConstantShell(pView->GetWrtShellPtr());
133 void SwNavigationPI::UpdateNavigateBy()
135 SfxUInt32Item aParam(FN_NAV_ELEMENT, m_pNavigateByComboBox->get_active_id().toUInt32());
136 const SfxPoolItem* aArgs[2];
137 aArgs[0] = &aParam;
138 aArgs[1] = nullptr;
139 SfxDispatcher* pDispatcher = GetCreateView()->GetFrame()->GetDispatcher();
140 pDispatcher->Execute(FN_NAV_ELEMENT, SfxCallMode::SYNCHRON, aArgs);
143 IMPL_LINK(SwNavigationPI, NavigateByComboBoxSelectHdl, weld::ComboBox&, rComboBox, void)
145 m_xContentTree->SelectContentType(rComboBox.get_active_text());
146 UpdateNavigateBy();
149 // Filling of the list box for outline view or documents
150 // The PI will be set to full size
151 void SwNavigationPI::FillBox()
153 if(m_pContentWrtShell)
155 m_xContentTree->SetHiddenShell( m_pContentWrtShell );
156 m_xContentTree->Display( false );
158 else
160 SwView *pView = GetCreateView();
161 if(!pView)
163 m_xContentTree->SetActiveShell(nullptr);
165 else if( pView != m_pActContView)
167 SwWrtShell* pWrtShell = pView->GetWrtShellPtr();
168 m_xContentTree->SetActiveShell(pWrtShell);
170 else
171 m_xContentTree->Display( true );
172 m_pActContView = pView;
173 if (m_pActContView)
174 m_xContentTree->UpdateTracking();
178 void SwNavigationPI::UsePage()
180 SwView *pView = GetCreateView();
181 SwWrtShell *pSh = pView ? &pView->GetWrtShell() : nullptr;
182 m_xEdit->set_value(1);
183 if (pSh)
185 const sal_uInt16 nPageCnt = pSh->GetPageCnt();
186 sal_uInt16 nPhyPage, nVirPage;
187 pSh->GetPageNum(nPhyPage, nVirPage);
189 m_xEdit->set_max(nPageCnt);
190 m_xEdit->set_width_chars(3);
191 m_xEdit->set_value(nPhyPage);
195 // Select handler of the toolboxes
196 IMPL_LINK(SwNavigationPI, ToolBoxSelectHdl, const OUString&, rCommand, void)
198 SwView *pView = GetCreateView();
199 if (!pView)
200 return;
201 SwWrtShell &rSh = pView->GetWrtShell();
202 // Get MouseModifier for Outline-Move
204 int nFuncId = 0;
205 bool bFocusToDoc = false;
206 if (rCommand == ".uno:ScrollToPrevious" || rCommand == ".uno:ScrollToNext")
208 bool *pbNext = new bool(true);
209 if (rCommand == ".uno:ScrollToPrevious")
210 *pbNext = false;
211 pView->MoveNavigationHdl(pbNext);
213 else if (rCommand == "root")
215 m_xContentTree->ToggleToRoot();
217 else if (rCommand == "listbox")
219 if (ParentIsFloatingWindow(m_xNavigatorDlg))
221 if (IsZoomedIn())
223 ZoomOut();
225 else
227 ZoomIn();
230 return;
232 // Functions that will trigger a direct action.
233 else if (rCommand == "footer")
235 rSh.MoveCursor();
236 const FrameTypeFlags eType = rSh.GetFrameType(nullptr,false);
237 if (eType & FrameTypeFlags::FOOTER)
239 if (rSh.EndPg())
240 nFuncId = FN_END_OF_PAGE;
242 else if (rSh.GotoFooterText())
243 nFuncId = FN_TO_FOOTER;
244 bFocusToDoc = true;
246 else if (rCommand == "header")
248 rSh.MoveCursor();
249 const FrameTypeFlags eType = rSh.GetFrameType(nullptr,false);
250 if (eType & FrameTypeFlags::HEADER)
252 if (rSh.SttPg())
253 nFuncId = FN_START_OF_PAGE;
255 else if (rSh.GotoHeaderText())
256 nFuncId = FN_TO_HEADER;
257 bFocusToDoc = true;
259 else if (rCommand == "anchor")
261 rSh.MoveCursor();
262 const FrameTypeFlags eFrameType = rSh.GetFrameType(nullptr,false);
263 // Jump from the footnote to the anchor.
264 if (eFrameType & FrameTypeFlags::FOOTNOTE)
266 if (rSh.GotoFootnoteAnchor())
267 nFuncId = FN_FOOTNOTE_TO_ANCHOR;
269 // Otherwise, jump to the first footnote text;
270 // go to the next footnote if this is not possible;
271 // if this is also not possible got to the footnote before.
272 else
274 if (rSh.GotoFootnoteText())
275 nFuncId = FN_FOOTNOTE_TO_ANCHOR;
276 else if (rSh.GotoNextFootnoteAnchor())
277 nFuncId = FN_NEXT_FOOTNOTE;
278 else if (rSh.GotoPrevFootnoteAnchor())
279 nFuncId = FN_PREV_FOOTNOTE;
281 bFocusToDoc = true;
283 else if (rCommand == "reminder")
285 rSh.GetView().GetViewFrame().GetDispatcher()->Execute(FN_SET_REMINDER, SfxCallMode::ASYNCHRON);
287 else if (rCommand == "chapterdown" ||
288 rCommand == "movedown" ||
289 rCommand == "chapterup" ||
290 rCommand == "moveup" ||
291 rCommand == "promote" ||
292 rCommand == "demote" ||
293 rCommand == "edit")
295 if (IsGlobalMode())
296 m_xGlobalTree->ExecCommand(rCommand);
297 else
299 // Standard: sublevels are taken
300 // do not take sublevels with Ctrl
301 bool bOutlineWithChildren = (KEY_MOD1 != m_xContent6ToolBox->get_modifier_state());
302 m_xContentTree->ExecCommand(rCommand, bOutlineWithChildren);
305 else if (rCommand == "contenttoggle" || rCommand == "globaltoggle")
307 ToggleTree();
308 bool bGlobalMode = IsGlobalMode();
309 m_pConfig->SetGlobalActive(bGlobalMode);
310 m_xGlobalToolBox->set_item_active("globaltoggle", bGlobalMode);
311 m_xContent1ToolBox->set_item_active("contenttoggle", bGlobalMode);
313 else if (rCommand == "save")
315 bool bSave = rSh.IsGlblDocSaveLinks();
316 rSh.SetGlblDocSaveLinks( !bSave );
317 m_xGlobalToolBox->set_item_active(rCommand, !bSave);
319 else if (rCommand == "dragmode")
320 m_xContent6ToolBox->set_menu_item_active("dragmode", !m_xContent6ToolBox->get_menu_item_active("dragmode"));
321 else if (rCommand == "headings")
322 m_xContent5ToolBox->set_menu_item_active("headings", !m_xContent5ToolBox->get_menu_item_active("headings"));
323 else if (rCommand == "update")
324 m_xGlobalToolBox->set_menu_item_active("update", !m_xGlobalToolBox->get_menu_item_active("update"));
325 else if (rCommand == "insert")
326 m_xGlobalToolBox->set_menu_item_active("insert", !m_xGlobalToolBox->get_menu_item_active("insert"));
328 if (nFuncId)
329 lcl_UnSelectFrame(&rSh);
330 if (bFocusToDoc)
331 pView->GetEditWin().GrabFocus();
334 // Click handler of the toolboxes
335 IMPL_LINK(SwNavigationPI, ToolBoxClickHdl, const OUString&, rCommand, void)
337 if (!m_xGlobalToolBox->get_menu_item_active(rCommand))
338 return;
340 if (rCommand == "update")
341 m_xGlobalTree->TbxMenuHdl(rCommand, *m_xUpdateMenu);
342 else if (rCommand == "insert")
343 m_xGlobalTree->TbxMenuHdl(rCommand, *m_xInsertMenu);
346 IMPL_LINK(SwNavigationPI, ToolBox6DropdownClickHdl, const OUString&, rCommand, void)
348 if (!m_xContent6ToolBox->get_menu_item_active(rCommand))
349 return;
351 if (rCommand != "dragmode")
352 return;
354 switch (m_nRegionMode)
356 case RegionMode::NONE:
357 m_xDragModeMenu->set_active("hyperlink", true);
358 break;
359 case RegionMode::LINK:
360 m_xDragModeMenu->set_active("link", true);
361 break;
362 case RegionMode::EMBEDDED:
363 m_xDragModeMenu->set_active("copy", true);
364 break;
368 IMPL_LINK(SwNavigationPI, DropModeMenuSelectHdl, const OUString&, rIdent, void)
370 if (rIdent == "hyperlink")
371 SetRegionDropMode(RegionMode::NONE);
372 else if (rIdent == "link")
373 SetRegionDropMode(RegionMode::LINK);
374 else if (rIdent == "copy")
375 SetRegionDropMode(RegionMode::EMBEDDED);
378 IMPL_LINK(SwNavigationPI, GlobalMenuSelectHdl, const OUString&, rIdent, void)
380 m_xGlobalTree->ExecuteContextMenuAction(rIdent);
383 IMPL_LINK(SwNavigationPI, ToolBox5DropdownClickHdl, const OUString&, rCommand, void)
385 if (!m_xContent5ToolBox->get_menu_item_active(rCommand))
386 return;
388 if (rCommand == "headings")
389 m_xHeadingsMenu->set_active(OUString::number(m_xContentTree->GetOutlineLevel()), true);
392 // Action-Handler Edit:
393 // Switches to the page if the structure view is not turned on.
394 bool SwNavigationPI::EditAction()
396 SwView *pView = GetCreateView();
397 if (!pView)
398 return false;
400 if (m_aPageChgIdle.IsActive())
401 m_aPageChgIdle.Stop();
403 // if the user has clicked into the document, forget about changing the page
404 if (pView->GetEditWin().HasFocus())
405 return false;
407 SwWrtShell &rSh = m_pCreateView->GetWrtShell();
408 sal_uInt16 nNewPage = m_xEdit->get_value();
410 rSh.GotoPage(nNewPage, true);
411 m_pCreateView->GetViewFrame().GetBindings().Invalidate(FN_STAT_PAGE);
413 return true;
416 void SwNavigationPI::ZoomOut()
418 if (!IsZoomedIn())
419 return;
420 SfxNavigator* pNav = m_xNavigatorDlg.get();
421 if (!pNav)
422 return;
423 m_bIsZoomedIn = false;
424 FillBox();
425 if (IsGlobalMode())
427 m_xGlobalBox->show();
428 m_xGlobalTree->ShowTree();
430 else
432 m_xContentBox->show();
433 m_xContentTree->ShowTree();
434 m_xDocListBox->show();
437 pNav->InvalidateChildSizeCache();
438 Size aOptimalSize(pNav->GetOptimalSize());
439 Size aNewSize(pNav->GetOutputSizePixel());
440 aNewSize.setHeight( m_aExpandedSize.Height() );
441 pNav->SetMinOutputSizePixel(aOptimalSize);
442 pNav->SetOutputSizePixel(aNewSize);
444 m_xContentTree->Select(); // Enable toolbox
445 m_pConfig->SetSmall(false);
446 m_xContent6ToolBox->set_item_active("listbox", true);
449 void SwNavigationPI::ZoomIn()
451 if (IsZoomedIn())
452 return;
453 SfxNavigator* pNav = m_xNavigatorDlg.get();
454 if (!pNav)
455 return;
457 m_aExpandedSize = m_xNavigatorDlg->GetSizePixel();
459 m_xContentBox->hide();
460 m_xContentTree->HideTree();
461 m_xGlobalBox->hide();
462 m_xGlobalTree->HideTree();
463 m_xDocListBox->hide();
464 m_bIsZoomedIn = true;
466 pNav->InvalidateChildSizeCache();
467 Size aOptimalSize(pNav->GetOptimalSize());
468 Size aNewSize(pNav->GetOutputSizePixel());
469 aNewSize.setHeight( aOptimalSize.Height() );
470 pNav->SetMinOutputSizePixel(aOptimalSize);
471 pNav->SetOutputSizePixel(aNewSize);
473 m_xContentTree->Select(); // Enable toolbox
475 m_pConfig->SetSmall(true);
476 m_xContent6ToolBox->set_item_active("listbox", false);
479 namespace {
481 enum StatusIndex
483 IDX_STR_HIDDEN = 0,
484 IDX_STR_ACTIVE = 1,
485 IDX_STR_INACTIVE = 2
490 std::unique_ptr<PanelLayout> SwNavigationPI::Create(weld::Widget* pParent,
491 const css::uno::Reference<css::frame::XFrame>& rxFrame,
492 SfxBindings* pBindings)
494 if( pParent == nullptr )
495 throw css::lang::IllegalArgumentException("no parent window given to SwNavigationPI::Create", nullptr, 0);
496 if( !rxFrame.is() )
497 throw css::lang::IllegalArgumentException("no XFrame given to SwNavigationPI::Create", nullptr, 0);
498 if( pBindings == nullptr )
499 throw css::lang::IllegalArgumentException("no SfxBindings given to SwNavigationPI::Create", nullptr, 0);
500 return std::make_unique<SwNavigationPI>(pParent, rxFrame, pBindings, nullptr);
503 SwNavigationPI::SwNavigationPI(weld::Widget* pParent,
504 const css::uno::Reference<css::frame::XFrame>& rxFrame,
505 SfxBindings* _pBindings, SfxNavigator* pNavigatorDlg)
506 : PanelLayout(pParent, "NavigatorPanel", "modules/swriter/ui/navigatorpanel.ui")
507 , m_aDocFullName(SID_DOCFULLNAME, *_pBindings, *this)
508 , m_aPageStats(FN_STAT_PAGE, *_pBindings, *this)
509 , m_xContent1ToolBox(m_xBuilder->weld_toolbar("content1"))
510 , m_xContent2ToolBox(m_xBuilder->weld_toolbar("content2"))
511 , m_xContent3ToolBox(m_xBuilder->weld_toolbar("content3"))
512 , m_xContent4ToolBox(m_xBuilder->weld_toolbar("content4"))
513 , m_xContent5ToolBox(m_xBuilder->weld_toolbar("content5"))
514 , m_xContent6ToolBox(m_xBuilder->weld_toolbar("content6"))
515 , m_xContent2Dispatch(new ToolbarUnoDispatcher(*m_xContent2ToolBox, *m_xBuilder, rxFrame))
516 , m_xContent3Dispatch(new ToolbarUnoDispatcher(*m_xContent3ToolBox, *m_xBuilder, rxFrame))
517 , m_xHeadingsMenu(m_xBuilder->weld_menu("headingsmenu"))
518 , m_xDragModeMenu(m_xBuilder->weld_menu("dragmodemenu"))
519 , m_xUpdateMenu(m_xBuilder->weld_menu("updatemenu"))
520 , m_xInsertMenu(m_xBuilder->weld_menu("insertmenu"))
521 , m_xGlobalToolBox(m_xBuilder->weld_toolbar("global"))
522 , m_xEdit(m_xBuilder->weld_spin_button("spinbutton"))
523 , m_xContentBox(m_xBuilder->weld_widget("contentbox"))
524 , m_xContentTree(new SwContentTree(m_xBuilder->weld_tree_view("contenttree"), this))
525 , m_xGlobalBox(m_xBuilder->weld_widget("globalbox"))
526 , m_xGlobalTree(new SwGlobalTree(m_xBuilder->weld_tree_view("globaltree"), this))
527 , m_xDocListBox(m_xBuilder->weld_combo_box("documents"))
528 , m_aPageChgIdle("SwNavigationPI m_aPageChgIdle")
529 , m_xNavigatorDlg(pNavigatorDlg)
530 , m_pContentView(nullptr)
531 , m_pContentWrtShell(nullptr)
532 , m_pActContView(nullptr)
533 , m_pCreateView(nullptr)
534 , m_pConfig(SW_MOD()->GetNavigationConfig())
535 , m_rBindings(*_pBindings)
536 , m_nRegionMode(RegionMode::NONE)
537 , m_bIsZoomedIn(false)
538 , m_bGlobalMode(false)
540 m_xContainer->connect_container_focus_changed(LINK(this, SwNavigationPI, SetFocusChildHdl));
542 Reference<XToolbarController> xController =
543 m_xContent2Dispatch->GetControllerForCommand(".uno:NavElement");
544 NavElementToolBoxControl* pToolBoxControl =
545 dynamic_cast<NavElementToolBoxControl*>(xController.get());
546 assert(pToolBoxControl);
547 m_pNavigateByComboBox = pToolBoxControl->GetComboBox();
549 // Restore content tree settings before calling UpdateInitShow. UpdateInitShow calls Fillbox,
550 // which calls Display and UpdateTracking. Incorrect outline levels could be displayed and
551 // unexpected content tracking could occur if these content tree settings are not done before.
552 m_xContentTree->SetOutlineLevel(static_cast<sal_uInt8>(m_pConfig->GetOutlineLevel()));
553 m_xContentTree->SetOutlineTracking(static_cast<sal_uInt8>(m_pConfig->GetOutlineTracking()));
554 for (ContentTypeId eCntTypeId : o3tl::enumrange<ContentTypeId>())
556 if (eCntTypeId != ContentTypeId::OUTLINE)
557 m_xContentTree->SetContentTypeTracking(
558 eCntTypeId, m_pConfig->IsContentTypeTrack(eCntTypeId));
561 if (const ContentTypeId nRootType = m_pConfig->GetRootType();
562 nRootType != ContentTypeId::UNKNOWN)
564 m_xContentTree->SetRootType(nRootType);
565 m_xContent5ToolBox->set_item_active("root", true);
566 if (nRootType == ContentTypeId::OUTLINE || nRootType == ContentTypeId::DRAWOBJECT)
567 m_xContentTree->set_selection_mode(SelectionMode::Multiple);
568 else
569 m_xContentTree->set_selection_mode(SelectionMode::Single);
571 else
572 m_xContentTree->set_selection_mode(SelectionMode::Single);
574 UpdateInitShow();
576 GetCreateView();
578 m_xContent1ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
579 m_xContent2ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
580 m_xContent3ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
581 m_xContent4ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
582 m_xContent5ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
583 m_xContent6ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
584 m_xGlobalToolBox->set_help_id(HID_NAVIGATOR_GLOBAL_TOOLBOX);
585 m_xDocListBox->set_help_id(HID_NAVIGATOR_LISTBOX);
586 m_xDocListBox->set_size_request(42, -1); // set a nominal width so it takes width of surroundings
588 // Insert the numeric field in the toolbox.
589 m_xEdit->set_accessible_name(m_xEdit->get_tooltip_text());
590 m_xEdit->set_width_chars(3);
591 m_xEdit->connect_activate(LINK(this, SwNavigationPI, EditActionHdl));
592 m_xEdit->connect_value_changed(LINK(this, SwNavigationPI, PageEditModifyHdl));
593 m_xEdit->set_help_id("modules/swriter/ui/navigatorpanel/numericfield");
595 if (!IsGlobalDoc())
597 m_xContent1ToolBox->set_item_visible("contenttoggle", false);
600 const TranslateId REGIONNAME_ARY[] =
602 STR_HYPERLINK,
603 STR_LINK_REGION,
604 STR_COPY_REGION
607 const TranslateId REGIONMODE_ARY[] =
609 STR_HIDDEN,
610 STR_ACTIVE,
611 STR_INACTIVE
614 static_assert(SAL_N_ELEMENTS(REGIONNAME_ARY) == SAL_N_ELEMENTS(REGIONMODE_ARY), "### unexpected size!");
615 static_assert(SAL_N_ELEMENTS(REGIONNAME_ARY) == static_cast<sal_uInt16>(RegionMode::EMBEDDED) + 1, "### unexpected size!");
617 for (sal_uInt16 i = 0; i <= static_cast<sal_uInt16>(RegionMode::EMBEDDED); ++i)
619 m_aStatusArr[i] = SwResId(REGIONMODE_ARY[i]);
622 m_aStatusArr[3] = SwResId(STR_ACTIVE_VIEW);
624 bool bFloatingNavigator = ParentIsFloatingWindow(m_xNavigatorDlg);
626 SetRegionDropMode(m_pConfig->GetRegionMode());
628 m_xContentTree->ShowTree();
629 m_xContent6ToolBox->set_item_active("listbox", true);
630 m_xContent6ToolBox->set_item_sensitive("listbox", bFloatingNavigator);
632 // TreeListBox for global document
633 m_xGlobalTree->set_selection_mode(SelectionMode::Multiple);
635 // Handler
636 Link<const OUString&, void> aLk = LINK(this, SwNavigationPI, ToolBoxSelectHdl);
637 m_xContent1ToolBox->connect_clicked(aLk);
638 m_xContent3ToolBox->connect_clicked(aLk);
639 m_xContent5ToolBox->connect_clicked(aLk);
640 m_xContent6ToolBox->connect_clicked(aLk);
641 m_xGlobalToolBox->connect_clicked(aLk);
642 m_xDocListBox->connect_changed(LINK(this, SwNavigationPI, DocListBoxSelectHdl));
643 m_xContent5ToolBox->set_item_menu("headings", m_xHeadingsMenu.get());
644 m_xHeadingsMenu->connect_activate(LINK(this, SwNavigationPI, HeadingsMenuSelectHdl));
645 m_xContent5ToolBox->connect_menu_toggled(LINK(this, SwNavigationPI, ToolBox5DropdownClickHdl));
646 m_xContent6ToolBox->set_item_menu("dragmode", m_xDragModeMenu.get());
647 m_xDragModeMenu->connect_activate(LINK(this, SwNavigationPI, DropModeMenuSelectHdl));
648 m_xContent6ToolBox->connect_menu_toggled(LINK(this, SwNavigationPI, ToolBox6DropdownClickHdl));
649 m_xGlobalToolBox->set_item_menu("update", m_xUpdateMenu.get());
650 m_xUpdateMenu->connect_activate(LINK(this, SwNavigationPI, GlobalMenuSelectHdl));
651 m_xGlobalToolBox->set_item_menu("insert", m_xInsertMenu.get());
652 m_xInsertMenu->connect_activate(LINK(this, SwNavigationPI, GlobalMenuSelectHdl));
653 m_xGlobalToolBox->connect_menu_toggled(LINK(this, SwNavigationPI, ToolBoxClickHdl));
654 m_xGlobalToolBox->set_item_active("globaltoggle", true);
655 m_pNavigateByComboBox->connect_changed(LINK(this, SwNavigationPI, NavigateByComboBoxSelectHdl));
657 // set toolbar of both modes to widest of each
658 m_xGlobalToolBox->set_size_request(m_xContent1ToolBox->get_preferred_size().Width() +
659 m_xContent2ToolBox->get_preferred_size().Width() +
660 m_xContent3ToolBox->get_preferred_size().Width() +
661 m_xContent4ToolBox->get_preferred_size().Width(), -1);
663 StartListening(*SfxGetpApp());
665 if(IsGlobalDoc())
667 SwView *pActView = GetCreateView();
668 if (pActView && pActView->GetWrtShellPtr())
669 m_xGlobalToolBox->set_item_active("save",
670 pActView->GetWrtShellPtr()->IsGlblDocSaveLinks());
671 if (m_pConfig->IsGlobalActive())
672 ToggleTree();
673 if (bFloatingNavigator)
674 m_xGlobalTree->grab_focus();
676 else if (bFloatingNavigator)
677 m_xContentTree->grab_focus();
678 UsePage();
679 m_aPageChgIdle.SetInvokeHandler(LINK(this, SwNavigationPI, ChangePageHdl));
680 m_aPageChgIdle.SetPriority(TaskPriority::LOWEST);
682 m_xContentTree->set_accessible_name(SwResId(STR_ACCESS_TL_CONTENT));
683 m_xGlobalTree->set_accessible_name(SwResId(STR_ACCESS_TL_GLOBAL));
684 m_xDocListBox->set_accessible_name(m_aStatusArr[3]);
686 m_aExpandedSize = m_xContainer->get_preferred_size();
688 if(comphelper::LibreOfficeKit::isActive())
690 m_xBuilder->weld_container("gridcontent16")->hide();
691 m_xDocListBox->hide();
692 m_xGlobalBox->hide();
693 m_xGlobalToolBox->hide();
694 m_xGlobalTree->HideTree();
698 weld::Window* SwNavigationPI::GetFrameWeld() const
700 if (m_xNavigatorDlg)
701 return m_xNavigatorDlg->GetFrameWeld();
702 return PanelLayout::GetFrameWeld();
705 SwNavigationPI::~SwNavigationPI()
707 if (IsGlobalDoc() && !IsGlobalMode())
709 SwView *pView = GetCreateView();
710 SwWrtShell &rSh = pView->GetWrtShell();
711 if (!rSh.IsAllProtect())
712 pView->GetDocShell()->SetReadOnlyUI(false);
715 EndListening(*SfxGetpApp());
717 if (m_oObjectShell)
719 if (m_oObjectShell->Is())
720 (*m_oObjectShell)->DoClose();
721 m_oObjectShell.reset();
724 m_xDocListBox.reset();
725 m_xGlobalTree.reset();
726 m_xGlobalBox.reset();
727 m_xContentTree.reset();
728 m_xContentBox.reset();
729 m_xGlobalToolBox.reset();
730 m_xEdit.reset();
731 m_xHeadingsMenu.reset();
732 m_xDragModeMenu.reset();
733 m_xUpdateMenu.reset();
734 m_xInsertMenu.reset();
735 m_xContent2Dispatch.reset();
736 m_xContent3Dispatch.reset();
737 m_xContent1ToolBox.reset();
738 m_xContent2ToolBox.reset();
739 m_xContent3ToolBox.reset();
740 m_xContent4ToolBox.reset();
741 m_xContent5ToolBox.reset();
742 m_xContent6ToolBox.reset();
744 m_aPageChgIdle.Stop();
746 m_aDocFullName.dispose();
747 m_aPageStats.dispose();
750 void SwNavigationPI::NotifyItemUpdate(sal_uInt16 nSID, SfxItemState /*eState*/,
751 const SfxPoolItem* /*pState*/)
753 if (nSID == SID_DOCFULLNAME)
755 SwView *pActView = GetCreateView();
756 if(pActView)
758 SwWrtShell* pWrtShell = pActView->GetWrtShellPtr();
759 m_xContentTree->SetActiveShell(pWrtShell);
760 bool bGlobal = IsGlobalDoc();
761 m_xContent1ToolBox->set_item_visible("contenttoggle", bGlobal);
762 if ((!bGlobal && IsGlobalMode()) || (!IsGlobalMode() && m_pConfig->IsGlobalActive()))
764 ToggleTree();
766 if (bGlobal)
768 m_xGlobalToolBox->set_item_active("save", pWrtShell->IsGlblDocSaveLinks());
771 else
773 m_xContentTree->SetActiveShell(nullptr);
775 UpdateListBox();
777 else if (nSID == FN_STAT_PAGE)
779 if(!comphelper::LibreOfficeKit::isActive())
781 SwView *pActView = GetCreateView();
782 if(pActView)
784 SwWrtShell &rSh = pActView->GetWrtShell();
785 m_xEdit->set_max(rSh.GetPageCnt());
786 m_xEdit->set_width_chars(3);
792 void SwNavigationPI::UpdateInitShow()
794 // if the parent isn't a float, then the navigator is displayed in
795 // the sidebar or is otherwise docked. While the navigator could change
796 // its size, the sidebar can not, and the navigator would just waste
797 // space. Therefore disable this button.
798 bool bParentIsFloatingWindow(ParentIsFloatingWindow(m_xNavigatorDlg));
799 m_xContent6ToolBox->set_item_sensitive("listbox", bParentIsFloatingWindow);
800 // show content if docked
801 if (!bParentIsFloatingWindow && IsZoomedIn())
802 ZoomOut();
803 if (!IsZoomedIn())
804 FillBox();
807 IMPL_LINK_NOARG(SwNavigationPI, SetFocusChildHdl, weld::Container&, void)
809 // update documents listbox
810 UpdateListBox();
813 // Notification on modified DocInfo
814 void SwNavigationPI::Notify( SfxBroadcaster& rBrdc, const SfxHint& rHint )
816 if(&rBrdc == m_pCreateView)
818 if (rHint.GetId() == SfxHintId::Dying)
820 EndListening(*m_pCreateView);
821 m_pCreateView = nullptr;
822 m_xContentTree->SetActiveShell(nullptr);
825 else
827 if (const SfxEventHint* pHint = dynamic_cast<const SfxEventHint*>(&rHint))
829 SfxEventHintId eEventId = pHint->GetEventId();
830 if (eEventId == SfxEventHintId::OpenDoc)
832 SwView *pActView = GetCreateView();
833 if(pActView)
835 SwWrtShell* pWrtShell = pActView->GetWrtShellPtr();
836 m_xContentTree->SetActiveShell(pWrtShell);
837 if (m_xGlobalTree->get_visible())
839 bool bUpdateAll = m_xGlobalTree->Update(false);
840 // If no update is needed, then update the font colors
841 // at the entries of broken links.
842 m_xGlobalTree->Display(!bUpdateAll);
850 IMPL_LINK( SwNavigationPI, HeadingsMenuSelectHdl, const OUString&, rMenuId, void )
852 if (!rMenuId.isEmpty())
853 m_xContentTree->SetOutlineLevel(rMenuId.toUInt32());
856 void SwNavigationPI::UpdateListBox()
858 if (!m_xDocListBox) // disposed
859 return;
861 m_xDocListBox->freeze();
862 m_xDocListBox->clear();
863 SwView *pActView = GetCreateView();
864 bool bDisable = pActView == nullptr;
865 SwView *pView = SwModule::GetFirstView();
866 sal_Int32 nCount = 0;
867 sal_Int32 nAct = 0;
868 sal_Int32 nConstPos = 0;
869 const SwView* pConstView = m_xContentTree->IsConstantView() &&
870 m_xContentTree->GetActiveWrtShell() ?
871 &m_xContentTree->GetActiveWrtShell()->GetView():
872 nullptr;
873 while (pView)
875 SfxObjectShell* pDoc = pView->GetDocShell();
876 // #i53333# don't show help pages here
877 if ( !pDoc->IsHelpDocument() )
879 OUString sEntry = pDoc->GetTitle() + " (";
880 if (pView == pActView)
882 nAct = nCount;
883 sEntry += m_aStatusArr[IDX_STR_ACTIVE];
885 else
886 sEntry += m_aStatusArr[IDX_STR_INACTIVE];
887 sEntry += ")";
888 m_xDocListBox->append_text(sEntry);
890 if (pConstView && pView == pConstView)
891 nConstPos = nCount;
893 nCount++;
895 pView = SwModule::GetNextView(pView);
897 m_xDocListBox->append_text(m_aStatusArr[3]); // "Active Window"
898 nCount++;
900 if(m_xContentTree->GetHiddenWrtShell())
902 OUString sEntry = m_xContentTree->GetHiddenWrtShell()->GetView().
903 GetDocShell()->GetTitle() +
904 " (" +
905 m_aStatusArr[IDX_STR_HIDDEN] +
906 ")";
907 m_xDocListBox->append_text(sEntry);
908 bDisable = false;
911 m_xDocListBox->thaw();
913 if(m_xContentTree->IsActiveView())
915 //Either the name of the current Document or "Active Document".
916 m_xDocListBox->set_active(pActView ? nAct : --nCount);
918 else if(m_xContentTree->IsHiddenView())
920 m_xDocListBox->set_active(nCount);
922 else
923 m_xDocListBox->set_active(nConstPos);
925 m_xDocListBox->set_sensitive(!bDisable);
928 IMPL_LINK(SwNavigationPI, DoneLink, SfxPoolItem const *, pItem, void)
930 const SfxViewFrameItem* pFrameItem = dynamic_cast<SfxViewFrameItem const *>( pItem );
931 if( !pFrameItem )
932 return;
934 SfxViewFrame* pFrame = pFrameItem->GetFrame();
935 if(pFrame)
937 m_xContentTree->clear();
938 m_pContentView = dynamic_cast<SwView*>( pFrame->GetViewShell() );
939 OSL_ENSURE(m_pContentView, "no SwView");
940 if(m_pContentView)
941 m_pContentWrtShell = m_pContentView->GetWrtShellPtr();
942 else
943 m_pContentWrtShell = nullptr;
944 m_oObjectShell.emplace( pFrame->GetObjectShell() );
945 FillBox();
949 OUString SwNavigationPI::CreateDropFileName( const TransferableDataHelper& rData )
951 OUString sFileName;
952 SotClipboardFormatId nFormat;
953 if( rData.HasFormat( nFormat = SotClipboardFormatId::FILE_LIST ))
955 FileList aFileList;
956 rData.GetFileList( nFormat, aFileList );
957 sFileName = aFileList.GetFile( 0 );
959 else if( rData.HasFormat( nFormat = SotClipboardFormatId::STRING ) ||
960 rData.HasFormat( nFormat = SotClipboardFormatId::SIMPLE_FILE ) ||
961 rData.HasFormat( nFormat = SotClipboardFormatId::FILENAME ))
963 (void)rData.GetString(nFormat, sFileName);
965 else if( rData.HasFormat( nFormat = SotClipboardFormatId::SOLK ) ||
966 rData.HasFormat( nFormat = SotClipboardFormatId::NETSCAPE_BOOKMARK )||
967 rData.HasFormat( nFormat = SotClipboardFormatId::FILECONTENT ) ||
968 rData.HasFormat( nFormat = SotClipboardFormatId::FILEGRPDESCRIPTOR ) ||
969 rData.HasFormat( nFormat = SotClipboardFormatId::UNIFORMRESOURCELOCATOR ))
971 INetBookmark aBkmk { OUString(), OUString() };
972 if (rData.GetINetBookmark(nFormat, aBkmk))
973 sFileName = aBkmk.GetURL();
975 if( !sFileName.isEmpty() )
977 sFileName = INetURLObject( sFileName ).GetMainURL( INetURLObject::DecodeMechanism::NONE );
979 return sFileName;
982 sal_Int8 SwNavigationPI::AcceptDrop()
984 return ( !m_xContentTree->IsInDrag() &&
985 ( m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE ) ||
986 m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::STRING ) ||
987 m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::SOLK ) ||
988 m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK )||
989 m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::FILECONTENT ) ||
990 m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::FILEGRPDESCRIPTOR ) ||
991 m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) ||
992 m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::FILENAME )))
993 ? DND_ACTION_COPY
994 : DND_ACTION_NONE;
997 sal_Int8 SwNavigationPI::ExecuteDrop( const ExecuteDropEvent& rEvt )
999 TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
1000 sal_Int8 nRet = DND_ACTION_NONE;
1001 if (m_xContentTree->IsInDrag())
1002 return nRet;
1004 OUString sFileName = SwNavigationPI::CreateDropFileName(aData);
1005 if (sFileName.isEmpty())
1006 return nRet;
1008 INetURLObject aTemp(sFileName);
1009 GraphicDescriptor aDesc(aTemp);
1010 if (aDesc.Detect()) // accept no graphics
1011 return nRet;
1013 if (-1 != sFileName.indexOf('#'))
1014 return nRet;
1016 if (m_sContentFileName.isEmpty() || m_sContentFileName != sFileName)
1018 nRet = rEvt.mnAction;
1019 sFileName = comphelper::string::stripEnd(sFileName, 0);
1020 m_sContentFileName = sFileName;
1021 if(m_oObjectShell)
1023 m_xContentTree->SetHiddenShell( nullptr );
1024 (*m_oObjectShell)->DoClose();
1025 m_oObjectShell.reset();
1027 SfxStringItem aFileItem(SID_FILE_NAME, sFileName );
1028 SfxStringItem aOptionsItem( SID_OPTIONS, "HRC" );
1029 SfxLinkItem aLink( SID_DONELINK,
1030 LINK( this, SwNavigationPI, DoneLink ) );
1031 if (SwView* pView = GetActiveView())
1032 pView->GetViewFrame().GetDispatcher()->ExecuteList(
1033 SID_OPENDOC, SfxCallMode::ASYNCHRON,
1034 { &aFileItem, &aOptionsItem, &aLink });
1036 return nRet;
1039 void SwNavigationPI::SetRegionDropMode(RegionMode nNewMode)
1041 m_nRegionMode = nNewMode;
1042 m_pConfig->SetRegionMode( m_nRegionMode );
1044 OUString sImageId;
1045 switch (nNewMode)
1047 case RegionMode::NONE:
1048 sImageId = RID_BMP_DROP_REGION;
1049 break;
1050 case RegionMode::LINK:
1051 sImageId = RID_BMP_DROP_LINK;
1052 break;
1053 case RegionMode::EMBEDDED:
1054 sImageId = RID_BMP_DROP_COPY;
1055 break;
1057 m_xContent6ToolBox->set_item_icon_name("dragmode", sImageId);
1060 void SwNavigationPI::ToggleTree()
1062 if (comphelper::LibreOfficeKit::isActive())
1064 m_xGlobalTree->HideTree();
1065 return;
1068 bool bGlobalDoc = IsGlobalDoc();
1069 if (!IsGlobalMode() && bGlobalDoc)
1071 if (IsZoomedIn())
1072 ZoomOut();
1073 m_xGlobalBox->show();
1074 m_xGlobalTree->ShowTree();
1075 m_xGlobalToolBox->show();
1076 m_xContentBox->hide();
1077 m_xContentTree->HideTree();
1078 m_xContent1ToolBox->hide();
1079 m_xContent2ToolBox->hide();
1080 m_xContent3ToolBox->hide();
1081 m_xContent4ToolBox->hide();
1082 m_xContent5ToolBox->hide();
1083 m_xContent6ToolBox->hide();
1084 m_xDocListBox->hide();
1085 SetGlobalMode(true);
1087 else
1089 m_xGlobalBox->hide();
1090 m_xGlobalTree->HideTree();
1091 m_xGlobalToolBox->hide();
1092 if (!IsZoomedIn())
1094 m_xContentBox->show();
1095 m_xContentTree->ShowTree();
1096 m_xContent1ToolBox->show();
1097 m_xContent2ToolBox->show();
1098 m_xContent3ToolBox->show();
1099 m_xContent4ToolBox->show();
1100 m_xContent5ToolBox->show();
1101 m_xContent6ToolBox->show();
1102 m_xDocListBox->show();
1104 SetGlobalMode(false);
1108 bool SwNavigationPI::IsGlobalDoc() const
1110 bool bRet = false;
1111 SwView *pView = GetCreateView();
1112 if (pView)
1114 SwWrtShell &rSh = pView->GetWrtShell();
1115 bRet = rSh.IsGlobalDoc();
1117 return bRet;
1120 IMPL_LINK_NOARG(SwNavigationPI, ChangePageHdl, Timer *, void)
1122 if (!m_xDocListBox) // disposed
1123 return;
1124 // tdf#134959 if the SpinButton changed value this Timer was launched, now
1125 // change to the desired page, but we leave focus where it currently is,
1126 // i.e. typically remaining in the spinbutton, or whatever other widget the
1127 // user moved to in the meantime
1128 EditAction();
1131 void SwNavigationPI::SelectNavigateByContentType(const OUString& rContentTypeName)
1133 if (auto nPos = m_pNavigateByComboBox->find_text(rContentTypeName); nPos != -1)
1135 m_pNavigateByComboBox->set_active(nPos);
1136 UpdateNavigateBy();
1140 IMPL_LINK_NOARG(SwNavigationPI, EditActionHdl, weld::Entry&, bool)
1142 // tdf#134959 if the user presses enter to activate the Entry
1143 // go to the page, and on success we move focus to the document
1144 if (EditAction())
1145 m_pCreateView->GetEditWin().GrabFocus();
1146 return true;
1149 IMPL_LINK_NOARG(SwNavigationPI, PageEditModifyHdl, weld::SpinButton&, void)
1151 if (m_aPageChgIdle.IsActive())
1152 m_aPageChgIdle.Stop();
1153 m_aPageChgIdle.Start();
1156 SwView* SwNavigationPI::GetCreateView() const
1158 if (!m_pCreateView)
1160 SwView* pView = SwModule::GetFirstView();
1161 while (pView)
1163 if(&pView->GetViewFrame().GetBindings() == &m_rBindings)
1165 const_cast<SwNavigationPI*>(this)->m_pCreateView = pView;
1166 const_cast<SwNavigationPI*>(this)->StartListening(*m_pCreateView);
1167 break;
1169 pView = SwModule::GetNextView(pView);
1172 return m_pCreateView;
1175 class SwNavigatorWin : public SfxNavigator
1177 private:
1178 std::unique_ptr<SwNavigationPI> m_xNavi;
1179 public:
1180 SwNavigatorWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr,
1181 vcl::Window* pParent, SfxChildWinInfo* pInfo);
1182 virtual void StateChanged(StateChangedType nStateChange) override;
1183 virtual void dispose() override
1185 m_xNavi.reset();
1186 SfxNavigator::dispose();
1188 virtual ~SwNavigatorWin() override
1190 disposeOnce();
1194 SwNavigatorWin::SwNavigatorWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr,
1195 vcl::Window* pParent, SfxChildWinInfo* pInfo)
1196 : SfxNavigator(_pBindings, _pMgr, pParent, pInfo)
1197 , m_xNavi(std::make_unique<SwNavigationPI>(m_xContainer.get(), _pBindings->GetActiveFrame(), _pBindings, this))
1199 _pBindings->Invalidate(SID_NAVIGATOR);
1201 SwNavigationConfig* pNaviConfig = SW_MOD()->GetNavigationConfig();
1203 SetMinOutputSizePixel(GetOptimalSize());
1204 if (pNaviConfig->IsSmall())
1205 m_xNavi->ZoomIn();
1208 void SwNavigatorWin::StateChanged(StateChangedType nStateChange)
1210 SfxNavigator::StateChanged(nStateChange);
1211 if (nStateChange == StateChangedType::InitShow)
1212 m_xNavi->UpdateInitShow();
1215 SFX_IMPL_DOCKINGWINDOW(SwNavigatorWrapper, SID_NAVIGATOR);
1217 SwNavigatorWrapper::SwNavigatorWrapper(vcl::Window *_pParent, sal_uInt16 nId,
1218 SfxBindings* pBindings, SfxChildWinInfo* pInfo)
1219 : SfxNavigatorWrapper(_pParent, nId)
1221 SetWindow(VclPtr<SwNavigatorWin>::Create(pBindings, this, _pParent, pInfo));
1222 Initialize();
1225 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */