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