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