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