LibreOffice Module vcl (master)  1
salvtables.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
21 #include <com/sun/star/awt/XWindow.hpp>
22 #include <com/sun/star/awt/XWindowPeer.hpp>
23 #include <o3tl/sorted_vector.hxx>
24 #include <officecfg/Office/Common.hxx>
25 #include <iconview.hxx>
26 #include <salframe.hxx>
27 #include <salinst.hxx>
28 #include <salvd.hxx>
29 #include <salprn.hxx>
30 #include <saltimer.hxx>
31 #include <salsession.hxx>
32 #include <salsys.hxx>
33 #include <salbmp.hxx>
34 #include <salobj.hxx>
35 #include <salmenu.hxx>
36 #include <strings.hrc>
37 #include <svdata.hxx>
38 #include <svimpbox.hxx>
39 #include <messagedialog.hxx>
40 #include <treeglue.hxx>
42 #include <unotools/configmgr.hxx>
43 #include <utility>
44 #include <tools/helpers.hxx>
45 #include <vcl/abstdlg.hxx>
46 #include <vcl/builder.hxx>
47 #include <vcl/toolkit/combobox.hxx>
48 #include <vcl/toolkit/dialog.hxx>
49 #include <vcl/toolkit/fixed.hxx>
51 #include <vcl/fmtfield.hxx>
52 #include <vcl/headbar.hxx>
53 #include <vcl/ivctrl.hxx>
54 #include <vcl/layout.hxx>
55 #include <vcl/menubtn.hxx>
56 #include <vcl/toolkit/prgsbar.hxx>
57 #include <vcl/ptrstyle.hxx>
58 #include <slider.hxx>
59 #include <vcl/sysdata.hxx>
60 #include <vcl/svlbitm.hxx>
61 #include <vcl/toolkit/svtabbx.hxx>
62 #include <vcl/tabctrl.hxx>
63 #include <vcl/tabpage.hxx>
64 #include <vcl/treelistentry.hxx>
65 #include <vcl/toolkit/throbber.hxx>
66 #include <vcl/toolkit/unowrap.hxx>
67 #include <vcl/weld.hxx>
68 #include <vcl/vclmedit.hxx>
69 #include <vcl/viewdataentry.hxx>
70 #include <vcl/virdev.hxx>
71 #include <bitmaps.hlst>
72 #include <calendar.hxx>
73 #include <wizdlg.hxx>
74 #include <salvtables.hxx>
75 
76 #include <boost/property_tree/ptree.hpp>
77 
79  : m_pWindow(nullptr)
80  , m_pProc(nullptr)
81 {
82 }
83 
84 // this file contains the virtual destructors of the sal interface
85 // compilers usually put their vtables where the destructor is
86 
88 
90 {
91  m_pWindow = pWindow;
92  m_pProc = pProc;
93 }
94 
95 // default to full-frame flushes
96 // on ports where partial-flushes are much cheaper this method should be overridden
98 
99 void SalFrame::SetRepresentedURL(const OUString&)
100 {
101  // currently this is Mac only functionality
102 }
103 
104 SalInstance::SalInstance(std::unique_ptr<comphelper::SolarMutex> pMutex)
105  : m_pYieldMutex(std::move(pMutex))
106 {
107 }
108 
110 
112 
113 sal_uInt32 SalInstance::ReleaseYieldMutexAll() { return m_pYieldMutex->release(true); }
114 
115 void SalInstance::AcquireYieldMutex(sal_uInt32 nCount) { m_pYieldMutex->acquire(nCount); }
116 
117 std::unique_ptr<SalSession> SalInstance::CreateSalSession() { return nullptr; }
118 
119 std::unique_ptr<SalMenu> SalInstance::CreateMenu(bool, Menu*)
120 {
121  // default: no native menus
122  return nullptr;
123 }
124 
125 std::unique_ptr<SalMenuItem> SalInstance::CreateMenuItem(const SalItemParams&) { return nullptr; }
126 
127 bool SalInstance::CallEventCallback(void const* pEvent, int nBytes)
128 {
129  return m_pEventInst.is() && m_pEventInst->dispatchEvent(pEvent, nBytes);
130 }
131 
132 SalTimer::~SalTimer() COVERITY_NOEXCEPT_FALSE {}
133 
135 {
136  if (ImplSVData* pSVData = ImplGetSVData())
137  {
138  auto& rCache = pSVData->maGDIData.maScaleCache;
139 
140  rCache.remove_if([this] (const lru_scale_cache::key_value_pair_t& rKeyValuePair)
141  { return rKeyValuePair.first.mpBitmap == this; });
142  }
143 }
144 
146 
148 
150 
151 bool SalPrinter::StartJob(const OUString*, const OUString&, const OUString&, ImplJobSetup*,
153 {
154  return false;
155 }
156 
158 
160 
162 
164 
166 {
167  return false;
168 }
169 
171 
172 bool SalMenu::AddMenuBarButton(const SalMenuButtonItem&) { return false; }
173 
174 void SalMenu::RemoveMenuBarButton(sal_uInt16) {}
175 
177 {
178  return tools::Rectangle();
179 }
180 
181 int SalMenu::GetMenuBarHeight() const { return 0; }
182 
184 
186 
188 {
189  if (!m_bEventListener)
190  {
191  m_xWidget->AddEventListener(LINK(this, SalInstanceWidget, EventListener));
192  m_bEventListener = true;
193  }
194 }
195 
196 // we want the ability to mark key events as handled, so use this variant
197 // for those, we get all keystrokes in this case, so we will need to filter
198 // them later
200 {
201  if (!m_bKeyEventListener)
202  {
203  Application::AddKeyListener(LINK(this, SalInstanceWidget, KeyEventListener));
204  m_bKeyEventListener = true;
205  }
206 }
207 
208 // we want the ability to know about mouse events that happen in our children
209 // so use this variant, we will need to filter them later
211 {
213  {
214  Application::AddEventListener(LINK(this, SalInstanceWidget, MouseEventListener));
215  m_bMouseEventListener = true;
216  }
217 }
218 
220 {
223  // turn off WB_CLIPCHILDREN otherwise the bg won't extend "under"
224  // transparent children of the widget
226 }
227 
229  bool bTakeOwnership)
230  : m_xWidget(pWidget)
231  , m_pBuilder(pBuilder)
232  , m_bTakeOwnership(bTakeOwnership)
233  , m_bEventListener(false)
234  , m_bKeyEventListener(false)
235  , m_bMouseEventListener(false)
236  , m_nBlockNotify(0)
237 {
238 }
239 
240 void SalInstanceWidget::set_sensitive(bool sensitive) { m_xWidget->Enable(sensitive); }
241 
243 
245 
247 
249 {
250  auto nStyle = m_xWidget->GetStyle() & ~(WB_TABSTOP | WB_NOTABSTOP);
251  if (bCanFocus)
252  nStyle |= WB_TABSTOP;
253  else
254  nStyle |= WB_NOTABSTOP;
255  m_xWidget->SetStyle(nStyle);
256 }
257 
259 
261 
263 
265 {
266  m_xWidget->set_property("has-default", OUString::boolean(has_default));
267 }
268 
270 
272 
274 
275 void SalInstanceWidget::set_size_request(int nWidth, int nHeight)
276 {
277  m_xWidget->set_width_request(nWidth);
278  m_xWidget->set_height_request(nHeight);
279 }
280 
282 {
284 }
285 
287 
289 {
291 }
292 
294 
295 Size SalInstanceWidget::get_pixel_size(const OUString& rText) const
296 {
297  //TODO, or do I want GetTextBoundRect ?, just using width at the moment anyway
298  return Size(m_xWidget->GetTextWidth(rText), m_xWidget->GetTextHeight());
299 }
300 
302 
303 OString SalInstanceWidget::get_buildable_name() const { return m_xWidget->get_id().toUtf8(); }
304 
305 void SalInstanceWidget::set_help_id(const OString& rId) { return m_xWidget->SetHelpId(rId); }
306 
307 OString SalInstanceWidget::get_help_id() const { return m_xWidget->GetHelpId(); }
308 
310 {
312 }
313 
315 
317 
319 {
320  m_xWidget->set_grid_top_attach(nAttach);
321 }
322 
324 
325 void SalInstanceWidget::set_hexpand(bool bExpand) { m_xWidget->set_hexpand(bExpand); }
326 
328 
329 void SalInstanceWidget::set_vexpand(bool bExpand) { m_xWidget->set_vexpand(bExpand); }
330 
332 
333 void SalInstanceWidget::set_secondary(bool bSecondary) { m_xWidget->set_secondary(bSecondary); }
334 
336 
338 
340 
342 
344 
346 
348 
350 
351 void SalInstanceWidget::set_accessible_name(const OUString& rName)
352 {
354 }
355 
357 
359 {
361 }
362 
364 {
365  vcl::Window* pAtkLabel
366  = pLabel ? dynamic_cast<SalInstanceWidget&>(*pLabel).getWidget() : nullptr;
368 }
369 
371 {
372  vcl::Window* pAtkLabeled
373  = pLabeled ? dynamic_cast<SalInstanceWidget&>(*pLabeled).getWidget() : nullptr;
375 }
376 
377 void SalInstanceWidget::set_tooltip_text(const OUString& rTip)
378 {
380 }
381 
383 
385 {
388 }
389 
391 {
392  m_xWidget->SetMnemonicActivateHdl(LINK(this, SalInstanceWidget, MnemonicActivateHdl));
394 }
395 
397 {
400 }
401 
403 {
406 }
407 
409 {
412 }
413 
415 {
418 }
419 
421 {
424 }
425 
427 {
430 }
431 
433 {
436 }
437 
438 bool SalInstanceWidget::get_extents_relative_to(Widget& rRelative, int& x, int& y, int& width,
439  int& height)
440 {
442  dynamic_cast<SalInstanceWidget&>(rRelative).getWidget()));
443  x = aRect.Left();
444  y = aRect.Top();
445  width = aRect.GetWidth();
446  height = aRect.GetHeight();
447  return true;
448 }
449 
451 
453 
455 
457 
459 
461 
463 
465 {
466  if (m_aMnemonicActivateHdl.IsSet())
469  Application::RemoveEventListener(LINK(this, SalInstanceWidget, MouseEventListener));
471  Application::RemoveKeyListener(LINK(this, SalInstanceWidget, KeyEventListener));
472  if (m_bEventListener)
473  m_xWidget->RemoveEventListener(LINK(this, SalInstanceWidget, EventListener));
474  if (m_bTakeOwnership)
476 }
477 
479 
481 
483 
485 
486 OUString SalInstanceWidget::strip_mnemonic(const OUString& rLabel) const
487 {
488  return rLabel.replaceFirst("~", "");
489 }
490 
492 {
493  // create with (annoying) separate alpha layer that LibreOffice itself uses
496 }
497 
498 css::uno::Reference<css::datatransfer::dnd::XDropTarget> SalInstanceWidget::get_drop_target()
499 {
500  return m_xWidget->GetDropTarget();
501 }
502 
504  const Link<tools::JsonWriter&, void>& rLink)
505 {
507 }
508 
510 {
512 }
513 
515 {
518 }
519 
521 {
523 }
524 
526 
528 {
529  if (rEvent.GetId() == VclEventId::WindowGetFocus)
530  m_aFocusInHdl.Call(*this);
531  else if (rEvent.GetId() == VclEventId::WindowLoseFocus)
532  m_aFocusOutHdl.Call(*this);
533  else if (rEvent.GetId() == VclEventId::WindowResize)
535 }
536 
537 namespace
538 {
539  MouseEvent TransformEvent(const MouseEvent& rEvent, const vcl::Window* pParent, const vcl::Window* pChild)
540  {
541  return MouseEvent(pParent->ScreenToOutputPixel(pChild->OutputToScreenPixel(rEvent.GetPosPixel())),
542  rEvent.GetClicks(), rEvent.GetMode(), rEvent.GetButtons(), rEvent.GetModifier());
543  }
544 }
545 
547 {
549  {
550  auto& rWinEvent = static_cast<VclWindowEvent&>(rEvent);
551  if (m_xWidget == rWinEvent.GetWindow())
552  {
553  const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
554  m_aMousePressHdl.Call(*pMouseEvent);
555  }
556  else if (m_xWidget->ImplIsChild(rWinEvent.GetWindow()))
557  {
558  const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
559  const MouseEvent aTransformedEvent(TransformEvent(*pMouseEvent, m_xWidget, rWinEvent.GetWindow()));
560  m_aMousePressHdl.Call(aTransformedEvent);
561  }
562  }
563  else if (rEvent.GetId() == VclEventId::WindowMouseButtonUp)
564  {
565  auto& rWinEvent = static_cast<VclWindowEvent&>(rEvent);
566  if (m_xWidget == rWinEvent.GetWindow())
567  {
568  const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
569  m_aMouseReleaseHdl.Call(*pMouseEvent);
570  }
571  else if (m_xWidget->ImplIsChild(rWinEvent.GetWindow()))
572  {
573  const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
574  const MouseEvent aTransformedEvent(TransformEvent(*pMouseEvent, m_xWidget, rWinEvent.GetWindow()));
575  m_aMouseReleaseHdl.Call(aTransformedEvent);
576  }
577  }
578  else if (rEvent.GetId() == VclEventId::WindowMouseMove)
579  {
580  auto& rWinEvent = static_cast<VclWindowEvent&>(rEvent);
581  if (m_xWidget == rWinEvent.GetWindow())
582  {
583  const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
584  m_aMouseMotionHdl.Call(*pMouseEvent);
585  }
586  else if (m_xWidget->ImplIsChild(rWinEvent.GetWindow()))
587  {
588  const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData());
589  const MouseEvent aTransformedEvent(TransformEvent(*pMouseEvent, m_xWidget, rWinEvent.GetWindow()));
590  m_aMouseMotionHdl.Call(aTransformedEvent);
591  }
592  }
593 }
594 
596 {
597  // we get all key events here, ignore them unless we have focus
598  if (!has_focus())
599  return false;
600  if (rEvent.GetId() == VclEventId::WindowKeyInput)
601  {
602  const KeyEvent* pKeyEvent = static_cast<const KeyEvent*>(rEvent.GetData());
603  return m_aKeyPressHdl.Call(*pKeyEvent);
604  }
605  else if (rEvent.GetId() == VclEventId::WindowKeyUp)
606  {
607  const KeyEvent* pKeyEvent = static_cast<const KeyEvent*>(rEvent.GetData());
608  return m_aKeyReleaseHdl.Call(*pKeyEvent);
609  }
610  return false;
611 }
612 
613 IMPL_LINK(SalInstanceWidget, EventListener, VclWindowEvent&, rEvent, void)
614 {
615  HandleEventListener(rEvent);
616 }
617 
618 IMPL_LINK(SalInstanceWidget, KeyEventListener, VclWindowEvent&, rEvent, bool)
619 {
620  return HandleKeyEventListener(rEvent);
621 }
622 
623 IMPL_LINK(SalInstanceWidget, MouseEventListener, VclSimpleEvent&, rEvent, void)
624 {
625  HandleMouseEventListener(rEvent);
626 }
627 
628 IMPL_LINK_NOARG(SalInstanceWidget, MnemonicActivateHdl, vcl::Window&, bool)
629 {
630  return m_aMnemonicActivateHdl.Call(*this);
631 }
632 
633 namespace
634 {
635 Image createImage(const OUString& rImage)
636 {
637  if (rImage.isEmpty())
638  return Image();
639  if (rImage.lastIndexOf('.') != rImage.getLength() - 4)
640  {
641  assert((rImage == "dialog-warning" || rImage == "dialog-error"
642  || rImage == "dialog-information")
643  && "unknown stock image");
644  if (rImage == "dialog-warning")
645  return Image(StockImage::Yes, IMG_WARN);
646  else if (rImage == "dialog-error")
647  return Image(StockImage::Yes, IMG_ERROR);
648  else if (rImage == "dialog-information")
649  return Image(StockImage::Yes, IMG_INFO);
650  }
651  return Image(StockImage::Yes, rImage);
652 }
653 
654 Image createImage(const VirtualDevice& rDevice)
655 {
656  return Image(rDevice.GetBitmapEx(Point(), rDevice.GetOutputSizePixel()));
657 }
658 
659 sal_uInt16 insert_to_menu(sal_uInt16 nLastId, PopupMenu* pMenu, int pos, const OUString& rId,
660  const OUString& rStr, const OUString* pIconName,
661  const VirtualDevice* pImageSurface, TriState eCheckRadioFalse)
662 {
663  const sal_uInt16 nNewid = nLastId + 1;
664 
665  MenuItemBits nBits;
666  if (eCheckRadioFalse == TRISTATE_TRUE)
667  nBits = MenuItemBits::CHECKABLE;
668  else if (eCheckRadioFalse == TRISTATE_FALSE)
670  else
671  nBits = MenuItemBits::NONE;
672 
673  pMenu->InsertItem(nNewid, rStr, nBits,
674  OUStringToOString(rId, RTL_TEXTENCODING_UTF8), pos == -1 ? MENU_APPEND : pos);
675  if (pIconName)
676  {
677  pMenu->SetItemImage(nNewid, createImage(*pIconName));
678  }
679  else if (pImageSurface)
680  {
681  pMenu->SetItemImage(nNewid, createImage(*pImageSurface));
682  }
683  return nNewid;
684 }
685 }
686 
687 SalInstanceMenu::SalInstanceMenu(PopupMenu* pMenu, bool bTakeOwnership)
688  : m_xMenu(pMenu)
689  , m_bTakeOwnership(bTakeOwnership)
690 {
691  const auto nCount = m_xMenu->GetItemCount();
692  m_nLastId = nCount ? pMenu->GetItemId(nCount - 1) : 0;
693  m_xMenu->SetSelectHdl(LINK(this, SalInstanceMenu, SelectMenuHdl));
694 }
696 {
697  SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pParent);
698  assert(pVclWidget);
699  m_xMenu->Execute(pVclWidget->getWidget(), rRect,
701  return m_xMenu->GetCurItemIdent();
702 }
703 void SalInstanceMenu::set_sensitive(const OString& rIdent, bool bSensitive)
704 {
705  m_xMenu->EnableItem(rIdent, bSensitive);
706 }
707 void SalInstanceMenu::set_active(const OString& rIdent, bool bActive)
708 {
709  m_xMenu->CheckItem(rIdent, bActive);
710 }
711 bool SalInstanceMenu::get_active(const OString& rIdent) const
712 {
713  return m_xMenu->IsItemChecked(m_xMenu->GetItemId(rIdent));
714 }
715 void SalInstanceMenu::set_label(const OString& rIdent, const OUString& rLabel)
716 {
717  m_xMenu->SetItemText(m_xMenu->GetItemId(rIdent), rLabel);
718 }
719 OUString SalInstanceMenu::get_label(const OString& rIdent) const
720 {
721  return m_xMenu->GetItemText(m_xMenu->GetItemId(rIdent));
722 }
723 void SalInstanceMenu::set_visible(const OString& rIdent, bool bShow)
724 {
725  m_xMenu->ShowItem(m_xMenu->GetItemId(rIdent), bShow);
726 }
728 void SalInstanceMenu::insert(int pos, const OUString& rId, const OUString& rStr,
729  const OUString* pIconName, VirtualDevice* pImageSurface,
730  TriState eCheckRadioFalse)
731 {
732  m_nLastId
733  = insert_to_menu(m_nLastId, m_xMenu, pos, rId, rStr, pIconName, pImageSurface, eCheckRadioFalse);
734 }
735 void SalInstanceMenu::insert_separator(int pos, const OUString& rId)
736 {
737  auto nInsertPos = pos == -1 ? MENU_APPEND : pos;
738  m_xMenu->InsertSeparator(rId.toUtf8(), nInsertPos);
739 }
740 void SalInstanceMenu::remove(const OString& rId)
741 {
743 }
747 {
749  if (m_bTakeOwnership)
751 }
752 
753 IMPL_LINK_NOARG(SalInstanceMenu, SelectMenuHdl, ::Menu*, bool)
754 {
755  signal_activate(m_xMenu->GetCurItemIdent());
756  /* tdf#131333 Menu::Select depends on a false here to allow
757  propagating a submens's selected id to its parent menu to become its
758  selected id.
759 
760  without this, while gen menus already have propagated this to its parent
761  in MenuFloatingWindow::EndExecute, SalMenus as used under kf5/macOS
762  won't propagate the selected id
763  */
764  return false;
765 }
766 
767 SalInstanceToolbar::SalInstanceToolbar(ToolBox* pToolBox, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
768  : SalInstanceWidget(pToolBox, pBuilder, bTakeOwnership)
769  , m_xToolBox(pToolBox)
770 {
771  m_xToolBox->SetSelectHdl(LINK(this, SalInstanceToolbar, ClickHdl));
772  m_xToolBox->SetDropdownClickHdl(LINK(this, SalInstanceToolbar, DropdownClick));
773 }
774 
775 void SalInstanceToolbar::set_item_sensitive(const OString& rIdent, bool bSensitive)
776 {
777  m_xToolBox->EnableItem(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), bSensitive);
778 }
779 
780 bool SalInstanceToolbar::get_item_sensitive(const OString& rIdent) const
781 {
782  return m_xToolBox->IsItemEnabled(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
783 }
784 
785 void SalInstanceToolbar::set_item_visible(const OString& rIdent, bool bVisible)
786 {
787  m_xToolBox->ShowItem(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), bVisible);
788 }
789 
790 void SalInstanceToolbar::set_item_help_id(const OString& rIdent, const OString& rHelpId)
791 {
792  m_xToolBox->SetHelpId(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), rHelpId);
793 }
794 
795 bool SalInstanceToolbar::get_item_visible(const OString& rIdent) const
796 {
797  return m_xToolBox->IsItemVisible(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
798 }
799 
800 void SalInstanceToolbar::set_item_active(const OString& rIdent, bool bActive)
801 {
802  sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
803  m_xToolBox->CheckItem(nItemId, bActive);
804 }
805 
806 bool SalInstanceToolbar::get_item_active(const OString& rIdent) const
807 {
808  return m_xToolBox->IsItemChecked(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
809 }
810 
811 void SalInstanceToolbar::set_menu_item_active(const OString& rIdent, bool bActive)
812 {
813  sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
815 
816  if (bActive)
817  {
818  m_sStartShowIdent = m_xToolBox->GetItemCommand(nItemId).toUtf8();
820  }
821 
822  auto pFloat = m_aFloats[nItemId];
823  if (pFloat)
824  {
825  if (bActive)
828  else
830  }
831  auto pPopup = m_aMenus[nItemId];
832  if (pPopup)
833  {
834  if (bActive)
835  {
836  tools::Rectangle aRect = m_xToolBox->GetItemRect(nItemId);
837  pPopup->Execute(m_xToolBox, aRect, PopupMenuFlags::ExecuteDown);
838  }
839  else
840  pPopup->EndExecute();
841  }
842 
843  m_sStartShowIdent.clear();
844 }
845 
846 bool SalInstanceToolbar::get_menu_item_active(const OString& rIdent) const
847 {
848  sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
850 
851  if (rIdent == m_sStartShowIdent)
852  return true;
853 
854  auto aFloat = m_aFloats.find(nItemId);
855  if (aFloat != m_aFloats.end())
856  {
857  return vcl::Window::GetDockingManager()->IsInPopupMode(aFloat->second);
858  }
859 
860  auto aPopup = m_aMenus.find(nItemId);
861  if (aPopup != m_aMenus.end())
862  {
863  return PopupMenu::GetActivePopupMenu() == aPopup->second;
864  }
865 
866  return false;
867 }
868 
869 void SalInstanceToolbar::set_item_popover(const OString& rIdent, weld::Widget* pPopover)
870 {
871  SalInstanceWidget* pPopoverWidget = dynamic_cast<SalInstanceWidget*>(pPopover);
872 
873  vcl::Window* pFloat = pPopoverWidget ? pPopoverWidget->getWidget() : nullptr;
874  if (pFloat)
875  {
876  pFloat->AddEventListener(LINK(this, SalInstanceToolbar, MenuToggleListener));
877  pFloat->EnableDocking();
878  }
879 
880  sal_uInt16 nId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
881  auto xOldFloat = m_aFloats[nId];
882  if (xOldFloat)
883  {
884  xOldFloat->RemoveEventListener(LINK(this, SalInstanceToolbar, MenuToggleListener));
885  }
886  m_aFloats[nId] = pFloat;
887  m_aMenus[nId] = nullptr;
888 }
889 
890 void SalInstanceToolbar::set_item_menu(const OString& rIdent, weld::Menu* pMenu)
891 {
892  SalInstanceMenu* pInstanceMenu = dynamic_cast<SalInstanceMenu*>(pMenu);
893 
894  PopupMenu* pPopup = pInstanceMenu ? pInstanceMenu->getMenu() : nullptr;
895 
896  sal_uInt16 nId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
897  m_aMenus[nId] = pPopup;
898  m_aFloats[nId] = nullptr;
899 }
900 
901 void SalInstanceToolbar::insert_separator(int pos, const OUString& /*rId*/)
902 {
903  auto nInsertPos = pos == -1 ? ToolBox::APPEND : pos;
904  m_xToolBox->InsertSeparator(nInsertPos, 5);
905 }
906 
908 
909 OString SalInstanceToolbar::get_item_ident(int nIndex) const
910 {
911  return m_xToolBox->GetItemCommand(m_xToolBox->GetItemId(nIndex)).toUtf8();
912 }
913 
914 void SalInstanceToolbar::set_item_ident(int nIndex, const OString& rIdent)
915 {
917  OUString::fromUtf8(rIdent));
918 }
919 
920 void SalInstanceToolbar::set_item_label(int nIndex, const OUString& rLabel)
921 {
922  m_xToolBox->SetItemText(m_xToolBox->GetItemId(nIndex), rLabel);
923 }
924 
925 OUString SalInstanceToolbar::get_item_label(const OString& rIdent) const
926 {
927  return m_xToolBox->GetItemText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
928 }
929 
930 void SalInstanceToolbar::set_item_label(const OString& rIdent, const OUString& rLabel)
931 {
932  m_xToolBox->SetItemText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), rLabel);
933 }
934 
935 void SalInstanceToolbar::set_item_icon_name(const OString& rIdent, const OUString& rIconName)
936 {
937  m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)),
938  Image(StockImage::Yes, rIconName));
939 }
940 
941 void SalInstanceToolbar::set_item_image(const OString& rIdent,
942  const css::uno::Reference<css::graphic::XGraphic>& rIcon)
943 {
944  m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), Image(rIcon));
945 }
946 
947 void SalInstanceToolbar::set_item_image(const OString& rIdent, VirtualDevice* pDevice)
948 {
949  if (pDevice)
950  m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)),
951  createImage(*pDevice));
952  else
953  m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), Image());
954 }
955 
957  const css::uno::Reference<css::graphic::XGraphic>& rIcon)
958 {
959  m_xToolBox->SetItemImage(m_xToolBox->GetItemId(nIndex), Image(rIcon));
960 }
961 
962 void SalInstanceToolbar::set_item_tooltip_text(int nIndex, const OUString& rTip)
963 {
965 }
966 
967 void SalInstanceToolbar::set_item_tooltip_text(const OString& rIdent, const OUString& rTip)
968 {
969  m_xToolBox->SetQuickHelpText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), rTip);
970 }
971 
972 OUString SalInstanceToolbar::get_item_tooltip_text(const OString& rIdent) const
973 {
974  return m_xToolBox->GetQuickHelpText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)));
975 }
976 
978 
980 {
982  switch (eType)
983  {
985  eButtonSize = ToolBoxButtonSize::Small;
986  break;
988  eButtonSize = ToolBoxButtonSize::Large;
989  break;
991  eButtonSize = ToolBoxButtonSize::Size32;
992  break;
993  }
994  if (m_xToolBox->GetToolboxButtonSize() != eButtonSize)
995  {
996  m_xToolBox->SetToolboxButtonSize(eButtonSize);
998  }
999 }
1000 
1002 {
1003  return m_xToolBox->GetModifier();
1004 }
1005 
1006 int SalInstanceToolbar::get_drop_index(const Point& rPoint) const
1007 {
1008  auto nRet = m_xToolBox->GetItemPos(rPoint);
1009  if (nRet == ToolBox::ITEM_NOTFOUND)
1010  return 0;
1011  return nRet;
1012 }
1013 
1015 {
1018 }
1019 
1021 {
1022  sal_uInt16 nItemId = m_xToolBox->GetCurItemId();
1023  signal_clicked(m_xToolBox->GetItemCommand(nItemId).toUtf8());
1024 }
1025 
1027 {
1028  sal_uInt16 nItemId = m_xToolBox->GetCurItemId();
1029  set_menu_item_active(m_xToolBox->GetItemCommand(nItemId).toUtf8(), true);
1030 }
1031 
1032 IMPL_LINK(SalInstanceToolbar, MenuToggleListener, VclWindowEvent&, rEvent, void)
1033 {
1034  if (rEvent.GetId() == VclEventId::WindowEndPopupMode)
1035  {
1036  for (auto& rFloat : m_aFloats)
1037  {
1038  if (rEvent.GetWindow() == rFloat.second)
1039  {
1040  sal_uInt16 nItemId = rFloat.first;
1041  signal_toggle_menu(m_xToolBox->GetItemCommand(nItemId).toUtf8());
1042  break;
1043  }
1044  }
1045  }
1046 }
1047 
1048 namespace
1049 {
1050 class SalInstanceSizeGroup : public weld::SizeGroup
1051 {
1052 private:
1053  std::shared_ptr<VclSizeGroup> m_xGroup;
1054 
1055 public:
1056  SalInstanceSizeGroup()
1057  : m_xGroup(std::make_shared<VclSizeGroup>())
1058  {
1059  }
1060  virtual void add_widget(weld::Widget* pWidget) override
1061  {
1062  SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
1063  assert(pVclWidget && pVclWidget->getWidget());
1064  pVclWidget->getWidget()->add_to_size_group(m_xGroup);
1065  }
1066  virtual void set_mode(VclSizeGroupMode eMode) override { m_xGroup->set_mode(eMode); }
1067 };
1068 }
1069 
1071 {
1072  vcl::Window* pChildLoop = _pWindow->GetWindow(GetWindowType::FirstChild);
1073  while (pChildLoop)
1074  {
1075  // does the window participate in the tabbing order?
1076  if (pChildLoop->GetStyle() & WB_DIALOGCONTROL)
1077  implResetDefault(pChildLoop);
1078 
1079  // is it a button?
1080  WindowType eType = pChildLoop->GetType();
1081  if ((WindowType::PUSHBUTTON == eType) || (WindowType::OKBUTTON == eType)
1082  || (WindowType::CANCELBUTTON == eType) || (WindowType::HELPBUTTON == eType)
1083  || (WindowType::IMAGEBUTTON == eType) || (WindowType::MENUBUTTON == eType)
1084  || (WindowType::MOREBUTTON == eType))
1085  {
1086  pChildLoop->SetStyle(pChildLoop->GetStyle() & ~WB_DEFBUTTON);
1087  }
1088 
1089  // the next one ...
1090  pChildLoop = pChildLoop->GetWindow(GetWindowType::Next);
1091  }
1092 }
1093 
1095  bool bTakeOwnership)
1096  : SalInstanceWidget(pContainer, pBuilder, bTakeOwnership)
1097  , m_xContainer(pContainer)
1098 {
1099 }
1100 
1102 {
1103  SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
1104  assert(pVclWidget);
1105  SalInstanceContainer* pNewVclParent = dynamic_cast<SalInstanceContainer*>(pNewParent);
1106  assert(!pNewParent || pNewVclParent);
1107  if (pNewVclParent)
1108  pVclWidget->getWidget()->SetParent(pNewVclParent->getWidget());
1109  else
1110  pVclWidget->getWidget()->SetParentToDefaultWindow();
1111 }
1112 
1114 {
1116 }
1117 
1118 css::uno::Reference<css::awt::XWindow> SalInstanceContainer::CreateChildFrame()
1119 {
1120  auto xPage = VclPtr<VclBin>::Create(m_xContainer.get());
1121  xPage->set_expand(true);
1122  xPage->Show();
1123  return css::uno::Reference<css::awt::XWindow>(xPage->GetComponentInterface(),
1124  css::uno::UNO_QUERY);
1125 }
1126 
1127 std::unique_ptr<weld::Container> SalInstanceWidget::weld_parent() const
1128 {
1129  vcl::Window* pParent = m_xWidget->GetParent();
1130  if (!pParent)
1131  return nullptr;
1132  return std::make_unique<SalInstanceContainer>(pParent, m_pBuilder, false);
1133 }
1134 
1136 {
1138  m_xWidget->PaintToDevice(&rOutput, Point());
1139 }
1140 
1141 namespace
1142 {
1143 class SalInstanceBox : public SalInstanceContainer, public virtual weld::Box
1144 {
1145 private:
1146  VclPtr<VclBox> m_xBox;
1147 public:
1148  SalInstanceBox(VclBox* pContainer, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1149  : SalInstanceContainer(pContainer, pBuilder, bTakeOwnership)
1150  , m_xBox(pContainer)
1151  {
1152  }
1153  virtual void reorder_child(weld::Widget* pWidget, int nNewPosition) override
1154  {
1155  SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
1156  assert(pVclWidget);
1157  pVclWidget->getWidget()->reorderWithinParent(nNewPosition);
1158  }
1159  virtual void sort_native_button_order() override
1160  {
1161  ::sort_native_button_order(*m_xBox);
1162  }
1163 };
1164 
1165 void CollectChildren(const vcl::Window& rCurrent, const basegfx::B2IPoint& rTopLeft,
1166  weld::ScreenShotCollection& rControlDataCollection)
1167 {
1168  if (rCurrent.IsVisible())
1169  {
1170  const Point aCurrentPos(rCurrent.GetPosPixel());
1171  const Size aCurrentSize(rCurrent.GetSizePixel());
1172  const basegfx::B2IPoint aCurrentTopLeft(rTopLeft.getX() + aCurrentPos.X(),
1173  rTopLeft.getY() + aCurrentPos.Y());
1174  const basegfx::B2IRange aCurrentRange(
1175  aCurrentTopLeft,
1176  aCurrentTopLeft + basegfx::B2IPoint(aCurrentSize.Width(), aCurrentSize.Height()));
1177 
1178  if (!aCurrentRange.isEmpty())
1179  {
1180  rControlDataCollection.emplace_back(rCurrent.GetHelpId(), aCurrentRange);
1181  }
1182 
1183  for (sal_uInt16 a(0); a < rCurrent.GetChildCount(); a++)
1184  {
1185  vcl::Window* pChild = rCurrent.GetChild(a);
1186  if (nullptr != pChild)
1187  {
1188  CollectChildren(*pChild, aCurrentTopLeft, rControlDataCollection);
1189  }
1190  }
1191  }
1192 }
1193 
1194 }
1195 
1197 {
1198  for (vcl::Window* pChild = pParent->GetWindow(GetWindowType::FirstChild); pChild;
1199  pChild = pChild->GetWindow(GetWindowType::Next))
1200  override_child_help(pChild);
1201  pParent->SetHelpHdl(LINK(this, SalInstanceWindow, HelpHdl));
1202 }
1203 
1205 {
1206  for (vcl::Window* pChild = pParent->GetWindow(GetWindowType::FirstChild); pChild;
1207  pChild = pChild->GetWindow(GetWindowType::Next))
1208  clear_child_help(pChild);
1210 }
1211 
1213  bool bTakeOwnership)
1214  : SalInstanceContainer(pWindow, pBuilder, bTakeOwnership)
1215  , m_xWindow(pWindow)
1216 {
1218 }
1219 
1220 void SalInstanceWindow::set_title(const OUString& rTitle) { m_xWindow->SetText(rTitle); }
1221 
1222 OUString SalInstanceWindow::get_title() const { return m_xWindow->GetText(); }
1223 
1225 {
1226  if (bBusy)
1227  m_xWindow->EnterWait();
1228  else
1229  m_xWindow->LeaveWait();
1230 }
1231 
1232 css::uno::Reference<css::awt::XWindow> SalInstanceWindow::GetXWindow()
1233 {
1234  css::uno::Reference<css::awt::XWindow> xWindow(m_xWindow->GetComponentInterface(),
1235  css::uno::UNO_QUERY);
1236  return xWindow;
1237 }
1238 
1240 {
1241  if (SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get()))
1242  {
1243  pSysWin->setOptimalLayoutSize();
1244  return;
1245  }
1246  if (DockingWindow* pDockWin = dynamic_cast<DockingWindow*>(m_xWindow.get()))
1247  {
1248  pDockWin->setOptimalLayoutSize();
1249  return;
1250  }
1251  assert(false && "must be system or docking window");
1252 }
1253 
1255 
1257 
1259 
1261 
1263 
1265 {
1266  return m_xWindow->GetDesktopRectPixel();
1267 }
1268 
1269 void SalInstanceWindow::set_centered_on_parent(bool /*bTrackGeometryRequests*/)
1270 {
1271  if (vcl::Window* pParent = m_xWidget->GetParent())
1272  {
1273  Size aParentGeometry(pParent->GetSizePixel());
1274  Size aGeometry(m_xWidget->get_preferred_size());
1275  auto nX = (aParentGeometry.Width() - aGeometry.Width()) / 2;
1276  auto nY = (aParentGeometry.Height() - aGeometry.Height()) / 2;
1277  m_xWidget->SetPosPixel(Point(nX, nY));
1278  }
1279 }
1280 
1282 
1284 
1286 {
1288 }
1289 
1290 void SalInstanceWindow::set_window_state(const OString& rStr)
1291 {
1292  SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
1293  assert(pSysWin);
1294  pSysWin->SetWindowState(rStr);
1295 }
1296 
1298 {
1299  SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
1300  assert(pSysWin);
1301  return pSysWin->GetWindowState(nMask);
1302 }
1303 
1305 
1307 {
1310 }
1311 
1313 {
1314  if (rEvent.GetId() == VclEventId::WindowActivate
1315  || rEvent.GetId() == VclEventId::WindowDeactivate)
1316  {
1318  return;
1319  }
1321 }
1322 
1324 {
1325  SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
1326  assert(pSysWin);
1327  pSysWin->createScreenshot(rOutput);
1328 }
1329 
1331 {
1333 
1334  // collect all children. Choose start pos to be negative
1335  // of target dialog's position to get all positions relative to (0,0)
1336  const Point aParentPos(m_xWindow->GetPosPixel());
1337  const basegfx::B2IPoint aTopLeft(-aParentPos.X(), -aParentPos.Y());
1338  CollectChildren(*m_xWindow, aTopLeft, aRet);
1339 
1340  return aRet;
1341 }
1342 
1344 
1346 {
1347  help();
1348  return false;
1349 }
1350 
1351 typedef std::set<VclPtr<vcl::Window>> winset;
1352 
1353 namespace
1354 {
1355 void hideUnless(const vcl::Window* pTop, const winset& rVisibleWidgets,
1356  std::vector<VclPtr<vcl::Window>>& rWasVisibleWidgets)
1357 {
1358  for (vcl::Window* pChild = pTop->GetWindow(GetWindowType::FirstChild); pChild;
1359  pChild = pChild->GetWindow(GetWindowType::Next))
1360  {
1361  if (!pChild->IsVisible())
1362  continue;
1363  if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end())
1364  {
1365  rWasVisibleWidgets.emplace_back(pChild);
1366  pChild->Hide();
1367  }
1368  else if (isContainerWindow(pChild))
1369  {
1370  hideUnless(pChild, rVisibleWidgets, rWasVisibleWidgets);
1371  }
1372  }
1373 }
1374 }
1375 
1377  bool bTakeOwnership)
1378  : SalInstanceWindow(pDialog, pBuilder, bTakeOwnership)
1379  , m_xDialog(pDialog)
1380  , m_nOldEditWidthReq(0)
1381  , m_nOldBorderWidth(0)
1382 {
1383  const bool bScreenshotMode(officecfg::Office::Common::Misc::ScreenshotMode::get());
1384  if (bScreenshotMode)
1385  {
1386  m_xDialog->SetPopupMenuHdl(LINK(this, SalInstanceDialog, PopupScreenShotMenuHdl));
1387  }
1388 }
1389 
1390 bool SalInstanceDialog::runAsync(std::shared_ptr<weld::DialogController> aOwner,
1391  const std::function<void(sal_Int32)>& rEndDialogFn)
1392 {
1394  aCtx.mxOwnerDialogController = aOwner;
1395  aCtx.maEndDialogFn = rEndDialogFn;
1396  VclButtonBox* pActionArea = m_xDialog->get_action_area();
1397  if (pActionArea)
1398  sort_native_button_order(*pActionArea);
1399  return m_xDialog->StartExecuteAsync(aCtx);
1400 }
1401 
1402 bool SalInstanceDialog::runAsync(std::shared_ptr<Dialog> const& rxSelf,
1403  const std::function<void(sal_Int32)>& rEndDialogFn)
1404 {
1405  assert(rxSelf.get() == this);
1407  // In order to store a shared_ptr to ourself, we have to have been constructed by make_shared,
1408  // which is that rxSelf enforces.
1409  aCtx.mxOwnerSelf = rxSelf;
1410  aCtx.maEndDialogFn = rEndDialogFn;
1411  VclButtonBox* pActionArea = m_xDialog->get_action_area();
1412  if (pActionArea)
1413  sort_native_button_order(*pActionArea);
1414  return m_xDialog->StartExecuteAsync(aCtx);
1415 }
1416 
1418 {
1419  SalInstanceWidget* pVclEdit = dynamic_cast<SalInstanceWidget*>(pEdit);
1420  assert(pVclEdit);
1421  SalInstanceWidget* pVclButton = dynamic_cast<SalInstanceWidget*>(pButton);
1422 
1423  vcl::Window* pRefEdit = pVclEdit->getWidget();
1424  vcl::Window* pRefBtn = pVclButton ? pVclButton->getWidget() : nullptr;
1425 
1426  auto nOldEditWidth = pRefEdit->GetSizePixel().Width();
1427  m_nOldEditWidthReq = pRefEdit->get_width_request();
1428 
1429  //We want just pRefBtn and pRefEdit to be shown
1430  //mark widgets we want to be visible, starting with pRefEdit
1431  //and all its direct parents.
1432  winset aVisibleWidgets;
1433  vcl::Window* pContentArea = m_xDialog->get_content_area();
1434  for (vcl::Window* pCandidate = pRefEdit;
1435  pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
1436  pCandidate = pCandidate->GetWindow(GetWindowType::RealParent))
1437  {
1438  aVisibleWidgets.insert(pCandidate);
1439  }
1440  //same again with pRefBtn, except stop if there's a
1441  //shared parent in the existing widgets
1442  for (vcl::Window* pCandidate = pRefBtn;
1443  pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
1444  pCandidate = pCandidate->GetWindow(GetWindowType::RealParent))
1445  {
1446  if (aVisibleWidgets.insert(pCandidate).second)
1447  break;
1448  }
1449 
1450  //hide everything except the aVisibleWidgets
1451  hideUnless(pContentArea, aVisibleWidgets, m_aHiddenWidgets);
1452 
1453  // the insert function case has an initially hidden edit widget, so it has
1454  // not start size, so take larger of actual size and size request
1455  pRefEdit->set_width_request(std::max(nOldEditWidth, m_nOldEditWidthReq));
1458  if (vcl::Window* pActionArea = m_xDialog->get_action_area())
1459  pActionArea->Hide();
1461  m_xRefEdit = pRefEdit;
1462 }
1463 
1465 {
1466  // All others: Show();
1467  for (VclPtr<vcl::Window> const& pWindow : m_aHiddenWidgets)
1468  {
1469  pWindow->Show();
1470  }
1471  m_aHiddenWidgets.clear();
1472 
1474  m_xRefEdit.clear();
1476  if (vcl::Window* pActionArea = m_xDialog->get_action_area())
1477  pActionArea->Show();
1479 }
1480 
1483 {
1485 }
1486 
1488 {
1489  VclButtonBox* pActionArea = m_xDialog->get_action_area();
1490  if (pActionArea)
1491  sort_native_button_order(*pActionArea);
1492  return m_xDialog->Execute();
1493 }
1494 
1495 void SalInstanceDialog::response(int nResponse) { m_xDialog->EndDialog(nResponse); }
1496 
1497 void SalInstanceDialog::add_button(const OUString& rText, int nResponse, const OString& rHelpId)
1498 {
1500  VclPtr<PushButton> xButton(
1502  xButton->SetText(rText);
1503  xButton->SetHelpId(rHelpId);
1504 
1505  switch (nResponse)
1506  {
1507  case RET_OK:
1508  xButton->set_id("ok");
1509  break;
1510  case RET_CLOSE:
1511  xButton->set_id("close");
1512  break;
1513  case RET_CANCEL:
1514  xButton->set_id("cancel");
1515  break;
1516  case RET_YES:
1517  xButton->set_id("yes");
1518  break;
1519  case RET_NO:
1520  xButton->set_id("no");
1521  break;
1522  }
1523 
1524  xButton->Show();
1525  m_xDialog->add_button(xButton, nResponse, true);
1526 }
1527 
1529 {
1530  if (get_modal() == bModal)
1531  return;
1532  m_xDialog->SetModalInputMode(bModal);
1533 }
1534 
1536 
1538 {
1539  m_xDialog->set_default_response(nResponse);
1540 }
1541 
1543 {
1545 }
1546 
1547 IMPL_LINK(SalInstanceDialog, PopupScreenShotMenuHdl, const CommandEvent&, rCEvt, bool)
1548 {
1549  if (CommandEventId::ContextMenu == rCEvt.GetCommand())
1550  {
1551  const Point aMenuPos(rCEvt.GetMousePosPixel());
1553  sal_uInt16 nLocalID(1);
1554 
1555  aMenu->InsertItem(nLocalID, VclResId(SV_BUTTONTEXT_SCREENSHOT));
1556  aMenu->SetHelpText(nLocalID, VclResId(SV_HELPTEXT_SCREENSHOT));
1557  aMenu->SetHelpId(nLocalID, "InteractiveScreenshotMode");
1558  aMenu->EnableItem(nLocalID);
1559 
1560  const sal_uInt16 nId(aMenu->Execute(m_xDialog, aMenuPos));
1561 
1562  // 0 == no selection (so not usable as ID)
1563  if (0 != nId)
1564  {
1565  // open screenshot annotation dialog
1568  = pFact->CreateScreenshotAnnotationDlg(*this);
1570 
1571  if (pDialog)
1572  {
1573  // currently just execute the dialog, no need to do
1574  // different things for ok/cancel. This may change later,
1575  // for that case use 'if (pDlg->Execute() == RET_OK)'
1576  pDialog->Execute();
1577  }
1578  }
1579 
1580  // consume event when:
1581  // - CommandEventId::ContextMenu
1582  // - bScreenshotMode
1583  return true;
1584  }
1585 
1586  return false;
1587 }
1588 
1590  bool bTakeOwnership)
1591  : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership)
1592  , m_xMessageDialog(pDialog)
1593 {
1594 }
1595 
1597 {
1599 }
1600 
1602 {
1604 }
1605 
1607 {
1609 }
1610 
1612 {
1614 }
1615 
1617 {
1619 }
1620 
1621 namespace
1622 {
1623 
1624 class SalInstanceAssistant : public SalInstanceDialog, public virtual weld::Assistant
1625 {
1626 private:
1627  VclPtr<vcl::RoadmapWizard> m_xWizard;
1628  std::vector<std::unique_ptr<SalInstanceContainer>> m_aPages;
1629  std::vector<VclPtr<TabPage>> m_aAddedPages;
1630  std::vector<int> m_aIds;
1631  std::vector<VclPtr<VclGrid>> m_aAddedGrids;
1632  Idle m_aUpdateRoadmapIdle;
1633 
1634  int find_page(const OString& rIdent) const
1635  {
1636  for (size_t i = 0; i < m_aAddedPages.size(); ++i)
1637  {
1638  if (m_aAddedPages[i]->get_id().toUtf8() == rIdent)
1639  return i;
1640  }
1641  return -1;
1642  }
1643 
1644  int find_id(int nId) const
1645  {
1646  for (size_t i = 0; i < m_aIds.size(); ++i)
1647  {
1648  if (nId == m_aIds[i])
1649  return i;
1650  }
1651  return -1;
1652  }
1653 
1654  DECL_LINK(OnRoadmapItemSelected, LinkParamNone*, void);
1655  DECL_LINK(UpdateRoadmap_Hdl, Timer*, void);
1656 
1657 public:
1658  SalInstanceAssistant(vcl::RoadmapWizard* pDialog, SalInstanceBuilder* pBuilder,
1659  bool bTakeOwnership)
1660  : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership)
1661  , m_xWizard(pDialog)
1662  {
1663  m_xWizard->SetItemSelectHdl(LINK(this, SalInstanceAssistant, OnRoadmapItemSelected));
1664 
1665  m_aUpdateRoadmapIdle.SetInvokeHandler(LINK(this, SalInstanceAssistant, UpdateRoadmap_Hdl));
1666  m_aUpdateRoadmapIdle.SetPriority(TaskPriority::HIGHEST);
1667  }
1668 
1669  virtual int get_current_page() const override { return find_id(m_xWizard->GetCurLevel()); }
1670 
1671  virtual int get_n_pages() const override { return m_aAddedPages.size(); }
1672 
1673  virtual OString get_page_ident(int nPage) const override
1674  {
1675  return m_aAddedPages[nPage]->get_id().toUtf8();
1676  }
1677 
1678  virtual OString get_current_page_ident() const override
1679  {
1680  return get_page_ident(get_current_page());
1681  }
1682 
1683  virtual void set_current_page(int nPage) override
1684  {
1686 
1687  // take the first shown page as the size for all pages
1688  if (m_xWizard->GetPageSizePixel().Width() == 0)
1689  {
1690  Size aFinalSize;
1691  for (int i = 0, nPages = get_n_pages(); i < nPages; ++i)
1692  {
1693  TabPage* pPage = m_xWizard->GetPage(m_aIds[i]);
1694  assert(pPage);
1695  Size aPageSize(pPage->get_preferred_size());
1696  if (aPageSize.Width() > aFinalSize.Width())
1697  aFinalSize.setWidth(aPageSize.Width());
1698  if (aPageSize.Height() > aFinalSize.Height())
1699  aFinalSize.setHeight(aPageSize.Height());
1700  }
1701  m_xWizard->SetPageSizePixel(aFinalSize);
1702  }
1703 
1704  (void)m_xWizard->ShowPage(m_aIds[nPage]);
1706  }
1707 
1708  virtual void set_current_page(const OString& rIdent) override
1709  {
1710  int nIndex = find_page(rIdent);
1711  if (nIndex == -1)
1712  return;
1713  set_current_page(nIndex);
1714  }
1715 
1716  virtual void set_page_index(const OString& rIdent, int nNewIndex) override
1717  {
1718  int nOldIndex = find_page(rIdent);
1719 
1720  if (nOldIndex == -1)
1721  return;
1722 
1723  if (nOldIndex == nNewIndex)
1724  return;
1725 
1727 
1728  auto entry = std::move(m_aAddedPages[nOldIndex]);
1729  m_aAddedPages.erase(m_aAddedPages.begin() + nOldIndex);
1730  m_aAddedPages.insert(m_aAddedPages.begin() + nNewIndex, std::move(entry));
1731 
1732  int nId = m_aIds[nOldIndex];
1733  m_aIds.erase(m_aIds.begin() + nOldIndex);
1734  m_aIds.insert(m_aIds.begin() + nNewIndex, nId);
1735 
1736  m_aUpdateRoadmapIdle.Start();
1737 
1739  }
1740 
1741  virtual weld::Container* append_page(const OString& rIdent) override
1742  {
1743  VclPtrInstance<TabPage> xPage(m_xWizard);
1744  VclPtrInstance<VclGrid> xGrid(xPage);
1745  xPage->set_id(OUString::fromUtf8(rIdent));
1746  xPage->Show();
1747  xGrid->set_hexpand(true);
1748  xGrid->set_vexpand(true);
1749  xGrid->Show();
1750  m_xWizard->AddPage(xPage);
1751  m_aIds.push_back(m_aAddedPages.size());
1752  m_xWizard->SetPage(m_aIds.back(), xPage);
1753  m_aAddedPages.push_back(xPage);
1754  m_aAddedGrids.push_back(xGrid);
1755 
1756  m_aUpdateRoadmapIdle.Start();
1757 
1758  m_aPages.emplace_back(new SalInstanceContainer(xGrid, m_pBuilder, false));
1759  return m_aPages.back().get();
1760  }
1761 
1762  virtual OUString get_page_title(const OString& rIdent) const override
1763  {
1764  int nIndex = find_page(rIdent);
1765  if (nIndex == -1)
1766  return OUString();
1767  return m_aAddedPages[nIndex]->GetText();
1768  }
1769 
1770  virtual void set_page_title(const OString& rIdent, const OUString& rTitle) override
1771  {
1772  int nIndex = find_page(rIdent);
1773  if (nIndex == -1)
1774  return;
1775  if (m_aAddedPages[nIndex]->GetText() != rTitle)
1776  {
1778  m_aAddedPages[nIndex]->SetText(rTitle);
1779  m_aUpdateRoadmapIdle.Start();
1781  }
1782  }
1783 
1784  virtual void set_page_sensitive(const OString& rIdent, bool bSensitive) override
1785  {
1786  int nIndex = find_page(rIdent);
1787  if (nIndex == -1)
1788  return;
1789  if (m_aAddedPages[nIndex]->IsEnabled() != bSensitive)
1790  {
1792  m_aAddedPages[nIndex]->Enable(bSensitive);
1793  m_aUpdateRoadmapIdle.Start();
1795  }
1796  }
1797 
1798  virtual void set_page_side_help_id(const OString& rHelpId) override
1799  {
1800  m_xWizard->SetRoadmapHelpId(rHelpId);
1801  }
1802 
1803  weld::Button* weld_widget_for_response(int nResponse) override;
1804 
1805  virtual ~SalInstanceAssistant() override
1806  {
1807  for (auto& rGrid : m_aAddedGrids)
1808  rGrid.disposeAndClear();
1809  for (auto& rPage : m_aAddedPages)
1810  rPage.disposeAndClear();
1811  }
1812 };
1813 
1814 }
1815 
1816 IMPL_LINK_NOARG(SalInstanceAssistant, OnRoadmapItemSelected, LinkParamNone*, void)
1817 {
1818  if (notify_events_disabled())
1819  return;
1820  auto nCurItemId = m_xWizard->GetCurrentRoadmapItemID();
1821  int nPageIndex(find_id(nCurItemId));
1822  if (!signal_jump_page(get_page_ident(nPageIndex)) && nCurItemId != m_xWizard->GetCurLevel())
1823  m_xWizard->SelectRoadmapItemByID(m_xWizard->GetCurLevel());
1824 }
1825 
1826 IMPL_LINK_NOARG(SalInstanceAssistant, UpdateRoadmap_Hdl, Timer*, void)
1827 {
1828  disable_notify_events();
1829 
1830  m_xWizard->DeleteRoadmapItems();
1831 
1832  int nPos = 0;
1833  for (size_t i = 0; i < m_aAddedPages.size(); ++i)
1834  {
1835  const OUString& rLabel = m_aAddedPages[i]->GetText();
1836  bool bSensitive = m_aAddedPages[i]->IsEnabled();
1837  if (rLabel.isEmpty())
1838  continue;
1839  m_xWizard->InsertRoadmapItem(nPos++, rLabel, m_aIds[i], bSensitive);
1840  }
1841 
1842  m_xWizard->SelectRoadmapItemByID(m_aIds[get_current_page()]);
1843 
1844  m_xWizard->ShowRoadmap(nPos != 0);
1845 
1846  enable_notify_events();
1847 }
1848 
1849 namespace
1850 {
1851 class SalInstanceFrame : public SalInstanceContainer, public virtual weld::Frame
1852 {
1853 private:
1855 
1856 public:
1857  SalInstanceFrame(VclFrame* pFrame, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1858  : SalInstanceContainer(pFrame, pBuilder, bTakeOwnership)
1859  , m_xFrame(pFrame)
1860  {
1861  }
1862 
1863  virtual void set_label(const OUString& rText) override { m_xFrame->set_label(rText); }
1864 
1865  virtual OUString get_label() const override { return m_xFrame->get_label(); }
1866 
1867  virtual std::unique_ptr<weld::Label> weld_label_widget() const override;
1868 };
1869 
1870 class SalInstancePaned : public SalInstanceContainer, public virtual weld::Paned
1871 {
1872 private:
1873  VclPtr<VclPaned> m_xPaned;
1874 
1875 public:
1876  SalInstancePaned(VclPaned* pPaned, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1877  : SalInstanceContainer(pPaned, pBuilder, bTakeOwnership)
1878  , m_xPaned(pPaned)
1879  {
1880  }
1881 
1882  virtual void set_position(int nPos) override
1883  {
1884  m_xPaned->set_position(nPos);
1885  }
1886 
1887  virtual int get_position() const override
1888  {
1889  return m_xPaned->get_position();
1890  }
1891 };
1892 
1893 class SalInstanceScrolledWindow : public SalInstanceContainer, public virtual weld::ScrolledWindow
1894 {
1895 private:
1896  VclPtr<VclScrolledWindow> m_xScrolledWindow;
1897  Link<ScrollBar*, void> m_aOrigVScrollHdl;
1898  Link<ScrollBar*, void> m_aOrigHScrollHdl;
1899  bool m_bUserManagedScrolling;
1900 
1901  DECL_LINK(VscrollHdl, ScrollBar*, void);
1902  DECL_LINK(HscrollHdl, ScrollBar*, void);
1903 
1904 public:
1905  SalInstanceScrolledWindow(VclScrolledWindow* pScrolledWindow, SalInstanceBuilder* pBuilder,
1906  bool bTakeOwnership)
1907  : SalInstanceContainer(pScrolledWindow, pBuilder, bTakeOwnership)
1908  , m_xScrolledWindow(pScrolledWindow)
1909  , m_bUserManagedScrolling(false)
1910  {
1911  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
1912  m_aOrigVScrollHdl = rVertScrollBar.GetScrollHdl();
1913  rVertScrollBar.SetScrollHdl(LINK(this, SalInstanceScrolledWindow, VscrollHdl));
1914  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1915  m_aOrigHScrollHdl = rHorzScrollBar.GetScrollHdl();
1916  rHorzScrollBar.SetScrollHdl(LINK(this, SalInstanceScrolledWindow, HscrollHdl));
1917  }
1918 
1919  virtual void hadjustment_configure(int value, int lower, int upper, int step_increment,
1920  int page_increment, int page_size) override
1921  {
1922  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1923  rHorzScrollBar.SetRangeMin(lower);
1924  rHorzScrollBar.SetRangeMax(upper);
1925  rHorzScrollBar.SetLineSize(step_increment);
1926  rHorzScrollBar.SetPageSize(page_increment);
1927  rHorzScrollBar.SetThumbPos(value);
1928  rHorzScrollBar.SetVisibleSize(page_size);
1929  }
1930 
1931  virtual int hadjustment_get_value() const override
1932  {
1933  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1934  return rHorzScrollBar.GetThumbPos();
1935  }
1936 
1937  virtual void hadjustment_set_value(int value) override
1938  {
1939  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1940  rHorzScrollBar.SetThumbPos(value);
1941  if (!m_bUserManagedScrolling)
1942  m_aOrigHScrollHdl.Call(&rHorzScrollBar);
1943  }
1944 
1945  virtual int hadjustment_get_upper() const override
1946  {
1947  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1948  return rHorzScrollBar.GetRangeMax();
1949  }
1950 
1951  virtual void hadjustment_set_upper(int upper) override
1952  {
1953  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1954  rHorzScrollBar.SetRangeMax(upper);
1955  }
1956 
1957  virtual int hadjustment_get_page_size() const override
1958  {
1959  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1960  return rHorzScrollBar.GetVisibleSize();
1961  }
1962 
1963  virtual void hadjustment_set_page_size(int size) override
1964  {
1965  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1966  return rHorzScrollBar.SetVisibleSize(size);
1967  }
1968 
1969  virtual void hadjustment_set_page_increment(int size) override
1970  {
1971  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1972  return rHorzScrollBar.SetPageSize(size);
1973  }
1974 
1975  virtual void hadjustment_set_step_increment(int size) override
1976  {
1977  ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar();
1978  return rHorzScrollBar.SetLineSize(size);
1979  }
1980 
1981  virtual void set_hpolicy(VclPolicyType eHPolicy) override
1982  {
1983  WinBits nWinBits = m_xScrolledWindow->GetStyle() & ~(WB_AUTOHSCROLL | WB_HSCROLL);
1984  if (eHPolicy == VclPolicyType::ALWAYS)
1985  nWinBits |= WB_HSCROLL;
1986  else if (eHPolicy == VclPolicyType::AUTOMATIC)
1987  nWinBits |= WB_AUTOHSCROLL;
1988  m_xScrolledWindow->SetStyle(nWinBits);
1989  m_xScrolledWindow->queue_resize();
1990  }
1991 
1992  virtual VclPolicyType get_hpolicy() const override
1993  {
1994  WinBits nWinBits = m_xScrolledWindow->GetStyle();
1995  if (nWinBits & WB_AUTOHSCROLL)
1996  return VclPolicyType::AUTOMATIC;
1997  else if (nWinBits & WB_HSCROLL)
1998  return VclPolicyType::ALWAYS;
1999  return VclPolicyType::NEVER;
2000  }
2001 
2002  virtual int get_hscroll_height() const override
2003  {
2004  return m_xScrolledWindow->getHorzScrollBar().get_preferred_size().Height();
2005  }
2006 
2007  virtual void vadjustment_configure(int value, int lower, int upper, int step_increment,
2008  int page_increment, int page_size) override
2009  {
2010  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2011  rVertScrollBar.SetRangeMin(lower);
2012  rVertScrollBar.SetRangeMax(upper);
2013  rVertScrollBar.SetLineSize(step_increment);
2014  rVertScrollBar.SetPageSize(page_increment);
2015  rVertScrollBar.SetThumbPos(value);
2016  rVertScrollBar.SetVisibleSize(page_size);
2017  }
2018 
2019  virtual int vadjustment_get_value() const override
2020  {
2021  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2022  return rVertScrollBar.GetThumbPos();
2023  }
2024 
2025  virtual void vadjustment_set_value(int value) override
2026  {
2027  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2028  rVertScrollBar.SetThumbPos(value);
2029  if (!m_bUserManagedScrolling)
2030  m_aOrigVScrollHdl.Call(&rVertScrollBar);
2031  }
2032 
2033  virtual int vadjustment_get_upper() const override
2034  {
2035  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2036  return rVertScrollBar.GetRangeMax();
2037  }
2038 
2039  virtual void vadjustment_set_upper(int upper) override
2040  {
2041  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2042  rVertScrollBar.SetRangeMax(upper);
2043  }
2044 
2045  virtual int vadjustment_get_lower() const override
2046  {
2047  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2048  return rVertScrollBar.GetRangeMin();
2049  }
2050 
2051  virtual void vadjustment_set_lower(int lower) override
2052  {
2053  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2054  rVertScrollBar.SetRangeMin(lower);
2055  }
2056 
2057  virtual int vadjustment_get_page_size() const override
2058  {
2059  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2060  return rVertScrollBar.GetVisibleSize();
2061  }
2062 
2063  virtual void vadjustment_set_page_size(int size) override
2064  {
2065  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2066  return rVertScrollBar.SetVisibleSize(size);
2067  }
2068 
2069  virtual void vadjustment_set_page_increment(int size) override
2070  {
2071  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2072  return rVertScrollBar.SetPageSize(size);
2073  }
2074 
2075  virtual void vadjustment_set_step_increment(int size) override
2076  {
2077  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2078  return rVertScrollBar.SetLineSize(size);
2079  }
2080 
2081  virtual void set_vpolicy(VclPolicyType eVPolicy) override
2082  {
2083  WinBits nWinBits = m_xScrolledWindow->GetStyle() & ~(WB_AUTOVSCROLL | WB_VSCROLL);
2084  if (eVPolicy == VclPolicyType::ALWAYS)
2085  nWinBits |= WB_VSCROLL;
2086  else if (eVPolicy == VclPolicyType::AUTOMATIC)
2087  nWinBits |= WB_AUTOVSCROLL;
2088  m_xScrolledWindow->SetStyle(nWinBits);
2089  m_xScrolledWindow->queue_resize();
2090  }
2091 
2092  virtual VclPolicyType get_vpolicy() const override
2093  {
2094  WinBits nWinBits = m_xScrolledWindow->GetStyle();
2095  if (nWinBits & WB_AUTOVSCROLL)
2096  return VclPolicyType::AUTOMATIC;
2097  else if (nWinBits & WB_VSCROLL)
2098  return VclPolicyType::ALWAYS;
2099  return VclPolicyType::NEVER;
2100  }
2101 
2102  virtual int get_vscroll_width() const override
2103  {
2104  return m_xScrolledWindow->getVertScrollBar().get_preferred_size().Width();
2105  }
2106 
2107  virtual void set_user_managed_scrolling() override
2108  {
2109  m_bUserManagedScrolling = true;
2110  m_xScrolledWindow->setUserManagedScrolling(true);
2111  }
2112 
2113  virtual ~SalInstanceScrolledWindow() override
2114  {
2115  ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar();
2116  rVertScrollBar.SetScrollHdl(m_aOrigVScrollHdl);
2117  }
2118 };
2119 
2120 }
2121 
2122 IMPL_LINK(SalInstanceScrolledWindow, VscrollHdl, ScrollBar*, pScrollBar, void)
2123 {
2124  signal_vadjustment_changed();
2125  if (!m_bUserManagedScrolling)
2126  m_aOrigVScrollHdl.Call(pScrollBar);
2127 }
2128 
2129 IMPL_LINK_NOARG(SalInstanceScrolledWindow, HscrollHdl, ScrollBar*, void)
2130 {
2131  signal_hadjustment_changed();
2132  if (!m_bUserManagedScrolling)
2133  m_aOrigHScrollHdl.Call(&m_xScrolledWindow->getHorzScrollBar());
2134 }
2135 
2137  : SalInstanceContainer(pNotebook, pBuilder, bTakeOwnership)
2138  , m_xNotebook(pNotebook)
2139 {
2140  m_xNotebook->SetActivatePageHdl(LINK(this, SalInstanceNotebook, ActivatePageHdl));
2141  m_xNotebook->SetDeactivatePageHdl(LINK(this, SalInstanceNotebook, DeactivatePageHdl));
2142 }
2143 
2145 {
2147 }
2148 
2149 OString SalInstanceNotebook::get_page_ident(int nPage) const
2150 {
2151  return m_xNotebook->GetPageName(m_xNotebook->GetPageId(nPage));
2152 }
2153 
2155 {
2157 }
2158 
2159 int SalInstanceNotebook::get_page_index(const OString& rIdent) const
2160 {
2161  sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent);
2162  sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(nPageId);
2163  if (nPageIndex == TAB_PAGE_NOTFOUND)
2164  return -1;
2165  return nPageIndex;
2166 }
2167 
2168 weld::Container* SalInstanceNotebook::get_page(const OString& rIdent) const
2169 {
2170  int nPageIndex = get_page_index(rIdent);
2171  if (nPageIndex == -1)
2172  return nullptr;
2173  sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent);
2174  TabPage* pPage = m_xNotebook->GetTabPage(nPageId);
2175  vcl::Window* pChild = pPage->GetChild(0);
2176  if (m_aPages.size() < nPageIndex + 1U)
2177  m_aPages.resize(nPageIndex + 1U);
2178  if (!m_aPages[nPageIndex])
2179  m_aPages[nPageIndex] = std::make_shared<SalInstanceContainer>(pChild, m_pBuilder, false);
2180  return m_aPages[nPageIndex].get();
2181 }
2182 
2184 {
2186 }
2187 
2188 void SalInstanceNotebook::set_current_page(const OString& rIdent)
2189 {
2191 }
2192 
2193 void SalInstanceNotebook::remove_page(const OString& rIdent)
2194 {
2195  sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent);
2196  sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(nPageId);
2197  if (nPageIndex == TAB_PAGE_NOTFOUND)
2198  return;
2199 
2200  m_xNotebook->RemovePage(nPageId);
2201  if (nPageIndex < m_aPages.size())
2202  m_aPages.erase(m_aPages.begin() + nPageIndex);
2203 
2204  auto iter = m_aAddedPages.find(rIdent);
2205  if (iter != m_aAddedPages.end())
2206  {
2207  iter->second.second.disposeAndClear();
2208  iter->second.first.disposeAndClear();
2209  m_aAddedPages.erase(iter);
2210  }
2211 }
2212 
2213 void SalInstanceNotebook::insert_page(const OString& rIdent, const OUString& rLabel, int nPos)
2214 {
2215  sal_uInt16 nPageCount = m_xNotebook->GetPageCount();
2216  sal_uInt16 nLastPageId = nPageCount ? m_xNotebook->GetPageId(nPageCount - 1) : 0;
2217  sal_uInt16 nNewPageId = nLastPageId + 1;
2218  while (m_xNotebook->GetPagePos(nNewPageId) != TAB_PAGE_NOTFOUND)
2219  ++nNewPageId;
2220  m_xNotebook->InsertPage(nNewPageId, rLabel, nPos == -1 ? TAB_APPEND : nPos);
2222  VclPtrInstance<VclGrid> xGrid(xPage);
2223  xPage->Show();
2224  xGrid->set_hexpand(true);
2225  xGrid->set_vexpand(true);
2226  xGrid->Show();
2227  m_xNotebook->SetTabPage(nNewPageId, xPage);
2228  m_xNotebook->SetPageName(nNewPageId, rIdent);
2229  m_aAddedPages.try_emplace(rIdent, xPage, xGrid);
2230 
2231  if (nPos != -1)
2232  {
2233  unsigned int nPageIndex = static_cast<unsigned int>(nPos);
2234  if (nPageIndex < m_aPages.size())
2235  m_aPages.insert(m_aPages.begin() + nPageIndex, nullptr);
2236  }
2237 }
2238 
2240 
2241 OUString SalInstanceNotebook::get_tab_label_text(const OString& rIdent) const
2242 {
2243  return m_xNotebook->GetPageText(m_xNotebook->GetPageId(rIdent));
2244 }
2245 
2246 void SalInstanceNotebook::set_tab_label_text(const OString& rIdent, const OUString& rText)
2247 {
2248  return m_xNotebook->SetPageText(m_xNotebook->GetPageId(rIdent), rText);
2249 }
2250 
2252 {
2253  for (auto& rItem : m_aAddedPages)
2254  {
2255  rItem.second.second.disposeAndClear();
2256  rItem.second.first.disposeAndClear();
2257  }
2260 }
2261 
2263 {
2264  return !m_aLeavePageHdl.IsSet() || m_aLeavePageHdl.Call(get_current_page_ident());
2265 }
2266 
2268 {
2269  m_aEnterPageHdl.Call(get_current_page_ident());
2270 }
2271 
2272 namespace
2273 {
2274 class SalInstanceVerticalNotebook : public SalInstanceContainer, public virtual weld::Notebook
2275 {
2276 private:
2277  VclPtr<VerticalTabControl> m_xNotebook;
2278  mutable std::vector<std::unique_ptr<SalInstanceContainer>> m_aPages;
2279 
2280  DECL_LINK(DeactivatePageHdl, VerticalTabControl*, bool);
2281  DECL_LINK(ActivatePageHdl, VerticalTabControl*, void);
2282 
2283 public:
2284  SalInstanceVerticalNotebook(VerticalTabControl* pNotebook, SalInstanceBuilder* pBuilder,
2285  bool bTakeOwnership)
2286  : SalInstanceContainer(pNotebook, pBuilder, bTakeOwnership)
2287  , m_xNotebook(pNotebook)
2288  {
2289  m_xNotebook->SetActivatePageHdl(LINK(this, SalInstanceVerticalNotebook, ActivatePageHdl));
2290  m_xNotebook->SetDeactivatePageHdl(
2291  LINK(this, SalInstanceVerticalNotebook, DeactivatePageHdl));
2292  }
2293 
2294  virtual int get_current_page() const override
2295  {
2296  return m_xNotebook->GetPagePos(m_xNotebook->GetCurPageId());
2297  }
2298 
2299  virtual OString get_page_ident(int nPage) const override
2300  {
2301  return m_xNotebook->GetPageId(nPage);
2302  }
2303 
2304  virtual OString get_current_page_ident() const override { return m_xNotebook->GetCurPageId(); }
2305 
2306  virtual int get_page_index(const OString& rIdent) const override
2307  {
2308  sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(rIdent);
2309  if (nPageIndex == TAB_PAGE_NOTFOUND)
2310  return -1;
2311  return nPageIndex;
2312  }
2313 
2314  virtual weld::Container* get_page(const OString& rIdent) const override
2315  {
2316  int nPageIndex = get_page_index(rIdent);
2317  if (nPageIndex == -1)
2318  return nullptr;
2319  auto pChild = m_xNotebook->GetPage(rIdent);
2320  if (m_aPages.size() < nPageIndex + 1U)
2321  m_aPages.resize(nPageIndex + 1U);
2322  if (!m_aPages[nPageIndex])
2323  m_aPages[nPageIndex].reset(new SalInstanceContainer(pChild, m_pBuilder, false));
2324  return m_aPages[nPageIndex].get();
2325  }
2326 
2327  virtual void set_current_page(int nPage) override
2328  {
2329  m_xNotebook->SetCurPageId(m_xNotebook->GetPageId(nPage));
2330  }
2331 
2332  virtual void set_current_page(const OString& rIdent) override
2333  {
2334  m_xNotebook->SetCurPageId(rIdent);
2335  }
2336 
2337  virtual void remove_page(const OString& rIdent) override
2338  {
2339  sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(rIdent);
2340  if (nPageIndex == TAB_PAGE_NOTFOUND)
2341  return;
2342  m_xNotebook->RemovePage(rIdent);
2343  if (nPageIndex < m_aPages.size())
2344  m_aPages.erase(m_aPages.begin() + nPageIndex);
2345  }
2346 
2347  virtual void insert_page(const OString& rIdent, const OUString& rLabel, int nPos) override
2348  {
2349  VclPtrInstance<VclGrid> xGrid(m_xNotebook->GetPageParent());
2350  xGrid->set_hexpand(true);
2351  xGrid->set_vexpand(true);
2352  m_xNotebook->InsertPage(rIdent, rLabel, Image(), "", xGrid, nPos);
2353 
2354  if (nPos != -1)
2355  {
2356  unsigned int nPageIndex = static_cast<unsigned int>(nPos);
2357  if (nPageIndex < m_aPages.size())
2358  m_aPages.insert(m_aPages.begin() + nPageIndex, nullptr);
2359  }
2360  }
2361 
2362  virtual int get_n_pages() const override { return m_xNotebook->GetPageCount(); }
2363 
2364  virtual void set_tab_label_text(const OString& rIdent, const OUString& rText) override
2365  {
2366  return m_xNotebook->SetPageText(rIdent, rText);
2367  }
2368 
2369  virtual OUString get_tab_label_text(const OString& rIdent) const override
2370  {
2371  return m_xNotebook->GetPageText(rIdent);
2372  }
2373 
2374  virtual ~SalInstanceVerticalNotebook() override
2375  {
2378  }
2379 };
2380 
2381 }
2382 
2383 IMPL_LINK_NOARG(SalInstanceVerticalNotebook, DeactivatePageHdl, VerticalTabControl*, bool)
2384 {
2385  return !m_aLeavePageHdl.IsSet() || m_aLeavePageHdl.Call(get_current_page_ident());
2386 }
2387 
2388 IMPL_LINK_NOARG(SalInstanceVerticalNotebook, ActivatePageHdl, VerticalTabControl*, void)
2389 {
2390  m_aEnterPageHdl.Call(get_current_page_ident());
2391 }
2392 
2393 SalInstanceButton::SalInstanceButton(::Button* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2394  : SalInstanceContainer(pButton, pBuilder, bTakeOwnership)
2395  , m_xButton(pButton)
2396  , m_aOldClickHdl(pButton->GetClickHdl())
2397 {
2398  m_xButton->SetClickHdl(LINK(this, SalInstanceButton, ClickHdl));
2399 }
2400 
2401 void SalInstanceButton::set_label(const OUString& rText) { m_xButton->SetText(rText); }
2402 
2404 {
2405  m_xButton->SetImageAlign(ImageAlign::Left);
2406  if (pDevice)
2407  m_xButton->SetModeImage(createImage(*pDevice));
2408  else
2410 }
2411 
2412 void SalInstanceButton::set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage)
2413 {
2414  m_xButton->SetImageAlign(ImageAlign::Left);
2415  m_xButton->SetModeImage(Image(rImage));
2416 }
2417 
2418 void SalInstanceButton::set_from_icon_name(const OUString& rIconName)
2419 {
2421 }
2422 
2424 {
2425  WinBits nBits = m_xButton->GetStyle();
2426  nBits &= ~WB_WORDBREAK;
2427  if (wrap)
2428  nBits |= WB_WORDBREAK;
2429  m_xButton->SetStyle(nBits);
2431 }
2432 
2433 OUString SalInstanceButton::get_label() const { return m_xButton->GetText(); }
2434 
2436 
2437 IMPL_LINK(SalInstanceButton, ClickHdl, ::Button*, pButton, void)
2438 {
2439  //if there's no handler set, disengage our intercept and
2440  //run the click again to get default behaviour for cancel/ok
2441  //etc buttons.
2442  if (!m_aClickHdl.IsSet())
2443  {
2444  pButton->SetClickHdl(m_aOldClickHdl);
2445  pButton->Click();
2446  pButton->SetClickHdl(LINK(this, SalInstanceButton, ClickHdl));
2447  return;
2448  }
2449  signal_clicked();
2450 }
2451 
2453 {
2454  PushButton* pButton = dynamic_cast<PushButton*>(m_xDialog->get_widget_for_response(nResponse));
2455  return pButton ? new SalInstanceButton(pButton, nullptr, false) : nullptr;
2456 }
2457 
2458 weld::Button* SalInstanceAssistant::weld_widget_for_response(int nResponse)
2459 {
2460  PushButton* pButton = nullptr;
2461  if (nResponse == RET_YES)
2462  pButton = m_xWizard->m_pNextPage;
2463  else if (nResponse == RET_NO)
2464  pButton = m_xWizard->m_pPrevPage;
2465  else if (nResponse == RET_OK)
2466  pButton = m_xWizard->m_pFinish;
2467  else if (nResponse == RET_CANCEL)
2468  pButton = m_xWizard->m_pCancel;
2469  else if (nResponse == RET_HELP)
2470  pButton = m_xWizard->m_pHelp;
2471  if (pButton)
2472  return new SalInstanceButton(pButton, nullptr, false);
2473  return nullptr;
2474 }
2475 
2476 namespace
2477 {
2478 class SalInstanceMenuButton : public SalInstanceButton, public virtual weld::MenuButton
2479 {
2480 private:
2481  VclPtr<::MenuButton> m_xMenuButton;
2482  sal_uInt16 m_nLastId;
2483 
2484  DECL_LINK(MenuSelectHdl, ::MenuButton*, void);
2485  DECL_LINK(ActivateHdl, ::MenuButton*, void);
2486 
2487 public:
2488  SalInstanceMenuButton(::MenuButton* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2489  : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2490  , m_xMenuButton(pButton)
2491  , m_nLastId(0)
2492  {
2493  m_xMenuButton->SetActivateHdl(LINK(this, SalInstanceMenuButton, ActivateHdl));
2494  m_xMenuButton->SetSelectHdl(LINK(this, SalInstanceMenuButton, MenuSelectHdl));
2495  if (PopupMenu* pMenu = m_xMenuButton->GetPopupMenu())
2496  {
2498  const auto nCount = pMenu->GetItemCount();
2499  m_nLastId = nCount ? pMenu->GetItemId(nCount - 1) : 0;
2500  }
2501  }
2502 
2503  virtual void set_active(bool active) override
2504  {
2505  if (active == get_active())
2506  return;
2507  if (active)
2508  m_xMenuButton->ExecuteMenu();
2509  else
2510  m_xMenuButton->CancelMenu();
2511  }
2512 
2513  virtual bool get_active() const override { return m_xMenuButton->InPopupMode(); }
2514 
2515  virtual void set_inconsistent(bool /*inconsistent*/) override
2516  {
2517  //not available
2518  }
2519 
2520  virtual bool get_inconsistent() const override { return false; }
2521 
2522  virtual void insert_item(int pos, const OUString& rId, const OUString& rStr,
2523  const OUString* pIconName, VirtualDevice* pImageSurface,
2524  TriState eCheckRadioFalse) override
2525  {
2526  m_nLastId = insert_to_menu(m_nLastId, m_xMenuButton->GetPopupMenu(), pos, rId, rStr,
2527  pIconName, pImageSurface, eCheckRadioFalse);
2528  }
2529 
2530  virtual void insert_separator(int pos, const OUString& rId) override
2531  {
2532  auto nInsertPos = pos == -1 ? MENU_APPEND : pos;
2533  m_xMenuButton->GetPopupMenu()->InsertSeparator(rId.toUtf8(), nInsertPos);
2534  }
2535 
2536  virtual void set_item_sensitive(const OString& rIdent, bool bSensitive) override
2537  {
2538  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2539  pMenu->EnableItem(rIdent, bSensitive);
2540  }
2541 
2542  virtual void remove_item(const OString& rId) override
2543  {
2544  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2545  pMenu->RemoveItem(pMenu->GetItemPos(pMenu->GetItemId(rId)));
2546  }
2547 
2548  virtual void clear() override
2549  {
2550  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2551  pMenu->Clear();
2552  }
2553 
2554  virtual void set_item_active(const OString& rIdent, bool bActive) override
2555  {
2556  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2557  pMenu->CheckItem(rIdent, bActive);
2558  }
2559 
2560  virtual void set_item_label(const OString& rIdent, const OUString& rText) override
2561  {
2562  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2563  pMenu->SetItemText(pMenu->GetItemId(rIdent), rText);
2564  }
2565 
2566  virtual OUString get_item_label(const OString& rIdent) const override
2567  {
2568  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2569  return pMenu->GetItemText(pMenu->GetItemId(rIdent));
2570  }
2571 
2572  virtual void set_item_visible(const OString& rIdent, bool bShow) override
2573  {
2574  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2575  pMenu->ShowItem(pMenu->GetItemId(rIdent), bShow);
2576  }
2577 
2578  virtual void set_item_help_id(const OString& rIdent, const OString& rHelpId) override
2579  {
2580  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2581  pMenu->SetHelpId(pMenu->GetItemId(rIdent), rHelpId);
2582  }
2583 
2584  virtual OString get_item_help_id(const OString& rIdent) const override
2585  {
2586  PopupMenu* pMenu = m_xMenuButton->GetPopupMenu();
2587  return pMenu->GetHelpId(pMenu->GetItemId(rIdent));
2588  }
2589 
2590  virtual void set_popover(weld::Widget* pPopover) override
2591  {
2592  SalInstanceWidget* pPopoverWidget = dynamic_cast<SalInstanceWidget*>(pPopover);
2593  m_xMenuButton->SetPopover(pPopoverWidget ? pPopoverWidget->getWidget() : nullptr);
2594  }
2595 
2596  virtual ~SalInstanceMenuButton() override
2597  {
2598  m_xMenuButton->SetSelectHdl(Link<::MenuButton*, void>());
2599  m_xMenuButton->SetActivateHdl(Link<::MenuButton*, void>());
2600  }
2601 };
2602 
2603 }
2604 
2605 IMPL_LINK_NOARG(SalInstanceMenuButton, MenuSelectHdl, ::MenuButton*, void)
2606 {
2607  signal_selected(m_xMenuButton->GetCurItemIdent());
2608 }
2609 
2610 IMPL_LINK_NOARG(SalInstanceMenuButton, ActivateHdl, ::MenuButton*, void)
2611 {
2612  if (notify_events_disabled())
2613  return;
2614  signal_toggled();
2615 }
2616 
2617 namespace
2618 {
2619 class SalInstanceLinkButton : public SalInstanceContainer, public virtual weld::LinkButton
2620 {
2621 private:
2622  VclPtr<FixedHyperlink> m_xButton;
2623  Link<FixedHyperlink&, void> m_aOrigClickHdl;
2624 
2625  DECL_LINK(ClickHdl, FixedHyperlink&, void);
2626 
2627 public:
2628  SalInstanceLinkButton(FixedHyperlink* pButton, SalInstanceBuilder* pBuilder,
2629  bool bTakeOwnership)
2630  : SalInstanceContainer(pButton, pBuilder, bTakeOwnership)
2631  , m_xButton(pButton)
2632  {
2633  m_aOrigClickHdl = m_xButton->GetClickHdl();
2634  m_xButton->SetClickHdl(LINK(this, SalInstanceLinkButton, ClickHdl));
2635  }
2636 
2637  virtual void set_label(const OUString& rText) override { m_xButton->SetText(rText); }
2638 
2639  virtual OUString get_label() const override { return m_xButton->GetText(); }
2640 
2641  virtual void set_uri(const OUString& rUri) override { m_xButton->SetURL(rUri); }
2642 
2643  virtual OUString get_uri() const override { return m_xButton->GetURL(); }
2644 
2645  virtual ~SalInstanceLinkButton() override { m_xButton->SetClickHdl(m_aOrigClickHdl); }
2646 };
2647 
2648 }
2649 
2650 IMPL_LINK(SalInstanceLinkButton, ClickHdl, FixedHyperlink&, rButton, void)
2651 {
2652  bool bConsumed = signal_activate_link();
2653  if (!bConsumed)
2654  m_aOrigClickHdl.Call(rButton);
2655 }
2656 
2657 namespace
2658 {
2659 class SalInstanceRadioButton : public SalInstanceButton, public virtual weld::RadioButton
2660 {
2661 private:
2662  VclPtr<::RadioButton> m_xRadioButton;
2663 
2664  DECL_LINK(ToggleHdl, ::RadioButton&, void);
2665 
2666 public:
2667  SalInstanceRadioButton(::RadioButton* pButton, SalInstanceBuilder* pBuilder,
2668  bool bTakeOwnership)
2669  : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2670  , m_xRadioButton(pButton)
2671  {
2672  m_xRadioButton->SetToggleHdl(LINK(this, SalInstanceRadioButton, ToggleHdl));
2673  }
2674 
2675  virtual void set_active(bool active) override
2676  {
2678  m_xRadioButton->Check(active);
2680  }
2681 
2682  virtual bool get_active() const override { return m_xRadioButton->IsChecked(); }
2683 
2684  virtual void set_image(VirtualDevice* pDevice) override
2685  {
2686  m_xRadioButton->SetImageAlign(ImageAlign::Center);
2687  if (pDevice)
2688  m_xRadioButton->SetModeImage(createImage(*pDevice));
2689  else
2690  m_xRadioButton->SetModeImage(Image());
2691  }
2692 
2693  virtual void set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) override
2694  {
2695  m_xRadioButton->SetImageAlign(ImageAlign::Center);
2696  m_xRadioButton->SetModeImage(Image(rImage));
2697  }
2698 
2699  virtual void set_from_icon_name(const OUString& rIconName) override
2700  {
2701  m_xRadioButton->SetModeRadioImage(Image(StockImage::Yes, rIconName));
2702  }
2703 
2704  virtual void set_inconsistent(bool /*inconsistent*/) override
2705  {
2706  //not available
2707  }
2708 
2709  virtual bool get_inconsistent() const override { return false; }
2710 
2711  virtual ~SalInstanceRadioButton() override
2712  {
2713  m_xRadioButton->SetToggleHdl(Link<::RadioButton&, void>());
2714  }
2715 };
2716 
2717 }
2718 
2719 IMPL_LINK_NOARG(SalInstanceRadioButton, ToggleHdl, ::RadioButton&, void)
2720 {
2721  if (notify_events_disabled())
2722  return;
2723  signal_toggled();
2724 }
2725 
2726 namespace
2727 {
2728 class SalInstanceToggleButton : public SalInstanceButton, public virtual weld::ToggleButton
2729 {
2730 private:
2731  VclPtr<PushButton> m_xToggleButton;
2732 
2733  DECL_LINK(ToggleListener, VclWindowEvent&, void);
2734 
2735 public:
2736  SalInstanceToggleButton(PushButton* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2737  : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2738  , m_xToggleButton(pButton)
2739  {
2740  }
2741 
2742  virtual void connect_toggled(const Link<ToggleButton&, void>& rLink) override
2743  {
2744  assert(!m_aToggleHdl.IsSet());
2745  m_xToggleButton->AddEventListener(LINK(this, SalInstanceToggleButton, ToggleListener));
2747  }
2748 
2749  virtual void set_active(bool active) override
2750  {
2752  m_xToggleButton->Check(active);
2754  }
2755 
2756  virtual bool get_active() const override { return m_xToggleButton->IsChecked(); }
2757 
2758  virtual void set_inconsistent(bool inconsistent) override
2759  {
2761  m_xToggleButton->SetState(inconsistent ? TRISTATE_INDET : TRISTATE_FALSE);
2763  }
2764 
2765  virtual bool get_inconsistent() const override
2766  {
2767  return m_xToggleButton->GetState() == TRISTATE_INDET;
2768  }
2769 
2770  virtual ~SalInstanceToggleButton() override
2771  {
2772  if (m_aToggleHdl.IsSet())
2773  m_xToggleButton->RemoveEventListener(
2774  LINK(this, SalInstanceToggleButton, ToggleListener));
2775  }
2776 };
2777 
2778 }
2779 
2780 IMPL_LINK(SalInstanceToggleButton, ToggleListener, VclWindowEvent&, rEvent, void)
2781 {
2782  if (notify_events_disabled())
2783  return;
2784  if (rEvent.GetId() == VclEventId::PushbuttonToggle)
2785  signal_toggled();
2786 }
2787 
2789  : SalInstanceButton(pButton, pBuilder, bTakeOwnership)
2790  , m_xCheckButton(pButton)
2791 {
2793 }
2794 
2796 {
2799  m_xCheckButton->Check(active);
2801 }
2802 
2804 
2806 {
2811 }
2812 
2814 {
2815  return m_xCheckButton->GetState() == TRISTATE_INDET;
2816 }
2817 
2819 {
2821 }
2822 
2824 {
2825  if (notify_events_disabled())
2826  return;
2827  m_xCheckButton->EnableTriState(false);
2828  signal_toggled();
2829 }
2830 
2831 namespace
2832 {
2833 class SalInstanceScale : public SalInstanceWidget, public virtual weld::Scale
2834 {
2835 private:
2836  VclPtr<Slider> m_xScale;
2837 
2838  DECL_LINK(SlideHdl, Slider*, void);
2839 
2840 public:
2841  SalInstanceScale(Slider* pScale, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2842  : SalInstanceWidget(pScale, pBuilder, bTakeOwnership)
2843  , m_xScale(pScale)
2844  {
2845  m_xScale->SetSlideHdl(LINK(this, SalInstanceScale, SlideHdl));
2846  }
2847 
2848  virtual void set_value(int value) override { m_xScale->SetThumbPos(value); }
2849 
2850  virtual void set_range(int min, int max) override
2851  {
2852  m_xScale->SetRangeMin(min);
2853  m_xScale->SetRangeMax(max);
2854  }
2855 
2856  virtual int get_value() const override { return m_xScale->GetThumbPos(); }
2857 
2858  virtual void set_increments(int step, int page) override
2859  {
2860  m_xScale->SetLineSize(step);
2861  m_xScale->SetPageSize(page);
2862  }
2863 
2864  virtual void get_increments(int& step, int& page) const override
2865  {
2866  step = m_xScale->GetLineSize();
2867  page = m_xScale->GetPageSize();
2868  }
2869 
2870  virtual ~SalInstanceScale() override { m_xScale->SetSlideHdl(Link<Slider*, void>()); }
2871 };
2872 
2873 }
2874 
2875 IMPL_LINK_NOARG(SalInstanceScale, SlideHdl, Slider*, void) { signal_value_changed(); }
2876 
2877 namespace
2878 {
2879 class SalInstanceSpinner : public SalInstanceWidget, public virtual weld::Spinner
2880 {
2881 private:
2882  VclPtr<Throbber> m_xThrobber;
2883 
2884 public:
2885  SalInstanceSpinner(Throbber* pThrobber, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2886  : SalInstanceWidget(pThrobber, pBuilder, bTakeOwnership)
2887  , m_xThrobber(pThrobber)
2888  {
2889  }
2890 
2891  virtual void start() override { m_xThrobber->start(); }
2892 
2893  virtual void stop() override { m_xThrobber->stop(); }
2894 };
2895 
2896 class SalInstanceProgressBar : public SalInstanceWidget, public virtual weld::ProgressBar
2897 {
2898 private:
2899  VclPtr<::ProgressBar> m_xProgressBar;
2900 
2901 public:
2902  SalInstanceProgressBar(::ProgressBar* pProgressBar, SalInstanceBuilder* pBuilder,
2903  bool bTakeOwnership)
2904  : SalInstanceWidget(pProgressBar, pBuilder, bTakeOwnership)
2905  , m_xProgressBar(pProgressBar)
2906  {
2907  }
2908 
2909  virtual void set_percentage(int value) override { m_xProgressBar->SetValue(value); }
2910 
2911  virtual OUString get_text() const override { return m_xProgressBar->GetText(); }
2912 
2913  virtual void set_text(const OUString& rText) override { m_xProgressBar->SetText(rText); }
2914 };
2915 
2916 class SalInstanceImage : public SalInstanceWidget, public virtual weld::Image
2917 {
2918 private:
2919  VclPtr<FixedImage> m_xImage;
2920 
2921 public:
2922  SalInstanceImage(FixedImage* pImage, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2923  : SalInstanceWidget(pImage, pBuilder, bTakeOwnership)
2924  , m_xImage(pImage)
2925  {
2926  }
2927 
2928  virtual void set_from_icon_name(const OUString& rIconName) override
2929  {
2930  m_xImage->SetImage(::Image(StockImage::Yes, rIconName));
2931  }
2932 
2933  virtual void set_image(VirtualDevice* pDevice) override
2934  {
2935  if (pDevice)
2936  m_xImage->SetImage(createImage(*pDevice));
2937  else
2938  m_xImage->SetImage(::Image());
2939  }
2940 
2941  virtual void set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) override
2942  {
2943  m_xImage->SetImage(::Image(rImage));
2944  }
2945 };
2946 
2947 class SalInstanceCalendar : public SalInstanceWidget, public virtual weld::Calendar
2948 {
2949 private:
2950  VclPtr<::Calendar> m_xCalendar;
2951 
2952  DECL_LINK(SelectHdl, ::Calendar*, void);
2953  DECL_LINK(ActivateHdl, ::Calendar*, void);
2954 
2955 public:
2956  SalInstanceCalendar(::Calendar* pCalendar, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
2957  : SalInstanceWidget(pCalendar, pBuilder, bTakeOwnership)
2958  , m_xCalendar(pCalendar)
2959  {
2960  m_xCalendar->SetSelectHdl(LINK(this, SalInstanceCalendar, SelectHdl));
2961  m_xCalendar->SetActivateHdl(LINK(this, SalInstanceCalendar, ActivateHdl));
2962  }
2963 
2964  virtual void set_date(const Date& rDate) override { m_xCalendar->SetCurDate(rDate); }
2965 
2966  virtual Date get_date() const override { return m_xCalendar->GetFirstSelectedDate(); }
2967 
2968  virtual ~SalInstanceCalendar() override
2969  {
2970  m_xCalendar->SetSelectHdl(Link<::Calendar*, void>());
2971  m_xCalendar->SetActivateHdl(Link<::Calendar*, void>());
2972  }
2973 };
2974 
2975 }
2976 
2977 IMPL_LINK_NOARG(SalInstanceCalendar, SelectHdl, ::Calendar*, void)
2978 {
2979  if (notify_events_disabled())
2980  return;
2981  signal_selected();
2982 }
2983 
2984 IMPL_LINK_NOARG(SalInstanceCalendar, ActivateHdl, ::Calendar*, void)
2985 {
2986  if (notify_events_disabled())
2987  return;
2988  signal_activated();
2989 }
2990 
2992  : TextFilter(OUString())
2993  , m_rInsertTextHdl(rInsertTextHdl)
2994 {
2995 }
2996 
2997 OUString WeldTextFilter::filter(const OUString& rText)
2998 {
2999  if (!m_rInsertTextHdl.IsSet())
3000  return rText;
3001  OUString sText(rText);
3002  const bool bContinue = m_rInsertTextHdl.Call(sText);
3003  if (!bContinue)
3004  return OUString();
3005  return sText;
3006 }
3007 
3008 SalInstanceEntry::SalInstanceEntry(Edit* pEntry, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
3009  : SalInstanceWidget(pEntry, pBuilder, bTakeOwnership)
3010  , m_xEntry(pEntry)
3011  , m_aTextFilter(m_aInsertTextHdl)
3012 {
3013  m_xEntry->SetModifyHdl(LINK(this, SalInstanceEntry, ChangeHdl));
3014  m_xEntry->SetActivateHdl(LINK(this, SalInstanceEntry, ActivateHdl));
3016 }
3017 
3018 void SalInstanceEntry::set_text(const OUString& rText)
3019 {
3021  m_xEntry->SetText(rText);
3023 }
3024 
3026 {
3027  return m_xEntry->GetText();
3028 }
3029 
3031 {
3032  m_xEntry->SetWidthInChars(nChars);
3033 }
3034 
3036 {
3037  return m_xEntry->GetWidthInChars();
3038 }
3039 
3041 {
3042  m_xEntry->SetMaxTextLen(nChars);
3043 }
3044 
3045 void SalInstanceEntry::select_region(int nStartPos, int nEndPos)
3046 {
3048  m_xEntry->SetSelection(Selection(nStartPos, nEndPos < 0 ? SELECTION_MAX : nEndPos));
3050 }
3051 
3052 bool SalInstanceEntry::get_selection_bounds(int& rStartPos, int& rEndPos)
3053 {
3054  const Selection& rSelection = m_xEntry->GetSelection();
3055  rStartPos = rSelection.Min();
3056  rEndPos = rSelection.Max();
3057  return rSelection.Len();
3058 }
3059 
3060 void SalInstanceEntry::replace_selection(const OUString& rText)
3061 {
3062  m_xEntry->ReplaceSelected(rText);
3063 }
3064 
3066 {
3068  if (nCursorPos < 0)
3070  else
3071  m_xEntry->SetSelection(Selection(nCursorPos, nCursorPos));
3073 }
3074 
3076 {
3077  return m_xEntry->GetSelection().Max();
3078 }
3079 
3081 {
3082  m_xEntry->SetReadOnly(!bEditable);
3083 }
3084 
3086 {
3087  return !m_xEntry->IsReadOnly();
3088 }
3089 
3091 {
3092  if (eType == weld::EntryMessageType::Error)
3093  {
3094  // tdf#114603: enable setting the background to a different color;
3095  // relevant for GTK; see also #i75179#
3098  m_xEntry->SetControlBackground(0xff6563);
3099  }
3100  else if (eType == weld::EntryMessageType::Warning)
3101  {
3102  // tdf#114603: enable setting the background to a different color;
3103  // relevant for GTK; see also #i75179#
3107  }
3108  else
3109  {
3113  }
3114 }
3115 
3117 {
3118  m_xEntry->SetPointFont(*m_xEntry, rFont);
3119  m_xEntry->Invalidate();
3120 }
3121 
3123 {
3124  if (rColor == COL_AUTO)
3126  else
3127  m_xEntry->SetControlForeground(rColor);
3128 }
3129 
3131 {
3132  assert(!m_aCursorPositionHdl.IsSet());
3133  m_xEntry->AddEventListener(LINK(this, SalInstanceEntry, CursorListener));
3135 }
3136 
3137 void SalInstanceEntry::set_placeholder_text(const OUString& rText)
3138 {
3139  m_xEntry->SetPlaceholderText(rText);
3140 }
3141 
3143 {
3144  return *m_xEntry;
3145 }
3146 
3148 {
3149  signal_changed();
3150 }
3151 
3153 {
3154  m_xEntry->Cut();
3155 }
3156 
3158 {
3159  m_xEntry->Copy();
3160 }
3161 
3163 {
3164  m_xEntry->Paste();
3165 }
3166 
3168 {
3169  WinBits nAlign(0);
3170  switch (eXAlign)
3171  {
3172  case TxtAlign::Left:
3173  nAlign = WB_LEFT;
3174  break;
3175  case TxtAlign::Center:
3176  nAlign = WB_CENTER;
3177  break;
3178  case TxtAlign::Right:
3179  nAlign = WB_RIGHT;
3180  break;
3181  }
3182  WinBits nBits = m_xEntry->GetStyle();
3183  nBits &= ~(WB_LEFT | WB_CENTER | WB_RIGHT);
3184  m_xEntry->SetStyle(nBits & nAlign);
3185 }
3186 
3188 {
3189  if (m_aCursorPositionHdl.IsSet())
3190  m_xEntry->RemoveEventListener(LINK(this, SalInstanceEntry, CursorListener));
3191  m_xEntry->SetTextFilter(nullptr);
3194 }
3195 
3196 IMPL_LINK_NOARG(SalInstanceEntry, ChangeHdl, Edit&, void) { signal_changed(); }
3197 
3198 IMPL_LINK(SalInstanceEntry, CursorListener, VclWindowEvent&, rEvent, void)
3199 {
3200  if (notify_events_disabled())
3201  return;
3202  if (rEvent.GetId() == VclEventId::EditSelectionChanged
3203  || rEvent.GetId() == VclEventId::EditCaretChanged)
3204  signal_cursor_position();
3205 }
3206 
3207 IMPL_LINK_NOARG(SalInstanceEntry, ActivateHdl, Edit&, bool) { return m_aActivateHdl.Call(*this); }
3208 
3209 namespace
3210 {
3211 struct SalInstanceTreeIter : public weld::TreeIter
3212 {
3213  SalInstanceTreeIter(const SalInstanceTreeIter* pOrig)
3214  : iter(pOrig ? pOrig->iter : nullptr)
3215  {
3216  }
3217  SalInstanceTreeIter(SvTreeListEntry* pIter)
3218  : iter(pIter)
3219  {
3220  }
3221  virtual bool equal(const TreeIter& rOther) const override
3222  {
3223  return iter == static_cast<const SalInstanceTreeIter&>(rOther).iter;
3224  }
3225  SvTreeListEntry* iter;
3226 };
3227 
3228 }
3229 
3231 
3233 
3235 {
3236 private:
3237  // owner for UserData
3238  std::vector<std::unique_ptr<OUString>> m_aUserData;
3242  // currently expanding parent that logically, but not currently physically,
3243  // contain placeholders
3245  // which columns should be custom rendered
3249 
3250  DECL_LINK(SelectHdl, SvTreeListBox*, void);
3251  DECL_LINK(DeSelectHdl, SvTreeListBox*, void);
3252  DECL_LINK(DoubleClickHdl, SvTreeListBox*, bool);
3253  DECL_LINK(ExpandingHdl, SvTreeListBox*, bool);
3254  DECL_LINK(EndDragHdl, HeaderBar*, void);
3255  DECL_LINK(HeaderBarClickedHdl, HeaderBar*, void);
3256  DECL_LINK(ToggleHdl, SvLBoxButtonData*, void);
3257  DECL_LINK(ModelChangedHdl, SvTreeListBox*, void);
3258  DECL_LINK(StartDragHdl, SvTreeListBox*, bool);
3259  DECL_STATIC_LINK(SalInstanceTreeView, FinishDragHdl, SvTreeListBox*, void);
3260  DECL_LINK(EditingEntryHdl, SvTreeListEntry*, bool);
3261  typedef std::pair<SvTreeListEntry*, OUString> IterString;
3262  DECL_LINK(EditedEntryHdl, IterString, bool);
3263  DECL_LINK(VisibleRangeChangedHdl, SvTreeListBox*, void);
3264  DECL_LINK(CompareHdl, const SvSortData&, sal_Int32);
3265  DECL_LINK(PopupMenuHdl, const CommandEvent&, bool);
3266  DECL_LINK(TooltipHdl, const HelpEvent&, bool);
3267  DECL_LINK(CustomRenderHdl, svtree_render_args, void);
3268  DECL_LINK(CustomMeasureHdl, svtree_measure_args, Size);
3269 
3270  // Each row has a cell for the expander image, (and an optional cell for a
3271  // checkbutton if enable_toggle_buttons has been called) which precede
3272  // index 0
3273  int to_internal_model(int col) const
3274  {
3275  if (m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN)
3276  ++col; // skip checkbutton column
3277  ++col; //skip expander column
3278  return col;
3279  }
3280 
3281  int to_external_model(int col) const
3282  {
3283  if (m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN)
3284  --col; // skip checkbutton column
3285  --col; //skip expander column
3286  return col;
3287  }
3288 
3289  bool IsDummyEntry(SvTreeListEntry* pEntry) const
3290  {
3291  return m_xTreeView->GetEntryText(pEntry).trim() == "<dummy>";
3292  }
3293 
3295  {
3296  if (pEntry->HasChildren())
3297  {
3298  auto pChild = m_xTreeView->FirstChild(pEntry);
3299  assert(pChild);
3300  if (IsDummyEntry(pChild))
3301  return pChild;
3302  }
3303  return nullptr;
3304  }
3305 
3306  static void set_font_color(SvTreeListEntry* pEntry, const Color& rColor)
3307  {
3308  if (rColor == COL_AUTO)
3309  pEntry->SetTextColor(std::optional<Color>());
3310  else
3311  pEntry->SetTextColor(rColor);
3312  }
3313 
3314  void AddStringItem(SvTreeListEntry* pEntry, const OUString& rStr, int nCol)
3315  {
3316  auto xCell = std::make_unique<SvLBoxString>(rStr);
3317  if (m_aCustomRenders.count(nCol))
3318  xCell->SetCustomRender();
3319  pEntry->AddItem(std::move(xCell));
3320  }
3321 
3322  void do_insert(const weld::TreeIter* pParent, int pos, const OUString* pStr,
3323  const OUString* pId, const OUString* pIconName,
3324  VirtualDevice* pImageSurface, bool bChildrenOnDemand,
3325  weld::TreeIter* pRet, bool bIsSeparator)
3326  {
3328  const SalInstanceTreeIter* pVclIter = static_cast<const SalInstanceTreeIter*>(pParent);
3329  SvTreeListEntry* iter = pVclIter ? pVclIter->iter : nullptr;
3330  auto nInsertPos = pos == -1 ? TREELIST_APPEND : pos;
3331  void* pUserData;
3332  if (pId)
3333  {
3334  m_aUserData.emplace_back(std::make_unique<OUString>(*pId));
3335  pUserData = m_aUserData.back().get();
3336  }
3337  else
3338  pUserData = nullptr;
3339 
3340  SvTreeListEntry* pEntry = new SvTreeListEntry;
3341  if (bIsSeparator)
3342  pEntry->SetFlags(pEntry->GetFlags() | SvTLEntryFlags::IS_SEPARATOR);
3343 
3344  if (m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN)
3345  AddStringItem(pEntry, "", -1);
3346 
3347  if (pIconName || pImageSurface)
3348  {
3349  Image aImage(pIconName ? createImage(*pIconName) : createImage(*pImageSurface));
3350  pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aImage, aImage, false));
3351  }
3352  else
3353  {
3354  Image aDummy;
3355  pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
3356  }
3357  if (pStr)
3358  AddStringItem(pEntry, *pStr, 0);
3359  pEntry->SetUserData(pUserData);
3360  m_xTreeView->Insert(pEntry, iter, nInsertPos);
3361 
3362  if (pRet)
3363  {
3364  SalInstanceTreeIter* pVclRetIter = static_cast<SalInstanceTreeIter*>(pRet);
3365  pVclRetIter->iter = pEntry;
3366  }
3367 
3368  if (bChildrenOnDemand)
3369  {
3370  SvTreeListEntry* pPlaceHolder = m_xTreeView->InsertEntry("<dummy>", pEntry, false, 0, nullptr);
3371  SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pPlaceHolder);
3372  pViewData->SetSelectable(false);
3373  }
3374 
3375  if (bIsSeparator)
3376  {
3377  SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
3378  pViewData->SetSelectable(false);
3379  }
3380 
3382  }
3383 
3385  {
3386  SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
3387  m_xTreeView->InitViewData(pViewData, pEntry);
3388  m_xTreeView->CheckBoxInserted(pEntry);
3389  }
3390 
3391  void do_set_toggle(SvTreeListEntry* pEntry, TriState eState, int col)
3392  {
3393  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3394  // if its the placeholder to allow a blank column, replace it now
3395  if (pEntry->GetItem(col).GetType() != SvLBoxItemType::Button)
3396  {
3397  SvLBoxButtonData* pData = m_bTogglesAsRadio ? &m_aRadioButtonData : &m_aCheckButtonData;
3398  pEntry->ReplaceItem(std::make_unique<SvLBoxButton>(pData), 0);
3400 
3401  }
3402  SvLBoxItem& rItem = pEntry->GetItem(col);
3403  assert(dynamic_cast<SvLBoxButton*>(&rItem));
3404  switch (eState)
3405  {
3406  case TRISTATE_TRUE:
3407  static_cast<SvLBoxButton&>(rItem).SetStateChecked();
3408  break;
3409  case TRISTATE_FALSE:
3410  static_cast<SvLBoxButton&>(rItem).SetStateUnchecked();
3411  break;
3412  case TRISTATE_INDET:
3413  static_cast<SvLBoxButton&>(rItem).SetStateTristate();
3414  break;
3415  }
3416 
3417  m_xTreeView->ModelHasEntryInvalidated(pEntry);
3418  }
3419 
3420  static TriState do_get_toggle(SvTreeListEntry* pEntry, int col)
3421  {
3422  if (static_cast<size_t>(col) == pEntry->ItemCount())
3423  return TRISTATE_FALSE;
3424 
3425  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3426  SvLBoxItem& rItem = pEntry->GetItem(col);
3427  assert(dynamic_cast<SvLBoxButton*>(&rItem));
3428  SvLBoxButton& rToggle = static_cast<SvLBoxButton&>(rItem);
3429  if (rToggle.IsStateTristate())
3430  return TRISTATE_INDET;
3431  else if (rToggle.IsStateChecked())
3432  return TRISTATE_TRUE;
3433  return TRISTATE_FALSE;
3434  }
3435 
3436  TriState get_toggle(SvTreeListEntry* pEntry, int col) const
3437  {
3438  if (col == -1)
3439  {
3440  assert(m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN);
3441  return do_get_toggle(pEntry, 0);
3442  }
3443  col = to_internal_model(col);
3444  return do_get_toggle(pEntry, col);
3445  }
3446 
3447  void set_toggle(SvTreeListEntry* pEntry, TriState eState, int col)
3448  {
3449  if (col == -1)
3450  {
3451  assert(m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN);
3452  do_set_toggle(pEntry, eState, 0);
3453  return;
3454  }
3455 
3456  col = to_internal_model(col);
3457 
3458  // blank out missing entries
3459  for (int i = pEntry->ItemCount(); i < col; ++i)
3460  AddStringItem(pEntry, "", i - 1);
3461 
3462  if (static_cast<size_t>(col) == pEntry->ItemCount())
3463  {
3464  SvLBoxButtonData* pData = m_bTogglesAsRadio ? &m_aRadioButtonData : &m_aCheckButtonData;
3465  pEntry->AddItem(std::make_unique<SvLBoxButton>(pData));
3467  }
3468 
3469  do_set_toggle(pEntry, eState, col);
3470  }
3471 
3472  bool get_text_emphasis(SvTreeListEntry* pEntry, int col) const
3473  {
3474  col = to_internal_model(col);
3475 
3476  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3477  SvLBoxItem& rItem = pEntry->GetItem(col);
3478  assert(dynamic_cast<SvLBoxString*>(&rItem));
3479  return static_cast<SvLBoxString&>(rItem).IsEmphasized();
3480  }
3481 
3482 public:
3483  SalInstanceTreeView(SvTabListBox* pTreeView, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
3484  : SalInstanceContainer(pTreeView, pBuilder, bTakeOwnership)
3485  , m_xTreeView(pTreeView)
3486  , m_aCheckButtonData(pTreeView, false)
3487  , m_aRadioButtonData(pTreeView, true)
3488  , m_bTogglesAsRadio(false)
3489  , m_nSortColumn(-1)
3490  {
3491  m_xTreeView->SetNodeDefaultImages();
3492  m_xTreeView->SetForceMakeVisible(true);
3493  m_xTreeView->SetSelectHdl(LINK(this, SalInstanceTreeView, SelectHdl));
3494  m_xTreeView->SetDeselectHdl(LINK(this, SalInstanceTreeView, DeSelectHdl));
3495  m_xTreeView->SetDoubleClickHdl(LINK(this, SalInstanceTreeView, DoubleClickHdl));
3496  m_xTreeView->SetExpandingHdl(LINK(this, SalInstanceTreeView, ExpandingHdl));
3497  m_xTreeView->SetPopupMenuHdl(LINK(this, SalInstanceTreeView, PopupMenuHdl));
3498  m_xTreeView->SetCustomRenderHdl(LINK(this, SalInstanceTreeView, CustomRenderHdl));
3499  m_xTreeView->SetCustomMeasureHdl(LINK(this, SalInstanceTreeView, CustomMeasureHdl));
3500  const long aTabPositions[] = { 0 };
3501  m_xTreeView->SetTabs(SAL_N_ELEMENTS(aTabPositions), aTabPositions);
3502  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3503 
3504  if (pHeaderBox)
3505  {
3506  if (HeaderBar* pHeaderBar = pHeaderBox->GetHeaderBar())
3507  {
3508  //make the last entry fill available space
3509  pHeaderBar->SetItemSize(pHeaderBar->GetItemId(pHeaderBar->GetItemCount() - 1),
3511  pHeaderBar->SetEndDragHdl(LINK(this, SalInstanceTreeView, EndDragHdl));
3512  pHeaderBar->SetSelectHdl(LINK(this, SalInstanceTreeView, HeaderBarClickedHdl));
3513  }
3514  pHeaderBox->SetEditingEntryHdl(LINK(this, SalInstanceTreeView, EditingEntryHdl));
3515  pHeaderBox->SetEditedEntryHdl(LINK(this, SalInstanceTreeView, EditedEntryHdl));
3516  }
3517  else
3518  {
3519  static_cast<LclTabListBox&>(*m_xTreeView)
3520  .SetModelChangedHdl(LINK(this, SalInstanceTreeView, ModelChangedHdl));
3521  static_cast<LclTabListBox&>(*m_xTreeView)
3522  .SetStartDragHdl(LINK(this, SalInstanceTreeView, StartDragHdl));
3523  static_cast<LclTabListBox&>(*m_xTreeView)
3524  .SetEndDragHdl(LINK(this, SalInstanceTreeView, FinishDragHdl));
3525  static_cast<LclTabListBox&>(*m_xTreeView)
3526  .SetEditingEntryHdl(LINK(this, SalInstanceTreeView, EditingEntryHdl));
3527  static_cast<LclTabListBox&>(*m_xTreeView)
3528  .SetEditedEntryHdl(LINK(this, SalInstanceTreeView, EditedEntryHdl));
3529  }
3530  m_aCheckButtonData.SetLink(LINK(this, SalInstanceTreeView, ToggleHdl));
3531  m_aRadioButtonData.SetLink(LINK(this, SalInstanceTreeView, ToggleHdl));
3532  }
3533 
3535  {
3537  m_xTreeView->SetTooltipHdl(LINK(this, SalInstanceTreeView, TooltipHdl));
3538  }
3539 
3540  virtual void columns_autosize() override
3541  {
3542  std::vector<long> aWidths;
3543  m_xTreeView->getPreferredDimensions(aWidths);
3544  if (aWidths.size() > 2)
3545  {
3546  std::vector<int> aColWidths;
3547  for (size_t i = 1; i < aWidths.size() - 1; ++i)
3548  aColWidths.push_back(aWidths[i] - aWidths[i - 1]);
3549  set_column_fixed_widths(aColWidths);
3550  }
3551  }
3552 
3553  virtual void freeze() override
3554  {
3556  m_xTreeView->SetUpdateMode(false);
3557  m_xTreeView->GetModel()->EnableInvalidate(false);
3558  }
3559 
3560  virtual void thaw() override
3561  {
3562  m_xTreeView->GetModel()->EnableInvalidate(true);
3563  m_xTreeView->SetUpdateMode(true);
3565  }
3566 
3567  virtual void set_column_fixed_widths(const std::vector<int>& rWidths) override
3568  {
3569  std::vector<long> aTabPositions;
3570  aTabPositions.push_back(0);
3571  for (size_t i = 0; i < rWidths.size(); ++i)
3572  aTabPositions.push_back(aTabPositions[i] + rWidths[i]);
3573  m_xTreeView->SetTabs(aTabPositions.size(), aTabPositions.data(), MapUnit::MapPixel);
3574  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3575  if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3576  {
3577  for (size_t i = 0; i < rWidths.size(); ++i)
3578  pHeaderBar->SetItemSize(pHeaderBar->GetItemId(i), rWidths[i]);
3579  }
3580  // call Resize to recalculate based on the new tabs
3581  m_xTreeView->Resize();
3582  }
3583 
3584  virtual void set_column_editables(const std::vector<bool>& rEditables) override
3585  {
3586  size_t nTabCount = rEditables.size();
3587  for (size_t i = 0 ; i < nTabCount; ++i)
3588  m_xTreeView->SetTabEditable(i, rEditables[i]);
3589  }
3590 
3591  virtual void set_centered_column(int nCol) override
3592  {
3593  m_xTreeView->SetTabJustify(nCol, SvTabJustify::AdjustCenter);
3594  }
3595 
3596  virtual int get_column_width(int nColumn) const override
3597  {
3598  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3599  if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3600  return pHeaderBar->GetItemSize(pHeaderBar->GetItemId(nColumn));
3601  // GetTab(0) gives the position of the bitmap which is automatically inserted by the TabListBox.
3602  // So the first text column's width is Tab(2)-Tab(1).
3603  auto nWidthPixel
3604  = m_xTreeView->GetLogicTab(nColumn + 2) - m_xTreeView->GetLogicTab(nColumn + 1);
3605  nWidthPixel -= SV_TAB_BORDER;
3606  return nWidthPixel;
3607  }
3608 
3609  virtual OUString get_column_title(int nColumn) const override
3610  {
3611  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3612  if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3613  {
3614  return pHeaderBar->GetItemText(pHeaderBar->GetItemId(nColumn));
3615  }
3616  return OUString();
3617  }
3618 
3619  virtual void set_column_title(int nColumn, const OUString& rTitle) override
3620  {
3621  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
3622  if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
3623  {
3624  return pHeaderBar->SetItemText(pHeaderBar->GetItemId(nColumn), rTitle);
3625  }
3626  }
3627 
3628  virtual void set_column_custom_renderer(int nColumn, bool bEnable) override
3629  {
3630  assert(n_children() == 0 && "tree must be empty");
3631  if (bEnable)
3632  m_aCustomRenders.insert(nColumn);
3633  else
3634  m_aCustomRenders.erase(nColumn);
3635  }
3636 
3637  virtual void show() override
3638  {
3639  if (LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()))
3640  pHeaderBox->GetParent()->Show();
3642  }
3643 
3644  virtual void hide() override
3645  {
3646  if (LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()))
3647  pHeaderBox->GetParent()->Hide();
3649  }
3650 
3651  virtual void insert(const weld::TreeIter* pParent, int pos, const OUString* pStr,
3652  const OUString* pId, const OUString* pIconName,
3653  VirtualDevice* pImageSurface, bool bChildrenOnDemand,
3654  weld::TreeIter* pRet) override
3655  {
3656  do_insert(pParent, pos, pStr, pId, pIconName, pImageSurface,
3657  bChildrenOnDemand, pRet, false);
3658  }
3659 
3660  virtual void insert_separator(int pos, const OUString& /*rId*/) override
3661  {
3662  OUString sSep(VclResId(STR_SEPARATOR));
3663  do_insert(nullptr, pos, &sSep, nullptr, nullptr, nullptr,
3664  false, nullptr, true);
3665  }
3666 
3667  virtual void
3668  bulk_insert_for_each(int nSourceCount,
3669  const std::function<void(weld::TreeIter&, int nSourceIndex)>& func,
3670  const std::vector<int>* pFixedWidths) override
3671  {
3672  freeze();
3673  clear();
3674  SalInstanceTreeIter aVclIter(static_cast<SvTreeListEntry*>(nullptr));
3675 
3676  m_xTreeView->nTreeFlags |= SvTreeFlags::MANINS;
3677 
3678  if (pFixedWidths)
3679  set_column_fixed_widths(*pFixedWidths);
3680 
3681  bool bHasAutoCheckButton(m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN);
3682  size_t nExtraCols = bHasAutoCheckButton ? 2 : 1;
3683 
3684  Image aDummy;
3685  for (int i = 0; i < nSourceCount; ++i)
3686  {
3687  aVclIter.iter = new SvTreeListEntry;
3688  if (bHasAutoCheckButton)
3689  AddStringItem(aVclIter.iter, "", -1);
3690  aVclIter.iter->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
3691  m_xTreeView->Insert(aVclIter.iter, nullptr, TREELIST_APPEND);
3692  func(aVclIter, i);
3693 
3694  if (!pFixedWidths)
3695  continue;
3696 
3697  size_t nFixedWidths = std::min(pFixedWidths->size(), aVclIter.iter->ItemCount());
3698  for (size_t j = 0; j < nFixedWidths; ++j)
3699  {
3700  SvLBoxItem& rItem = aVclIter.iter->GetItem(j + nExtraCols);
3701  SvViewDataItem* pViewDataItem = m_xTreeView->GetViewDataItem(aVclIter.iter, &rItem);
3702  pViewDataItem->mnWidth = (*pFixedWidths)[j];
3703  }
3704  }
3705 
3706  m_xTreeView->nTreeFlags &= ~SvTreeFlags::MANINS;
3707 
3708  thaw();
3709  }
3710 
3711  virtual void set_font_color(int pos, const Color& rColor) override
3712  {
3713  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3714  set_font_color(pEntry, rColor);
3715  }
3716 
3717  virtual void set_font_color(const weld::TreeIter& rIter, const Color& rColor) override
3718  {
3719  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3720  set_font_color(rVclIter.iter, rColor);
3721  }
3722 
3723  virtual void remove(int pos) override
3724  {
3726  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3727  m_xTreeView->RemoveEntry(pEntry);
3729  }
3730 
3731  virtual int find_text(const OUString& rText) const override
3732  {
3733  for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry;
3734  pEntry = m_xTreeView->Next(pEntry))
3735  {
3736  if (SvTabListBox::GetEntryText(pEntry, 0) == rText)
3737  return SvTreeList::GetRelPos(pEntry);
3738  }
3739  return -1;
3740  }
3741 
3742  virtual int find_id(const OUString& rId) const override
3743  {
3744  for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry;
3745  pEntry = m_xTreeView->Next(pEntry))
3746  {
3747  const OUString* pId = static_cast<const OUString*>(pEntry->GetUserData());
3748  if (!pId)
3749  continue;
3750  if (rId == *pId)
3751  return SvTreeList::GetRelPos(pEntry);
3752  }
3753  return -1;
3754  }
3755 
3756  virtual void swap(int pos1, int pos2) override
3757  {
3758  int min = std::min(pos1, pos2);
3759  int max = std::max(pos1, pos2);
3760  SvTreeList* pModel = m_xTreeView->GetModel();
3761  SvTreeListEntry* pEntry1 = pModel->GetEntry(nullptr, min);
3762  SvTreeListEntry* pEntry2 = pModel->GetEntry(nullptr, max);
3763  pModel->Move(pEntry1, pEntry2);
3764  }
3765 
3766  virtual void clear() override
3767  {
3769  m_xTreeView->Clear();
3770  m_aUserData.clear();
3772  }
3773 
3774  virtual int n_children() const override
3775  {
3776  return m_xTreeView->GetModel()->GetChildList(nullptr).size();
3777  }
3778 
3779  virtual int iter_n_children(const weld::TreeIter& rIter) const override
3780  {
3781  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3782  return m_xTreeView->GetModel()->GetChildList(rVclIter.iter).size();
3783  }
3784 
3785  virtual void select(int pos) override
3786  {
3787  assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
3789  if (pos == -1 || (pos == 0 && n_children() == 0))
3790  m_xTreeView->SelectAll(false);
3791  else
3792  {
3793  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3794  m_xTreeView->Select(pEntry, true);
3795  m_xTreeView->MakeVisible(pEntry);
3796  }
3798  }
3799 
3800  virtual int get_cursor_index() const override
3801  {
3802  SvTreeListEntry* pEntry = m_xTreeView->GetCurEntry();
3803  if (!pEntry)
3804  return -1;
3805  return SvTreeList::GetRelPos(pEntry);
3806  }
3807 
3808  virtual void set_cursor(int pos) override
3809  {
3811  if (pos == -1)
3812  m_xTreeView->SetCurEntry(nullptr);
3813  else
3814  {
3815  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3816  m_xTreeView->SetCurEntry(pEntry);
3817  }
3819  }
3820 
3821  virtual void scroll_to_row(int pos) override
3822  {
3823  assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
3825  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3826  m_xTreeView->MakeVisible(pEntry);
3828  }
3829 
3830  virtual bool is_selected(int pos) const override
3831  {
3832  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3833  return m_xTreeView->IsSelected(pEntry);
3834  }
3835 
3836  virtual void unselect(int pos) override
3837  {
3838  assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
3840  if (pos == -1)
3841  m_xTreeView->SelectAll(true);
3842  else
3843  {
3844  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3845  m_xTreeView->Select(pEntry, false);
3846  }
3848  }
3849 
3850  virtual std::vector<int> get_selected_rows() const override
3851  {
3852  std::vector<int> aRows;
3853 
3854  aRows.reserve(m_xTreeView->GetSelectionCount());
3855  for (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected(); pEntry;
3856  pEntry = m_xTreeView->NextSelected(pEntry))
3857  aRows.push_back(SvTreeList::GetRelPos(pEntry));
3858 
3859  return aRows;
3860  }
3861 
3862  OUString get_text(SvTreeListEntry* pEntry, int col) const
3863  {
3864  if (col == -1)
3865  return SvTabListBox::GetEntryText(pEntry, 0);
3866 
3867  col = to_internal_model(col);
3868 
3869  if (static_cast<size_t>(col) == pEntry->ItemCount())
3870  return OUString();
3871 
3872  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3873  SvLBoxItem& rItem = pEntry->GetItem(col);
3874  assert(dynamic_cast<SvLBoxString*>(&rItem));
3875  return static_cast<SvLBoxString&>(rItem).GetText();
3876  }
3877 
3878  virtual OUString get_text(int pos, int col) const override
3879  {
3880  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3881  return get_text(pEntry, col);
3882  }
3883 
3884  void set_text(SvTreeListEntry* pEntry, const OUString& rText, int col)
3885  {
3886  if (col == -1)
3887  {
3888  m_xTreeView->SetEntryText(pEntry, rText);
3889  return;
3890  }
3891 
3892  col = to_internal_model(col);
3893 
3894  // blank out missing entries
3895  for (int i = pEntry->ItemCount(); i < col; ++i)
3896  AddStringItem(pEntry, "", i - 1);
3897 
3898  if (static_cast<size_t>(col) == pEntry->ItemCount())
3899  {
3900  AddStringItem(pEntry, rText, col - 1);
3901  SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
3902  m_xTreeView->InitViewData(pViewData, pEntry);
3903  }
3904  else
3905  {
3906  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3907  SvLBoxItem& rItem = pEntry->GetItem(col);
3908  assert(dynamic_cast<SvLBoxString*>(&rItem));
3909  static_cast<SvLBoxString&>(rItem).SetText(rText);
3910  }
3911  m_xTreeView->ModelHasEntryInvalidated(pEntry);
3912  }
3913 
3914  virtual void set_text(int pos, const OUString& rText, int col) override
3915  {
3916  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3917  set_text(pEntry, rText, col);
3918  }
3919 
3920  void set_sensitive(SvTreeListEntry* pEntry, bool bSensitive, int col)
3921  {
3922  if (col == -1)
3923  {
3924  auto nFlags = pEntry->GetFlags() & ~SvTLEntryFlags::SEMITRANSPARENT;
3925  if (!bSensitive)
3926  nFlags = nFlags | SvTLEntryFlags::SEMITRANSPARENT;
3927  pEntry->SetFlags(nFlags);
3928  const sal_uInt16 nCount = pEntry->ItemCount();
3929  for (sal_uInt16 nCur = 0; nCur < nCount; ++nCur)
3930  {
3931  SvLBoxItem& rItem = pEntry->GetItem(nCur);
3932  if (rItem.GetType() == SvLBoxItemType::String)
3933  {
3934  rItem.Enable(bSensitive);
3935  m_xTreeView->ModelHasEntryInvalidated(pEntry);
3936  break;
3937  }
3938  }
3939  return;
3940  }
3941 
3942  col = to_internal_model(col);
3943 
3944  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
3945  SvLBoxItem& rItem = pEntry->GetItem(col);
3946  rItem.Enable(bSensitive);
3947 
3948  m_xTreeView->ModelHasEntryInvalidated(pEntry);
3949  }
3950 
3952 
3953  virtual void set_sensitive(int pos, bool bSensitive, int col) override
3954  {
3955  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3956  set_sensitive(pEntry, bSensitive, col);
3957  }
3958 
3959  virtual void set_sensitive(const weld::TreeIter& rIter, bool bSensitive, int col) override
3960  {
3961  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3962  set_sensitive(rVclIter.iter, bSensitive, col);
3963  }
3964 
3965  virtual TriState get_toggle(int pos, int col) const override
3966  {
3967  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3968  return get_toggle(pEntry, col);
3969  }
3970 
3971  virtual TriState get_toggle(const weld::TreeIter& rIter, int col) const override
3972  {
3973  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3974  return get_toggle(rVclIter.iter, col);
3975  }
3976 
3977  virtual void enable_toggle_buttons(weld::ColumnToggleType eType) override
3978  {
3979  assert(n_children() == 0 && "tree must be empty");
3980  m_bTogglesAsRadio = eType == weld::ColumnToggleType::Radio;
3981 
3982  SvLBoxButtonData* pData = m_bTogglesAsRadio ? &m_aRadioButtonData : &m_aCheckButtonData;
3983  m_xTreeView->EnableCheckButton(pData);
3984  // EnableCheckButton clobbered this, restore it
3985  pData->SetLink(LINK(this, SalInstanceTreeView, ToggleHdl));
3986  }
3987 
3988  virtual void set_toggle(int pos, TriState eState, int col) override
3989  {
3990  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
3991  set_toggle(pEntry, eState, col);
3992  }
3993 
3994  virtual void set_toggle(const weld::TreeIter& rIter, TriState eState, int col) override
3995  {
3996  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
3997  set_toggle(rVclIter.iter, eState, col);
3998  }
3999 
4000  virtual void set_extra_row_indent(const weld::TreeIter& rIter, int nIndentLevel) override
4001  {
4002  weld::TreeIter& rNonConstIter = const_cast<weld::TreeIter&>(rIter);
4003  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNonConstIter);
4004  rVclIter.iter->SetExtraIndent(nIndentLevel);
4005  }
4006 
4007  void set_text_emphasis(SvTreeListEntry* pEntry, bool bOn, int col)
4008  {
4009  col = to_internal_model(col);
4010 
4011  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4012  SvLBoxItem& rItem = pEntry->GetItem(col);
4013  assert(dynamic_cast<SvLBoxString*>(&rItem));
4014  static_cast<SvLBoxString&>(rItem).Emphasize(bOn);
4015 
4016  m_xTreeView->ModelHasEntryInvalidated(pEntry);
4017  }
4018 
4019  virtual void set_text_emphasis(const weld::TreeIter& rIter, bool bOn, int col) override
4020  {
4021  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4022  set_text_emphasis(rVclIter.iter, bOn, col);
4023  }
4024 
4025  virtual void set_text_emphasis(int pos, bool bOn, int col) override
4026  {
4027  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4028  set_text_emphasis(pEntry, bOn, col);
4029  }
4030 
4031  virtual bool get_text_emphasis(const weld::TreeIter& rIter, int col) const override
4032  {
4033  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4034  return get_text_emphasis(rVclIter.iter, col);
4035  }
4036 
4037  virtual bool get_text_emphasis(int pos, int col) const override
4038  {
4039  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4040  return get_text_emphasis(pEntry, col);
4041  }
4042 
4043  void set_text_align(SvTreeListEntry* pEntry, double fAlign, int col)
4044  {
4045  col = to_internal_model(col);
4046 
4047  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4048  SvLBoxItem& rItem = pEntry->GetItem(col);
4049  assert(dynamic_cast<SvLBoxString*>(&rItem));
4050  static_cast<SvLBoxString&>(rItem).Align(fAlign);
4051 
4052  m_xTreeView->ModelHasEntryInvalidated(pEntry);
4053  }
4054 
4055  virtual void set_text_align(const weld::TreeIter& rIter, double fAlign, int col) override
4056  {
4057  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4058  set_text_align(rVclIter.iter, fAlign, col);
4059  }
4060 
4061  virtual void set_text_align(int pos, double fAlign, int col) override
4062  {
4063  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4064  set_text_align(pEntry, fAlign, col);
4065  }
4066 
4067  virtual void connect_editing(
4068  const Link<const weld::TreeIter&, bool>& rStartLink,
4069  const Link<const iter_string&, bool>& rEndLink) override
4070  {
4071  m_xTreeView->EnableInplaceEditing(rStartLink.IsSet() || rEndLink.IsSet());
4072  weld::TreeView::connect_editing(rStartLink, rEndLink);
4073  }
4074 
4075  virtual void start_editing(const weld::TreeIter& rIter) override
4076  {
4077  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4078  m_xTreeView->EditEntry(rVclIter.iter);
4079  }
4080 
4081  virtual void end_editing() override { m_xTreeView->EndEditing(); }
4082 
4083  void set_image(SvTreeListEntry* pEntry, const Image& rImage, int col)
4084  {
4085  if (col == -1)
4086  {
4087  m_xTreeView->SetExpandedEntryBmp(pEntry, rImage);
4088  m_xTreeView->SetCollapsedEntryBmp(pEntry, rImage);
4089  return;
4090  }
4091 
4092  col = to_internal_model(col);
4093 
4094  // blank out missing entries
4095  for (int i = pEntry->ItemCount(); i < col; ++i)
4096  AddStringItem(pEntry, "", i - 1);
4097 
4098  if (static_cast<size_t>(col) == pEntry->ItemCount())
4099  {
4100  pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(rImage, rImage, false));
4101  SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
4102  m_xTreeView->InitViewData(pViewData, pEntry);
4103  }
4104  else
4105  {
4106  assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount());
4107  SvLBoxItem& rItem = pEntry->GetItem(col);
4108  assert(dynamic_cast<SvLBoxContextBmp*>(&rItem));
4109  static_cast<SvLBoxContextBmp&>(rItem).SetBitmap1(rImage);
4110  static_cast<SvLBoxContextBmp&>(rItem).SetBitmap2(rImage);
4111  }
4112 
4113  m_xTreeView->SetEntryHeight(pEntry);
4114  m_xTreeView->ModelHasEntryInvalidated(pEntry);
4115  }
4116 
4117  virtual void set_image(int pos, const OUString& rImage, int col) override
4118  {
4119  set_image(m_xTreeView->GetEntry(nullptr, pos), createImage(rImage), col);
4120  }
4121 
4122  virtual void set_image(int pos, const css::uno::Reference<css::graphic::XGraphic>& rImage,
4123  int col) override
4124  {
4125  set_image(m_xTreeView->GetEntry(nullptr, pos), Image(rImage), col);
4126  }
4127 
4128  virtual void set_image(int pos, VirtualDevice& rImage, int col) override
4129  {
4130  set_image(m_xTreeView->GetEntry(nullptr, pos), createImage(rImage), col);
4131  }
4132 
4133  virtual void set_image(const weld::TreeIter& rIter, const OUString& rImage, int col) override
4134  {
4135  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4136  set_image(rVclIter.iter, createImage(rImage), col);
4137  }
4138 
4139  virtual void set_image(const weld::TreeIter& rIter,
4140  const css::uno::Reference<css::graphic::XGraphic>& rImage,
4141  int col) override
4142  {
4143  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4144  set_image(rVclIter.iter, Image(rImage), col);
4145  }
4146 
4147  virtual void set_image(const weld::TreeIter& rIter, VirtualDevice& rImage, int col) override
4148  {
4149  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4150  set_image(rVclIter.iter, createImage(rImage), col);
4151  }
4152 
4153  const OUString* getEntryData(int index) const
4154  {
4155  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, index);
4156  return pEntry ? static_cast<const OUString*>(pEntry->GetUserData()) : nullptr;
4157  }
4158 
4159  virtual OUString get_id(int pos) const override
4160  {
4161  const OUString* pRet = getEntryData(pos);
4162  if (!pRet)
4163  return OUString();
4164  return *pRet;
4165  }
4166 
4167  void set_id(SvTreeListEntry* pEntry, const OUString& rId)
4168  {
4169  m_aUserData.emplace_back(std::make_unique<OUString>(rId));
4170  pEntry->SetUserData(m_aUserData.back().get());
4171  }
4172 
4173  virtual void set_id(int pos, const OUString& rId) override
4174  {
4175  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
4176  set_id(pEntry, rId);
4177  }
4178 
4179  virtual int get_selected_index() const override
4180  {
4181  assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen");
4182  SvTreeListEntry* pEntry = m_xTreeView->FirstSelected();
4183  if (!pEntry)
4184  return -1;
4185  return SvTreeList::GetRelPos(pEntry);
4186  }
4187 
4188  virtual OUString get_selected_text() const override
4189  {
4190  assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen");
4191  if (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected())
4192  return m_xTreeView->GetEntryText(pEntry);
4193  return OUString();
4194  }
4195 
4196  virtual OUString get_selected_id() const override
4197  {
4198  assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen");
4199  if (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected())
4200  {
4201  if (const OUString* pStr = static_cast<const OUString*>(pEntry->GetUserData()))
4202  return *pStr;
4203  }
4204  return OUString();
4205  }
4206 
4207  virtual std::unique_ptr<weld::TreeIter>
4208  make_iterator(const weld::TreeIter* pOrig) const override
4209  {
4210  return std::unique_ptr<weld::TreeIter>(
4211  new SalInstanceTreeIter(static_cast<const SalInstanceTreeIter*>(pOrig)));
4212  }
4213 
4214  virtual void copy_iterator(const weld::TreeIter& rSource, weld::TreeIter& rDest) const override
4215  {
4216  const SalInstanceTreeIter& rVclSource(static_cast<const SalInstanceTreeIter&>(rSource));
4217  SalInstanceTreeIter& rVclDest(static_cast<SalInstanceTreeIter&>(rDest));
4218  rVclDest.iter = rVclSource.iter;
4219  }
4220 
4221  virtual bool get_selected(weld::TreeIter* pIter) const override
4222  {
4223  SvTreeListEntry* pEntry = m_xTreeView->FirstSelected();
4224  auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter);
4225  if (pVclIter)
4226  pVclIter->iter = pEntry;
4227  return pEntry != nullptr;
4228  }
4229 
4230  virtual bool get_cursor(weld::TreeIter* pIter) const override
4231  {
4232  SvTreeListEntry* pEntry = m_xTreeView->GetCurEntry();
4233  auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter);
4234  if (pVclIter)
4235  pVclIter->iter = pEntry;
4236  return pEntry != nullptr;
4237  }
4238 
4239  virtual void set_cursor(const weld::TreeIter& rIter) override
4240  {
4241  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4243  m_xTreeView->SetCurEntry(rVclIter.iter);
4245  }
4246 
4247  virtual bool get_iter_first(weld::TreeIter& rIter) const override
4248  {
4249  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4250  rVclIter.iter = m_xTreeView->GetEntry(0);
4251  return rVclIter.iter != nullptr;
4252  }
4253 
4254  virtual bool iter_next_sibling(weld::TreeIter& rIter) const override
4255  {
4256  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4257  rVclIter.iter = rVclIter.iter->NextSibling();
4258  return rVclIter.iter != nullptr;
4259  }
4260 
4261  virtual bool iter_previous_sibling(weld::TreeIter& rIter) const override
4262  {
4263  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4264  rVclIter.iter = rVclIter.iter->PrevSibling();
4265  return rVclIter.iter != nullptr;
4266  }
4267 
4268  virtual bool iter_next(weld::TreeIter& rIter) const override
4269  {
4270  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4271  rVclIter.iter = m_xTreeView->Next(rVclIter.iter);
4272  if (rVclIter.iter && IsDummyEntry(rVclIter.iter))
4273  return iter_next(rVclIter);
4274  return rVclIter.iter != nullptr;
4275  }
4276 
4277  virtual bool iter_previous(weld::TreeIter& rIter) const override
4278  {
4279  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4280  rVclIter.iter = m_xTreeView->Prev(rVclIter.iter);
4281  if (rVclIter.iter && IsDummyEntry(rVclIter.iter))
4282  return iter_previous(rVclIter);
4283  return rVclIter.iter != nullptr;
4284  }
4285 
4286  virtual bool iter_next_visible(weld::TreeIter& rIter) const override
4287  {
4288  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4289  rVclIter.iter = m_xTreeView->NextVisible(rVclIter.iter);
4290  if (rVclIter.iter && IsDummyEntry(rVclIter.iter))
4291  return iter_next_visible(rVclIter);
4292  return rVclIter.iter != nullptr;
4293  }
4294 
4295  virtual bool iter_children(weld::TreeIter& rIter) const override
4296  {
4297  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4298  rVclIter.iter = m_xTreeView->FirstChild(rVclIter.iter);
4299  bool bRet = rVclIter.iter != nullptr;
4300  if (bRet)
4301  {
4302  //on-demand dummy entry doesn't count
4303  return !IsDummyEntry(rVclIter.iter);
4304  }
4305  return bRet;
4306  }
4307 
4308  virtual bool iter_parent(weld::TreeIter& rIter) const override
4309  {
4310  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
4311  rVclIter.iter = m_xTreeView->GetParent(rVclIter.iter);
4312  return rVclIter.iter != nullptr;
4313  }
4314 
4315  virtual void remove(const weld::TreeIter& rIter) override
4316  {
4318  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4319  m_xTreeView->RemoveEntry(rVclIter.iter);
4321  }
4322 
4323  virtual void select(const weld::TreeIter& rIter) override
4324  {
4325  assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
4327  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4328  m_xTreeView->Select(rVclIter.iter, true);
4330  }
4331 
4332  virtual void scroll_to_row(const weld::TreeIter& rIter) override
4333  {
4334  assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze");
4336  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4337  m_xTreeView->MakeVisible(rVclIter.iter);
4339  }
4340 
4341  virtual void unselect(const weld::TreeIter& rIter) override
4342  {
4343  assert(m_xTreeView->IsUpdateMode() && "don't unselect when frozen");
4345  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4346  m_xTreeView->Select(rVclIter.iter, false);
4348  }
4349 
4350  virtual int get_iter_depth(const weld::TreeIter& rIter) const override
4351  {
4352  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4353  return m_xTreeView->GetModel()->GetDepth(rVclIter.iter);
4354  }
4355 
4356  virtual bool iter_has_child(const weld::TreeIter& rIter) const override
4357  {
4358  weld::TreeIter& rNonConstIter = const_cast<weld::TreeIter&>(rIter);
4359  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNonConstIter);
4360  SvTreeListEntry* restore(rVclIter.iter);
4361  bool ret = iter_children(rNonConstIter);
4362  rVclIter.iter = restore;
4363  return ret;
4364  }
4365 
4366  virtual bool get_row_expanded(const weld::TreeIter& rIter) const override
4367  {
4368  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4369  return m_xTreeView->IsExpanded(rVclIter.iter);
4370  }
4371 
4372  virtual bool get_children_on_demand(const weld::TreeIter& rIter) const override
4373  {
4374  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4375  if (m_aExpandingPlaceHolderParents.count(rVclIter.iter))
4376  return true;
4377  return GetPlaceHolderChild(rVclIter.iter) != nullptr;
4378  }
4379 
4380  virtual void set_children_on_demand(const weld::TreeIter& rIter, bool bChildrenOnDemand) override
4381  {
4383 
4384  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4385 
4386  SvTreeListEntry* pPlaceHolder = GetPlaceHolderChild(rVclIter.iter);
4387 
4388  if (bChildrenOnDemand && !pPlaceHolder)
4389  {
4390  pPlaceHolder = m_xTreeView->InsertEntry("<dummy>", rVclIter.iter, false, 0, nullptr);
4391  SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pPlaceHolder);
4392  pViewData->SetSelectable(false);
4393  }
4394  else if (!bChildrenOnDemand && pPlaceHolder)
4395  m_xTreeView->RemoveEntry(pPlaceHolder);
4396 
4398  }
4399 
4400  virtual void expand_row(const weld::TreeIter& rIter) override
4401  {
4402  assert(m_xTreeView->IsUpdateMode() && "don't expand when frozen");
4403  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4404  if (!m_xTreeView->IsExpanded(rVclIter.iter) && signal_expanding(rIter))
4405  m_xTreeView->Expand(rVclIter.iter);
4406  }
4407 
4408  virtual void collapse_row(const weld::TreeIter& rIter) override
4409  {
4410  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4411  if (m_xTreeView->IsExpanded(rVclIter.iter) && signal_collapsing(rIter))
4412  m_xTreeView->Collapse(rVclIter.iter);
4413  }
4414 
4415  virtual OUString get_text(const weld::TreeIter& rIter, int col) const override
4416  {
4417  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4418  return get_text(rVclIter.iter, col);
4419  }
4420 
4421  virtual void set_text(const weld::TreeIter& rIter, const OUString& rText, int col) override
4422  {
4423  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4424  set_text(rVclIter.iter, rText, col);
4425  }
4426 
4427  virtual OUString get_id(const weld::TreeIter& rIter) const override
4428  {
4429  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4430  const OUString* pStr = static_cast<const OUString*>(rVclIter.iter->GetUserData());
4431  if (pStr)
4432  return *pStr;
4433  return OUString();
4434  }
4435 
4436  virtual void set_id(const weld::TreeIter& rIter, const OUString& rId) override
4437  {
4438  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4439  set_id(rVclIter.iter, rId);
4440  }
4441 
4443  sal_uInt8 eDNDConstants) override
4444  {
4445  m_xTreeView->SetDragHelper(rHelper, eDNDConstants);
4446  }
4447 
4448  virtual void set_selection_mode(SelectionMode eMode) override
4449  {
4450  m_xTreeView->SetSelectionMode(eMode);
4451  }
4452 
4453  virtual void all_foreach(const std::function<bool(weld::TreeIter&)>& func) override
4454  {
4455  SalInstanceTreeIter aVclIter(m_xTreeView->First());
4456  while (aVclIter.iter)
4457  {
4458  if (func(aVclIter))
4459  return;
4460  iter_next(aVclIter);
4461  }
4462  }
4463 
4464  virtual void selected_foreach(const std::function<bool(weld::TreeIter&)>& func) override
4465  {
4466  SalInstanceTreeIter aVclIter(m_xTreeView->FirstSelected());
4467  while (aVclIter.iter)
4468  {
4469  if (func(aVclIter))
4470  return;
4471  aVclIter.iter = m_xTreeView->NextSelected(aVclIter.iter);
4472  }
4473  }
4474 
4475  virtual void visible_foreach(const std::function<bool(weld::TreeIter&)>& func) override
4476  {
4477  SalInstanceTreeIter aVclIter(m_xTreeView->GetFirstEntryInView());
4478  while (aVclIter.iter)
4479  {
4480  if (func(aVclIter))
4481  return;
4482  aVclIter.iter = m_xTreeView->GetNextEntryInView(aVclIter.iter);
4483  }
4484  }
4485 
4487  {
4489  m_xTreeView->SetScrolledHdl(LINK(this, SalInstanceTreeView, VisibleRangeChangedHdl));
4490  }
4491 
4492  virtual void remove_selection() override
4493  {
4495  SvTreeListEntry* pSelected = m_xTreeView->FirstSelected();
4496  while (pSelected)
4497  {
4498  SvTreeListEntry* pNextSelected = m_xTreeView->NextSelected(pSelected);
4499  m_xTreeView->RemoveEntry(pSelected);
4500  pSelected = pNextSelected;
4501  }
4503  }
4504 
4505  virtual bool is_selected(const weld::TreeIter& rIter) const override
4506  {
4507  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4508  return m_xTreeView->IsSelected(rVclIter.iter);
4509  }
4510 
4511  virtual int get_iter_index_in_parent(const weld::TreeIter& rIter) const override
4512  {
4513  const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
4514  return SvTreeList::GetRelPos(rVclIter.iter);
4515  }
4516 
4517  virtual int iter_compare(const weld::TreeIter& a, const weld::TreeIter& b) const override
4518  {
4519  const SalInstanceTreeIter& rVclIterA = static_cast<const SalInstanceTreeIter&>(a);
4520  const SalInstanceTreeIter& rVclIterB = static_cast<const SalInstanceTreeIter&>(b);
4521  const SvTreeList* pModel = m_xTreeView->GetModel();
4522  auto nAbsPosA = pModel->GetAbsPos(rVclIterA.iter);
4523  auto nAbsPosB = pModel->GetAbsPos(rVclIterB.iter);
4524  if (nAbsPosA < nAbsPosB)
4525  return -1;
4526  if (nAbsPosA > nAbsPosB)
4527  return 1;
4528  return 0;
4529  }
4530 
4531  virtual void move_subtree(weld::TreeIter& rNode, const weld::TreeIter* pNewParent,
4532  int nIndexInNewParent) override
4533  {
4534  SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNode);
4535  const SalInstanceTreeIter* pVclParentIter
4536  = static_cast<const SalInstanceTreeIter*>(pNewParent);
4537  m_xTreeView->GetModel()->Move(
4538  rVclIter.iter, pVclParentIter ? pVclParentIter->iter : nullptr, nIndexInNewParent);
4539  }
4540 
4541  virtual int count_selected_rows() const override { return m_xTreeView->GetSelectionCount(); }
4542 
4543  virtual int get_height_rows(int nRows) const override
4544  {
4545  return m_xTreeView->GetEntryHeight() * nRows;
4546  }
4547 
4548  virtual void make_sorted() override
4549  {
4550  assert(m_xTreeView->IsUpdateMode() && "don't sort when frozen");
4551  m_xTreeView->SetStyle(m_xTreeView->GetStyle() | WB_SORT);
4552  m_xTreeView->GetModel()->SetCompareHdl(LINK(this, SalInstanceTreeView, CompareHdl));
4553  set_sort_order(true);
4554  }
4555 
4556  virtual void set_sort_func(
4557  const std::function<int(const weld::TreeIter&, const weld::TreeIter&)>& func) override
4558  {
4560  SvTreeList* pListModel = m_xTreeView->GetModel();
4561  pListModel->Resort();
4562  }
4563 
4564  virtual void make_unsorted() override
4565  {
4566  m_xTreeView->SetStyle(m_xTreeView->GetStyle() & ~WB_SORT);
4567  }
4568 
4569  virtual void set_sort_order(bool bAscending) override
4570  {
4571  SvTreeList* pListModel = m_xTreeView->GetModel();
4572  pListModel->SetSortMode(bAscending ? SortAscending : SortDescending);
4573  pListModel->Resort();
4574  }
4575 
4576  virtual bool get_sort_order() const override
4577  {
4578  return m_xTreeView->GetModel()->GetSortMode() == SortAscending;
4579  }
4580 
4581  virtual void set_sort_indicator(TriState eState, int col) override
4582  {
4583  assert(col >= 0 && "cannot sort on expander column");
4584 
4585  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
4586  if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
4587  {
4588  sal_uInt16 nTextId = pHeaderBar->GetItemId(col);
4589  HeaderBarItemBits nBits = pHeaderBar->GetItemBits(nTextId);
4590  nBits &= ~HeaderBarItemBits::UPARROW;
4591  nBits &= ~HeaderBarItemBits::DOWNARROW;
4592  if (eState != TRISTATE_INDET)
4593  {
4594  if (eState == TRISTATE_TRUE)
4596  else
4597  nBits |= HeaderBarItemBits::UPARROW;
4598  }
4599  pHeaderBar->SetItemBits(nTextId, nBits);
4600  }
4601  }
4602 
4603  virtual TriState get_sort_indicator(int col) const override
4604  {
4605  assert(col >= 0 && "cannot sort on expander column");
4606 
4607  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
4608  if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
4609  {
4610  sal_uInt16 nTextId = pHeaderBar->GetItemId(col);
4611  HeaderBarItemBits nBits = pHeaderBar->GetItemBits(nTextId);
4612  if (nBits & HeaderBarItemBits::DOWNARROW)
4613  return TRISTATE_TRUE;
4614  if (nBits & HeaderBarItemBits::UPARROW)
4615  return TRISTATE_FALSE;
4616  }
4617 
4618  return TRISTATE_INDET;
4619  }
4620 
4621  virtual int get_sort_column() const override { return m_nSortColumn; }
4622 
4623  virtual void set_sort_column(int nColumn) override
4624  {
4625  if (nColumn == -1)
4626  {
4627  make_unsorted();
4628  m_nSortColumn = -1;
4629  return;
4630  }
4631 
4632  if (nColumn != m_nSortColumn)
4633  {
4634  m_nSortColumn = nColumn;
4635  m_xTreeView->GetModel()->Resort();
4636  }
4637  }
4638 
4640 
4641  virtual bool get_dest_row_at_pos(const Point& rPos, weld::TreeIter* pResult, bool bDnDMode) override
4642  {
4643  LclTabListBox* pTreeView = !bDnDMode ? dynamic_cast<LclTabListBox*>(m_xTreeView.get()) : nullptr;
4644  SvTreeListEntry* pTarget = pTreeView ? pTreeView->GetTargetAtPoint(rPos, false) : m_xTreeView->GetDropTarget(rPos);
4645 
4646  if (pTarget && pResult)
4647  {
4648  SalInstanceTreeIter& rSalIter = static_cast<SalInstanceTreeIter&>(*pResult);
4649  rSalIter.iter = pTarget;
4650  }
4651 
4652  return pTarget != nullptr;
4653  }
4654 
4655  virtual void unset_drag_dest_row() override
4656  {
4657  m_xTreeView->UnsetDropTarget();
4658  }
4659 
4660  virtual tools::Rectangle get_row_area(const weld::TreeIter& rIter) const override
4661  {
4662  return m_xTreeView->GetBoundingRect(static_cast<const SalInstanceTreeIter&>(rIter).iter);
4663  }
4664 
4665  virtual TreeView* get_drag_source() const override { return g_DragSource; }
4666 
4667  virtual int vadjustment_get_value() const override
4668  {
4669  int nValue = -1;
4670  const SvTreeListEntry* pEntry = m_xTreeView->GetFirstEntryInView();
4671  if (pEntry)
4672  nValue = m_xTreeView->GetAbsPos(pEntry);
4673  return nValue;
4674  }
4675 
4676  virtual void vadjustment_set_value(int nValue) override
4677  {
4678  if (nValue == -1)
4679  return;
4680  bool bUpdate = m_xTreeView->IsUpdateMode();
4681  if (bUpdate)
4682  m_xTreeView->SetUpdateMode(false);
4683  m_xTreeView->ScrollToAbsPos(nValue);
4684  if (bUpdate)
4685  m_xTreeView->SetUpdateMode(true);
4686  }
4687 
4688  void set_show_expanders(bool bShow) override
4689  {
4690  m_xTreeView->set_property("show-expanders", OUString::boolean(bShow));
4691  }
4692 
4693  virtual ~SalInstanceTreeView() override
4694  {
4695  LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
4696  if (pHeaderBox)
4697  {
4698  if (HeaderBar* pHeaderBar = pHeaderBox->GetHeaderBar())
4699  {
4700  pHeaderBar->SetSelectHdl(Link<HeaderBar*, void>());
4701  pHeaderBar->SetEndDragHdl(Link<HeaderBar*, void>());
4702  }
4703  }
4704  else
4705  {
4706  static_cast<LclTabListBox&>(*m_xTreeView).SetEndDragHdl(Link<SvTreeListBox*, void>());
4707  static_cast<LclTabListBox&>(*m_xTreeView).SetStartDragHdl(Link<SvTreeListBox*, bool>());
4708  static_cast<LclTabListBox&>(*m_xTreeView)
4710  }
4714  m_xTreeView->SetSelectHdl(Link<SvTreeListBox*, void>());
4720  }
4721 };
4722 
4723 IMPL_LINK(SalInstanceTreeView, TooltipHdl, const HelpEvent&, rHEvt, bool)
4724 {
4725  if (notify_events_disabled())
4726  return false;
4727  Point aPos(m_xTreeView->ScreenToOutputPixel(rHEvt.GetMousePosPixel()));
4728  SvTreeListEntry* pEntry = m_xTreeView->GetEntry(aPos);
4729  if (pEntry)
4730  {
4731  SalInstanceTreeIter aIter(pEntry);
4732  OUString aTooltip = signal_query_tooltip(aIter);
4733  if (aTooltip.isEmpty())
4734  return false;
4735  Size aSize(m_xTreeView->GetOutputSizePixel().Width(), m_xTreeView->GetEntryHeight());
4736  tools::Rectangle aScreenRect(
4737  m_xTreeView->OutputToScreenPixel(m_xTreeView->GetEntryPosition(pEntry)), aSize);
4738  Help::ShowQuickHelp(m_xTreeView, aScreenRect, aTooltip);
4739  }
4740  return true;
4741 }
4742 
4743 IMPL_LINK(SalInstanceTreeView, CustomRenderHdl, svtree_render_args, payload, void)
4744 {
4745  vcl::RenderContext& rRenderDevice = std::get<0>(payload);
4746  const tools::Rectangle& rRect = std::get<1>(payload);
4747  const SvTreeListEntry& rEntry = std::get<2>(payload);
4748  const OUString* pId = static_cast<const OUString*>(rEntry.GetUserData());
4749  if (!pId)
4750  return;
4751  signal_custom_render(rRenderDevice, rRect, m_xTreeView->IsSelected(&rEntry), *pId);
4752 }
4753 
4755 {
4756  vcl::RenderContext& rRenderDevice = payload.first;
4757  const SvTreeListEntry& rEntry = payload.second;
4758  const OUString* pId = static_cast<const OUString*>(rEntry.GetUserData());
4759  if (!pId)
4760  return Size();
4761  return signal_custom_get_size(rRenderDevice, *pId);
4762 }
4763 
4764 IMPL_LINK(SalInstanceTreeView, CompareHdl, const SvSortData&, rSortData, sal_Int32)
4765 {
4766  const SvTreeListEntry* pLHS = rSortData.pLeft;
4767  const SvTreeListEntry* pRHS = rSortData.pRight;
4768  assert(pLHS && pRHS);
4769 
4770  if (m_aCustomSort)
4771  return m_aCustomSort(SalInstanceTreeIter(const_cast<SvTreeListEntry*>(pLHS)),
4772  SalInstanceTreeIter(const_cast<SvTreeListEntry*>(pRHS)));
4773 
4774  const SvLBoxString* pLeftTextItem;
4775  const SvLBoxString* pRightTextItem;
4776 
4777  if (m_nSortColumn != -1)
4778  {
4779  size_t col = to_internal_model(m_nSortColumn);
4780 
4781  if (col < pLHS->ItemCount())
4782  {
4783  const SvLBoxString& rLeftTextItem
4784  = static_cast<const SvLBoxString&>(pLHS->GetItem(col));
4785  pLeftTextItem = &rLeftTextItem;
4786  }
4787  else
4788  pLeftTextItem = nullptr;
4789  if (col < pRHS->ItemCount())
4790  {
4791  const SvLBoxString& rRightTextItem
4792  = static_cast<const SvLBoxString&>(pRHS->GetItem(col));
4793  pRightTextItem = &rRightTextItem;
4794  }
4795  else
4796  pRightTextItem = nullptr;
4797  }
4798  else
4799  {
4800  pLeftTextItem
4801  = static_cast<const SvLBoxString*>(pLHS->GetFirstItem(SvLBoxItemType::String));
4802  pRightTextItem
4803  = static_cast<const SvLBoxString*>(pRHS->GetFirstItem(SvLBoxItemType::String));
4804  }
4805 
4806  return m_xTreeView->DefaultCompare(pLeftTextItem, pRightTextItem);
4807 }
4808 
4809 IMPL_LINK_NOARG(SalInstanceTreeView, VisibleRangeChangedHdl, SvTreeListBox*, void)
4810 {
4811  if (notify_events_disabled())
4812  return;
4813  signal_visible_range_changed();
4814 }
4815 
4817 {
4818  if (notify_events_disabled())
4819  return;
4820  signal_model_changed();
4821 }
4822 
4824 {
4825  bool bUnsetDragIcon(false); // ignored for vcl
4826  if (m_aDragBeginHdl.Call(bUnsetDragIcon))
4827  return true;
4828  g_DragSource = this;
4829  return false;
4830 }
4831 
4833 {
4834  g_DragSource = nullptr;
4835 }
4836 
4838 {
4839  SvTreeListEntry* pEntry = pData->GetActEntry();
4840  SvLBoxButton* pBox = pData->GetActBox();
4841 
4842  // tdf#122874 Select the row, calling SelectHdl, before handling
4843  // the toggle
4844  if (!m_xTreeView->IsSelected(pEntry))
4845  {
4846  m_xTreeView->SelectAll(false);
4847  m_xTreeView->Select(pEntry, true);
4848  }
4849 
4850  // additionally set the cursor into the row the toggled element is in
4851  m_xTreeView->pImpl->m_pCursor = pEntry;
4852 
4853  for (int i = 0, nCount = pEntry->ItemCount(); i < nCount; ++i)
4854  {
4855  SvLBoxItem& rItem = pEntry->GetItem(i);
4856  if (&rItem == pBox)
4857  {
4858  int nCol = to_external_model(i);
4859  signal_toggled(iter_col(SalInstanceTreeIter(pEntry), nCol));
4860  break;
4861  }
4862  }
4863 }
4864 
4866 {