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