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