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